Replaces the 'Open questions' section with 'Resolved decisions' and propagates the four decisions into the relevant phases: - Hard cut: no config.ui.layout flag. Phase 6 now includes the removal of .nav-header, side-menu.css and the #tab1..#tab4 block with a git grep verification step. - Macros: Control row binds to config.macros.slice(0, 8); Settings -> Macros owns the master list and reordering. - Pin to Control: deferred, status strip stays at State / V&F / Spindle / Job for this iteration. - Feed/spindle override: bottom drawer triggered by the Spindle KPI tile, reusing override_feed / override_speed. Goals (s.1) and Phase 6 testing checklist updated to match.
170 lines
14 KiB
Markdown
170 lines
14 KiB
Markdown
# UX Redesign — Implementation Plan
|
||
|
||
Reference mock: `docs/mocks/v09_full_ux.html`
|
||
Target hardware: 10.8" portable monitor, 1920×1080, capacitive touch, Chrome fullscreen.
|
||
|
||
## 1. Goals
|
||
|
||
The redesign keeps every existing feature but reorganizes the page into a single-screen control surface for finger-touch use:
|
||
|
||
- A slim 96 px header replaces the 140 px nav-header. Only logo + ONEFINITY wordmark + tab bar + system pill + READY badge + octagonal STOP.
|
||
- 4 top-level sections accessed via underline-ribbon tabs in the header:
|
||
1. **Control** — jog pad, DRO table, status strip, macro row.
|
||
2. **Program** — Auto run controls, file actions, G-code listing, 3D viewer.
|
||
3. **Console** — MDI, Messages, Indicators (sub-tabs).
|
||
4. **Settings** — paged settings (replaces the Pure left rail).
|
||
- Touch targets ≥ 64 px (jog tiles 72 px, axis action icons 72 px, macro buttons 84 px).
|
||
- All action chip-soup (WiFi/Camera/Rotary/IP/Version) collapses into one "All systems · view" pill that opens a popover. Burger menu removed (Settings tab supersedes it).
|
||
- V09 jog/macro palette: flat soft slate (#3f4b63), no drop shadow; yellow (#fde047) accent for active states (step seg, tab underline, macro number badge).
|
||
- Spindle override / feed override sliders live in a bottom-edge drawer triggered by tapping the Spindle KPI tile (no permanent screen real estate).
|
||
- Hard cut: no `config.ui.layout` flag; the new shell replaces the old in a single release.
|
||
|
||
## 2. Scope of code change
|
||
|
||
The build is Pug + Stylus + Browserify Vue (Vue 1.x). `index.pug` defines the chrome; `src/pug/templates/*.pug` defines each view; `src/js/*.js` mirrors them as Vue components routed by `currentView` from the URL hash.
|
||
|
||
Files we will touch:
|
||
|
||
- `src/pug/index.pug` — replace `#layout / #menu / #main / .nav-header` with the new header + tab bar + body. Drop the burger and the side-menu include.
|
||
- `src/pug/templates/control-view.pug` — restructure into the new Control panel (jog grid + DRO table + status strip + macro row). MDI/Messages/Indicators move out.
|
||
- New `src/pug/templates/program-view.pug` — Auto sub-panel content (action bar, file bar, gcode-viewer, path-viewer).
|
||
- New `src/pug/templates/console-view.pug` — MDI / Messages / Indicators sub-tabs hosting existing `console.pug` and `indicators.pug` partials.
|
||
- `src/js/app.js` — extend `parse_hash` so `#program`, `#console`, `#settings` resolve; expose tab state for the header to highlight.
|
||
- `src/js/control-view.js` — keep jog/DRO logic, drop the Auto/MDI/Messages/Indicators internal `tab` state and template hooks.
|
||
- New `src/js/program-view.js`, `src/js/console-view.js` — extracted Vue components.
|
||
- `src/stylus/style.styl` — add `.app-shell`, `.head`, `.tabs-host`, `.ktab`, panel styles, V09 jog tokens. Keep legacy classes alive until templates fully migrated.
|
||
- `src/static/css/side-menu.css` — stop including in `index.pug`.
|
||
- Settings: keep `settings-view.pug`, `admin-general-view.pug`, `admin-network-view.pug`, `motor-view.pug`, `tool-view.pug`, `io-view.pug`, etc., and surface them through a left-rail navigator inside the Settings panel rather than the sidebar.
|
||
- Settings → Macros owns the full macro list (1…N). Control's macro row is a slice of the first 8; reordering happens in Settings.
|
||
|
||
## 3. Routing model
|
||
|
||
We keep the existing URL hash routing because everything in `src/js/app.js#parse_hash` and the deep-linked menu items (`#motor:0`, `#admin-network`, etc.) depend on it.
|
||
|
||
| URL hash | Top tab | Notes |
|
||
|-------------------------|------------|-------------------------------------------------------|
|
||
| `#control` | Control | Default |
|
||
| `#program` / `#program:auto` | Program | Auto sub-view (only sub-view for now) |
|
||
| `#console` / `#console:mdi` | Console | MDI default, also `:messages` and `:indicators` |
|
||
| `#settings` | Settings | Settings home (Display & Units) |
|
||
| `#admin-general`, `#admin-network`, `#motor:N`, `#tool`, `#io`, `#help`, `#cheat-sheet` | Settings | Existing routes remain, surfaced in the Settings left rail |
|
||
|
||
The header tab bar maps URL prefix → active tab. A tiny helper `topTabFromHash(hash)` lives in `app.js` and is reused by the header template.
|
||
|
||
## 4. Step-by-step
|
||
|
||
### Phase 1 — Mock parity (1–2 days)
|
||
1. Add `docs/mocks/v09_full_ux.html` (done) so anyone can preview the target.
|
||
2. Move the V09 palette into Stylus tokens at the top of `style.styl`:
|
||
```styl
|
||
$jog-bg = #3f4b63
|
||
$jog-hover = #4a5777
|
||
$jog-dir = #5b6885
|
||
$jog-ghost = #8c97ad
|
||
$accent = #fde047
|
||
$accent-ink = #0f172a
|
||
```
|
||
3. Build the header in `index.pug`:
|
||
```pug
|
||
.app-shell
|
||
header.head
|
||
.brand-blk
|
||
.brand-logo
|
||
.brand-name ONEFINITY
|
||
nav.tabs-host(role="tablist")
|
||
a.ktab(:class="{active: topTab === 'control'}", href="#control")
|
||
.fa.fa-gamepad
|
||
| Control
|
||
a.ktab(:class="{active: topTab === 'program'}", href="#program") …
|
||
a.ktab(:class="{active: topTab === 'console'}", href="#console") …
|
||
a.ktab(:class="{active: topTab === 'settings'}", href="#settings") …
|
||
button.sys-btn(@click="toggle_sys_popover") …
|
||
span.state-badge(:class="state_class")
|
||
estop(@click="estop")
|
||
```
|
||
4. Style the header tabs as **underline ribbon** (V02): transparent fills, slate-gray text, dark text + 5 px yellow underline on active. CSS already proven in the mock.
|
||
5. Move the rotary toggle and pi-temp warning into the system pill popover.
|
||
|
||
### Phase 2 — Control panel (2 days)
|
||
1. Rewrite the outer markup of `control-view.pug` to a CSS grid:
|
||
```
|
||
.control-grid → 720px jog-card | 1fr right-col(dro-card + status-strip)
|
||
```
|
||
Drop the `<table>`-based outer layout (axes table stays — it's a real data table).
|
||
2. Replace the legacy `<button>` elements in the jog table with `.jbtn` markup that pulls colors from `$jog-*` tokens. Keep the `@click="jog_fn(...)"` bindings unchanged.
|
||
3. Build the new `.step-seg` with the existing `jog_incr` model. The four buttons stay wired to `jog_incr = 'fine' | 'small' | 'medium' | 'large'`.
|
||
4. Build `.dro-card` from the existing `table.axes` markup. Each row gets the new 7-column grid; axis cells just need `.dro-axis`, `.dro-pos`, `.dro-sec` classes.
|
||
5. Move the four KPI tiles (`State / Velocity-Feed / Spindle / Job`) into `.status-strip`. Existing `state.v`, `state.feed`, `state.s`, `state.line` bindings are unchanged.
|
||
6. Move `.macros-div` into a `.macro-row` 8-column grid. The row binds to `config.macros.slice(0, 8)`; macros 9…N are editable and runnable only from Settings → Macros (no drawer in Control). Reordering in Settings changes which macros appear in the visible 8.
|
||
7. Drop the legacy `.tabs / #tab1 …` block from `control-view.pug` entirely.
|
||
|
||
### Phase 3 — Program panel (1.5 days)
|
||
1. New file `src/pug/templates/program-view.pug` with `.program-card` and the action / file bars.
|
||
2. Move the Auto bar (RUN, STOP, UPLOAD FOLDER, UPLOAD FILE, DOWNLOAD FILE, DELETE) and the file-select strip (Create Folder, Delete Folder, folder picker, file picker, sort) out of `control-view.pug` into here. Use the V09 button styles (`.action-btn`, `.action-btn.run`, `.action-btn.danger`, `.file-btn`, `.file-select`).
|
||
3. Embed `path-viewer` and `gcode-viewer` in `.program-body { 1fr 600px }`. Both Vue components render unchanged.
|
||
4. New `src/js/program-view.js` exporting the same data model the existing `Auto` tab uses (`gcode_files`, `state.selected`, `start_pause`, etc.). The fastest path: move the relevant computed/methods into a mixin `gcode-program-mixin.js` consumed by both old and new components during the migration.
|
||
5. Wire `<component :is="currentView + '-view'">` in `index.pug` to pick up `program-view`.
|
||
|
||
### Phase 4 — Console panel (1 day)
|
||
1. New `src/pug/templates/console-view.pug` with the inner `.ptab-bar` (MDI / Messages / Indicators) and `data-sub` panels.
|
||
2. The MDI panel reuses the existing `<input v-model="mdi" @keyup.enter="submit_mdi">` plus the on-screen keypad (G0/G1/G2/G3/G28/G92/M3/M5 + axis letters + CLEAR/SEND).
|
||
3. The Messages panel pulls from the existing `popupMessages` array + a new `messages_log` state we will accumulate from `app.js`'s `error` and `popupMessages` channels (no protocol change).
|
||
4. The Indicators panel mounts the existing `<indicators :state="state" :template="template">` component.
|
||
5. Sub-tab state is local Vue state (`activeSub: 'mdi' | 'messages' | 'indicators'`) plus URL fragment after `:` so deep links keep working.
|
||
|
||
### Phase 5 — Settings panel (1 day)
|
||
1. New `src/pug/templates/settings-view.pug` with a left rail and a content slot.
|
||
2. The left rail is data-driven from a list of existing settings views: General, Network, Motion (settings-view), Spindle (tool-view), Safety (admin-general subset), Camera, Macros (settings-view subset), I/O, Motors, Help, About.
|
||
3. The content slot uses `<component :is="settingsSub + '-view'">` so each existing pug template renders unchanged (`admin-general-view.pug`, `admin-network-view.pug`, `motor-view.pug`, `tool-view.pug`, `io-view.pug`, `settings-view.pug`, `help-view.pug`, `cheat-sheet-view.pug`).
|
||
4. Existing routes (`#admin-network`, `#motor:0`, …) resolve to Settings + the matching left-rail item. We lose nothing.
|
||
5. Decommission the side menu in `index.pug` and stop including `side-menu.css`.
|
||
|
||
### Phase 6 — Polish & rollout (0.5 days)
|
||
1. Pulse-dot animation for the READY badge (CSS keyframes already in the mock).
|
||
2. System pill popover content: WiFi state + button, Camera state + retry, Rotary toggle, IP address, firmware version, "Open Settings".
|
||
3. Disabled states: jog buttons + macro buttons honor `is_ready` like before; gray them out instead of hiding.
|
||
4. Decimal-places setting from the existing `display_units` plumbing — wire to a new `precision` config the DRO reads.
|
||
5. Build the **Spindle override drawer**: clicking the `.stat-card` for Spindle toggles `.override-drawer.open` anchored to the bottom edge of the body. The drawer hosts the two existing `<input type="range">` controls for `feed_override` and `speed_override` plus `Reset` buttons. Bind to the existing `override_feed` / `override_speed` methods.
|
||
6. **Hard cut cleanup:** delete the legacy `.nav-header`, side-menu markup, and the inline `.tabs / #tab1…#tab4` block from `control-view.pug`. Remove `src/static/css/side-menu.css` from `index.pug` includes. Sweep `style.styl` for orphan rules (`.nav-header`, `.brand`, `.menu-link`, `.pure-menu*` overrides, `.tabs > input` selectors) and delete them in the same commit so we don't ship dead CSS.
|
||
|
||
## 5. Migration risks & mitigations
|
||
|
||
| Risk | Mitigation |
|
||
|----------------------------------------------|---------------------------------------------------------------------------------------------|
|
||
| Existing deep links from PDFs / forum posts (`#admin-network`) break | Keep the same hashes; only their visual shell changes. `parse_hash` resolves them. |
|
||
| Vue 1.x doesn't support modern slot syntax we used in the mock | The mock is plain HTML for visual review; production code uses the existing Vue 1 patterns. No new Vue features required. |
|
||
| Touch monitor with HDMI vs USB-C may report different DPI | The new layout is fluid inside 1920 × 1080 only when fullscreen Chrome. Provide a CSS `@media (max-width: 1820px)` fallback that scales the macro row to 4 columns and stacks the right column under the jog. |
|
||
| Existing customers rely on muscle memory of the side menu | Settings tab opens directly to the same left-rail navigator. First-launch toast: "Side menu moved to Settings." |
|
||
| `path-viewer` / `gcode-viewer` are heavy three.js components | They live in the Program tab now; we lazy-mount with `v-if="currentView === 'program'"` so Control stays light. |
|
||
| MDI input could lose focus when the inner `.ptab` is switched | Keep the input mounted, just hide non-active subs with `display:none`. |
|
||
|
||
## 6. Testing checklist
|
||
|
||
- Chrome on the 10.8" 1920 × 1080 monitor, fullscreen — every panel fits without scrolling at 100 %.
|
||
- Chrome at 1366 × 768 — fallback layout works (Control collapses jog above DRO).
|
||
- Touch hit-tests: every interactive target ≥ 48 px on its shortest side, primary jog tiles ≥ 72 px.
|
||
- Existing flows still work end-to-end: home all axes, run a small program, MDI a `G0 X10`, switch to Imperial, upload a folder, delete a file.
|
||
- Hash routing: hand-type `#motor:1` and confirm Settings tab activates with Motor 1 selected.
|
||
- Spindle override drawer: tap Spindle KPI tile, sliders move feed/speed override, `Reset` returns both to 100 %, tile tap closes drawer.
|
||
- Macro row shows macros 1–8 only; reordering in Settings → Macros changes which 8 appear on Control.
|
||
- Pulse-dot animation respects `prefers-reduced-motion`.
|
||
- Hard-cut cleanup verified: `git grep` finds no references to the old `.nav-header`, `side-menu.css`, or the `#tab1…#tab4` selectors after the rename.
|
||
|
||
## 7. Estimated effort
|
||
|
||
About 6–7 working days for one developer:
|
||
|
||
1. Mock parity & header — 1.5 days
|
||
2. Control panel (incl. macro slice + DRO grid) — 2 days
|
||
3. Program panel — 1.5 days
|
||
4. Console panel — 1 day
|
||
5. Settings shell — 1 day
|
||
6. Override drawer, polish, hard-cut cleanup, regression tests — 0.5–1 day
|
||
|
||
## 8. Resolved decisions
|
||
|
||
- **Rollout: hard cut.** No `config.ui.layout` feature flag, no parallel legacy shell. The new `index.pug` tree replaces the old one in a single release; the old `.nav-header`, side menu, and embedded `.tabs` block are deleted (not gated). One pre-release internal QA pass on real hardware before tagging.
|
||
- **Macros above 8: Settings owns the master list; Control surfaces the first 8 (configurable).** The Control macro row reads from `config.macros[0..7]`; everything beyond index 7 is editable / runnable only from Settings → Macros. Users can reorder which macros land in the visible 8 there.
|
||
- **"Pin to Control" indicator slot: defer.** Not in this redesign. Tracked as a follow-up; current status strip stays fixed at State / Velocity·Feed / Spindle / Job.
|
||
- **Feed & spindle override: drawer triggered by the Spindle KPI tile.** The Spindle card in the status strip becomes tappable. Tap opens a bottom-edge drawer (≈ 220 px tall) containing the two existing range inputs (`feed_override`, `speed_override`) at touch-friendly size with `Reset to 100 %` buttons. Closes by tapping the tile again or the drawer chevron. No protocol change; reuses the existing `override_feed` / `override_speed` handlers.
|