@nationaldesignstudio/react 0.2.0 → 0.5.0

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.
Files changed (97) hide show
  1. package/dist/component-registry.md +1310 -127
  2. package/dist/components/atoms/background/background.d.ts +13 -27
  3. package/dist/components/atoms/button/button.d.ts +64 -72
  4. package/dist/components/atoms/button/button.figma.d.ts +1 -0
  5. package/dist/components/atoms/button/icon-button.d.ts +62 -110
  6. package/dist/components/atoms/input/input-group.d.ts +278 -0
  7. package/dist/components/atoms/input/input.d.ts +121 -0
  8. package/dist/components/atoms/popover/popover.d.ts +195 -0
  9. package/dist/components/atoms/select/select.d.ts +131 -0
  10. package/dist/components/atoms/tooltip/tooltip.d.ts +161 -0
  11. package/dist/components/organisms/card/card.d.ts +3 -3
  12. package/dist/components/sections/hero/hero.d.ts +2 -2
  13. package/dist/components/sections/prose/prose.d.ts +3 -3
  14. package/dist/components/sections/river/river.d.ts +1 -1
  15. package/dist/components/sections/tout/tout.d.ts +4 -4
  16. package/dist/components/shared/floating-arrow.d.ts +34 -0
  17. package/dist/index.d.ts +12 -0
  18. package/dist/index.js +13935 -7622
  19. package/dist/index.js.map +1 -1
  20. package/dist/lib/form-control.d.ts +106 -0
  21. package/dist/tokens.css +4725 -19065
  22. package/package.json +2 -1
  23. package/src/components/atoms/accordion/accordion.stories.tsx +1 -1
  24. package/src/components/atoms/accordion/accordion.tsx +2 -2
  25. package/src/components/atoms/background/background.tsx +71 -109
  26. package/src/components/atoms/button/button.figma.tsx +37 -0
  27. package/src/components/atoms/button/button.stories.tsx +253 -115
  28. package/src/components/atoms/button/button.test.tsx +289 -5
  29. package/src/components/atoms/button/button.tsx +40 -101
  30. package/src/components/atoms/button/button.visual.test.tsx +28 -32
  31. package/src/components/atoms/button/icon-button.stories.tsx +44 -101
  32. package/src/components/atoms/button/icon-button.test.tsx +26 -94
  33. package/src/components/atoms/button/icon-button.tsx +81 -224
  34. package/src/components/atoms/input/index.ts +17 -0
  35. package/src/components/atoms/input/input-group.stories.tsx +646 -0
  36. package/src/components/atoms/input/input-group.test.tsx +362 -0
  37. package/src/components/atoms/input/input-group.tsx +409 -0
  38. package/src/components/atoms/input/input.stories.tsx +228 -0
  39. package/src/components/atoms/input/input.test.tsx +167 -0
  40. package/src/components/atoms/input/input.tsx +104 -0
  41. package/src/components/atoms/pager-control/pager-control.stories.tsx +6 -8
  42. package/src/components/atoms/pager-control/pager-control.tsx +12 -12
  43. package/src/components/atoms/popover/index.ts +30 -0
  44. package/src/components/atoms/popover/popover.stories.tsx +531 -0
  45. package/src/components/atoms/popover/popover.test.tsx +486 -0
  46. package/src/components/atoms/popover/popover.tsx +488 -0
  47. package/src/components/atoms/select/index.ts +18 -0
  48. package/src/components/atoms/select/select.stories.tsx +455 -0
  49. package/src/components/atoms/select/select.tsx +324 -0
  50. package/src/components/atoms/tooltip/index.ts +24 -0
  51. package/src/components/atoms/tooltip/tooltip.stories.tsx +348 -0
  52. package/src/components/atoms/tooltip/tooltip.test.tsx +363 -0
  53. package/src/components/atoms/tooltip/tooltip.tsx +347 -0
  54. package/src/components/dev-tools/dev-toolbar/dev-toolbar.stories.tsx +8 -17
  55. package/src/components/dev-tools/dev-toolbar/dev-toolbar.tsx +3 -3
  56. package/src/components/foundation/typography/typography.stories.tsx +401 -0
  57. package/src/components/organisms/card/card.stories.tsx +19 -19
  58. package/src/components/organisms/card/card.test.tsx +1 -1
  59. package/src/components/organisms/card/card.tsx +3 -3
  60. package/src/components/organisms/card/card.visual.test.tsx +11 -11
  61. package/src/components/organisms/navbar/navbar.tsx +2 -2
  62. package/src/components/organisms/navbar/navbar.visual.test.tsx +2 -2
  63. package/src/components/organisms/us-gov-banner/us-gov-banner.tsx +2 -2
  64. package/src/components/sections/banner/banner.stories.tsx +1 -5
  65. package/src/components/sections/banner/banner.test.tsx +2 -2
  66. package/src/components/sections/banner/banner.tsx +6 -6
  67. package/src/components/sections/card-grid/card-grid.tsx +5 -5
  68. package/src/components/sections/faq-section/faq-section.tsx +2 -2
  69. package/src/components/sections/hero/hero.stories.tsx +7 -7
  70. package/src/components/sections/hero/hero.test.tsx +5 -5
  71. package/src/components/sections/hero/hero.tsx +10 -11
  72. package/src/components/sections/prose/prose.test.tsx +2 -2
  73. package/src/components/sections/prose/prose.tsx +6 -7
  74. package/src/components/sections/river/river.stories.tsx +8 -8
  75. package/src/components/sections/river/river.test.tsx +4 -4
  76. package/src/components/sections/river/river.tsx +8 -16
  77. package/src/components/sections/tout/tout.stories.tsx +7 -31
  78. package/src/components/sections/tout/tout.test.tsx +1 -1
  79. package/src/components/sections/tout/tout.tsx +11 -11
  80. package/src/components/sections/two-column-section/two-column-section.tsx +7 -9
  81. package/src/components/shared/floating-arrow.tsx +78 -0
  82. package/src/components/shared/index.ts +5 -0
  83. package/src/index.ts +98 -0
  84. package/src/lib/form-control.ts +71 -0
  85. package/src/stories/grid-system.stories.tsx +309 -0
  86. package/src/stories/{Introduction.mdx → introduction.mdx} +29 -15
  87. package/src/stories/{ThemeProvider.stories.tsx → theme-provider.stories.tsx} +8 -22
  88. package/src/stories/{TokenShowcase.stories.tsx → token-showcase.stories.tsx} +1 -20
  89. package/src/stories/token-showcase.tsx +777 -0
  90. package/src/styles.css +3 -0
  91. package/src/tests/token-resolution.test.tsx +298 -0
  92. package/src/theme/hooks.ts +1 -1
  93. package/src/theme/index.ts +1 -1
  94. package/src/theme/theme-provider.test.tsx +270 -0
  95. package/src/theme/{ThemeProvider.tsx → theme-provider.tsx} +18 -2
  96. package/src/stories/GridSystem.stories.tsx +0 -84
  97. package/src/stories/TokenShowcase.tsx +0 -1429
@@ -24,7 +24,7 @@ describe("Card Visual Regression", () => {
24
24
  <CardContent>
25
25
  <CardBody>
26
26
  <CardEyebrow>Optional Eyebrow</CardEyebrow>
27
- <div className="flex flex-col gap-[6px]">
27
+ <div className="flex flex-col gap-6">
28
28
  <CardTitle>Card Title</CardTitle>
29
29
  <CardDescription>
30
30
  Use cards when citizens need to scan items at a glance.
@@ -32,10 +32,10 @@ describe("Card Visual Regression", () => {
32
32
  </div>
33
33
  </CardBody>
34
34
  <CardActions>
35
- <Button size="default" variant="charcoal">
35
+ <Button size="md" variant="primary">
36
36
  Primary
37
37
  </Button>
38
- <Button size="default" variant="charcoalOutline">
38
+ <Button size="md" variant="primary-outline">
39
39
  Secondary
40
40
  </Button>
41
41
  </CardActions>
@@ -59,7 +59,7 @@ describe("Card Visual Regression", () => {
59
59
  <CardContent>
60
60
  <CardBody>
61
61
  <CardEyebrow>Eyebrow</CardEyebrow>
62
- <div className="flex flex-col gap-[9px]">
62
+ <div className="flex flex-col gap-8">
63
63
  <CardTitle>
64
64
  Cards can support multi line headings easily.
65
65
  </CardTitle>
@@ -69,10 +69,10 @@ describe("Card Visual Regression", () => {
69
69
  </div>
70
70
  </CardBody>
71
71
  <CardActions>
72
- <Button size="sm" variant="charcoal">
72
+ <Button size="sm" variant="primary">
73
73
  Primary
74
74
  </Button>
75
- <Button size="sm" variant="charcoalOutline">
75
+ <Button size="sm" variant="primary-outline">
76
76
  Secondary
77
77
  </Button>
78
78
  </CardActions>
@@ -93,7 +93,7 @@ describe("Card Visual Regression", () => {
93
93
  <CardContent>
94
94
  <CardBody>
95
95
  <CardEyebrow>Category</CardEyebrow>
96
- <div className="flex flex-col gap-[6px]">
96
+ <div className="flex flex-col gap-6">
97
97
  <CardTitle>Card Without Image</CardTitle>
98
98
  <CardDescription>
99
99
  Cards can be used without images for text-focused content.
@@ -101,7 +101,7 @@ describe("Card Visual Regression", () => {
101
101
  </div>
102
102
  </CardBody>
103
103
  <CardActions>
104
- <Button size="default" variant="charcoal">
104
+ <Button size="md" variant="primary">
105
105
  Learn More
106
106
  </Button>
107
107
  </CardActions>
@@ -124,7 +124,7 @@ describe("Card Visual Regression", () => {
124
124
  <CardImage />
125
125
  <CardContent>
126
126
  <CardBody>
127
- <div className="flex flex-col gap-[6px]">
127
+ <div className="flex flex-col gap-6">
128
128
  <CardTitle>Card Title</CardTitle>
129
129
  <CardDescription>
130
130
  The eyebrow is optional and can be omitted when not needed.
@@ -132,7 +132,7 @@ describe("Card Visual Regression", () => {
132
132
  </div>
133
133
  </CardBody>
134
134
  <CardActions>
135
- <Button size="default" variant="charcoal">
135
+ <Button size="md" variant="primary">
136
136
  Primary
137
137
  </Button>
138
138
  </CardActions>
@@ -156,7 +156,7 @@ describe("Card Visual Regression", () => {
156
156
  <CardContent>
157
157
  <CardBody>
158
158
  <CardEyebrow>Information</CardEyebrow>
159
- <div className="flex flex-col gap-[6px]">
159
+ <div className="flex flex-col gap-6">
160
160
  <CardTitle>Informational Card</CardTitle>
161
161
  <CardDescription>
162
162
  Cards without actions can be used for purely informational
@@ -138,7 +138,7 @@ const NavbarLink = React.forwardRef<HTMLAnchorElement, NavbarLinkProps>(
138
138
  <Comp
139
139
  ref={ref}
140
140
  className={cn(
141
- "typography-brand-medium-link-small text-gray-900 transition-colors hover:text-gray-700",
141
+ "typography-body-small font-medium text-gray-900 transition-colors hover:text-gray-700",
142
142
  active && "text-gray-1100",
143
143
  className,
144
144
  )}
@@ -301,7 +301,7 @@ const NavbarMobileMenuLink = React.forwardRef<
301
301
  <Comp
302
302
  ref={ref}
303
303
  className={cn(
304
- "typography-brand-medium-link-medium text-gray-900 transition-colors hover:text-gray-700",
304
+ "typography-body-medium font-medium text-gray-900 transition-colors hover:text-gray-700",
305
305
  "py-spacing-component-navbar-padding-y-mobile",
306
306
  active && "text-gray-1100",
307
307
  className,
@@ -26,7 +26,7 @@ describe("Navbar Visual Regression", () => {
26
26
  <NavbarLink href="#">Contact</NavbarLink>
27
27
  </NavbarLinks>
28
28
  <NavbarActions>
29
- <Button size="sm" variant="charcoal">
29
+ <Button size="sm" variant="primary">
30
30
  Sign In
31
31
  </Button>
32
32
  </NavbarActions>
@@ -55,7 +55,7 @@ describe("Navbar Visual Regression", () => {
55
55
  <NavbarLink href="#">Contact</NavbarLink>
56
56
  </NavbarLinks>
57
57
  <NavbarActions>
58
- <Button size="sm" variant="charcoal">
58
+ <Button size="sm" variant="primary">
59
59
  Sign In
60
60
  </Button>
61
61
  </NavbarActions>
@@ -3,8 +3,8 @@ import { tv, type VariantProps } from "tailwind-variants";
3
3
 
4
4
  const usGovBannerVariants = tv({
5
5
  slots: {
6
- root: "flex w-full items-center justify-center py-spacing-12",
7
- content: "flex items-center gap-spacing-8",
6
+ root: "flex w-full items-center justify-center py-12",
7
+ content: "flex items-center gap-8",
8
8
  text: "text-[11px] leading-[13px] tracking-[0.17px]",
9
9
  },
10
10
  variants: {
@@ -143,11 +143,7 @@ export const CustomBackground: Story = {
143
143
  <Banner
144
144
  heading="Custom Styled Banner"
145
145
  description="This banner has a custom background color applied via className."
146
- action={
147
- <Button variant="outline" colorScheme="light">
148
- Action
149
- </Button>
150
- }
146
+ action={<Button variant="secondary-outline">Action</Button>}
151
147
  className="bg-gray-1000 text-gray-50 [&_h2]:text-gray-50 [&_p]:text-gray-200"
152
148
  />
153
149
  ),
@@ -156,8 +156,8 @@ describe("Banner", () => {
156
156
 
157
157
  const banner = page.getByTestId("banner");
158
158
  // Mobile padding
159
- await expect.element(banner).toHaveClass(/px-spacing-20/);
160
- await expect.element(banner).toHaveClass(/py-spacing-32/);
159
+ await expect.element(banner).toHaveClass(/px-20/);
160
+ await expect.element(banner).toHaveClass(/py-32/);
161
161
  });
162
162
  });
163
163
 
@@ -21,9 +21,9 @@ const bannerVariants = tv({
21
21
  "col-full",
22
22
  // Responsive padding: mobile -> tablet -> desktop
23
23
  // Uses primitive spacing tokens
24
- "px-spacing-20 py-spacing-32",
25
- "md:p-spacing-56",
26
- "lg:px-spacing-72 lg:pb-spacing-72 lg:pt-0",
24
+ "px-20 py-32",
25
+ "md:p-56",
26
+ "lg:px-72 lg:pb-72 lg:pt-0",
27
27
  ],
28
28
  variants: {
29
29
  colorScheme: {
@@ -95,12 +95,12 @@ const Banner = React.forwardRef<HTMLElement, BannerProps>(
95
95
  <div
96
96
  className={cn(
97
97
  // Uses primitive spacing tokens
98
- "flex flex-col md:flex-row gap-spacing-20 items-start md:items-center md:justify-between",
99
- colorScheme === "dark" && "border-t border-gray-700 py-spacing-36",
98
+ "flex flex-col md:flex-row gap-20 items-start md:items-center md:justify-between",
99
+ colorScheme === "dark" && "border-t border-gray-700 py-36",
100
100
  )}
101
101
  >
102
102
  {/* Copy section */}
103
- <div className="flex flex-col gap-spacing-6 items-start">
103
+ <div className="flex flex-col gap-6 items-start">
104
104
  <h2
105
105
  className={cn(
106
106
  "typography-subheading-small",
@@ -16,9 +16,9 @@ const cardGridVariants = tv({
16
16
  base: [
17
17
  "grid-container",
18
18
  // Small (mobile): 72px y padding
19
- "py-spacing-72",
19
+ "py-72",
20
20
  // Large (desktop): 128px y padding
21
- "lg:py-spacing-128",
21
+ "lg:py-128",
22
22
  ],
23
23
  variants: {
24
24
  variant: {
@@ -83,9 +83,9 @@ const CardGrid = React.forwardRef<HTMLElement, CardGridProps>(
83
83
  <h2
84
84
  className={cn(
85
85
  "col-full",
86
- "typography-headline-small text-gray-900",
86
+ "typography-h4 text-gray-900",
87
87
  // Gap after title: mobile default, md: 56px, lg: 64px
88
- "mb-spacing-36 md:mb-spacing-56 lg:mb-spacing-64",
88
+ "mb-36 md:mb-56 lg:mb-64",
89
89
  )}
90
90
  >
91
91
  {title}
@@ -96,7 +96,7 @@ const CardGrid = React.forwardRef<HTMLElement, CardGridProps>(
96
96
  className={cn(
97
97
  "col-full",
98
98
  // Mobile: single column
99
- "grid grid-cols-1 gap-spacing-20",
99
+ "grid grid-cols-1 gap-20",
100
100
  // Tablet: 2 columns
101
101
  "md:grid-cols-2",
102
102
  // Desktop: 3 columns for variant A, 2 columns for variant B
@@ -66,9 +66,9 @@ const FaqSection = React.forwardRef<HTMLElement, FaqSectionProps>(
66
66
  title={title}
67
67
  className={cn(
68
68
  // Override title typography to be larger
69
- "[&_h2]:typography-subheading-large",
69
+ "[&_h2]:typography-h4",
70
70
  // Accordion typography overrides
71
- "[&_button]:typography-body-large [&_button]:md:typography-subheading-small",
71
+ "[&_button]:typography-body-large [&_button]:md:typography-h5",
72
72
  "[&_[data-accordion-panel]]:typography-body-medium [&_[data-accordion-panel]]:md:typography-body-large",
73
73
  className,
74
74
  )}
@@ -159,7 +159,7 @@ export const WithCloudflareStream: Story = {
159
159
  * Mock banner component for story demonstration
160
160
  */
161
161
  const MockBanner = () => (
162
- <div className="bg-gray-1200 px-spacing-16 py-spacing-8 text-center text-14 text-text-inverted">
162
+ <div className="bg-gray-1200 px-16 py-8 text-center text-14 text-text-inverted">
163
163
  An official website of the United States government
164
164
  </div>
165
165
  );
@@ -168,10 +168,10 @@ const MockBanner = () => (
168
168
  * Mock navigation component for story demonstration
169
169
  */
170
170
  const MockNavigation = () => (
171
- <nav className="flex items-center justify-between px-spacing-56 py-spacing-16">
172
- <div className="flex items-center gap-spacing-24">
171
+ <nav className="flex items-center justify-between px-56 py-16">
172
+ <div className="flex items-center gap-24">
173
173
  <div className="size-48 rounded-full bg-gray-50" />
174
- <div className="flex gap-spacing-24 text-14 text-text-inverted">
174
+ <div className="flex gap-24 text-14 text-text-inverted">
175
175
  <span className="cursor-pointer hover:opacity-80">Link 1</span>
176
176
  <span className="cursor-pointer hover:opacity-80">Link 2</span>
177
177
  </div>
@@ -199,7 +199,7 @@ export const WithTopSlot: Story = {
199
199
  */
200
200
  export const WithRoundedCorners: Story = {
201
201
  render: () => (
202
- <div className="bg-bg-page p-spacing-32">
202
+ <div className="bg-bg-page p-32">
203
203
  <Hero
204
204
  variant="A1"
205
205
  title="Rounded Corners"
@@ -234,7 +234,7 @@ export const WithTopAndRoundedCorners: Story = {
234
234
  </>
235
235
  }
236
236
  >
237
- <p className="mt-spacing-16 max-w-[560px] text-20 text-text-inverted">
237
+ <p className="mt-16 max-w-[560px] text-20 text-text-inverted">
238
238
  A subtitle or description can be added as children
239
239
  </p>
240
240
  </Hero>
@@ -261,7 +261,7 @@ export const UsingSubComponents: Story = {
261
261
  <h1 className="text-64 font-medium text-text-inverted lg:text-128">
262
262
  Custom Layout
263
263
  </h1>
264
- <p className="mt-spacing-16 text-20 text-text-inverted">
264
+ <p className="mt-16 text-20 text-text-inverted">
265
265
  Using HeroHeader and HeroContent sub-components
266
266
  </p>
267
267
  </HeroContent>
@@ -67,8 +67,8 @@ describe("Hero", () => {
67
67
  render(<Hero title="Default" data-testid="hero" />);
68
68
 
69
69
  const hero = page.getByTestId("hero");
70
- // Uses semantic token bg-bg-overlay for default background
71
- await expect.element(hero).toHaveClass(/bg-bg-overlay/);
70
+ // Uses semantic token bg-bg-page for default dark colorScheme
71
+ await expect.element(hero).toHaveClass(/bg-bg-page/);
72
72
  });
73
73
 
74
74
  test("applies minimum height for viewport coverage", async () => {
@@ -115,7 +115,7 @@ describe("Hero", () => {
115
115
  render(<Hero title="A1 Hero" variant="A1" data-testid="hero" />);
116
116
 
117
117
  const hero = page.getByTestId("hero");
118
- await expect.element(hero).toHaveClass(/bg-bg-overlay/);
118
+ await expect.element(hero).toHaveClass(/bg-bg-page/);
119
119
  await expect.element(hero).toHaveClass(/min-h-\[80vh\]/);
120
120
  });
121
121
 
@@ -123,7 +123,7 @@ describe("Hero", () => {
123
123
  render(<Hero title="A2 Hero" variant="A2" data-testid="hero" />);
124
124
 
125
125
  const hero = page.getByTestId("hero");
126
- await expect.element(hero).toHaveClass(/bg-bg-overlay/);
126
+ await expect.element(hero).toHaveClass(/bg-bg-page/);
127
127
  await expect.element(hero).toHaveClass(/min-h-\[80vh\]/);
128
128
  });
129
129
 
@@ -131,7 +131,7 @@ describe("Hero", () => {
131
131
  render(<Hero title="A3 Hero" variant="A3" data-testid="hero" />);
132
132
 
133
133
  const hero = page.getByTestId("hero");
134
- await expect.element(hero).toHaveClass(/bg-bg-overlay/);
134
+ await expect.element(hero).toHaveClass(/bg-bg-page/);
135
135
  await expect.element(hero).toHaveClass(/min-h-\[80vh\]/);
136
136
  });
137
137
  });
@@ -18,8 +18,7 @@ export {
18
18
  type BackgroundVideoProps as HeroBackgroundVideoProps,
19
19
  } from "@/components/atoms/background";
20
20
 
21
- const DEFAULT_TITLE_TYPOGRAPHY =
22
- "text-64 leading-64 tracking-64 md:text-128 md:leading-128 md:tracking-128 lg:text-192 lg:leading-192 lg:tracking-192 font-medium";
21
+ const DEFAULT_TITLE_TYPOGRAPHY = "typography-h1-display";
23
22
 
24
23
  const heroVariants = tv({
25
24
  slots: {
@@ -27,8 +26,8 @@ const heroVariants = tv({
27
26
  top: "relative z-10 w-full",
28
27
  content: [
29
28
  "relative z-10 mx-auto flex w-full max-w-screen-xl flex-1 flex-col",
30
- "p-spacing-20",
31
- "md:p-spacing-56",
29
+ "p-20",
30
+ "md:p-56",
32
31
  ],
33
32
  title: DEFAULT_TITLE_TYPOGRAPHY,
34
33
  },
@@ -36,15 +35,15 @@ const heroVariants = tv({
36
35
  variant: {
37
36
  A1: {
38
37
  root: "min-h-[80vh]",
39
- content: ["justify-end", "lg:p-spacing-72"],
38
+ content: ["justify-end", "lg:p-72"],
40
39
  },
41
40
  A2: {
42
41
  root: "min-h-[80vh]",
43
- content: ["justify-start", "lg:p-spacing-64"],
42
+ content: ["justify-start", "lg:p-64"],
44
43
  },
45
44
  A3: {
46
45
  root: "min-h-[80vh]",
47
- content: ["items-center justify-center", "lg:p-spacing-64"],
46
+ content: ["items-center justify-center", "lg:p-64"],
48
47
  },
49
48
  },
50
49
  colorScheme: {
@@ -80,9 +79,9 @@ const heroHeaderVariants = tv({
80
79
  const heroContentVariants = tv({
81
80
  base: [
82
81
  "relative z-10 mx-auto flex w-full max-w-screen-xl flex-1 flex-col",
83
- "p-spacing-20",
84
- "md:p-spacing-56",
85
- "lg:p-spacing-72",
82
+ "p-20",
83
+ "md:p-56",
84
+ "lg:p-72",
86
85
  ],
87
86
  });
88
87
 
@@ -136,7 +135,7 @@ export interface HeroProps
136
135
  title?: string;
137
136
  /**
138
137
  * Custom typography class for the title using primitive tokens.
139
- * Default: "text-64 leading-64 tracking-64 md:text-128 md:leading-128 md:tracking-128 lg:text-192 lg:leading-192 lg:tracking-192"
138
+ * Default: "typography-h1-display"
140
139
  */
141
140
  titleClassName?: string;
142
141
  /**
@@ -131,7 +131,7 @@ describe("Prose", () => {
131
131
  );
132
132
 
133
133
  const heading = page.getByRole("heading", { name: "H2 Test" });
134
- await expect.element(heading).toHaveClass(/typography-headline-medium/);
134
+ await expect.element(heading).toHaveClass(/typography-h3/);
135
135
  });
136
136
 
137
137
  test("h3 heading has correct typography class", async () => {
@@ -144,7 +144,7 @@ describe("Prose", () => {
144
144
  );
145
145
 
146
146
  const heading = page.getByRole("heading", { name: "H3 Test" });
147
- await expect.element(heading).toHaveClass(/typography-headline-small/);
147
+ await expect.element(heading).toHaveClass(/typography-h4/);
148
148
  });
149
149
  });
150
150
 
@@ -23,7 +23,7 @@ const Prose = React.forwardRef<HTMLDivElement, ProseProps>(
23
23
  className={cn(
24
24
  "flex w-full max-w-[700px] flex-col overflow-hidden",
25
25
  // Responsive gap between sections
26
- "gap-spacing-56 md:gap-spacing-72 xl:gap-spacing-96",
26
+ "gap-56 md:gap-72 xl:gap-96",
27
27
  className,
28
28
  )}
29
29
  {...props}
@@ -52,15 +52,14 @@ export interface ProseSectionProps extends React.HTMLAttributes<HTMLElement> {
52
52
  * A section within Prose content, containing a heading and body text.
53
53
  *
54
54
  * Responsive typography:
55
- * - h2: Uses typography-headline-medium (42px mobile → 56px tablet → 72px desktop)
56
- * - h3: Uses typography-headline-small (32px mobile → 42px tablet → 56px desktop)
57
- * - Body: Uses typography-body-medium (16px mobile/tablet → 18px desktop)
55
+ * - h2: Uses typography-h3
56
+ * - h3: Uses typography-h4
57
+ * - Body: Uses typography-body-medium
58
58
  */
59
59
  const ProseSection = React.forwardRef<HTMLElement, ProseSectionProps>(
60
60
  ({ className, heading, as = "h2", children, ...props }, ref) => {
61
61
  const Heading = as;
62
- const headingClass =
63
- as === "h2" ? "typography-headline-medium" : "typography-headline-small";
62
+ const headingClass = as === "h2" ? "typography-h3" : "typography-h4";
64
63
 
65
64
  return (
66
65
  <section
@@ -68,7 +67,7 @@ const ProseSection = React.forwardRef<HTMLElement, ProseSectionProps>(
68
67
  className={cn(
69
68
  "flex w-full flex-col",
70
69
  // Responsive gap between heading and body
71
- "gap-spacing-24 md:gap-spacing-40",
70
+ "gap-24 md:gap-40",
72
71
  className,
73
72
  )}
74
73
  {...props}
@@ -51,7 +51,7 @@ Playground.args = {
51
51
  headline: "Feature Headline",
52
52
  body: "Use rivers to present content with supporting media. They work great for feature highlights, product showcases, and storytelling sections.",
53
53
  primaryAction: <Button>Primary Action</Button>,
54
- secondaryAction: <Button variant="charcoalOutline">Secondary</Button>,
54
+ secondaryAction: <Button variant="outline">Secondary</Button>,
55
55
  media: <PlaceholderImage />,
56
56
  };
57
57
 
@@ -69,7 +69,7 @@ export const VariantA: Story = {
69
69
  headline="Text Left, Media Right"
70
70
  body="Variant A places the text content on the left (9 columns) and media on the right (15 columns) on desktop viewports. On mobile and tablet, they stack vertically."
71
71
  primaryAction={<Button>Primary Action</Button>}
72
- secondaryAction={<Button variant="charcoalOutline">Secondary</Button>}
72
+ secondaryAction={<Button variant="outline">Secondary</Button>}
73
73
  media={<PlaceholderImage />}
74
74
  />
75
75
  ),
@@ -85,7 +85,7 @@ export const VariantB: Story = {
85
85
  headline="Media Left, Text Right"
86
86
  body="Variant B places the media on the left (15 columns) and text content on the right (9 columns) on desktop viewports. On mobile and tablet, they stack vertically with text first."
87
87
  primaryAction={<Button>Primary Action</Button>}
88
- secondaryAction={<Button variant="charcoalOutline">Secondary</Button>}
88
+ secondaryAction={<Button variant="outline">Secondary</Button>}
89
89
  media={<PlaceholderImage />}
90
90
  />
91
91
  ),
@@ -102,7 +102,7 @@ export const VariantADesktop: Story = {
102
102
  headline="Desktop View"
103
103
  body="On desktop (lg, 1440px), the content spans 9 columns and the media spans 15 columns in a horizontal layout."
104
104
  primaryAction={<Button>Primary</Button>}
105
- secondaryAction={<Button variant="charcoalOutline">Secondary</Button>}
105
+ secondaryAction={<Button variant="outline">Secondary</Button>}
106
106
  media={<PlaceholderImage />}
107
107
  />
108
108
  ),
@@ -118,7 +118,7 @@ export const VariantATablet: Story = {
118
118
  headline="Tablet View"
119
119
  body="On tablet (md, 768px), the content and media stack vertically with the text above the media."
120
120
  primaryAction={<Button>Primary</Button>}
121
- secondaryAction={<Button variant="charcoalOutline">Secondary</Button>}
121
+ secondaryAction={<Button variant="outline">Secondary</Button>}
122
122
  media={<PlaceholderImage />}
123
123
  />
124
124
  ),
@@ -135,7 +135,7 @@ export const VariantAMobile: Story = {
135
135
  body="On mobile (sm, 320px), content is stacked with smaller button sizing."
136
136
  primaryAction={<Button size="sm">Primary</Button>}
137
137
  secondaryAction={
138
- <Button size="sm" variant="charcoalOutline">
138
+ <Button size="sm" variant="outline">
139
139
  Secondary
140
140
  </Button>
141
141
  }
@@ -154,7 +154,7 @@ export const VariantBDesktop: Story = {
154
154
  headline="Desktop View - Reversed"
155
155
  body="Variant B reverses the layout, placing media on the left and content on the right."
156
156
  primaryAction={<Button>Primary</Button>}
157
- secondaryAction={<Button variant="charcoalOutline">Secondary</Button>}
157
+ secondaryAction={<Button variant="outline">Secondary</Button>}
158
158
  media={<PlaceholderImage />}
159
159
  />
160
160
  ),
@@ -224,7 +224,7 @@ export const WithImage: Story = {
224
224
  headline="Real World Example"
225
225
  body="Rivers work great with actual images, videos, or any media content. The media column is designed to accommodate various aspect ratios."
226
226
  primaryAction={<Button>Get Started</Button>}
227
- secondaryAction={<Button variant="charcoalOutline">Learn More</Button>}
227
+ secondaryAction={<Button variant="outline">Learn More</Button>}
228
228
  media={
229
229
  <img
230
230
  src="https://images.unsplash.com/photo-1551434678-e076c223a692?w=800&h=600&fit=crop"
@@ -177,9 +177,9 @@ describe("River", () => {
177
177
 
178
178
  const river = page.getByTestId("river");
179
179
  // Mobile padding
180
- await expect.element(river).toHaveClass(/px-spacing-20/);
181
- await expect.element(river).toHaveClass(/pt-spacing-72/);
182
- await expect.element(river).toHaveClass(/pb-spacing-20/);
180
+ await expect.element(river).toHaveClass(/px-20/);
181
+ await expect.element(river).toHaveClass(/pt-72/);
182
+ await expect.element(river).toHaveClass(/pb-20/);
183
183
  });
184
184
  });
185
185
 
@@ -246,7 +246,7 @@ describe("River", () => {
246
246
  );
247
247
 
248
248
  const headline = page.getByRole("heading", { level: 2 });
249
- await expect.element(headline).toHaveClass(/typography-headline-small/);
249
+ await expect.element(headline).toHaveClass(/typography-h4/);
250
250
  await expect.element(headline).toHaveClass(/text-gray-900/);
251
251
  });
252
252
 
@@ -16,11 +16,11 @@ const riverVariants = tv({
16
16
  base: [
17
17
  "col-full",
18
18
  // Small (mobile): 20px x, 72px top, 20px bottom
19
- "px-spacing-20 pt-spacing-72 pb-spacing-20",
19
+ "px-20 pt-72 pb-20",
20
20
  // Medium (tablet): 56px x, 96px y
21
- "md:px-spacing-56 md:py-spacing-96",
21
+ "md:px-56 md:py-96",
22
22
  // Large (desktop): 72px x, 128px y
23
- "lg:px-spacing-72 lg:py-spacing-128",
23
+ "lg:px-72 lg:py-128",
24
24
  ],
25
25
  variants: {
26
26
  variant: {
@@ -77,7 +77,7 @@ export interface RiverProps
77
77
  * headline="Feature Headline"
78
78
  * body="Description of the feature..."
79
79
  * primaryAction={<Button>Primary</Button>}
80
- * secondaryAction={<Button variant="charcoalOutline">Secondary</Button>}
80
+ * secondaryAction={<Button variant="outline">Secondary</Button>}
81
81
  * media={<img src="..." alt="Feature" />}
82
82
  * />
83
83
  * </div>
@@ -106,19 +106,14 @@ const River = React.forwardRef<HTMLElement, RiverProps>(
106
106
  )}
107
107
  >
108
108
  {/* Text content with 16px gap - uses primitive spacing tokens */}
109
- <div className="flex flex-col gap-spacing-16">
110
- <h2 className="typography-headline-small text-gray-900">
111
- {headline}
112
- </h2>
109
+ <div className="flex flex-col gap-16">
110
+ <h2 className="typography-h4 text-gray-900">{headline}</h2>
113
111
  <p className="typography-body-small text-gray-800">{body}</p>
114
112
  </div>
115
113
 
116
114
  {/* Buttons with 36px gap from text, responsive sizes - uses primitive spacing tokens */}
117
115
  <div
118
- className={cn(
119
- "flex flex-row gap-spacing-16 mt-spacing-36",
120
- "[&>*]:flex-shrink-0",
121
- )}
116
+ className={cn("flex flex-row gap-16 mt-36", "[&>*]:flex-shrink-0")}
122
117
  >
123
118
  {primaryAction}
124
119
  {secondaryAction}
@@ -147,10 +142,7 @@ const River = React.forwardRef<HTMLElement, RiverProps>(
147
142
  >
148
143
  {/* Inner grid container for 24-col layout - uses primitive spacing tokens */}
149
144
  <div
150
- className={cn(
151
- "grid grid-cols-1 gap-spacing-36",
152
- "lg:grid-cols-24 lg:gap-spacing-36",
153
- )}
145
+ className={cn("grid grid-cols-1 gap-36", "lg:grid-cols-24 lg:gap-36")}
154
146
  >
155
147
  {variant === "B" ? (
156
148
  <>