feat(ui): adopt Seven design system across the frontend#65
Merged
Conversation
chore: promote develop to master (gateway account roles + routing fixes)
Foundation: reconcile index.css so @etus/tokens wins (drop colliding radius/shadow/breakpoint/text tokens, the 88 color palettes, and the decorative utilities banned by DESIGN.md); load Inter + JetBrains Mono. Shell: sidebar.tsx becomes AppSidebar built on Seven's Sidebar system (single mode, collapsible icon, SidebarAvatar); _authenticated.tsx mounts SidebarProvider + SidebarInset. Screens: settings/account/team/integrations move to TextInput, Divider, Switch and Checkbox; main.tsx uses Seven's Toaster; error-boundary uses Button; loading-skeleton uses SkeletonLoader. The local input, separator, skeleton and sonner components now have zero consumers. Validated in the browser. Plan: docs/plans/2026-06-16-001-migrate-frontend-seven-ds-plan.md
Delete the now-orphaned local UI primitives (input, separator, skeleton, sonner) - all consumers moved to @etus/seven-react. Add an ESLint guard-rail: raw button/input/select/textarea are banned in src/client/routes and the sidebar, pointing to the Seven equivalents (proven to trigger on a probe file). Document the "UI = Seven" rule in CLAUDE.md (components, tokens, brand, guard-rail, validate against seven.etus.io).
The user menu in the sidebar footer never opened: SidebarAvatar does not forward props, so it could not act as a DropdownMenuTrigger. Use a SidebarMenuButton (the canonical pattern) instead. Restore the client test suite after the Seven migration: make the jsdom ResizeObserver a real constructor and add Radix pointer-capture shims (the suite errored without them), drop tests for the deleted local primitives, and update the shell tests (sidebar, authenticated-layout, error-components, dashboard, integrations) to the new structure. 230 tests pass, coverage 89%.
… components These screens were already Seven-only but hand-rolled their layouts from Card. Swap them for the design system's purpose-built components so derived products compose from Seven rather than rebuilding it: - dashboard: stat Cards -> DashboardCard (title/value/valueDescription/icon). KPICard was rejected: it hides all sub-text when no delta is given, and the template's placeholder metrics have no trend data to invent. - login: centered Card -> split-screen matching Seven's curated /login (form in <main>, brand panel in <aside>, mint primary OAuth button). The landmarks also restore the <main> that root-layout asserts. - workspaces: super-admin Card -> Callout variant="success"; empty-state Card -> Empty/EmptyMedia/EmptyTitle/EmptyDescription. Validated each in the browser against the published showcase. 230 client tests pass unchanged; coverage 89.7%/84.5%/94.3%.
…undle) Production build measurement: route-splitting already works (/login chunk is 4.6 kB), but every route loads a shared 2.2 MB index chunk because @etus/ui ships a monolithic 1.7 MB index.js that inlines all components + recharts. sideEffects:false on the packages + a cleared vite cache produced a byte-identical build, so consumer-side tree-shaking cannot help. The real fix is upstream (Seven shipping per-component ESM). Experiments reverted.
The sidebar and login render the logo as a mint rounded-square plate with the icon; the 404, invite, and landing pages used a bare icon, so the brand mark looked different depending on the entry point. Use the same plate everywhere. Includes the bhono-app template mirror.
Audit vs the published showcase: all 11 screens are faithful Seven. One cosmetic drift was fixed (brand mark on 404/invite/landing). One upstream finding: the sidebar active item renders mint-strong (the real SidebarMenuButton behavior) instead of the Figma subtle gray, because Seven only exposes data-mode (which gates the Figma styling) in dual mode. A data-mode fix was applied to the Seven working tree; the active-bg cascade residual was handed to the Seven team. Full writeup: seven/docs/audits/sidebar-single-mode-styling-bug.md.
Seven's app shells separate the header from the content via the content tuck (rounded-tl border on the inset), not a header border-b. Drop the border-b so the topbar floats like the Seven reference. Includes the bhono-app template mirror.
From the multi-reviewer pass on the Seven migration: - test(sidebar): the theme-toggle test now asserts the persisted theme change instead of just rendering (was vacuous — Rule 6). - chore(lint): widen the raw-control guard-rail from routes/** + sidebar.tsx to all of src/client/components/** (except icons.tsx) — closes the gap where a raw <button> in error-boundary.tsx would pass unguarded. - refactor: drop the unused SidebarSkeleton (+ its tests) and the dead ?? 'dashboard' breadcrumb fallback (this layout never renders at /). - test(toaster): extract AppToaster to its own module and cover that it forwards the resolved theme to Seven's Toaster. - nits: the user-menu dropdown header shows the name (not a second copy of the email); narrow the error/pending layout assertions to the intent class. typecheck + lint + 226 client tests green; coverage 89.7%/84.6%/94.3%.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Migrates the entire frontend to the Seven design system (
@etus/seven-react) so the boilerplate is a clean DS base for derived products. Every UI element now comes from Seven — no raw HTML controls or local UI primitives remain.Changes
Foundation
index.css: drop tokens/palettes/utilities that collided with Seven; JetBrains Mono perDESIGN.md; Seven owns color/radius/spacing/typography.index.html: load Inter + JetBrains Mono.Shell
AppSidebarrewritten on Seven's Sidebar system (collapsible icon rail, ⌘B, mobile sheet);_authenticatedshell =SidebarProvider+SidebarInset.Toasterinmain.tsx.Screens (logic preserved, presentation = Seven)
TextInput,Divider,Switch,Checkbox,Table,Dialog.DashboardCard./login(<main>+<aside>landmarks, mint OAuth button, brand panel).Callout; empty-state →Empty.Guard-rails & docs
<button>/<input>/<select>/<textarea>in routes (proven to fire).CLAUDE.mddocuments the "UI = Seven" rule.Notable fix
The rewrite surfaced a real bug: the sidebar user menu never opened because
SidebarAvatardoesn't forward props (so it couldn't be aDropdownMenuTrigger). Switched to the canonicalSidebarMenuButton.Testing
typecheck+lint+buildgreen.Known limitation (not addressed here)
Public-route bundle:
/login's own chunk is 4.6 kB, but every route loads a shared 2.2 MB chunk because@etus/uiships a monolithic, non-tree-shakeableindex.js.sideEffects:false+ cleared cache produced a byte-identical build, so the fix is upstream in Seven (per-component ESM +sideEffects). Documented in the migration plan (U4.2).Out of scope
E2E (Playwright) selectors not yet updated for the new UI.
🤖 Generated with Claude Code