Skip to content

UI alignment: brand mark, beacon loader, ds top bar everywhere — GlobalNav removed - #117

Merged
ib823 merged 4 commits into
mainfrom
claude/codebase-audit-optimization-p6i6co
Aug 8, 2026
Merged

UI alignment: brand mark, beacon loader, ds top bar everywhere — GlobalNav removed#117
ib823 merged 4 commits into
mainfrom
claude/codebase-audit-optimization-p6i6co

Conversation

@ib823

@ib823 ib823 commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Four slices of the UI-alignment programme, in commit order:

1. Port findings: the WBS third level is the fourth phantom — parity checklist complete.
No UI can create a subtask (makeTaskChild/promoteTask/toggleTaskCollapse have zero callers), the legacy canvas renders flat, and the API never persists parentTaskId. Both canvases render the identical flat list, so parity already holds. With this, everything the legacy canvas observably does is either ported behind ?canvas=next or established never to have existed; the gate before flipping the default is visual comparison on real plans.

2. Brand alignment. The mark rebuilt on the Brand spec's stated 48-unit grid (ring 16/inner arc 9/dot 4, 44° gap, stem to y=41) instead of vectorised artwork; the favicon route implements the size ramp (≥40 full → ring+dot → dot alone) with the gold dot never recoloured for status.

3. The beacon loader (ds/BeaconLoader): the Brand loading identity — 1800ms wave cycle from the dot, 28% track, determinate ring on a pathLength-normalised dash, 400ms CSS appear gate, reduced-motion via media query. Placed on /gantt-tool restore and /architecture/v3; HexLoader deleted.

4. The ds AppShell top bar replaces GlobalNav on /dashboard, /gantt-tool and /architecture/v3; GlobalNav is deleted. Each screen gains the composites-spec top bar: destination nav with aria-current, the sync chip (gantt store's six sync states collapsed onto the chip's four), and a ds-native account cluster (admin pill, email-as-account-link, logout confirmed in a ds Modal — deliberately not the antd LogoutButton, which would ship antd to every tool route's first load). AppShell itself gains a fullBleed mode for tool surfaces and a default brand of the 26px mark beside the live-text wordmark — inlined SVG at the ramp's 24–39px stroke (2.8), which also avoids the next/image runtime that regressed two route budgets. Tier2Header survives as tool chrome until the sub-nav slice.

Honest note on process: the first attempt at slice 4 overwrote the existing, already-spec-compliant ds/AppShell before tsc exposed that ten migrated routes depend on it; it was restored from HEAD and the slice builds on it instead.

Verified: tsc, lint, 2157 unit tests, fresh production build with all 23 bundle budgets green (the pre-push hook reruns the full gate).

…cklist is complete

Investigated to the end rather than to the first plausible answer, like the
three before it:

  - No UI can create a subtask. makeTaskChild, promoteTask,
    toggleTaskCollapse and getTaskWithChildren in the store have zero
    callers anywhere; AddTaskModal and EditTaskModal never pass
    parentTaskId.

  - No UI renders subtask structure. The legacy canvas contains no
    reference to parentTaskId, childTasks, or task.level — tasks draw flat,
    with no indent, no twisty, no collapse.

  - The API never persists parentTaskId: zero references under src/app/api,
    so even a subtask smuggled in through JSON import flattens on the next
    save and reload.

The parity twist that makes this a finding rather than a slice: both
canvases render the identical thing — a flat task list — so parity already
holds. Building the tree UI would be a new feature wearing a port's
clothes, and it would have to START with making the API persist the field,
or the tree would evaporate on every reload.

With this, the port's parity checklist is complete. Everything the legacy
canvas observably does is either ported behind ?canvas=next or established
never to have existed: bar drag/resize, dependency editing, resource
drag-assignment, WBS nesting. Deliberately not ported and stated: column
resizing, manual capacity overrides. The remaining gate before flipping the
default is human visual comparison on real plans — not another slice.

docs/REMEDIATION.md 3.1 records the finding; the stale "what it does not
cover yet" header in GanttCanvasNext is replaced with the true parity
status. 175 ds/seam tests pass unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TArsz4CrMDAKmeALMozkR5
@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cockpit Ready Ready Preview Aug 8, 2026 6:38am

…was the wrong master

The uploaded UI reference turned out to be the committed docs/design set in a
newer iteration, and its one genuinely new document, brand.html, is the
authority on the mark. It explicitly rebuilds the supplied artwork on a
stated grid: "the original's radii and gap were close to these but not on
any system, which is why it resisted clean scaling." Yesterday's rebrand
vectorised the artwork faithfully — which made it faithfully wrong against
the system. Corrected:

  - public/logo-cockpit.svg is redrawn to the construction: 48-unit grid,
    ring centre (24,21), radii 16/9/4, 44-degree gap centred on vertical
    (endpoints at y 35.84), an exactly-180-degree inner arc, stem 28→41,
    one 2.5-unit stroke. Colours are the spec's two flat tokens —
    brand/slate #3A5060 and brand/gold #E5C264. The gradient dot is gone:
    "no gradient in the strokes or the dot" is on the misuse list, and the
    gradient body is the spec's named "one thing to drop".

  - /api/favicon now implements the SIZE RAMP instead of scaling: full mark
    at 24px+, the inner arc drops at 20-23 (stroke 3.2, dot 4.6), the stem
    drops at 16-19 (stroke 3.6, dot 5.4), and under 16px the mark is the
    dot alone in the structure colour — "a beacon at 12px is a dot;
    pretending otherwise is noise." All five forms and all three plates
    were rendered and inspected, not assumed.

  - The disconnected-state dot recolour is reverted: "Never recolour the
    dot. Not to signal status." Status is now expressed by the plate colour
    only, with strokes following the surface rule (light #E9EEF6 on dark
    plates, slate on the amber one). The default plate becomes the app-icon
    rule: slate field, light strokes, gold dot.

  - GlobalNav: mark at 26px per the placement table, and the image is now
    decorative (alt="") because the wordmark beside it is live text — a
    labelled image there announced "Cockpit" twice.

docs/design gains brand.html and the newer screens-auth, screens-core and
sync iterations from the upload; the other eight uploaded documents were
byte-identical to what was already committed. The README's status table is
brought up to date (it still said layers 2-5 "not started"). An earlier step
of this work briefly overwrote that README with a new one and copied all
twelve documents in under duplicate names; both mistakes were caught against
git history and reverted before commit.

Not yet done from the Brand spec, recorded in the README: the loading
identity (the beacon-emits loader, indeterminate/determinate/reduced-motion)
which should replace HexLoader on full-surface loads.

Full suite under coverage: 2151 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TArsz4CrMDAKmeALMozkR5
The beacon emits: a wave leaves the dot and travels out past the inner arc
to the ring, the same gesture the mark already draws, now in time. Every
number is the Brand spec's motion table, none tuned by eye: 1800ms cycle,
wave scaled 0.42 → 1.92 from the dot centre at cubic-bezier(.25,.6,.35,1),
two instances half a cycle apart, dot pulsing 1 → 1.16 in phase and never
changing colour, ring and stem holding at 28% as the unfilled track so the
mark is never mid-disassembly.

Determinate mode fills the outer ring clockwise from the bottom gap. The
ring path is pathLength-normalised to 100 so the dash IS the percentage —
the spec's 88.3 real units never need converting, which is one unit
conversion that can never be wrong. 0% shows the track only; out-of-range
values clamp.

Three of the spec's rules are structural here rather than stylistic:

  - "Under 400ms of expected wait, show nothing at all" — the panel is
    invisible for its first 400ms via CSS animation-delay, so the rule
    holds even while JavaScript is busy, which is exactly when a loader is
    on screen.
  - Reduced motion is enforced by media query, not a JS branch: waves rest
    as a static mark, and the status line carries the change.
  - The SVG never announces. The visible status line is the live region and
    carries the STATE ("Loading your project…", "…, 64%"), never the brand.

Placed on the two full-surface loads — /gantt-tool's project restore and
/architecture/v3 — which are the beacon's only sanctioned surfaces; the
misuse list is explicit that it is never an inline or button spinner.

HexLoader is deleted. Its one live use was architecture/v3; the gantt-tool
import had been dead since that page moved to the AuthShell wait. First
piece of "old UI to be removed" actually removed.

Verified by rendering both modes mid-animation and inspecting the frames,
plus 6 component tests. Full suite under coverage: 2157 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TArsz4CrMDAKmeALMozkR5
The tier-1 GlobalNav (Dashboard / Timeline / Architecture tabs, user
dropdown) is deleted; /dashboard, /gantt-tool and /architecture/v3 now
mount the design-system AppShell, which the earlier route migrations
already proved out. What each screen gains from the composites spec: the
sync chip in the top bar (live region, never collapses — the gantt
store's six sync states collapse onto the chip's four in
navigation/global-nav.ts), destination nav with aria-current, and the
skip-link target on the shell's own <main>.

AppShell changes, kept minimal:
- The default brand is now the beacon mark at 26px beside the live-text
  wordmark. The mark is inlined SVG rather than an <img> of the logo
  file, for two reasons: next/image's client runtime regressed the
  /account and /settings/security route budgets (89.5/49.9kB over
  87/42kB), and 26px sits in the Brand ramp's 24–39px band whose full
  form is drawn at stroke 2.8 — the ≥40px file's 2.5 was the wrong form.
- `fullBleed` lets a tool surface own its scroll and width; centring the
  Gantt canvas in a padded 1280px column would clip the very thing the
  screen exists to show.

The top bar's account cluster (navigation/UserMenu.tsx) is ds-native:
admin pill, email-as-account-link, and a logout confirmed in a ds Modal
that repeats LogoutButton's hardened sequence (server logout, storage
cleared, replace + hard reload). Deliberately not the antd LogoutButton:
antd in the top bar would have shipped to every tool route's first load.

Honest note: the first attempt at this slice overwrote the existing,
already-spec-compliant ds AppShell with a fresh implementation before
tsc exposed that ten migrated routes depend on it; it was restored from
HEAD and this slice builds on it instead. Tier2Header (project selector,
save text, toolbar) survives this slice as tool chrome — replacing it is
the sub-nav slice, and its save-status text now duplicates the top-bar
chip until then.

Verified: tsc, lint, 2157 unit tests, fresh production build with all
23 bundle budgets green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TArsz4CrMDAKmeALMozkR5
@ib823 ib823 changed the title Port findings: the WBS third level is the fourth phantom — parity checklist complete UI alignment: brand mark, beacon loader, ds top bar everywhere — GlobalNav removed Aug 8, 2026
@ib823
ib823 marked this pull request as ready for review August 8, 2026 07:21
@ib823
ib823 merged commit d2d7422 into main Aug 8, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants