@nationaldesignstudio/react 0.0.15 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/src/App.css +0 -0
- package/src/App.tsx +7 -0
- package/src/assets/fonts/PPNeueMontreal-Variable.woff2 +0 -0
- package/src/assets/react.svg +1 -0
- package/src/components/atoms/accordion/accordion.stories.tsx +228 -0
- package/src/components/atoms/accordion/accordion.tsx +219 -0
- package/src/components/atoms/accordion/index.ts +6 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-quiet-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-quiet-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-disabled-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-disabled-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-quiet-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-quiet-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-large-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-large-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-medium-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-medium-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-small-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-small-chromium-linux.png +0 -0
- package/src/components/atoms/button/button.stories.tsx +102 -0
- package/src/components/atoms/button/button.test.tsx +135 -0
- package/src/components/atoms/button/button.tsx +139 -0
- package/src/components/atoms/button/button.visual.test.tsx +102 -0
- package/src/components/atoms/button/icon-button.stories.tsx +166 -0
- package/src/components/atoms/button/icon-button.tsx +120 -0
- package/src/components/atoms/button/index.ts +6 -0
- package/src/components/atoms/ndstudio-footer/index.ts +1 -0
- package/src/components/atoms/ndstudio-footer/ndstudio-footer.tsx +55 -0
- package/src/components/atoms/pager-control/index.ts +5 -0
- package/src/components/atoms/pager-control/pager-control.stories.tsx +209 -0
- package/src/components/atoms/pager-control/pager-control.test.tsx +130 -0
- package/src/components/atoms/pager-control/pager-control.tsx +329 -0
- package/src/components/dev-tools/dev-toolbar/dev-toolbar.stories.tsx +82 -0
- package/src/components/dev-tools/dev-toolbar/dev-toolbar.tsx +196 -0
- package/src/components/dev-tools/dev-toolbar/index.ts +1 -0
- package/src/components/dev-tools/grid-overlay/grid-overlay.tsx +41 -0
- package/src/components/dev-tools/grid-overlay/index.ts +1 -0
- package/src/components/dev-tools/index.ts +2 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-default-vertical-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-default-vertical-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-horizontal-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-horizontal-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-minimal-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-minimal-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-actions-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-actions-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-eyebrow-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-eyebrow-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-image-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-image-chromium-linux.png +0 -0
- package/src/components/organisms/card/card.stories.tsx +293 -0
- package/src/components/organisms/card/card.test.tsx +245 -0
- package/src/components/organisms/card/card.tsx +225 -0
- package/src/components/organisms/card/card.visual.test.tsx +197 -0
- package/src/components/organisms/card/index.ts +19 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-active-link-chromium-darwin.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-active-link-chromium-linux.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-brand-only-chromium-darwin.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-brand-only-chromium-linux.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-default-chromium-darwin.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-default-chromium-linux.png +0 -0
- package/src/components/organisms/navbar/index.ts +18 -0
- package/src/components/organisms/navbar/navbar.stories.tsx +313 -0
- package/src/components/organisms/navbar/navbar.test.tsx +190 -0
- package/src/components/organisms/navbar/navbar.tsx +323 -0
- package/src/components/organisms/navbar/navbar.visual.test.tsx +85 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-icon-chromium-darwin.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-icon-chromium-linux.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-text-chromium-darwin.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-text-chromium-linux.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-default-chromium-darwin.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-default-chromium-linux.png +0 -0
- package/src/components/organisms/us-gov-banner/index.ts +1 -0
- package/src/components/organisms/us-gov-banner/us-gov-banner.stories.tsx +35 -0
- package/src/components/organisms/us-gov-banner/us-gov-banner.test.tsx +107 -0
- package/src/components/organisms/us-gov-banner/us-gov-banner.tsx +73 -0
- package/src/components/organisms/us-gov-banner/us-gov-banner.visual.test.tsx +46 -0
- package/src/components/sections/banner/banner.stories.tsx +150 -0
- package/src/components/sections/banner/banner.test.tsx +185 -0
- package/src/components/sections/banner/banner.tsx +130 -0
- package/src/components/sections/banner/index.ts +2 -0
- package/src/components/sections/card-grid/card-grid.stories.tsx +351 -0
- package/src/components/sections/card-grid/card-grid.tsx +116 -0
- package/src/components/sections/card-grid/index.ts +1 -0
- package/src/components/sections/faq-section/faq-section.stories.tsx +453 -0
- package/src/components/sections/faq-section/faq-section.tsx +84 -0
- package/src/components/sections/faq-section/index.ts +2 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-desktop-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-desktop-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-mobile-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-mobile-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-tablet-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-tablet-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-desktop-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-desktop-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-mobile-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-mobile-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-tablet-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-tablet-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-desktop-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-desktop-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-mobile-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-mobile-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-tablet-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-tablet-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-custom-class-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-custom-class-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-default-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-long-title-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-long-title-chromium-linux.png +0 -0
- package/src/components/sections/hero/hero.stories.tsx +274 -0
- package/src/components/sections/hero/hero.test.tsx +135 -0
- package/src/components/sections/hero/hero.tsx +453 -0
- package/src/components/sections/hero/hero.visual.test.tsx +140 -0
- package/src/components/sections/hero/index.ts +10 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-h3-heading-chromium-darwin.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-h3-heading-chromium-linux.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-paragraphs-chromium-darwin.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-paragraphs-chromium-linux.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-sections-chromium-darwin.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-sections-chromium-linux.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-single-section-chromium-darwin.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-single-section-chromium-linux.png +0 -0
- package/src/components/sections/prose/index.ts +6 -0
- package/src/components/sections/prose/prose.stories.tsx +144 -0
- package/src/components/sections/prose/prose.test.tsx +178 -0
- package/src/components/sections/prose/prose.tsx +88 -0
- package/src/components/sections/prose/prose.visual.test.tsx +105 -0
- package/src/components/sections/river/index.ts +1 -0
- package/src/components/sections/river/river.stories.tsx +237 -0
- package/src/components/sections/river/river.test.tsx +268 -0
- package/src/components/sections/river/river.tsx +173 -0
- package/src/components/sections/tout/index.ts +1 -0
- package/src/components/sections/tout/tout.stories.tsx +171 -0
- package/src/components/sections/tout/tout.test.tsx +242 -0
- package/src/components/sections/tout/tout.tsx +270 -0
- package/src/components/sections/two-column-section/index.ts +5 -0
- package/src/components/sections/two-column-section/two-column-section.stories.tsx +285 -0
- package/src/components/sections/two-column-section/two-column-section.tsx +162 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-event-listener.ts +73 -0
- package/src/index.ts +155 -0
- package/src/lib/theme.ts +1000 -0
- package/src/lib/utils.ts +6 -0
- package/src/main.tsx +13 -0
- package/src/stories/GridSystem.stories.tsx +84 -0
- package/src/stories/Introduction.mdx +114 -0
- package/src/stories/ThemeProvider.stories.tsx +357 -0
- package/src/stories/TokenShowcase.stories.tsx +92 -0
- package/src/stories/TokenShowcase.tsx +1429 -0
- package/src/styles.css +11 -0
- package/src/theme/ThemeProvider.tsx +297 -0
- package/src/theme/hooks.ts +40 -0
- package/src/theme/index.ts +43 -0
- package/src/theme/utils.ts +104 -0
package/src/lib/utils.ts
ADDED
package/src/main.tsx
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { StrictMode } from "react";
|
|
2
|
+
import { createRoot } from "react-dom/client";
|
|
3
|
+
import "./styles.css";
|
|
4
|
+
import App from "./App.tsx";
|
|
5
|
+
|
|
6
|
+
const rootElement = document.getElementById("root");
|
|
7
|
+
if (rootElement) {
|
|
8
|
+
createRoot(rootElement).render(
|
|
9
|
+
<StrictMode>
|
|
10
|
+
<App />
|
|
11
|
+
</StrictMode>,
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Spatial Grid System
|
|
5
|
+
*
|
|
6
|
+
* Responsive grid tokens that adapt across breakpoints:
|
|
7
|
+
* - Large (lg): 1440px+ - 24 columns, 72px margin, 24px gutter
|
|
8
|
+
* - Medium (md): 768px+ - 12 columns, 56px margin, 20px gutter
|
|
9
|
+
* - Small (sm): 320px+ - 4 columns, 24px margin, 12px gutter
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const GridColumn = ({ index }: { index: number }) => (
|
|
13
|
+
<div className="h-12 bg-brand-primary/20 border border-brand-primary/40 rounded flex items-center justify-center">
|
|
14
|
+
<span className="text-xs font-mono text-brand-primary">{index + 1}</span>
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const GridVisualization = () => (
|
|
19
|
+
<div className="w-full bg-gray-100 py-8">
|
|
20
|
+
<div className="w-full max-w-[90rem] mx-auto px-[var(--spatial-grid-small-margin)] md:px-[var(--spatial-grid-medium-margin)] lg:px-[var(--spatial-grid-large-margin)]">
|
|
21
|
+
<div className="grid grid-cols-4 md:grid-cols-12 lg:grid-cols-24 gap-[var(--spatial-grid-small-gutter)] md:gap-[var(--spatial-grid-medium-gutter)] lg:gap-[var(--spatial-grid-large-gutter)]">
|
|
22
|
+
{Array.from({ length: 24 }).map((_, i) => (
|
|
23
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: Static grid columns never reorder
|
|
24
|
+
<GridColumn key={i} index={i} />
|
|
25
|
+
))}
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const meta = {
|
|
32
|
+
title: "Design System/Grid System",
|
|
33
|
+
component: GridVisualization,
|
|
34
|
+
parameters: {
|
|
35
|
+
layout: "fullscreen",
|
|
36
|
+
},
|
|
37
|
+
} satisfies Meta<typeof GridVisualization>;
|
|
38
|
+
|
|
39
|
+
export default meta;
|
|
40
|
+
type Story = StoryObj<typeof meta>;
|
|
41
|
+
|
|
42
|
+
export const Default: Story = {};
|
|
43
|
+
|
|
44
|
+
export const Desktop: Story = {
|
|
45
|
+
globals: { viewport: { value: "lg" } },
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const Tablet: Story = {
|
|
49
|
+
globals: { viewport: { value: "md" } },
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const Mobile: Story = {
|
|
53
|
+
globals: { viewport: { value: "sm" } },
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const ColumnSpans = () => (
|
|
57
|
+
<div className="w-full py-8 px-[var(--spatial-grid-large-margin)]">
|
|
58
|
+
<div className="max-w-[90rem] mx-auto grid grid-cols-24 gap-[var(--spatial-grid-large-gutter)]">
|
|
59
|
+
<div className="col-span-full h-12 bg-gray-200 rounded flex items-center px-4">
|
|
60
|
+
<code className="text-sm font-mono">col-span-full</code>
|
|
61
|
+
</div>
|
|
62
|
+
<div className="col-start-4 col-end-22 h-12 bg-gray-200 rounded flex items-center px-4">
|
|
63
|
+
<code className="text-sm font-mono">
|
|
64
|
+
col-start-4 col-end-22 (18 cols)
|
|
65
|
+
</code>
|
|
66
|
+
</div>
|
|
67
|
+
<div className="col-start-7 col-end-19 h-12 bg-gray-200 rounded flex items-center px-4">
|
|
68
|
+
<code className="text-sm font-mono">
|
|
69
|
+
col-start-7 col-end-19 (12 cols)
|
|
70
|
+
</code>
|
|
71
|
+
</div>
|
|
72
|
+
<div className="col-start-9 col-end-17 h-12 bg-gray-200 rounded flex items-center px-4">
|
|
73
|
+
<code className="text-sm font-mono">
|
|
74
|
+
col-start-9 col-end-17 (8 cols)
|
|
75
|
+
</code>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
export const Spans: Story = {
|
|
82
|
+
render: () => <ColumnSpans />,
|
|
83
|
+
globals: { viewport: { value: "lg" } },
|
|
84
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Meta } from "@storybook/addon-docs/blocks";
|
|
2
|
+
|
|
3
|
+
<Meta title="Introduction" />
|
|
4
|
+
|
|
5
|
+
# NDS Design System
|
|
6
|
+
|
|
7
|
+
Welcome to the **NDS Design System** component library. This Storybook documents all available components, their variants, and design tokens.
|
|
8
|
+
|
|
9
|
+
## Getting Started
|
|
10
|
+
|
|
11
|
+
### Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bun add @nationaldesignstudio/react
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Setup Tailwind CSS v4
|
|
18
|
+
|
|
19
|
+
Import the generated tokens CSS in your main CSS file:
|
|
20
|
+
|
|
21
|
+
```css
|
|
22
|
+
/* app.css or globals.css */
|
|
23
|
+
@import "tailwindcss";
|
|
24
|
+
@import "@nationaldesignstudio/react/tokens.css";
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
This gives you access to all design tokens as CSS variables and Tailwind utilities.
|
|
28
|
+
|
|
29
|
+
### Using Components
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import { Button } from "@nationaldesignstudio/react";
|
|
33
|
+
|
|
34
|
+
function App() {
|
|
35
|
+
return <Button variant="primary">Click me</Button>;
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Typography Styles
|
|
40
|
+
|
|
41
|
+
The design system provides pre-built typography classes for consistent text styling. Typography utilities use the `typography-` prefix to avoid conflicts with Tailwind's `text-*` color utilities.
|
|
42
|
+
|
|
43
|
+
### Product Typography
|
|
44
|
+
|
|
45
|
+
For app UIs, dashboards, and interfaces:
|
|
46
|
+
|
|
47
|
+
```html
|
|
48
|
+
<h1 class="typography-product-title-large">Page Title</h1>
|
|
49
|
+
<h2 class="typography-product-headline-medium">Section Header</h2>
|
|
50
|
+
<p class="typography-product-body-medium">Body text content...</p>
|
|
51
|
+
<span class="typography-product-caption-small">Caption text</span>
|
|
52
|
+
<button class="typography-product-button-medium">Click me</button>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Available styles: `typography-product-{category}-{size}` where category is: `title`, `headline`, `body`, `label`, `caption`, `button`, `input`, `link`, `navigation`, `overline`, `tabbar`
|
|
56
|
+
|
|
57
|
+
### Brand Typography
|
|
58
|
+
|
|
59
|
+
For landing pages and promotional content:
|
|
60
|
+
|
|
61
|
+
```html
|
|
62
|
+
<h1 class="typography-brand-medium-display-hero">Hero</h1>
|
|
63
|
+
<h2 class="typography-brand-medium-headline-large">Big Headline</h2>
|
|
64
|
+
<p class="typography-brand-medium-body-large">Marketing copy...</p>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Available namespaces: `brand-large` (desktop), `brand-medium` (tablet), `brand-small` (mobile)
|
|
68
|
+
|
|
69
|
+
Available styles: `typography-brand-{breakpoint}-{category}-{size}` where category is: `display`, `headline`, `subheading`, `body`, `label`, `caption`, `button`, `link`
|
|
70
|
+
|
|
71
|
+
## Color Tokens
|
|
72
|
+
|
|
73
|
+
All colors are available as Tailwind utilities:
|
|
74
|
+
|
|
75
|
+
```html
|
|
76
|
+
<div class="bg-blue-500 text-gray-900">...</div>
|
|
77
|
+
<div class="bg-alpha-black-50">Semi-transparent overlay</div>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
See **Design System > Tokens > Colors** for the full palette.
|
|
81
|
+
|
|
82
|
+
## Spacing Tokens
|
|
83
|
+
|
|
84
|
+
Consistent spacing values:
|
|
85
|
+
|
|
86
|
+
```html
|
|
87
|
+
<div class="p-spacing-16 m-spacing-24 gap-spacing-8">...</div>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Features
|
|
91
|
+
|
|
92
|
+
- **Design Tokens** - Comprehensive token system for colors, spacing, and typography
|
|
93
|
+
- **Accessibility** - Components tested for WCAG compliance
|
|
94
|
+
- **TypeScript** - Full type safety with detailed prop documentation
|
|
95
|
+
- **Tailwind CSS v4** - Built on modern Tailwind with CSS variables
|
|
96
|
+
|
|
97
|
+
## Structure
|
|
98
|
+
|
|
99
|
+
- **Components** - Reusable UI components (Button, etc.)
|
|
100
|
+
- **Design System > Tokens** - Visual token documentation
|
|
101
|
+
|
|
102
|
+
## Development
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Run Storybook locally
|
|
106
|
+
cd packages/react
|
|
107
|
+
bun run storybook
|
|
108
|
+
|
|
109
|
+
# Build tokens after changes
|
|
110
|
+
bun run build
|
|
111
|
+
|
|
112
|
+
# Run tests
|
|
113
|
+
bun run test
|
|
114
|
+
```
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Button } from "../components/atoms/button";
|
|
3
|
+
import {
|
|
4
|
+
Card,
|
|
5
|
+
CardActions,
|
|
6
|
+
CardBody,
|
|
7
|
+
CardContent,
|
|
8
|
+
CardDescription,
|
|
9
|
+
CardTitle,
|
|
10
|
+
} from "../components/organisms/card";
|
|
11
|
+
import { ThemeProvider, useCSSVars } from "../theme";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Shared demo component using actual Button, Card, and Typography components.
|
|
15
|
+
* Used across all theme stories to showcase theming differences.
|
|
16
|
+
*/
|
|
17
|
+
function ThemeDemo({ title }: { title?: string }) {
|
|
18
|
+
const cssVars = useCSSVars();
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div style={cssVars} className="p-6">
|
|
22
|
+
<div className="bg-bg-page p-6 rounded-lg min-h-[300px]">
|
|
23
|
+
{title && (
|
|
24
|
+
<h2 className="typography-subheading-small text-text-primary mb-4">
|
|
25
|
+
{title}
|
|
26
|
+
</h2>
|
|
27
|
+
)}
|
|
28
|
+
|
|
29
|
+
{/* Typography showcase */}
|
|
30
|
+
<div className="mb-6">
|
|
31
|
+
<p className="typography-body-large text-text-primary mb-2">
|
|
32
|
+
Primary text using typography tokens
|
|
33
|
+
</p>
|
|
34
|
+
<p className="typography-body-small text-text-secondary">
|
|
35
|
+
Secondary text for supporting content
|
|
36
|
+
</p>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
{/* Button variants */}
|
|
40
|
+
<div className="flex flex-wrap gap-3 mb-6">
|
|
41
|
+
<Button variant="primary">Primary</Button>
|
|
42
|
+
<Button variant="secondary">Secondary</Button>
|
|
43
|
+
<Button variant="primaryOutline">Outline</Button>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
{/* Card component */}
|
|
47
|
+
<Card className="max-w-sm">
|
|
48
|
+
<CardContent>
|
|
49
|
+
<CardBody>
|
|
50
|
+
<CardTitle>Card Title</CardTitle>
|
|
51
|
+
<CardDescription>
|
|
52
|
+
This card demonstrates surface tokens including border radius
|
|
53
|
+
and stroke width.
|
|
54
|
+
</CardDescription>
|
|
55
|
+
</CardBody>
|
|
56
|
+
<CardActions>
|
|
57
|
+
<Button variant="primary" size="sm">
|
|
58
|
+
Action
|
|
59
|
+
</Button>
|
|
60
|
+
<Button variant="secondary" size="sm">
|
|
61
|
+
Cancel
|
|
62
|
+
</Button>
|
|
63
|
+
</CardActions>
|
|
64
|
+
</CardContent>
|
|
65
|
+
</Card>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const meta: Meta<typeof ThemeProvider> = {
|
|
72
|
+
title: "Theme/ThemeProvider",
|
|
73
|
+
component: ThemeProvider,
|
|
74
|
+
parameters: {
|
|
75
|
+
layout: "fullscreen",
|
|
76
|
+
docs: {
|
|
77
|
+
description: {
|
|
78
|
+
component: `
|
|
79
|
+
The ThemeProvider component applies theme tokens as CSS variables using type-safe theme names.
|
|
80
|
+
|
|
81
|
+
## Props
|
|
82
|
+
|
|
83
|
+
- \`color\`: Color theme name - "base" | "dark" | "institution" | "civic" (defaults to "base")
|
|
84
|
+
- \`surface\`: Surface theme name - "base" | "sharp" | "framed" | "soft" (defaults to "base")
|
|
85
|
+
|
|
86
|
+
## Usage
|
|
87
|
+
|
|
88
|
+
\`\`\`tsx
|
|
89
|
+
import { ThemeProvider, useCSSVars } from '@nationaldesignstudio/react';
|
|
90
|
+
|
|
91
|
+
// Use defaults (base themes)
|
|
92
|
+
function App() {
|
|
93
|
+
return (
|
|
94
|
+
<ThemeProvider>
|
|
95
|
+
<Layout />
|
|
96
|
+
</ThemeProvider>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Use specific themes
|
|
101
|
+
function ThemedApp() {
|
|
102
|
+
return (
|
|
103
|
+
<ThemeProvider color="civic" surface="sharp">
|
|
104
|
+
<Layout />
|
|
105
|
+
</ThemeProvider>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function Layout() {
|
|
110
|
+
const cssVars = useCSSVars();
|
|
111
|
+
return (
|
|
112
|
+
<div style={cssVars}>
|
|
113
|
+
<Button variant="primary">Click me</Button>
|
|
114
|
+
</div>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
\`\`\`
|
|
118
|
+
`,
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
tags: ["autodocs"],
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export default meta;
|
|
126
|
+
type Story = StoryObj<typeof ThemeProvider>;
|
|
127
|
+
|
|
128
|
+
// =============================================================================
|
|
129
|
+
// Color Theme Stories
|
|
130
|
+
// =============================================================================
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Base color theme - the default light color palette.
|
|
134
|
+
*/
|
|
135
|
+
export const BaseColor: Story = {
|
|
136
|
+
render: () => (
|
|
137
|
+
<ThemeProvider color="base">
|
|
138
|
+
<ThemeDemo title="Base Color Theme" />
|
|
139
|
+
</ThemeProvider>
|
|
140
|
+
),
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Dark color theme - inverted colors for dark mode.
|
|
145
|
+
*/
|
|
146
|
+
export const DarkColor: Story = {
|
|
147
|
+
render: () => (
|
|
148
|
+
<ThemeProvider color="dark">
|
|
149
|
+
<ThemeDemo title="Dark Color Theme" />
|
|
150
|
+
</ThemeProvider>
|
|
151
|
+
),
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Institution color theme - warm brown palette with green accents.
|
|
156
|
+
*/
|
|
157
|
+
export const InstitutionColor: Story = {
|
|
158
|
+
render: () => (
|
|
159
|
+
<ThemeProvider color="institution">
|
|
160
|
+
<ThemeDemo title="Institution Color Theme" />
|
|
161
|
+
</ThemeProvider>
|
|
162
|
+
),
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Civic color theme - for government/public sector applications.
|
|
167
|
+
*/
|
|
168
|
+
export const CivicColor: Story = {
|
|
169
|
+
render: () => (
|
|
170
|
+
<ThemeProvider color="civic">
|
|
171
|
+
<ThemeDemo title="Civic Color Theme" />
|
|
172
|
+
</ThemeProvider>
|
|
173
|
+
),
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Color theme comparison - all color variants side by side.
|
|
178
|
+
*/
|
|
179
|
+
export const ColorComparison: Story = {
|
|
180
|
+
render: () => (
|
|
181
|
+
<div className="grid grid-cols-2 gap-4">
|
|
182
|
+
<ThemeProvider color="base">
|
|
183
|
+
<ThemeDemo title="Base" />
|
|
184
|
+
</ThemeProvider>
|
|
185
|
+
<ThemeProvider color="dark">
|
|
186
|
+
<ThemeDemo title="Dark" />
|
|
187
|
+
</ThemeProvider>
|
|
188
|
+
<ThemeProvider color="institution">
|
|
189
|
+
<ThemeDemo title="Institution" />
|
|
190
|
+
</ThemeProvider>
|
|
191
|
+
<ThemeProvider color="civic">
|
|
192
|
+
<ThemeDemo title="Civic" />
|
|
193
|
+
</ThemeProvider>
|
|
194
|
+
</div>
|
|
195
|
+
),
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
// =============================================================================
|
|
199
|
+
// Surface Theme Stories
|
|
200
|
+
// =============================================================================
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Base surface theme - default border radius and stroke widths.
|
|
204
|
+
*/
|
|
205
|
+
export const BaseSurface: Story = {
|
|
206
|
+
render: () => (
|
|
207
|
+
<ThemeProvider surface="base">
|
|
208
|
+
<ThemeDemo title="Base Surface Theme" />
|
|
209
|
+
</ThemeProvider>
|
|
210
|
+
),
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Sharp surface theme - minimal border radius for an angular look.
|
|
215
|
+
*/
|
|
216
|
+
export const SharpSurface: Story = {
|
|
217
|
+
render: () => (
|
|
218
|
+
<ThemeProvider surface="sharp">
|
|
219
|
+
<ThemeDemo title="Sharp Surface Theme" />
|
|
220
|
+
</ThemeProvider>
|
|
221
|
+
),
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Framed surface theme - heavier borders and no button radius.
|
|
226
|
+
*/
|
|
227
|
+
export const FramedSurface: Story = {
|
|
228
|
+
render: () => (
|
|
229
|
+
<ThemeProvider surface="framed">
|
|
230
|
+
<ThemeDemo title="Framed Surface Theme" />
|
|
231
|
+
</ThemeProvider>
|
|
232
|
+
),
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Soft surface theme - large rounded corners and minimal strokes.
|
|
237
|
+
*/
|
|
238
|
+
export const SoftSurface: Story = {
|
|
239
|
+
render: () => (
|
|
240
|
+
<ThemeProvider surface="soft">
|
|
241
|
+
<ThemeDemo title="Soft Surface Theme" />
|
|
242
|
+
</ThemeProvider>
|
|
243
|
+
),
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Surface theme comparison - all surface variants side by side.
|
|
248
|
+
* Notice the different border radius and stroke widths on buttons and cards.
|
|
249
|
+
*/
|
|
250
|
+
export const SurfaceComparison: Story = {
|
|
251
|
+
render: () => (
|
|
252
|
+
<div className="grid grid-cols-2 gap-4">
|
|
253
|
+
<ThemeProvider surface="base">
|
|
254
|
+
<ThemeDemo title="Base" />
|
|
255
|
+
</ThemeProvider>
|
|
256
|
+
<ThemeProvider surface="sharp">
|
|
257
|
+
<ThemeDemo title="Sharp" />
|
|
258
|
+
</ThemeProvider>
|
|
259
|
+
<ThemeProvider surface="framed">
|
|
260
|
+
<ThemeDemo title="Framed" />
|
|
261
|
+
</ThemeProvider>
|
|
262
|
+
<ThemeProvider surface="soft">
|
|
263
|
+
<ThemeDemo title="Soft" />
|
|
264
|
+
</ThemeProvider>
|
|
265
|
+
</div>
|
|
266
|
+
),
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
// =============================================================================
|
|
270
|
+
// Combined Theme Stories
|
|
271
|
+
// =============================================================================
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Civic color + Sharp surface - example of combining color and surface themes.
|
|
275
|
+
*/
|
|
276
|
+
export const CivicSharp: Story = {
|
|
277
|
+
render: () => (
|
|
278
|
+
<ThemeProvider color="civic" surface="sharp">
|
|
279
|
+
<ThemeDemo title="Civic + Sharp" />
|
|
280
|
+
</ThemeProvider>
|
|
281
|
+
),
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Institution color + Framed surface - example of combining color and surface themes.
|
|
286
|
+
*/
|
|
287
|
+
export const InstitutionFramed: Story = {
|
|
288
|
+
render: () => (
|
|
289
|
+
<ThemeProvider color="institution" surface="framed">
|
|
290
|
+
<ThemeDemo title="Institution + Framed" />
|
|
291
|
+
</ThemeProvider>
|
|
292
|
+
),
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Dark color + Sharp surface - angular dark mode.
|
|
297
|
+
*/
|
|
298
|
+
export const DarkSharp: Story = {
|
|
299
|
+
render: () => (
|
|
300
|
+
<ThemeProvider color="dark" surface="sharp">
|
|
301
|
+
<ThemeDemo title="Dark + Sharp" />
|
|
302
|
+
</ThemeProvider>
|
|
303
|
+
),
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Civic color + Soft surface - rounded, friendly civic theme.
|
|
308
|
+
*/
|
|
309
|
+
export const CivicSoft: Story = {
|
|
310
|
+
render: () => (
|
|
311
|
+
<ThemeProvider color="civic" surface="soft">
|
|
312
|
+
<ThemeDemo title="Civic + Soft" />
|
|
313
|
+
</ThemeProvider>
|
|
314
|
+
),
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Default theme - no props needed, uses base for both.
|
|
319
|
+
*/
|
|
320
|
+
export const Default: Story = {
|
|
321
|
+
render: () => (
|
|
322
|
+
<ThemeProvider>
|
|
323
|
+
<ThemeDemo title="Default (Base + Base)" />
|
|
324
|
+
</ThemeProvider>
|
|
325
|
+
),
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
// =============================================================================
|
|
329
|
+
// Interactive Playground
|
|
330
|
+
// =============================================================================
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Interactive playground - use controls to select any combination of themes.
|
|
334
|
+
*/
|
|
335
|
+
export const Playground: Story = {
|
|
336
|
+
args: {
|
|
337
|
+
color: "base",
|
|
338
|
+
surface: "base",
|
|
339
|
+
},
|
|
340
|
+
argTypes: {
|
|
341
|
+
color: {
|
|
342
|
+
control: "select",
|
|
343
|
+
options: ["base", "dark", "institution", "civic"],
|
|
344
|
+
description: "Color theme",
|
|
345
|
+
},
|
|
346
|
+
surface: {
|
|
347
|
+
control: "select",
|
|
348
|
+
options: ["base", "sharp", "framed", "soft"],
|
|
349
|
+
description: "Surface theme",
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
render: (args) => (
|
|
353
|
+
<ThemeProvider color={args.color} surface={args.surface}>
|
|
354
|
+
<ThemeDemo title={`${args.color} + ${args.surface}`} />
|
|
355
|
+
</ThemeProvider>
|
|
356
|
+
),
|
|
357
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import type { ComponentProps } from "react";
|
|
3
|
+
import {
|
|
4
|
+
ColorTokens,
|
|
5
|
+
ResponsiveTypography,
|
|
6
|
+
SemanticSpacingTokens,
|
|
7
|
+
SpacingTokens,
|
|
8
|
+
TokenShowcase,
|
|
9
|
+
TypographyTokens,
|
|
10
|
+
} from "./TokenShowcase";
|
|
11
|
+
|
|
12
|
+
const meta = {
|
|
13
|
+
title: "Design System/Tokens",
|
|
14
|
+
component: TokenShowcase,
|
|
15
|
+
parameters: {
|
|
16
|
+
layout: "fullscreen",
|
|
17
|
+
docs: {
|
|
18
|
+
description: {
|
|
19
|
+
component:
|
|
20
|
+
"Design tokens from the design system. These tokens provide a consistent foundation for colors, spacing, and typography across the application.",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
tags: ["autodocs"],
|
|
25
|
+
} satisfies Meta<ComponentProps<typeof TokenShowcase>>;
|
|
26
|
+
|
|
27
|
+
export default meta;
|
|
28
|
+
type Story = StoryObj<typeof meta>;
|
|
29
|
+
|
|
30
|
+
export const AllTokens: Story = {};
|
|
31
|
+
|
|
32
|
+
export const Colors: Story = {
|
|
33
|
+
render: () => (
|
|
34
|
+
<div className="p-8">
|
|
35
|
+
<ColorTokens />
|
|
36
|
+
</div>
|
|
37
|
+
),
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const Spacing: Story = {
|
|
41
|
+
render: () => (
|
|
42
|
+
<div className="p-8 min-h-screen">
|
|
43
|
+
<div className="max-w-4xl mx-auto">
|
|
44
|
+
<SpacingTokens />
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
),
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const Typography: Story = {
|
|
51
|
+
render: () => (
|
|
52
|
+
<div className="p-8 min-h-screen">
|
|
53
|
+
<div className="max-w-6xl mx-auto">
|
|
54
|
+
<TypographyTokens />
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
),
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const SemanticSpacing: Story = {
|
|
61
|
+
render: () => (
|
|
62
|
+
<div className="p-8 min-h-screen">
|
|
63
|
+
<div className="max-w-4xl mx-auto">
|
|
64
|
+
<SemanticSpacingTokens />
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
),
|
|
68
|
+
parameters: {
|
|
69
|
+
docs: {
|
|
70
|
+
description: {
|
|
71
|
+
story:
|
|
72
|
+
"Purpose-driven spacing tokens for components (buttons, cards, forms), layouts (hero, sections, containers, grids), and content stacks (vertical rhythm between elements).",
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const Breakpoints: Story = {
|
|
79
|
+
render: () => (
|
|
80
|
+
<div className="p-8">
|
|
81
|
+
<ResponsiveTypography />
|
|
82
|
+
</div>
|
|
83
|
+
),
|
|
84
|
+
parameters: {
|
|
85
|
+
docs: {
|
|
86
|
+
description: {
|
|
87
|
+
story:
|
|
88
|
+
"Typography that adapts across breakpoints. Use the viewport toolbar to switch between sm (320px), md (768px), and lg (1440px).",
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
};
|