Plan: V09 full UX redesign mock + implementation plan
- docs/mocks/v09_full_ux.html — high-fidelity 1920x1080 mock showing the proposed Control / Program / Console / Settings tab layout with the V09 flat slate jog/macro palette and an underline ribbon header tab style. - plans/2026-04-30_ux_redesign.md — phased implementation plan to port index.pug + control-view.pug to the new shell while keeping hash routing and existing settings/admin views intact.
This commit is contained in:
163
plans/2026-04-30_ux_redesign.md
Normal file
163
plans/2026-04-30_ux_redesign.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# 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).
|
||||
|
||||
## 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.
|
||||
|
||||
## 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. Cap visible buttons to 8 — overflow lives in Settings → Macros (or an "All macros" sheet for later).
|
||||
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. Add a feature flag `config.ui.layout = "v09" | "legacy"` in `config-template.json`. If `legacy`, keep the old `index.pug` tree for one release. Default to `v09` after a beta cycle.
|
||||
|
||||
## 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.
|
||||
- Pulse-dot animation respects `prefers-reduced-motion`.
|
||||
- Audit `style.styl` for orphan rules from removed templates and delete them.
|
||||
|
||||
## 7. Estimated effort
|
||||
|
||||
About 6–7 working days for one developer:
|
||||
|
||||
1. Mock parity & header — 1.5 days
|
||||
2. Control panel — 2 days
|
||||
3. Program panel — 1.5 days
|
||||
4. Console panel — 1 day
|
||||
5. Settings shell — 1 day
|
||||
6. Polish, feature flag, regression tests — 0.5–1 day
|
||||
|
||||
## 8. Open questions
|
||||
|
||||
- Do we ship the redesign behind `config.ui.layout` or a single hard cut? Recommendation: feature flag for one beta release, then default-on.
|
||||
- Macros above 8: drawer in Control or move overflow into Settings → Macros? Recommendation: Settings owns the master list; Control surfaces the first 8 (configurable).
|
||||
- Do we want a "Pin to Control" affordance (e.g. let the user pin a chosen indicator into the status strip)? Defer to a later iteration.
|
||||
- Spindle override / feed override sliders are not in the V09 mock. Decide whether they live in the status strip or as a quick-action drawer pulled from the bottom edge. Recommendation: drawer triggered by the spindle KPI tile.
|
||||
Reference in New Issue
Block a user