You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit c9e500e
Browse filesBrowse the repository at this point in the historyBrowse files
refactor(coder-web): the Coder UI takes the console's button vocabulary, vendored, and a measurement decides which sites cannot (#366)
47 → 23. The Coder UI renders INSIDE the console — `index.css` `@source`s its directory so its
classes compile against the console's tokens — so until now one screen carried two button
systems: four steps in the shell, 47 hand-authored shapes in the body.
## The vocabulary transfers; the module cannot
Checked before applying it, because "a different app with its own conventions" was the open
question:
- **Not by importing the console's.** `store/console` depends on `@proagentstore/coder-web`
(`package.json`, `workspace:*`). The arrow already points that way; reversing it is a cycle.
- **Not by moving it into `@proagentstore/sdk`,** which both do depend on. Tailwind v4 finds
classes by scanning source text and skips `node_modules` — which is precisely why
`store/console/src/index.css` carries an explicit `@source` for this directory, after classes
used only here were silently never generated and its desktop controls vanished. Strings in a
built `dist/` would walk straight back into that. The SDK is also published to npm for agent
authors, and the console's private design decisions are not their API.
So it is **vendored** — the same bargain this repo already strikes for the design tokens, which
`store/admin` carries as a byte-identical `@theme` block held equal by `designTokens.test.ts`
(DESIGN-SYSTEM.md §4, "three copies"). Duplication a machine can police, rather than an
abstraction that cannot be built. The table now sits between `vendored:button-vocabulary` markers
in both files and `control-classes.test.ts` requires the region byte-identical, plus a third
assertion tying the text back to the exported records so a stale paste cannot pass while the
runtime table has changed underneath it.
## Eight sites were disqualified by a measurement, not a judgement, and that is the finding
`.hidden{display:none}` is emitted **before** `.inline-flex` in the built stylesheet. So
`className="hidden sm:flex"` on a `<Button>` does not hide it: `BUTTON_BASE` wins. Silently, with
no error, on mobile only — and it looks correct on the desktop the author is testing on. The whole
coding-session header is responsive that way (`hidden sm:flex`, `sm:hidden`).
Those eight are not unmigrated work; they are a gap in the table. `Button.tsx`'s docstring said
"colour handed in there does not reliably win" without saying how to tell, and now carries the
test: safe when the vocabulary sets no rule for that CSS property (`border-dashed`,
`active:scale-95`, position); otherwise only when the incoming utility sorts later — measured, with
`transition-transform` as the counter-example that DOES win, while replacing `transition-property`
and taking the hover colour transition with it.
## What moved, and one accessibility side effect worth naming
`CodingTab` 7, `CopilotView` 6, `ReposList` 4, `RepoSettingsModal` 3, `EnginesModal` 3,
`AddRepoForm` 1. Same rule as every previous pass: `text-sm` → `lg`, `text-xs` → `md` or `sm` by
padding; icon-only controls → `size="icon"`. Repo delete and End session became
`variant="danger"` rather than a red hover.
The five-icon solo header was `px-1.5 py-1` around a 13px glyph — about 21px tall, under the 24px
WCAG floor #389 put into `BUTTON_SIZE`. This package never had that floor because it never had the
table; `size="icon"`'s `min-h-6 min-w-6` gives it to them. `ReposList`'s Play/Stop stays
hand-written (an accent active arm no variant has) and so stays under the floor — recorded rather
than left to be discovered.
The 23 that remain: 8 responsive-display, 4 active-arm toggles, 2 pills, 2 press-affordance
composer controls (`active:scale-95`, a #163 requirement), 1 overlay, 1 card-shaped, 1
responsive-padding, 1 composer send, 1 jump-to-bottom pill, 2 modal buttons with the same press
affordance. Pin lowered 47 → 23 in this commit.
Verified in a throwaway worktree at `origin/main`: typecheck 11/11 · vitest **7816 passed / 449
files** · biome --error-on-warnings · all 8 check-* gates · docs:drift · **e2e 365 passed**
(chromium + webkit, including the #431 320/390px Coder tab-row specs that exercise exactly the
responsive header this commit left alone).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
{openSession&&<Buttonsize="icon"onClick={copySummaryJson}title="Copy conversation as JSON"aria-label="Copy conversation as JSON"><Copysize={13}/></Button>}
1030
+
{openSession&&<Buttonsize="icon"onClick={restartSession}title="Restart the CLI"aria-label="Restart the CLI"><RotateCwsize={13}/></Button>}
<buttontype="button"onClick={loop.approveProposedIssue}className="text-xs px-3 py-1.5 rounded-lg bg-accent text-white font-bold">Approve & run #{loop.proposedIssue.number}</button>
0 commit comments