start refactoring menubar and toolbar components

This commit is contained in:
Stewart Allen 2026-02-22 15:17:20 -05:00
commit ce423fddcc
15 changed files with 539 additions and 456 deletions

View file

@ -318,8 +318,7 @@ details[open] summary::after {
.dark #render-tools .pop,
.dark #render-tools svg,
.dark .pop-tics > div,
.dark #top,
.dark #top .content,
.dark #menubar.content,
.dark #app-name,
.dark .set2-group,
.dark .set2-group .var-row,
@ -390,7 +389,7 @@ details[open] summary::after {
.dark #oplist div:hover .del {
color: #777;
}
.dark #top .content > div:hover {
.dark #menubar.content > div:hover {
background-color: var(--blue-1);
}
.dark .top-menu label {
@ -449,7 +448,7 @@ details[open] summary::after {
}
/* top menu bar, drop menus */
#top, #app-name {
#app-name {
background-color: #fff;
text-transform: capitalize;
font-family: sans-serif;
@ -507,16 +506,17 @@ details[open] summary::after {
.top-menu > span:hover .top-menu-drop {
display: flex;
}
.top-menu-left .content {
/* .top-menu-right .content {
border-top-right-radius: 4px;
}
.top-menu-right {
align-items: self-end;
} */
.top-menu-left {
align-items: self-start;
}
.top-menu-center .content > div > label {
text-align: center !important;
}
.top-menu-right .content {
.top-menu-left .content {
border-top-left-radius: 4px;
}
.top-menu-drop {
@ -532,7 +532,7 @@ details[open] summary::after {
width: 15px;
}
#top .content {
#menubar.content {
gap: 2px;
display: flex;
align-items: center;
@ -545,63 +545,44 @@ details[open] summary::after {
border-bottom-right-radius: 4px;
border-bottom-left-radius: 4px;
}
#top .content {
#menubar.content {
display: flex;
flex-direction: column;
align-items: stretch;
padding: 2px;
}
#top .content > div {
#menubar.content > div {
display: flex;
flex-direction: row;
}
#top .content > div > label {
#menubar.content > div > label {
text-align: left;
flex-grow: 1;
}
#top .content > div > span {
#menubar.content > div > span {
text-align: right;
}
#top .content > div > span {
#menubar.content > div > span {
padding: 2px 7px 2px 7px;
padding-left: 10px;
text-align: center;
}
#top .content > div > label {
#menubar.content > div > label {
padding: 2px 7px 2px 7px;
justify-self: stretch;
align-self: stretch;
border-radius: 3px;
}
#top .content > div:hover {
#menubar.content > div:hover {
background-color: var(--blue-4);
}
#app-name {
position: absolute;
top: 0;
left: 50%;
z-index: 50;
transform: translateX(-50%);
}
#app-name {
cursor: pointer;
}
#app-name hr {
margin: 1px;
}
#app-name:hover #app-name-pop {
display: flex;
}
#app-name-pop {
color: var(--fg-gray);
font-family: sans-serif;
position: absolute;
top: 100%;
}
#app-name-pop .content {
text-align: center;
color: var(--appname-blue);
font-weight: bold;
align-self: center;
justify-self: stretch;
height: 100%;
}
#app,div {
@ -1164,59 +1145,39 @@ details[open] summary::after {
background-color: var(--main-color);
color: white;
}
/* top center toolbar */
#render-tools {
/* mode toolbar */
#mode-tools {
pointer-events: all;
position: absolute;
gap: 2px;
top: 3px;
top: 0;
left: 0;
right: 0;
align-items: center;
justify-content: center;
flex-direction: row;
}
#render-tools span {
position: relative;
#mode-tools > span {
text-transform: capitalize;
display: flex;
flex-direction: row;
align-items: center;
color: var(--menubar-fore);
background-color: var(--menubar-back);
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-left: 1px solid var(--border-gray);
border-right: 1px solid var(--border-gray);
border-bottom: 1px solid var(--border-gray);
padding: 3px 5px 3px 5px;
}
#render-tools svg {
font-size: 20px;
#mode-tools svg {
aspect-ratio: 1/1;
background-color: #fff;
border: 1px solid #aaa;
border-radius: 3px;
padding: 8px;
font-size: 20px;
padding: 0 5px 0 0;
}
#render-tools svg:hover {
border: 1px solid blue;
background-color: var(--blue-4);
}
/** tool pop menus */
#render-tools .pop:before {
position: absolute;
top: -10px;
left: -20px;
width: calc(100% + 40px);
height: calc(100% + 20px);
/* background-color: red; */
content: "";
}
#render-tools .pop {
background-color: #fff;
border: 1px solid #aaa;
border-radius: 3px;
position: absolute;
margin-top: 3px;
padding: 3px;
top: 100%;
left: 50%;
transform: translateX(-50%);
text-align: center;
white-space: nowrap;
}
#render-tools > span:not(:hover) .pop {
display: none;
#mode-tools > span:hover {
border-color: var(--appname-blue);
background-color: rgba(0,0,0,0.4);
}
/** fdm extruder drop-down */
#ft-nozzle .splat {
@ -2662,4 +2623,4 @@ details[open] summary::after {
.devel #code-preview > div,
.devel #code-preview-textarea {
height: 100%;
}
}

View file

@ -19,16 +19,24 @@
<title>Kiri:Moto</title>
<script>
const isDark = localStorage['kiri-dark'] === 'true';
document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');
if (isDark) {
document.documentElement.classList.add('dark');
document.documentElement.style.background = '#000000';
function setDarkLight(isDark) {
const dde = document.documentElement;
dde.setAttribute('data-theme', isDark ? 'dark' : 'light');
if (isDark) {
dde.classList.add('dark');
dde.style.background = '#000000';
} else {
dde.classList.remove('dark');
dde.style.background = '#ffffff';
}
}
setDarkLight(isDark);
</script>
<link rel="icon" href="/icon/kirimoto.png">
<link rel="apple-touch-icon" href="/icon/kirimoto.png">
<link rel="stylesheet" type="text/css" href="/moto/palette.css">
<link rel="stylesheet" type="text/css" href="index.css">
<link rel="stylesheet" type="text/css" href="/moto/menubar.css">
<link href="manifest.json" rel="manifest">
<link href="/font/css/all.min.css" rel="stylesheet">
<!-- <script type="module" src="/lib/kiri/run/worker.js"></script> -->
@ -46,323 +54,33 @@
<div id="top-sep"></div>
<!-- top menu bar -->
<div id="top" class="f-row">
<div class="f-row top-menu">
<span id="view-arrange">
<span><i class="fas fa-shapes"></i></span>
<label lk="arrange">arrange</label>
</span>
<span id="act-slice">
<span><i class="fas fa-bars"></i></span>
<label id="label-slice" title="generate layer slices" lk="slice">preview</label>
</span>
<span id="act-preview">
<span><i class="fas fa-layer-group"></i></span>
<label id="label-preview" title="show routing and paths" lk="preview">preview</label>
</span>
<span id="act-animate">
<span><i class="fas fa-film"></i></span>
<label id="label-animate" title="render routing on a mesh" lk="animate">animate</label>
</span>
<span id="act-export">
<span><i class="fas fa-file-download"></i></span>
<label id="label-export" title="generate gcode" lk="export">export</label>
</span>
</div>
<div class="grow"></div>
<div id="app-name" class="f-col a-center top-menu">
<span class="grow">
<span id="app-name-text" class="km-font">Kiri:Moto</span>
<div id="app-name-pop" class="top-menu-drop top-menu-center">
<div class="content">
<div>
<label id="app-info">version</label>
</div>
<hr width="100%">
<div>
<label id="app-mesh">mesh edit</label>
</div>
<hr>
<div id="install">
<label lk="install">install</label>
</div>
<div id="uninstall" class="hide">
<label lk="uninstall">uninstall</label>
</div>
<div id="app-quit" class="hide">
<label lk="quit">quit</label>
</div>
</div>
</div>
</span>
</div>
<div id="doit" class="f-row a-center">
<button id="undo"><i class="fas fa-undo-alt"></i></button>
<button id="redo"><i class="fas fa-redo-alt"></i></button>
</div>
<div class="grow"></div>
<div class="f-row top-menu">
<span>
<i class="fas fa-folder"></i>
<label lk="fe_menu">files</label>
<div class="top-menu-drop top-menu-right">
<div class="content">
<div id="file-new">
<label lk="new">new</label>
<span><i class="fas fa-file"></i></span>
</div>
<hr>
<div id="file-recent">
<label lk="recent">recent</label>
<span><i class="fas fa-list"></i></span>
</div>
<div id="file-import">
<label lk="import">import</label>
<span><i class="fas fa-file-upload"></i></span>
<!-- required file input loaders -->
<input id="load-file" type="file" name="loadme" style="display:none" accept=".km,.kmz,.stl,.obj,.svg,.png,.jpg,.jpeg,.gcode,.nc"></input>
</div>
<hr>
<div id="app-export">
<label lk="export">export</label>
<span><i class="fas fa-download"></i></span>
</div>
</div>
</div>
</span>
<span>
<i class="fas fa-eye"></i>
<label lk="vu_menu">view</label>
<div class="top-menu-drop top-menu-right">
<div class="content">
<div id="view-fit">
<label lk="contents">contents</label>
<span><i class="fas fa-expand"></i></span>
</div>
<div id="view-home">
<label lk="home">home</label>
<span><i class="fas fa-home"></i></span>
</div>
<hr>
<div id="view-top">
<label lk="top">top</label>
<span><i class="fas fa-square"></i></span>
</div>
<div id="view-front">
<label lk="front">top</label>
<span><i class="fas fa-square"></i></span>
</div>
<div id="view-back">
<label lk="back">top</label>
<span><i class="fas fa-square"></i></span>
</div>
<div id="view-left">
<label lk="left">top</label>
<span><i class="fas fa-square"></i></span>
</div>
<div id="view-right">
<label lk="right">top</label>
<span><i class="fas fa-square"></i></span>
</div>
<hr>
<div id="app-xpnd">
<label lk="fullscreen">fullscreen</label>
<span><i class="fas fa-maximize"></i></span>
</div>
</div>
</div>
</span>
<span>
<i class="fas fa-code-branch"></i>
<label lk="mo_menu">mode</label>
<div class="top-menu-drop top-menu-right">
<div class="content">
<div id="mode-fdm">
<label title="3D Additive Printing Processes">FDM</label>
<span><i class="fas fa-layer-group"></i></span>
</div>
<div id="mode-cam">
<label title="CNC Mills and Subtractive Processes">CNC</label>
<span><i class="fas fa-bore-hole"></i></span>
</div>
<div id="mode-sla">
<label title="mSLA Resin Printing">SLA</label>
<span><i class="fas fa-cube"></i></span>
</div>
<hr>
<div id="mode-laser">
<label title="Laser Cutting and Engraving">Laser</label>
<span><i class="fas fa-bolt"></i></span>
</div>
<div id="mode-wjet">
<label title="WaterJet Cutting">Water</label>
<span><i class="fas fa-location-pin"></i></span>
</div>
<div id="mode-wedm">
<label title="Wire EDM Cutting">Wire</label>
<span><i class="fas fa-ellipsis-vertical"></i></span>
</div>
<div id="mode-drag">
<label title="Drag Knife Cutting">Drag</label>
<span><i class="fas fa-caret-left"></i></span>
</div>
</div>
</div>
</span>
<span>
<i class="fas fa-cog"></i>
<label lk="su_menu">setup</label>
<div class="top-menu-drop top-menu-right">
<div class="content">
<div id="set-device">
<label lk="machines">machines</label>
<span><i class="fas fa-cube"></i></span>
</div>
<div id="set-profs">
<label lk="profs">profiles</label>
<span><i class="fas fa-sliders-h"></i></span>
</div>
<div id="set-tools">
<label lk="tools">tools</label>
<span><i class="fas fa-tools"></i></span>
</div>
<div id="set-prefs">
<label lk="prefs">prefs</label>
<span><i class="fa-solid fa-square-check"></i></span>
</div>
</div>
</div>
</span>
<span>
<i class="fas fa-question-circle"></i>
<label lk="info">info</label>
<div class="top-menu-drop top-menu-right">
<div class="content">
<div id="app-help">
<label lk="help">help</label>
</div>
<div id="app-don8">
<label lk="donate">donate</label>
</div>
</div>
</div>
</span>
<span>
<i class="fas fa-language"></i>
<div class="top-menu-drop top-menu-right">
<div class="content">
<div><label id="lset-zh">简体中文</label></div>
<div><label id="lset-da">dansk</label></div>
<div><label id="lset-de">deutsch</label></div>
<div><label id="lset-en">english</label></div>
<div><label id="lset-es">español</label></div>
<div><label id="lset-fr">français</label></div>
<div><label id="lset-pl" class="nocap">polski</label></div>
<div><label id="lset-pt">português</label></div>
</div>
</div>
</span>
</div>
</div>
<div id="menubar" class="f-row"></div>
<!-- line betwwen menu bar and main application windows -->
<div id="progress"><div id="progbar"></div><div id="progtxt">loading</div></div>
<!-- toolbar with mesh and rendering options -->
<div>
<div id="render-tools">
<span id="tool-nozzle"><i class="fas fa-location-pin" title="extruder"></i>
<div id="ft-nozzle" class="f-col pop"></div>
</span>
<span id="tool-rotate"><i class="fas fa-rotate-right" title="rotate selection"></i>
<div id="ft-rotate" class="grid pop">
<div id="rot_x_lt"><i class="fas fa-chevron-left"></i></div>
<label>X</label>
<div id="rot_x_gt"><i class="fas fa-chevron-right"></i></div>
<input id="rot_x" class="value center" size="6" value="90">
<div id="rot_y_lt"><i class="fas fa-chevron-left"></i></div>
<label>Y</label>
<div id="rot_y_gt"><i class="fas fa-chevron-right"></i></div>
<input id="rot_y" class="value center" size="6" value="90">
<div id="rot_z_lt"><i class="fas fa-chevron-left"></i></div>
<label>Z</label>
<div id="rot_z_gt"><i class="fas fa-chevron-right"></i></div>
<input id="rot_z" class="value center" size="6" value="90">
<div class="buttons f-row">
<button id="unrotate" class="grow" lk="reset">reset</button>
</div>
</div>
</span>
<span id="tool-scale"><i class="fas fa-expand" title="scale or resize selection"></i>
<div id="ft-scale" class="grid pop">
<div><label>X</label><input id="lock_x" type="checkbox" checked></div>
<div><label>Y</label><input id="lock_y" type="checkbox" checked></div>
<div><label>Z</label><input id="lock_z" type="checkbox" checked></div>
<label id="lab-axis" lk="axis">axis</label>
<input id="size_x" size="8" class="value">
<input id="size_y" size="8" class="value">
<input id="size_z" size="8" class="value">
<label id="lab-size" lk="size">size</label>
<input id="scale_x" size="8" class="value" value="1">
<input id="scale_y" size="8" class="value" value="1">
<input id="scale_z" size="8" class="value" value="1">
<label id="lab-scale" lk="scale">scale</label>
<div class="buttons f-row">
<button id="scale-reset" class="grow j-center">reset</button>
</div>
</div>
</span>
<span id="tool-mesh"><i class="fas fa-dice-d20"></i>
<div id="ft-mesh" class="grow f-col pop">
<div id="ft-mesh-btn">
<div><button id="mesh-merge" lk="rc_merg">Merge</button></div>
<div><button id="mesh-split" lk="rc_splt">Isolate Bodies</button></div>
<div><button id="mesh-export-obj" lk="rc_xobj">export OBJ</button></div>
<div><button id="mesh-export-stl" lk="rc_xstl">export STL</button></div>
</div>
</div>
</span>
<span id="context-mirror" xlk="rc_mirr">
<i class="fas fa-arrows-left-right-to-line"></i>
<div class="pop">mirror selection</div>
</span>
<span id="context-duplicate" xlk="rc_dupl">
<i class="fas fa-copy"></i>
<div class="pop">duplicate selection</div>
</span>
<span id="context-layflat" xlk="rc_lafl">
<i class="fas fa-arrows-down-to-line"></i>
<div class="pop">choose a face to place<br>on the work surface</div>
</span>
<span id="context-lefty" xlk="rc_lafl">
<i class="fas fa-arrows-down-to-line rot90"></i>
<div class="pop">choose a face to align<br>to the y axis</div>
</span>
<span id="context-setfocus" xlk="rc_focs">
<i class="fas fa-eye"></i>
<div class="pop">choose focal point<br>camera orbit center</div>
</span>
<span id="context-contents" xlk="rc_focs">
<i class="fas fa-arrows-to-circle"></i>
<div class="pop">fit workspace contents</div>
</span>
<span id="render-solid" class="j-center">
<i class="fas fa-square"></i>
<div class="pop">render objects solid</div>
</span>
<span id="render-wire" class="j-center">
<i class="fas fa-border-all"></i>
<div class="pop">render objects wireframe</div>
</span>
<span id="render-ghost" class="a-center">
<i class="fas fa-border-none"></i>
<div class="pop">render objects transparent</div>
</span>
<span id="render-edges" class="a-center">
<i class="fa-regular fa-square"></i>
<div class="pop">trace edges</div>
</span>
</div>
<div id="mode-tools">
<span id="view-arrange">
<span><i class="fas fa-shapes"></i></span>
<span lk="arrange">arrange</span>
</span>
<span id="act-slice">
<span><i class="fas fa-bars"></i></span>
<label id="label-slice" title="generate layer slices" lk="slice">preview</label>
</span>
<span id="act-preview">
<span><i class="fas fa-layer-group"></i></span>
<label id="label-preview" title="show routing and paths" lk="preview">preview</label>
</span>
<span id="act-animate">
<span><i class="fas fa-film"></i></span>
<label id="label-animate" title="render routing on a mesh" lk="animate">animate</label>
</span>
<span id="act-export">
<span><i class="fas fa-file-download"></i></span>
<label id="label-export" title="generate gcode" lk="export">export</label>
</span>
</div>
<div id="mid" class="grow f-row">

126
web/moto/menubar.css Normal file
View file

@ -0,0 +1,126 @@
#menubar {
position: relative;
z-index: 50;
background-color: var(--menubar-back);
color: var(--menubar-fore);
text-transform: capitalize;
align-items: center;
border-bottom: 1px solid var(--border-gray);
}
.menubar-separator {
align-self: stretch;
align-items: center;
background: var(--menubar-vsep);
margin: 5px;
width: 1px;
}
.menubar-appname,
.menubar-mode {
color: var(--appname-blue);
cursor: default;
align-self: stretch;
align-items: center;
margin: 4px 0 4px 0;
padding: 4px 12px 4px 12px;
border-radius: 0;
user-select: none;
}
.menubar-appname {
font-weight: bold;
}
#menubar .top-menu {
display: flex;
align-items: stretch;
white-space: nowrap;
}
#menubar .top-menu > span {
cursor: default;
position: relative;
display: flex;
gap: 8px;
align-items: center;
margin: 2px;
padding: 8px 12px;
border: 1px solid transparent;
border-radius: 6px;
user-select: none;
}
#menubar .top-menu > span:hover {
border-color: var(--appname-blue);
background-color: rgba(0,0,0,0.4);
}
#menubar .top-menu > span:hover .top-menu-drop {
display: flex;
}
#menubar .top-menu label,
#menubar .top-menu svg {
color: inherit;
}
#menubar .top-menu hr {
width: 100%;
margin: 0;
border: 0;
border-top: 0.5px solid var(--menubar-vsep);
}
#menubar .top-menu-drop {
display: none;
position: absolute;
top: 100%;
left: 0;
z-index: 90;
font-family: sans-serif;
padding-top: 3px;
}
#menubar .top-menu-right {
left: auto;
right: 0;
}
#menubar .top-menu-drop .content {
display: flex;
flex-direction: column;
gap: 6px;
border: 1px solid var(--border-gray);
border-radius: 6px;
background: var(--menubar-back);
color: var(--menubar-fore);
padding: 4px;
}
#menubar .top-menu-drop .content > div {
display: flex;
align-items: center;
gap: 15px;
border: 1px solid transparent;
border-radius: 6px;
padding: 4px 8px;
}
#menubar .top-menu-drop .content > div > label {
flex-grow: 1;
text-align: left;
}
#menubar .top-menu-drop .content > div > span {
display: flex;
justify-content: flex-end;
min-width: 16px;
}
#menubar .top-menu-drop .content > div:hover,
#menubar .top-menu-drop .content > div.selected,
#menubar .top-menu > span.selected {
border-color: var(--appname-blue);
background-color: rgba(0,0,0,0.4);
}

View file

@ -4,43 +4,18 @@
*/
:root {
/* semantic core */
--color-bg: #f6f8fb;
--color-bg-elev: #ffffff;
--color-bg-subtle: #eef2f7;
--color-surface: #ffffff;
--color-surface-2: #f3f6fb;
--color-text: #1b2430;
--color-text-muted: #556173;
--color-border: #a6b3c3;
--color-border-strong: #6a7a90;
--color-accent: #5a9fd4;
--color-accent-hover: #7bb8e8;
--color-focus: rgba(90,159,212,0.35);
--color-selection: rgba(90,159,212,0.45);
--color-selection-hover: rgba(90,159,212,0.8);
--color-success: #4ade80;
--color-warning: #fbbf24;
--color-danger: #f87171;
--appname-blue: #5a9fd4;
--menubar-vsep: rgba(0,0,0,0.2);
--menubar-back: rgba(128,128,128,0.5);
--menubar-fore: rgba(20,20,20,1.0);
--border-gray: rgba(128,128,128,0.5);
}
:root.dark,
:root[data-theme="dark"] {
--color-bg: #0f1116;
--color-bg-elev: #161a22;
--color-bg-subtle: #1b2230;
--color-surface: #1a1f29;
--color-surface-2: #222936;
--color-text: #e2e8f0;
--color-text-muted: #a5b0c0;
--color-border: #444f63;
--color-border-strong: #6d7a93;
--color-accent: #5a9fd4;
--color-accent-hover: #7bb8e8;
--color-focus: rgba(90,159,212,0.4);
--color-selection: rgba(90,159,212,0.5);
--color-selection-hover: rgba(90,159,212,0.95);
--color-success: #4ade80;
--color-warning: #fbbf24;
--color-danger: #f87171;
--appname-blue: #5a9fd4;
--menubar-vsep: rgba(255,255,255,0.2);
--menubar-back: rgba(50,50,50,0.9);
--menubar-fore: rgba(250,250,250,1.0);
--border-gray: rgba(128,128,128,0.5);
}