diff --git a/desktop-next/src/features/design-system/ui/ColorTablePage.tsx b/desktop-next/src/features/design-system/ui/ColorTablePage.tsx index 58c573c649..6e937ddeec 100644 --- a/desktop-next/src/features/design-system/ui/ColorTablePage.tsx +++ b/desktop-next/src/features/design-system/ui/ColorTablePage.tsx @@ -1,4 +1,3 @@ -import { Link } from "@tanstack/react-router"; import { Fragment } from "react"; import { @@ -9,7 +8,7 @@ import { } from "@/features/design-system/useResolvedToken"; import { RAMPS, ROLE_GROUPS } from "@/shared/tokens/registry"; -import { Note, PageHeader, Section } from "./primitives"; +import { PageHeader, Section } from "./primitives"; /** * Every token in one table: the name you type, the base token it resolves @@ -77,33 +76,13 @@ export function ColorTablePage() { return ( <> - + - - Roles are the only layer a screen may use. Ramp steps are listed - underneath so you can see what a role resolves through, but a component - referencing one directly is a bug. The reasoning behind each name lives - on the{" "} - - colour page - - . - - -
+
-
+
diff --git a/desktop-next/src/features/design-system/ui/ColourPage.tsx b/desktop-next/src/features/design-system/ui/ColourPage.tsx index a410145a7d..afe365aa7e 100644 --- a/desktop-next/src/features/design-system/ui/ColourPage.tsx +++ b/desktop-next/src/features/design-system/ui/ColourPage.tsx @@ -5,7 +5,7 @@ import { type Role, } from "@/shared/tokens/registry"; -import { Note, PageHeader, Section, Swatch } from "./primitives"; +import { PageHeader, Section, Swatch } from "./primitives"; /** * A role, sitting directly on the page. @@ -34,7 +34,6 @@ function RoleRow({ role }: { role: Role }) { ) : null} -

{role.use}

{role.exception ? (

Exception: {role.exception} @@ -48,23 +47,14 @@ function RoleRow({ role }: { role: Role }) { export function ColourPage() { return ( <> - + -

+
{RAMPS.map((ramp) => (

{ramp.name}

-

- {ramp.description} -

-
+
{ROLE_GROUPS.map((group) => (

{group.name}

-

- {group.description} -

{group.roles.map((role) => ( @@ -111,10 +95,7 @@ export function ColourPage() {
-
+
{/* No swatch here to do the separating, so these entries keep a little structure — the token name leads and the spacing groups it with its reason. Still no card: this is prose, not data. */} @@ -129,13 +110,6 @@ export function ColourPage() { ))}
- - - Every dark value in this system is authored rather than observed — the - design exploration it was derived from is light-only. Toggle the mode in - the sidebar and treat anything that looks wrong as a finding, not a - given. - ); } diff --git a/desktop-next/src/features/design-system/ui/ComponentPage.tsx b/desktop-next/src/features/design-system/ui/ComponentPage.tsx index 10788bfba6..07de320bbb 100644 --- a/desktop-next/src/features/design-system/ui/ComponentPage.tsx +++ b/desktop-next/src/features/design-system/ui/ComponentPage.tsx @@ -42,10 +42,7 @@ export function ComponentPage({ entry }: { entry: CatalogEntry }) { export function ComponentNotFound() { return ( <> - + Browse all components diff --git a/desktop-next/src/features/design-system/ui/ComponentsPage.tsx b/desktop-next/src/features/design-system/ui/ComponentsPage.tsx index dddb516aac..5561315e28 100644 --- a/desktop-next/src/features/design-system/ui/ComponentsPage.tsx +++ b/desktop-next/src/features/design-system/ui/ComponentsPage.tsx @@ -26,10 +26,7 @@ export function ComponentsPage() { ); return ( <> - +
Find a component @@ -77,9 +74,6 @@ export function ComponentsPage() {

{entry.name}

-

- {entry.description} -

diff --git a/desktop-next/src/features/design-system/ui/CompositionsPage.tsx b/desktop-next/src/features/design-system/ui/CompositionsPage.tsx index c3fa64a4ce..8090458c58 100644 --- a/desktop-next/src/features/design-system/ui/CompositionsPage.tsx +++ b/desktop-next/src/features/design-system/ui/CompositionsPage.tsx @@ -98,14 +98,8 @@ export function CompositionsPage() { const [saved, setSaved] = useState(false); return ( <> - -
+ +
@@ -151,10 +145,7 @@ export function CompositionsPage() {
-
+
@@ -202,10 +193,7 @@ export function CompositionsPage() {
-
+
diff --git a/desktop-next/src/features/design-system/ui/ElevationPage.tsx b/desktop-next/src/features/design-system/ui/ElevationPage.tsx index cbaee31b71..f3d02d10bd 100644 --- a/desktop-next/src/features/design-system/ui/ElevationPage.tsx +++ b/desktop-next/src/features/design-system/ui/ElevationPage.tsx @@ -1,14 +1,11 @@ import { ELEVATION } from "@/shared/tokens/registry"; -import { Note, PageHeader, Section } from "./primitives"; +import { PageHeader, Section } from "./primitives"; export function ElevationPage() { return ( <> - +
@@ -27,14 +24,6 @@ export function ElevationPage() { ))}
- - - Elevation is carried by shadow in light mode and by lightness in dark - mode. On a near-black background there is nothing darker for a shadow to - cast, so a floating surface becomes a step lighter instead — which is - why `bg-float` and `bg-panel` share a light value and diverge in dark. - Never reach for a stronger shadow to make something float in dark mode. - ); } diff --git a/desktop-next/src/features/design-system/ui/GlassPage.tsx b/desktop-next/src/features/design-system/ui/GlassPage.tsx index 690b14c300..61af3a3b0f 100644 --- a/desktop-next/src/features/design-system/ui/GlassPage.tsx +++ b/desktop-next/src/features/design-system/ui/GlassPage.tsx @@ -1,7 +1,7 @@ import { Tabs } from "@buzz/ui"; import { BLUR, RAMPS } from "@/shared/tokens/registry"; -import { Note, PageHeader, Section, Swatch } from "./primitives"; +import { PageHeader, Section, Swatch } from "./primitives"; const GLASS = RAMPS.find((ramp) => ramp.id === "glass"); @@ -34,15 +34,9 @@ function ChromePill() { export function GlassPage() { return ( <> - + -
+
@@ -53,14 +47,13 @@ export function GlassPage() { blur-chrome - selected bg-chrome-selected — - opaque where its container is glass + selected bg-chrome-selected
{GLASS ? ( -
+
{GLASS.steps.map((step) => ( ) : null} -
+
{BLUR.map((blur) => (
-
+
{`box-shadow:\n inset 0 1px 0 var(--rim-lit),\n inset 0 -1px 0 var(--rim-shade);`}
- - CSS borders accept only solid colours, so every gradient-border - technique is a workaround. `border-image` takes a gradient but ignores - `border-radius`, which is fatal on a pill. The two-background - `background-clip` trick respects radius but needs an opaque inner - fill, so it bleeds across a translucent surface. Two inset shadows - respect radius, cost nothing, and work over translucency. The known - limit is that each shadow is one solid colour, so a corner transitions - in two discrete edges rather than a smooth sweep. -
- - - A glass hover changes opacity and never blur — re-blurring a large - surface every frame is expensive enough to feel. Glass surfaces use - their own `-glass-hover` rather than the shared `bg-hover`, which is a - neutral built to sit on an opaque surface. - ); } diff --git a/desktop-next/src/features/design-system/ui/GrowthPage.tsx b/desktop-next/src/features/design-system/ui/GrowthPage.tsx index a38a49d5f0..748e2f286b 100644 --- a/desktop-next/src/features/design-system/ui/GrowthPage.tsx +++ b/desktop-next/src/features/design-system/ui/GrowthPage.tsx @@ -1,6 +1,6 @@ import { GROWTH_PROCEDURE } from "@/shared/tokens/registry"; -import { Note, PageHeader, Section } from "./primitives"; +import { PageHeader, Section } from "./primitives"; const AUDIT: Array<[string, string]> = [ [ @@ -39,15 +39,9 @@ const AUDIT: Array<[string, string]> = [ export function GrowthPage() { return ( <> - + -
+
    {GROWTH_PROCEDURE.map((step, index) => (
  1. @@ -60,10 +54,7 @@ export function GrowthPage() {
-
+
{AUDIT.map(([check, action]) => (
- - - Promotion from proposed to core is a metadata change, not a rename. - Renaming call sites would give promotion a migration cost, and anything - with a cost does not happen. - ); } diff --git a/desktop-next/src/features/design-system/ui/MotionPage.tsx b/desktop-next/src/features/design-system/ui/MotionPage.tsx index c89f752715..dbbfde6383 100644 --- a/desktop-next/src/features/design-system/ui/MotionPage.tsx +++ b/desktop-next/src/features/design-system/ui/MotionPage.tsx @@ -8,11 +8,8 @@ export function MotionPage() { if (!group) throw new Error("Missing foundation group"); return ( <> - -
+ +
diff --git a/desktop-next/src/features/design-system/ui/OpenSourcePage.tsx b/desktop-next/src/features/design-system/ui/OpenSourcePage.tsx index 2ca4c17439..108622b9a8 100644 --- a/desktop-next/src/features/design-system/ui/OpenSourcePage.tsx +++ b/desktop-next/src/features/design-system/ui/OpenSourcePage.tsx @@ -31,10 +31,7 @@ const differences = [ export function OpenSourcePage() { return ( <> - +
@@ -60,10 +57,8 @@ export function OpenSourcePage() {

- @buzz/design-tokens contains the role registry, light and dark values, - typography, geometry, and motion. @buzz/ui consumes those roles. This - catalog is a consumer of both packages; components do not import the - catalog, router, Tauri, or a private service. + @buzz/design-tokens defines the tokens; @buzz/ui provides the + components.

           {`import '@fontsource-variable/inter/index.css';\nimport { Button, Field, Input } from '@buzz/ui';\n\n\n  Project name\n  \n\n`}
@@ -71,11 +66,7 @@ export function OpenSourcePage() {
       

- Run the Vite catalog locally or build static files for a public host. - A host serving the catalog needs an SPA fallback to index.html for - nested routes. Storybook itself is open source and could be another - consumer later; it is not a runtime dependency or a hosting - requirement. + Static hosts need an index.html fallback for nested routes.

           {`pnpm install --frozen-lockfile\npnpm --filter buzz-desktop-next dev\npnpm --filter buzz-desktop-next build\npnpm --filter buzz-desktop-next preview`}
@@ -83,23 +74,15 @@ export function OpenSourcePage() {
       

- This is a web and React foundation for desktop-next. It does not - replace Flutter widgets or migrate the existing desktop client. The - package is usable in the workspace and has a compiled distribution; - npm publication is a separate release step. Charts currently cover - categorical bars, and the carousel uses manual navigation. There is no - promise of API compatibility with shadcn or internal BlockUI - implementations. + React components for desktop-next, available as workspace packages and + compiled files.

- No private implementation, font, icon, screenshot, or internal - documentation bundle is included. New Buzz code uses the repository - license. Inter and JetBrains Mono use the SIL Open Font License; - Lucide carries ISC and Feather-derived MIT notices; behavior - dependencies carry their own public licenses. Full notices live in - packages/ui/THIRD_PARTY_NOTICES.md. + Repository license for Buzz code; SIL OFL for fonts; ISC and MIT + notices for Lucide. See packages/ui/THIRD_PARTY_NOTICES.md for + dependency licenses.

- +
-
+
{[ - [ - "01", - "Foundations", - "A closed vocabulary for color, type, space, corners, depth, and motion.", - "/design/color", - ], - [ - "02", - "Components", - "Public behavior, Buzz styling, explicit variants, and accessible states.", - "/design/components", - ], - [ - "03", - "Compositions", - "Product patterns and validated generated responses made from the same parts.", - "/design/compositions", - ], - ].map(([number, title, description, to]) => ( + ["01", "Foundations", "/design/color"], + ["02", "Components", "/design/components"], + ["03", "Compositions", "/design/compositions"], + ].map(([number, title, to]) => (

{number}

{title}

-

{description}

))}
-

- Inspired by BlockUI’s visual direction and implemented for Buzz’s - open-source architecture. Fonts and icons are public, assets are - self-hosted, and the documentation is part of the app. Switch modes to - inspect every example in light and dark. -

Read the adaptation guide → diff --git a/desktop-next/src/features/design-system/ui/RadiusPage.tsx b/desktop-next/src/features/design-system/ui/RadiusPage.tsx index 06ec32f5d7..1ec1ccffe8 100644 --- a/desktop-next/src/features/design-system/ui/RadiusPage.tsx +++ b/desktop-next/src/features/design-system/ui/RadiusPage.tsx @@ -6,7 +6,7 @@ export function RadiusPage() { if (!group) throw new Error("Missing foundation group"); return ( <> - +
diff --git a/desktop-next/src/features/design-system/ui/SpacingPage.tsx b/desktop-next/src/features/design-system/ui/SpacingPage.tsx index ef18182391..deec6178e5 100644 --- a/desktop-next/src/features/design-system/ui/SpacingPage.tsx +++ b/desktop-next/src/features/design-system/ui/SpacingPage.tsx @@ -6,14 +6,11 @@ export function SpacingPage() { if (!group) throw new Error("Missing foundation group"); return ( <> - +
-
+
diff --git a/desktop-next/src/features/design-system/ui/TypographyPage.tsx b/desktop-next/src/features/design-system/ui/TypographyPage.tsx index 8f8a345c3c..724aca1106 100644 --- a/desktop-next/src/features/design-system/ui/TypographyPage.tsx +++ b/desktop-next/src/features/design-system/ui/TypographyPage.tsx @@ -5,7 +5,7 @@ import { type TypeRole, } from "@/shared/tokens/registry"; -import { Note, PageHeader, Row, Rows, Section, Specimens } from "./primitives"; +import { PageHeader, Row, Rows, Section, Specimens } from "./primitives"; /** * Every specimen below is set in the role it documents, so the page is the @@ -27,7 +27,6 @@ function RoleSpecimen({ role }: { role: TypeRole }) { {role.size} / {role.lineHeight} / {role.tracking} / {role.weight} -

{role.use}

); } @@ -35,15 +34,9 @@ function RoleSpecimen({ role }: { role: TypeRole }) { export function TypographyPage() { return ( <> - + -
+
{TYPE_FAMILIES.map((family) => (
@@ -55,18 +48,12 @@ export function TypographyPage() { {family.name}

{family.token} -

- {family.use} -

))}
-
+
{TYPE_ROLES.map((role) => ( @@ -75,7 +62,7 @@ export function TypographyPage() {
{TYPE_RAMPS.map((ramp) => ( -
+
{ramp.steps.map((step) => ( @@ -94,43 +81,20 @@ export function TypographyPage() {
))} -
+

Every size is relative. Never px.

-

- Fixed pixel text freezes against keyboard zoom and ignores the - person's font-size preference. The current client shipped a - message-timeline regression from exactly this and now has a CI - guard rejecting arbitrary size literals. This ramp derives - entirely from one virtual rem, so both dials work by construction. -

No all-caps, and no tracked-out labels.

-

- A capitalised label is harder to read than the sentence-case - version and reads as enterprise chrome. Section labels earn their - quietness from size and colour — text-meta on text-tertiary — - rather than from being shouted. There is no uppercase utility in - this system. -

- - - Inter Variable is bundled with the catalog, and JetBrains Mono covers - code. Fonts load from local assets. Every component uses these named - roles so type stays consistent as the system evolves. - ); } diff --git a/desktop-next/src/features/design-system/ui/VocabularyPage.tsx b/desktop-next/src/features/design-system/ui/VocabularyPage.tsx index 16b2bccad0..0ff509dab1 100644 --- a/desktop-next/src/features/design-system/ui/VocabularyPage.tsx +++ b/desktop-next/src/features/design-system/ui/VocabularyPage.tsx @@ -4,15 +4,12 @@ import { VOCABULARY, } from "@/shared/tokens/registry"; -import { Note, PageHeader, Section } from "./primitives"; +import { PageHeader, Section } from "./primitives"; export function VocabularyPage() { return ( <> - +
@@ -39,10 +36,7 @@ export function VocabularyPage() {
-
+
{GRAMMAR}
@@ -65,12 +59,6 @@ export function VocabularyPage() {
- - - One modifier, one material, one state per name. A name that does not - parse under this grammar is reported by the audit with its correct - spelling. - ); } diff --git a/desktop-next/src/features/design-system/ui/primitives.tsx b/desktop-next/src/features/design-system/ui/primitives.tsx index 0b93d2d666..c49d13e5ed 100644 --- a/desktop-next/src/features/design-system/ui/primitives.tsx +++ b/desktop-next/src/features/design-system/ui/primitives.tsx @@ -13,20 +13,17 @@ import type { ReactNode } from "react"; export function PageHeader({ title, - intro, status, }: { title: string; - intro: string; status?: string; }) { return ( -
+

{title}

{status ? {status} : null}
-

{intro}

); } @@ -41,52 +38,19 @@ export function StatusPill({ children }: { children: ReactNode }) { export function Section({ title, - description, children, }: { title: string; - description?: string; children: ReactNode; }) { return (
-
-

{title}

- {description ? ( -

{description}

- ) : null} -
+

{title}

{children}
); } -export function Note({ children }: { children: ReactNode }) { - return ( -

- {children} -

- ); -} - -export function Stub({ what, decide }: { what: string; decide: string[] }) { - return ( -
-

{what}

-
-

Still to decide

-
    - {decide.map((item) => ( -
  • - {item} -
  • - ))} -
-
-
- ); -} - /** * A list of uniform rows — the tabular case, where every row looks alike and the * eye needs a line to track along. Dividers, no container: the section heading diff --git a/desktop-next/tests/density.spec.ts b/desktop-next/tests/density.spec.ts index cedbc96df7..67b276ecda 100644 --- a/desktop-next/tests/density.spec.ts +++ b/desktop-next/tests/density.spec.ts @@ -39,7 +39,7 @@ test("density changes geometry throughout without changing type or losing a draf await expect(page.locator(".catalog-grid")).toHaveCSS("row-gap", "32px"); await expect(page.locator("main header").first()).toHaveCSS( "margin-bottom", - "42px", + "24px", ); await expect(draft).toHaveCSS("min-height", "64px");