Skip to content

tests: add UI primitive stories and fix design-sync previews#3626

Merged
ThomasK33 merged 2 commits into
mainfrom
design-sync-ui-primitives
Jun 24, 2026
Merged

tests: add UI primitive stories and fix design-sync previews#3626
ThomasK33 merged 2 commits into
mainfrom
design-sync-ui-primitives

Conversation

@ThomasK33

Copy link
Copy Markdown
Member

Summary

Adds Storybook stories for 8 core Mux UI primitives and syncs them into the Claude Design design system, and fixes the design-sync preview rendering so component cards show their content on the gallery's main page.

Background

The design-system sync previously shipped only app-level feature components (tool-call cards, settings sections, banners) — none of Mux's foundational primitives (Button, Input, Select, …) were storied, so the sync (which only covers storied components) had no building blocks for the design agent to compose with. Separately, design-sync preview cards rendered as empty dark boxes on the gallery main page; the component was only visible after clicking "Edit".

Implementation

  • Preview clipping fix: globals.css pins html,body,#root,#storybook-root to 100vh, which clamps documentElement.scrollHeight inside the gallery's auto-sizing iframe so cards never grow to fit content. MuxPreviewShell now injects a height:auto reset so the gallery measures the true content height. No-op for fixed-overlay previews (their scrollHeight already floors at the viewport).
  • Primitive stories: 8 new Components/<Name> stories (Button, Input, Checkbox, Switch, Select, Dialog, Tooltip, Popover) using the lightweight isolated meta.
  • Design-sync coverage: gen-barrel.mjs now exports the compound subcomponents (Dialog/Tooltip/Popover parts) onto window.Mux, and excludes the chat composer by path so the Input primitive keeps the canonical name without a title-segment collision. Adds owned previews and config overrides (cardMode: single for overlays; skip Select's play-driven Open). Bundle stays at 4.48 MB (under the 5 MB cap); render-check is 33/33 clean.

Validation

  • make typecheck, make lint, prettier: clean.
  • Storybook builds; all new stories render correctly (verified via screenshots of the built Storybook).
  • design-sync: all 33 components render cleanly; the 8 new primitives grade match against their storybook reference; uploaded and verified on the design-system project.

Risks

Low — no app/product behavior changes. The only src/ additions are new Storybook story files; everything else is .design-sync/ tooling. Chromatic will show 8 new stories (new baselines to accept).

- Fix design-sync preview clipping: MuxPreviewShell resets the html/body
  100vh lock from globals.css so the Claude Design gallery sizes cards to
  content instead of clamping documentElement.scrollHeight.
- Add Storybook stories for 8 core UI primitives (Button, Input, Checkbox,
  Switch, Select, Dialog, Tooltip, Popover) under Components/.
- Extend design-sync to bundle, grade, and upload the primitives: export
  compound subcomponents from gen-barrel, exclude the chat composer by path
  so the Input primitive keeps its name, add owned previews and overrides
  (cardMode single for overlays, skip Select's play-driven Open).
- Refresh conventions header (agent-mode token accuracy) and NOTES.

Change-Id: Icc840f38d910a641f77fa76468786f314045449f
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 71328d15f6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .design-sync/gen-barrel.mjs Outdated
Address Codex review: the synced Dialog primitive exposed content/header/
footer parts but omitted DialogTrigger and DialogClose, so a design agent
could only use it defaultOpen or fully controlled. Export both so consumers
can declaratively open the dialog and make footer buttons close it.

Change-Id: I9728a80625405c4698c609fc77f6a0d2443e51b5
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Addressed the Dialog parts finding: gen-barrel.mjs now also exports DialogTrigger and DialogClose (alongside the content/header/footer parts), so the synced Dialog primitive can be opened declaratively via a trigger and closed by footer buttons — not just defaultOpen/controlled. The barrel was regenerated and the design-system bundle re-synced.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

Reviewed commit: e9b95ce566

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ThomasK33
ThomasK33 added this pull request to the merge queue Jun 24, 2026
Merged via the queue into main with commit b1a2d14 Jun 24, 2026
24 checks passed
@ThomasK33
ThomasK33 deleted the design-sync-ui-primitives branch June 24, 2026 15:33
@mux-bot mux-bot Bot mentioned this pull request Jun 24, 2026
LeonidasZhak pushed a commit to LeonidasZhak/mux that referenced this pull request Jun 30, 2026
## Summary

Long-lived auto-cleanup PR maintained by the **Auto-Cleanup Agent**.
Each pass lands at most one extremely low-risk, behavior-preserving
cleanup drawn from recently merged `main` activity, then advances the
checkpoint below.

Auto-cleanup checkpoint: 620c2a6

This PR currently contains six accumulated cleanups against `main`:

1. `src/node/services/taskService.ts` — dedupe queued-message foreground
backgrounding into a private helper.
2. `src/node/services/workflows/workflowScriptResolver.ts` — reuse the
`SKILL_SCRIPT_PATH_PREFIX` constant for canonical-path construction.
3. `src/node/services/workflows/WorkflowTaskServiceAdapter.ts` — extract
the duplicated agent-task creation arg shape into a shared
`WorkflowTaskCreateArgs` type.
4. `src/constants/workspaceTags.ts` (new) — centralize the
workspace-turn task tag keys, removing the cross-layer
`"mux.taskHandleId"` string duplication.
5. `src/node/services/tools/workflowProgress.ts` — extract the
duplicated "latest phase" lookup into a shared `getLatestPhaseEvent`
helper.
6. `src/browser/features/RightSidebar/Workflows/WorkflowBadges.tsx` —
map workflow run-status glyphs through an exhaustive
`Record<WorkflowRunStatus, LucideIcon>` instead of a repeated
`if`-chain.

## This pass

Rebased the branch onto the latest `origin/main` (clean) and considered
the three new commits since the prior checkpoint:

- coder#3624 (`feat: add Workflows right-sidebar tab with live run
streaming`)
- coder#3626 (`tests: add UI primitive stories and fix design-sync previews`)
- coder#3627 (`feat: return workflow plan agent results`)

coder#3624 added `WorkflowBadges.tsx`, whose `WorkflowStatusIcon` selected a
glyph through a four-branch `if`-chain that re-spelled the identical
`className="h-3 w-3 shrink-0"` + `style={{ color }}` props in every
branch and fell back to a default `<Circle>` for unmatched statuses.
Replaced that with a module-level `WORKFLOW_STATUS_ICON:
Record<WorkflowRunStatus, LucideIcon>` map (mirroring the existing
`WORKFLOW_STATUS_META` / `WORKFLOW_TONE_VAR` records in the same
feature) and render the looked-up icon once. Behavior-preserving: the
map reproduces the prior mapping exactly (`pending`/`running` →
`Circle`, `backgrounded`/`interrupted` → `Pause`, `completed` → `Check`,
`failed` → `X`), and using a `Record` makes the mapping exhaustive so a
newly added run status is a compile error here rather than a silent
fall-through. coder#3626 (Storybook/design-sync, test-only) and coder#3627
(already extracts its own `__muxAgentReturnValue` runtime helper)
offered no additional low-risk dedup.

<details>
<summary>Prior pass — workflowProgress getLatestPhaseEvent
helper</summary>

coder#3623 added `src/node/services/tools/workflowProgress.ts`, in which both
`buildWorkflowProgressSummary` and `formatWorkflowProgressNote`
independently re-spelled the same `run.events.findLast((event) =>
event.type === "phase")` expression to find the latest phase event.
Extracted that into a single private `getLatestPhaseEvent(run)` helper
and referenced it from both functions, giving the "latest phase"
definition one source of truth so the summary builder and the note
formatter can't drift. Behavior-preserving: the helper's body and
inferred return type are identical to the inline expression, so both
call sites compute exactly the same value.

</details>

<details>
<summary>Prior pass — checkpoint-only advance for coder#3621 (Claude Design
integration)</summary>

coder#3621 is purely additive and lives entirely under `.design-sync/` (plus
one `.gitignore` entry); it contains zero production (`src/`) code.
`.design-sync/**` is outside both the ESLint scope (`src/**`) and the
TypeScript `include`, so `make static-check` cannot validate the
behavior-preservation of any refactor there. That pass advanced the
checkpoint without a code change.

</details>

<details>
<summary>Prior pass — workspace-turn task tag keys
centralization</summary>

The workspace-turn task tag key `"mux.taskHandleId"` is **written** by
`TaskService.createWorkspaceTurn` (node, coder#3617/coder#3619) and **read** by
`findWorkspaceForTaskTarget` in `TaskToolCall.tsx` (browser, coder#3613) —
the same magic string duplicated across the node/browser boundary.
Extracted the three workspace-turn task tag keys (`handle`,
`ownerWorkspaceId`, `turn`) into a new `@/constants/workspaceTags`
module and referenced `WORKSPACE_TURN_TASK_TAGS` from both the node
write site and the browser read site. Behavior-preserving: the extracted
values are byte-identical to the previous literals, so the persisted tag
keys and all lookups are unchanged.

</details>

<details>
<summary>Prior pass — WorkflowTaskServiceAdapter WorkflowTaskCreateArgs
type</summary>

`WorkflowTaskServiceLike` (in `WorkflowTaskServiceAdapter.ts`) declared
the agent-task creation argument object **twice** — once inline in
`create(args: { ... })` and again inside `createMany?(args: Array<{ ...
}>)` — as byte-identical 10-field shapes. Extracted a named
`WorkflowTaskCreateArgs` interface and referenced it from both `create`
and `createMany`. Behavior-preserving: structurally identical interface,
signatures unchanged.

</details>

<details>
<summary>Prior pass — workflowScriptResolver SKILL_SCRIPT_PATH_PREFIX
reuse</summary>

In `workflowScriptResolver.ts`, the `skill://` prefix is named by the
module-level constant `SKILL_SCRIPT_PATH_PREFIX`, but the two
canonical-path builders re-spelled the literal `` `skill://${...}` ``
instead of reusing the constant. Both builders now interpolate
`${SKILL_SCRIPT_PATH_PREFIX}`. Behavior-preserving:
`SKILL_SCRIPT_PATH_PREFIX` is exactly `"skill://"`, so the interpolation
is byte-identical.

</details>

<details>
<summary>Prior pass — taskService queued-message dedup</summary>

Considered coder#3605 (`fix: background foreground waits for prequeued
messages`), which open-coded the same queued-message guard at two
`TaskService` wait-registration sites. Both sites now delegate to a
single private helper
`backgroundForegroundWaitIfQueued(shouldBackgroundOnQueuedMessage,
requestingWorkspaceId)`. Behavior-preserving: the helper folds in the
`requestingWorkspaceId` truthiness guard and the pushed call is
unchanged.

</details>

## Validation

- `make static-check` is green for the touched code (ESLint, `tsconfig`
+ `tsconfig.main.json`, Prettier). (`fmt-shell-check` is the only
non-passing step, solely because the `shfmt` binary is absent in this
environment; no shell files are touched.)
- Targeted tests pass: `bun test
src/browser/features/RightSidebar/Workflows/workflowDisplay.test.ts
src/browser/features/RightSidebar/Workflows/projectWorkflowRun.test.ts`
(32 tests) cover the same Workflows feature module the change lives in.

## Risks

Minimal. All accumulated changes are pure local extractions / constant
reuse; no logic, types, or call semantics change.

---

_Generated with `mux` • Model: `anthropic:claude-opus-4-8` • Thinking:
`xhigh`_

<!-- mux-attribution: model=anthropic:claude-opus-4-8 thinking=xhigh -->

---------

Co-authored-by: mux-bot[bot] <264182336+mux-bot[bot]@users.noreply.github.com>
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.

1 participant