Skip to content

mac UI/UX pass 1: design system, render loop, tool-window shell, tree/tabs, preview - #471

Merged
GoKubar merged 10 commits into
mainfrom
agent/kabir-claude/ui-design-tokens
Sep 14, 2026
Merged

GoKubar merged 10 commits into
mainfrom
agent/kabir-claude/ui-design-tokens

Conversation

@GoKubar

@GoKubar GoKubar commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

First half of the design pass from the installed design kit (context/design-principles.md, context/style-guide.md, references/), steps 1–4 of the order of work in .claude/agents/ui-ux-implementer.md.

What's here

  • Render loop (Tests/DesignSnapshots): surfaces render in real off-screen HostedWindows windows and are captured through the window server (CGWindowListCreateImage of our own window — cacheDisplay/CALayer.render paint macOS 26 glass subtrees blank). Deterministic (record-then-assert green, 3× stability run); reference PNGs committed for nine surfaces × both appearances.
  • DesignSystem.swift (step 1): spacing/radii/row-height/type tokens, semantic colours on AppKit semantic colours, state opacities, layout minimums, preview page constants, Reduce-Motion-gated durations, and FileTypeStyle (colour-coded file identity). Main-window chrome carries no raw numeric/colour literals; secondary windows (Nearby, CaptureInbox, scaffolds, history) migrate when touched.
  • Window shell (step 2): flat tool-window layout — icon rail, stacked Project/Outline column (Outline ships collapsed), Problems out of the sidebar (bottom panel + status-bar badge are its homes), three-chip toolbar (Compile+producer menu, Export, Commands) plus Captures toggle, full-width status bar, hairline-and-tonal-shift framing, 900pt window minimum with preview collapsing to a toggle when narrow. FocusOrder/help text/CommandTableTests updated together.
  • Status bar breadcrumb (step 2): main.tex › Chapter › Section at the caret, clickable, edit-debounced scan (unit-tested chain logic).
  • File tree + tabs (step 3): 24pt rows, full-row hover/selection, colour-as-identity icons shared between tree and tabs; Islands active tab (raised card on recessed strip), close control on hover/active only, dot for modified; byte counters and edited/saved captions left the strip.
  • Preview (step 4): two-tier header — page N / M + zoom % at rest, dimmed; controls (−/+, Fit Width, new Fit Page ⌘⇧9, v2/dark) fade in on pointer-over without reflow; FIXTURE/HISTORICAL badges only as state; producer/capability detail in tooltips. Page indicator rides the existing anchor probe.

Gates

  • swift build clean; CommandTableTests (README/command-table/menu parity), OutlineStructureTests, PreviewAnchoringTests, PreviewZoomTests green; full suite 1223 tests / 137 skipped / effectively 0 failures (two were stale snapshot references from a concurrent re-record mid-run; the dedicated re-run is green 3×).
  • Snapshots recorded and asserted green both appearances.

Steps 5–8 (problems panel + gutter fix-it, outline/palette/completion, find/settings, states + full light-dark pass) follow on a stacked branch.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Xd5Hmwh5GHNTiAmHUJ1MZu

GoKubar and others added 10 commits September 14, 2026 17:12
…el, shell surface snapshots

Surfaces render inside real off-screen HostedWindows windows now: List rows
only populate in a window, NavigationSplitView and .toolbar need one, and
vibrancy materials draw black off-screen (neutralized to their plain colour,
the Reduce-Transparency ground). DesignFixtures builds a deterministic demo
project (3 pages, extra tabs, synthetic TeX diagnostics) with machine
preferences pinned. StatusBar/EditorPane/PreviewPane/PreviewHeader lose
'private' so the loop can render them alone.

Implementation-Agent: Claude Fable (lane mac-ui-design, linux-primary)
Commit-Executor: Claude Fable (direct git, observed Cursor usage limit)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xd5Hmwh5GHNTiAmHUJ1MZu
…splay

macOS 26 glass materials (NSContainerConcentricGlassEffectView and friends,
wrapping every NavigationSplitView sidebar) never reach cacheDisplay or
CALayer.render — the sidebar snapshotted blank white. CGWindowListCreateImage
of our own off-screen window composites what the user actually sees, needs no
Screen Recording permission for the calling process's windows, and turned out
deterministic across runs (asserted green immediately after recording). The
symbol is bound with dlsym because it is deprecated and Swift cannot silence
a deprecation without deprecating every caller; ScreenCaptureKit is not a
substitute here because it does need the permission. Baseline PNGs of the
current design are recorded for all nine surfaces, both appearances.

Implementation-Agent: Claude Fable (lane mac-ui-design, linux-primary)
Commit-Executor: Claude Fable (direct git, observed Cursor usage limit)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xd5Hmwh5GHNTiAmHUJ1MZu
The token file from context/style-guide.md — spacing scale, radii, row
heights, type sizes, semantic colours (all defined on AppKit semantic
colours so light/dark/follow-system are structural), interaction-state
opacities, split minimums, preview page constants, motion durations gated
on ReduceMotion — plus FileTypeStyle, the IntelliJ-style colour-coded file
identity used from step 3 on.

Migrated in this pass: ContentView (status bar, preview header, capture and
bridge bars, sheets), DocumentTabBar, WorkspaceSidebar, ProblemsPanel,
DiagnosticsPanel, CommandPalette, PreviewView, PreviewV2View, PreviewZoom,
WordCountStatusView, EditorIntelligence (gutter paints + quick info),
EditorPreferences, ProjectSearchPanel, MathHoverPreview. Values were snapped
to the token scale where they were within a point or two (14→12, 10→8,
5→4/6, 3→2), which the re-recorded snapshots show as sub-pixel-to-2pt
shifts; captions standardise on the 11pt secondary token. Secondary windows
(Nearby, CaptureInbox, scaffolds, history, citation rename) migrate when
their surfaces are touched.

Implementation-Agent: Claude Fable (lane mac-ui-design, linux-primary)
Commit-Executor: Claude Fable (direct git, observed Cursor usage limit)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xd5Hmwh5GHNTiAmHUJ1MZu
…tool column, three-chip toolbar, 900pt minimum

IntelliJ's structure with Xcode's restraint (design-principles §1/§4):
a left icon rail toggles the tool windows; the tool column stacks the
Project tree above the Outline (which ships collapsed); Problems left the
column — its homes are the bottom panel and the status-bar badge; regions
separate by hairlines and one tonal shift, and the status bar spans the
window. NavigationSplitView is gone (its macOS 26 glass sidebar also never
reached the off-screen render loop).

The title bar now carries the chrome budget: Compile (producer menu behind
its chevron), Export, Commands, plus the Captures toggle. The v2-pane and
dark-preview switches moved into the preview header; Find in Project,
Rename Citation, Durable History and Nearby ride their menus, shortcuts
and the palette, which the toolbar tooltips still name.

Below the width where both columns fit, the preview collapses to a toggle
(tab bar to show, preview header to come back) instead of being crushed;
the window minimum drops from 1200 to 900pt. FocusOrder gains the rail as
pane 1 and the help text follows reality; CommandTableTests pin the new
structure.

Implementation-Agent: Claude Fable (lane mac-ui-design, linux-primary)
Commit-Executor: Claude Fable (direct git, observed Cursor usage limit)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xd5Hmwh5GHNTiAmHUJ1MZu
'main.tex › Résumé of a small journey › At the café' — the enclosing
sectioning chain at the caret (DocumentOutline.breadcrumb, unit-tested:
ancestors are the nearest preceding lower level, a following section closes
its siblings' subsections, the preamble shows none). Environments and
labels stay out: the lexical scan records no \end positions, and a segment
that may already be closed would lie. Segments click through to their
section; the outline rescan is edit-debounced and caret moves only re-pick
the chain from cached items. Indicators (word count, latency, route,
revisions, problem counts) move to the trailing side, IntelliJ-fashion.

Implementation-Agent: Claude Fable (lane mac-ui-design, linux-primary)
Commit-Executor: Claude Fable (direct git, observed Cursor usage limit)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xd5Hmwh5GHNTiAmHUJ1MZu
… 24pt tree rows

FileTypeStyle is now the one vocabulary for what a file is — .tex blue
(entry filled), .bib purple, .cls/.sty teal, .pdf red, images green,
generated grey — used identically by the project tree and the tab strip
(design-principles §6: colour is identity, never decoration). Tree and
outline rows drop to 24pt with full-row hover and selection highlights.

Tabs get the Islands treatment (§5): the active tab is a filled rounded
card raised out of the recessed strip (hairline + soft shadow), inactive
tabs are icon + name with no chrome, the close control appears only on
hover and on the active tab, and the modified state is the filled dot. The
per-tab durable-revision counter, the edited/saved caption and the
byte/UTF-16 readout leave the strip — the dot, tooltips and the status bar
already carry them (Xcode restraint: an arguable element loses).

Implementation-Agent: Claude Fable (lane mac-ui-design, linux-primary)
Commit-Executor: Claude Fable (direct git, observed Cursor usage limit)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xd5Hmwh5GHNTiAmHUJ1MZu
… pointer-over; Fit Page (⌘⇧9)

Design-principles §8: at rest the header shows only the page indicator and
zoom percentage, dimmed, plus quiet state — the fixed-slot compile spinner,
a FIXTURE/HISTORICAL badge only when the pages are not the worker's current
result, staleness text and capability warnings. On pointer-over the second
tier fades in place (150ms ease-out, gated on Reduce Motion, no reflow):
zoom −/+, Fit Width, the new Fit Page, and the preview-scoped v2/dark
switches. Producer name and layout-capability detail moved into the header
tooltip. No error cards in this column, before or after.

The page indicator rides the anchoring probe (the page under the viewport's
top edge, reported only on change); Fit Page is a real command — table
entry, View menu, ⌘⇧9, palette, README row — computed from the pane
geometry the preview already reports. Toolbar-location claims in the table
and README now match the three-chip toolbar.

Implementation-Agent: Claude Fable (lane mac-ui-design, linux-primary)
Commit-Executor: Claude Fable (direct git, observed Cursor usage limit)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xd5Hmwh5GHNTiAmHUJ1MZu
@d-q222

d-q222 commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

daniel-parent: overlap notes, nothing blocking. I test-merged this head against my open Mac PRs.

Merge in whatever order suits you. If #471 lands first I'll rebase all three onto it the same hour. If you'd rather land my smaller three first, their heads are dc248db6 (#426), 5d89665c (#429) and 5d178b9c (#411), and you'd absorb the list conflicts here.

I'm not starting any new Mac UI work while this design pass is in flight; my new lanes are compiler, math-layout, render-pipeline and CLI.

@GoKubar
GoKubar merged commit fed3388 into main Sep 14, 2026
21 checks passed
d-q222 added a commit that referenced this pull request Sep 14, 2026
…to Line / :N

Merged origin/main (includes #471/#476 design system and scoped command
palette). The only conflict was CommandPalette.swift.

Resolution: keep #476's PaletteScope / PaletteEntry structure and DS tokens.
Re-added this PR's Go to Line command in perform(), plus :N as a query
prefix that emits a lineJump palette entry. No clash — #476 uses ':' only
in internal ids (file:, cmd:), not as a typed prefix. GoToLineSheet
restyled onto DS tokens.

Tests (apps/mac):
  swift test --filter 'GoToLineTests|CommandTableTests|CommandPalette'
    Executed 18 tests, with 2 failures — both DesignSnapshots
    ShellSnapshotTests.testCommandPalette (known-failing class on this Mac).
  swift test --skip-build --filter 'GoToLineTests|CommandTableTests' --skip DesignSnapshots
    Executed 17 tests, with 0 failures (CommandTableTests 8, GoToLineTests 9).

Next: push this branch; then PR #411 problems-order in its own worktree.

Implementation-Agent: cursor-agent cursor-grok-4.6
Commit-Executor: cursor-agent
Lane-Owner: daniel-parent (mac-m5pro-dq222)
Co-authored-by: Cursor <cursoragent@cursor.com>
d-q222 added a commit that referenced this pull request Sep 14, 2026
…rseded UI

Merged origin/main (includes #471/#476 Problems panel). Conflicts were
ProblemsPanel.swift and DiagnosticsPanel.swift.

Kept only EditorDiagnostics.listBucket grouping: author errors (0), then
warnings (1), then FlashTeX gaps (2), stable within each bucket. groups()
feeds the panel, copy-text, and stepOccurrence, so next/previous occurrence
and ⌘⌥] land on the first error rather than an earlier gap. goToDiagnostic
still walks underlined marks in document order (it does not iterate groups).
Status-bar badges remain counts, not a list.

Dropped as superseded by #476: count chips (including zeros), the old
header/row chrome, the DiagnosticsListView chip caption, and the 180 pt
idealHeight (#476 already tokens this at DS.Layout.problemsIdealHeight).
Kept #476's "N not implemented" gap count rendering.

Adapted WorkspaceShellTests off the 180 pt assertion. Added
testThreeGapsThenWarningThenErrorListsTheErrorFirst.

Tests (apps/mac):
  swift test --filter 'EditorDiagnostics|ProblemsPanel|DiagnosticsPanel|CommandTable'
    Executed 60 tests, 7 skipped, 2 failures — both DesignSnapshots
    ShellSnapshotTests.testProblemsPanel (known-failing class on this Mac).
    Product suites all passed (DiagnosticsPanelTests 15, CommandTableTests 8,
    EditorDiagnostics* green).
  swift test --skip-build --skip NearbyInterfaceTests --skip NearbyLANInterfaceTests --skip DesignSnapshots
    Executed 1220 tests, with 135 tests skipped and 0 failures.
  RustPDFExportPipeTests: 4 passed including testTimeoutTerminatesAStuckWriter
    (1.002 s); no isolation re-run.

Next: push this branch.

Implementation-Agent: cursor-agent cursor-grok-4.6
Commit-Executor: cursor-agent
Lane-Owner: daniel-parent (mac-m5pro-dq222)
Co-authored-by: Cursor <cursoragent@cursor.com>
@GoKubar
GoKubar deleted the agent/kabir-claude/ui-design-tokens branch September 16, 2026 04:17
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