@nationaldesignstudio/react 0.5.2 → 0.5.4

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 (161) hide show
  1. package/package.json +10 -2
  2. package/src/components/organisms/navbar/navbar.tsx +8 -8
  3. package/src/App.css +0 -0
  4. package/src/App.tsx +0 -7
  5. package/src/assets/fonts/PPNeueMontreal-Variable.woff2 +0 -0
  6. package/src/assets/react.svg +0 -1
  7. package/src/components/atoms/accordion/accordion.stories.tsx +0 -228
  8. package/src/components/atoms/accordion/accordion.test.tsx +0 -231
  9. package/src/components/atoms/accordion/index.ts +0 -6
  10. package/src/components/atoms/background/background.test.tsx +0 -213
  11. package/src/components/atoms/background/index.ts +0 -22
  12. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-chromium-darwin.png +0 -0
  13. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-chromium-linux.png +0 -0
  14. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-chromium-darwin.png +0 -0
  15. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-chromium-linux.png +0 -0
  16. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-quiet-chromium-darwin.png +0 -0
  17. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-quiet-chromium-linux.png +0 -0
  18. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-disabled-chromium-darwin.png +0 -0
  19. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-disabled-chromium-linux.png +0 -0
  20. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-chromium-darwin.png +0 -0
  21. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-chromium-linux.png +0 -0
  22. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-chromium-darwin.png +0 -0
  23. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-chromium-linux.png +0 -0
  24. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-quiet-chromium-darwin.png +0 -0
  25. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-quiet-chromium-linux.png +0 -0
  26. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-large-chromium-darwin.png +0 -0
  27. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-large-chromium-linux.png +0 -0
  28. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-medium-chromium-darwin.png +0 -0
  29. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-medium-chromium-linux.png +0 -0
  30. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-small-chromium-darwin.png +0 -0
  31. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-small-chromium-linux.png +0 -0
  32. package/src/components/atoms/button/button.stories.tsx +0 -289
  33. package/src/components/atoms/button/button.test.tsx +0 -419
  34. package/src/components/atoms/button/button.visual.test.tsx +0 -98
  35. package/src/components/atoms/button/icon-button.stories.tsx +0 -260
  36. package/src/components/atoms/button/icon-button.test.tsx +0 -186
  37. package/src/components/atoms/button/index.ts +0 -6
  38. package/src/components/atoms/input/index.ts +0 -17
  39. package/src/components/atoms/input/input-group.stories.tsx +0 -646
  40. package/src/components/atoms/input/input-group.test.tsx +0 -362
  41. package/src/components/atoms/input/input.stories.tsx +0 -228
  42. package/src/components/atoms/input/input.test.tsx +0 -167
  43. package/src/components/atoms/ndstudio-footer/index.ts +0 -1
  44. package/src/components/atoms/pager-control/index.ts +0 -5
  45. package/src/components/atoms/pager-control/pager-control.stories.tsx +0 -207
  46. package/src/components/atoms/pager-control/pager-control.test.tsx +0 -130
  47. package/src/components/atoms/popover/index.ts +0 -30
  48. package/src/components/atoms/popover/popover.stories.tsx +0 -531
  49. package/src/components/atoms/popover/popover.test.tsx +0 -486
  50. package/src/components/atoms/select/index.ts +0 -18
  51. package/src/components/atoms/select/select.stories.tsx +0 -455
  52. package/src/components/atoms/tooltip/index.ts +0 -24
  53. package/src/components/atoms/tooltip/tooltip.stories.tsx +0 -348
  54. package/src/components/atoms/tooltip/tooltip.test.tsx +0 -363
  55. package/src/components/dev-tools/dev-toolbar/dev-toolbar.stories.tsx +0 -73
  56. package/src/components/dev-tools/dev-toolbar/index.ts +0 -1
  57. package/src/components/dev-tools/grid-overlay/index.ts +0 -1
  58. package/src/components/dev-tools/index.ts +0 -2
  59. package/src/components/foundation/typography/typography.stories.tsx +0 -401
  60. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-default-vertical-chromium-darwin.png +0 -0
  61. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-default-vertical-chromium-linux.png +0 -0
  62. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-horizontal-chromium-darwin.png +0 -0
  63. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-horizontal-chromium-linux.png +0 -0
  64. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-minimal-chromium-darwin.png +0 -0
  65. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-minimal-chromium-linux.png +0 -0
  66. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-actions-chromium-darwin.png +0 -0
  67. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-actions-chromium-linux.png +0 -0
  68. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-eyebrow-chromium-darwin.png +0 -0
  69. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-eyebrow-chromium-linux.png +0 -0
  70. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-image-chromium-darwin.png +0 -0
  71. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-image-chromium-linux.png +0 -0
  72. package/src/components/organisms/card/card.stories.tsx +0 -293
  73. package/src/components/organisms/card/card.test.tsx +0 -247
  74. package/src/components/organisms/card/card.visual.test.tsx +0 -197
  75. package/src/components/organisms/card/index.ts +0 -26
  76. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-active-link-chromium-darwin.png +0 -0
  77. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-active-link-chromium-linux.png +0 -0
  78. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-brand-only-chromium-darwin.png +0 -0
  79. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-brand-only-chromium-linux.png +0 -0
  80. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-default-chromium-darwin.png +0 -0
  81. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-default-chromium-linux.png +0 -0
  82. package/src/components/organisms/navbar/index.ts +0 -18
  83. package/src/components/organisms/navbar/navbar.stories.tsx +0 -313
  84. package/src/components/organisms/navbar/navbar.test.tsx +0 -190
  85. package/src/components/organisms/navbar/navbar.visual.test.tsx +0 -85
  86. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-icon-chromium-darwin.png +0 -0
  87. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-icon-chromium-linux.png +0 -0
  88. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-text-chromium-darwin.png +0 -0
  89. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-text-chromium-linux.png +0 -0
  90. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-default-chromium-darwin.png +0 -0
  91. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-default-chromium-linux.png +0 -0
  92. package/src/components/organisms/us-gov-banner/index.ts +0 -5
  93. package/src/components/organisms/us-gov-banner/us-gov-banner.stories.tsx +0 -35
  94. package/src/components/organisms/us-gov-banner/us-gov-banner.test.tsx +0 -107
  95. package/src/components/organisms/us-gov-banner/us-gov-banner.visual.test.tsx +0 -46
  96. package/src/components/sections/banner/banner.stories.tsx +0 -150
  97. package/src/components/sections/banner/banner.test.tsx +0 -185
  98. package/src/components/sections/banner/index.ts +0 -2
  99. package/src/components/sections/card-grid/card-grid.stories.tsx +0 -351
  100. package/src/components/sections/card-grid/index.ts +0 -1
  101. package/src/components/sections/faq-section/faq-section.stories.tsx +0 -453
  102. package/src/components/sections/faq-section/index.ts +0 -2
  103. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-desktop-chromium-darwin.png +0 -0
  104. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-desktop-chromium-linux.png +0 -0
  105. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-mobile-chromium-darwin.png +0 -0
  106. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-mobile-chromium-linux.png +0 -0
  107. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-tablet-chromium-darwin.png +0 -0
  108. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-tablet-chromium-linux.png +0 -0
  109. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-desktop-chromium-darwin.png +0 -0
  110. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-desktop-chromium-linux.png +0 -0
  111. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-mobile-chromium-darwin.png +0 -0
  112. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-mobile-chromium-linux.png +0 -0
  113. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-tablet-chromium-darwin.png +0 -0
  114. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-tablet-chromium-linux.png +0 -0
  115. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-desktop-chromium-darwin.png +0 -0
  116. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-desktop-chromium-linux.png +0 -0
  117. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-mobile-chromium-darwin.png +0 -0
  118. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-mobile-chromium-linux.png +0 -0
  119. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-tablet-chromium-darwin.png +0 -0
  120. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-tablet-chromium-linux.png +0 -0
  121. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-custom-class-chromium-darwin.png +0 -0
  122. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-custom-class-chromium-linux.png +0 -0
  123. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-default-chromium-linux.png +0 -0
  124. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-long-title-chromium-darwin.png +0 -0
  125. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-long-title-chromium-linux.png +0 -0
  126. package/src/components/sections/hero/hero.stories.tsx +0 -397
  127. package/src/components/sections/hero/hero.test.tsx +0 -138
  128. package/src/components/sections/hero/hero.visual.test.tsx +0 -140
  129. package/src/components/sections/hero/index.ts +0 -23
  130. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-h3-heading-chromium-darwin.png +0 -0
  131. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-h3-heading-chromium-linux.png +0 -0
  132. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-paragraphs-chromium-darwin.png +0 -0
  133. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-paragraphs-chromium-linux.png +0 -0
  134. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-sections-chromium-darwin.png +0 -0
  135. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-sections-chromium-linux.png +0 -0
  136. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-single-section-chromium-darwin.png +0 -0
  137. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-single-section-chromium-linux.png +0 -0
  138. package/src/components/sections/prose/index.ts +0 -6
  139. package/src/components/sections/prose/prose.stories.tsx +0 -144
  140. package/src/components/sections/prose/prose.test.tsx +0 -178
  141. package/src/components/sections/prose/prose.visual.test.tsx +0 -105
  142. package/src/components/sections/quote-block/index.ts +0 -5
  143. package/src/components/sections/river/index.ts +0 -1
  144. package/src/components/sections/river/river.stories.tsx +0 -237
  145. package/src/components/sections/river/river.test.tsx +0 -268
  146. package/src/components/sections/tout/index.ts +0 -1
  147. package/src/components/sections/tout/tout.stories.tsx +0 -171
  148. package/src/components/sections/tout/tout.test.tsx +0 -242
  149. package/src/components/sections/two-column-section/index.ts +0 -5
  150. package/src/components/sections/two-column-section/two-column-section.stories.tsx +0 -285
  151. package/src/components/shared/index.ts +0 -5
  152. package/src/index.ts +0 -293
  153. package/src/main.tsx +0 -13
  154. package/src/stories/grid-system.stories.tsx +0 -309
  155. package/src/stories/introduction.mdx +0 -128
  156. package/src/stories/theme-provider.stories.tsx +0 -349
  157. package/src/stories/token-showcase.stories.tsx +0 -73
  158. package/src/stories/token-showcase.tsx +0 -777
  159. package/src/styles.css +0 -14
  160. package/src/tests/token-resolution.test.tsx +0 -298
  161. package/src/theme/theme-provider.test.tsx +0 -270
@@ -1,268 +0,0 @@
1
- import { describe, expect, test } from "vitest";
2
- import { page } from "vitest/browser";
3
- import { render } from "vitest-browser-react";
4
- import { River } from "./river";
5
-
6
- const PlaceholderMedia = () => <div data-testid="media">Media</div>;
7
-
8
- describe("River", () => {
9
- describe("Accessibility", () => {
10
- test("renders as section landmark", async () => {
11
- render(
12
- <River
13
- headline="Test Headline"
14
- body="Test body"
15
- primaryAction={<button type="button">Action</button>}
16
- media={<PlaceholderMedia />}
17
- data-testid="river"
18
- />,
19
- );
20
-
21
- const river = page.getByTestId("river");
22
- await expect.element(river).toBeInTheDocument();
23
- });
24
-
25
- test("headline renders as h2", async () => {
26
- render(
27
- <River
28
- headline="River Headline"
29
- body="Test body"
30
- primaryAction={<button type="button">Action</button>}
31
- media={<PlaceholderMedia />}
32
- />,
33
- );
34
-
35
- await expect
36
- .element(
37
- page.getByRole("heading", { level: 2, name: "River Headline" }),
38
- )
39
- .toBeInTheDocument();
40
- });
41
-
42
- test("body text is accessible", async () => {
43
- render(
44
- <River
45
- headline="Test"
46
- body="Accessible body text"
47
- primaryAction={<button type="button">Action</button>}
48
- media={<PlaceholderMedia />}
49
- />,
50
- );
51
-
52
- await expect
53
- .element(page.getByText("Accessible body text"))
54
- .toBeInTheDocument();
55
- });
56
- });
57
-
58
- describe("Props", () => {
59
- test("renders with required props", async () => {
60
- render(
61
- <River
62
- headline="Required Headline"
63
- body="Required body"
64
- primaryAction={<button type="button">Primary</button>}
65
- media={<PlaceholderMedia />}
66
- />,
67
- );
68
-
69
- await expect
70
- .element(page.getByText("Required Headline"))
71
- .toBeInTheDocument();
72
- await expect.element(page.getByText("Required body")).toBeInTheDocument();
73
- await expect
74
- .element(page.getByRole("button", { name: "Primary" }))
75
- .toBeInTheDocument();
76
- await expect.element(page.getByTestId("media")).toBeInTheDocument();
77
- });
78
-
79
- test("renders secondary action when provided", async () => {
80
- render(
81
- <River
82
- headline="Test"
83
- body="Test"
84
- primaryAction={<button type="button">Primary</button>}
85
- secondaryAction={<button type="button">Secondary</button>}
86
- media={<PlaceholderMedia />}
87
- />,
88
- );
89
-
90
- await expect
91
- .element(page.getByRole("button", { name: "Primary" }))
92
- .toBeInTheDocument();
93
- await expect
94
- .element(page.getByRole("button", { name: "Secondary" }))
95
- .toBeInTheDocument();
96
- });
97
-
98
- test("does not render secondary action when not provided", async () => {
99
- render(
100
- <River
101
- headline="Test"
102
- body="Test"
103
- primaryAction={<button type="button">Primary</button>}
104
- media={<PlaceholderMedia />}
105
- />,
106
- );
107
-
108
- await expect
109
- .element(page.getByRole("button", { name: "Primary" }))
110
- .toBeInTheDocument();
111
- // Should only have one button
112
- const buttons = page.getByRole("button");
113
- await expect.element(buttons).toBeInTheDocument();
114
- });
115
-
116
- test("supports custom className", async () => {
117
- render(
118
- <River
119
- headline="Test"
120
- body="Test"
121
- primaryAction={<button type="button">Action</button>}
122
- media={<PlaceholderMedia />}
123
- className="custom-class"
124
- data-testid="river"
125
- />,
126
- );
127
-
128
- const river = page.getByTestId("river");
129
- await expect.element(river).toHaveClass(/custom-class/);
130
- });
131
-
132
- test("spreads additional props to section element", async () => {
133
- render(
134
- <River
135
- headline="Test"
136
- body="Test"
137
- primaryAction={<button type="button">Action</button>}
138
- media={<PlaceholderMedia />}
139
- data-testid="river"
140
- aria-label="River section"
141
- />,
142
- );
143
-
144
- const river = page.getByTestId("river");
145
- await expect
146
- .element(river)
147
- .toHaveAttribute("aria-label", "River section");
148
- });
149
- });
150
-
151
- describe("Styling", () => {
152
- test("applies col-full for grid alignment", async () => {
153
- render(
154
- <River
155
- headline="Test"
156
- body="Test"
157
- primaryAction={<button type="button">Action</button>}
158
- media={<PlaceholderMedia />}
159
- data-testid="river"
160
- />,
161
- );
162
-
163
- const river = page.getByTestId("river");
164
- await expect.element(river).toHaveClass(/col-full/);
165
- });
166
-
167
- test("applies responsive padding classes", async () => {
168
- render(
169
- <River
170
- headline="Test"
171
- body="Test"
172
- primaryAction={<button type="button">Action</button>}
173
- media={<PlaceholderMedia />}
174
- data-testid="river"
175
- />,
176
- );
177
-
178
- const river = page.getByTestId("river");
179
- // Mobile padding
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
- });
184
- });
185
-
186
- describe("Variants", () => {
187
- test("variant A is default", async () => {
188
- render(
189
- <River
190
- headline="Test"
191
- body="Test"
192
- primaryAction={<button type="button">Action</button>}
193
- media={<PlaceholderMedia />}
194
- data-testid="river"
195
- />,
196
- );
197
-
198
- const river = page.getByTestId("river");
199
- await expect.element(river).toBeInTheDocument();
200
- });
201
-
202
- test("variant A renders content before media", async () => {
203
- render(
204
- <River
205
- variant="A"
206
- headline="Test Headline"
207
- body="Test"
208
- primaryAction={<button type="button">Action</button>}
209
- media={<PlaceholderMedia />}
210
- data-testid="river"
211
- />,
212
- );
213
-
214
- // Both should be present
215
- await expect.element(page.getByText("Test Headline")).toBeInTheDocument();
216
- await expect.element(page.getByTestId("media")).toBeInTheDocument();
217
- });
218
-
219
- test("variant B renders media before content", async () => {
220
- render(
221
- <River
222
- variant="B"
223
- headline="Test Headline"
224
- body="Test"
225
- primaryAction={<button type="button">Action</button>}
226
- media={<PlaceholderMedia />}
227
- data-testid="river"
228
- />,
229
- );
230
-
231
- // Both should be present
232
- await expect.element(page.getByText("Test Headline")).toBeInTheDocument();
233
- await expect.element(page.getByTestId("media")).toBeInTheDocument();
234
- });
235
- });
236
-
237
- describe("Content", () => {
238
- test("headline has correct styling", async () => {
239
- render(
240
- <River
241
- headline="Styled Headline"
242
- body="Test"
243
- primaryAction={<button type="button">Action</button>}
244
- media={<PlaceholderMedia />}
245
- />,
246
- );
247
-
248
- const headline = page.getByRole("heading", { level: 2 });
249
- await expect.element(headline).toHaveClass(/typography-h4/);
250
- await expect.element(headline).toHaveClass(/text-gray-900/);
251
- });
252
-
253
- test("body has correct styling", async () => {
254
- render(
255
- <River
256
- headline="Test"
257
- body="Styled body text"
258
- primaryAction={<button type="button">Action</button>}
259
- media={<PlaceholderMedia />}
260
- />,
261
- );
262
-
263
- const body = page.getByText("Styled body text");
264
- await expect.element(body).toHaveClass(/typography-body-small/);
265
- await expect.element(body).toHaveClass(/text-gray-800/);
266
- });
267
- });
268
- });
@@ -1 +0,0 @@
1
- export { Tout, type ToutProps } from "./tout";
@@ -1,171 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/react-vite";
2
- import { Button } from "../../atoms/button";
3
- import { NdstudioFooter } from "../../atoms/ndstudio-footer";
4
- import { Tout } from ".";
5
-
6
- const meta: Meta<typeof Tout> = {
7
- title: "Sections/Tout",
8
- component: Tout,
9
- parameters: {
10
- layout: "fullscreen",
11
- },
12
- argTypes: {
13
- headline: {
14
- control: "text",
15
- description: "The headline text",
16
- },
17
- body: {
18
- control: "text",
19
- description: "The body text",
20
- },
21
- },
22
- } as Meta<typeof Tout>;
23
-
24
- export default meta;
25
- type Story = StoryObj<typeof Tout>;
26
-
27
- const PlaceholderBackground = () => (
28
- <div className="absolute inset-0 bg-gradient-to-br from-gray-300 to-gray-400" />
29
- );
30
-
31
- const ImageBackground = () => (
32
- <img
33
- src="https://images.unsplash.com/photo-1557804506-669a67965ba0?w=1600&h=900&fit=crop"
34
- alt=""
35
- className="absolute inset-0 w-full h-full object-cover"
36
- />
37
- );
38
-
39
- export const Playground: Story = {
40
- render: (args) => <Tout {...args} />,
41
- };
42
- Playground.args = {
43
- headline: "Brand-Large/Headline/Small",
44
- body: "A river pattern stacks content in a simple vertical flow: one clear heading, a short block of copy, then the next step. It's ideal for guiding citizens through a process or story, keeping focus moving straight down the page with minimal choices and well-timed calls to action.",
45
- primaryAction: <Button>Primary</Button>,
46
- secondaryAction: <Button variant="secondary-outline">Secondary</Button>,
47
- backgroundMedia: <PlaceholderBackground />,
48
- };
49
-
50
- // =============================================================================
51
- // Responsive Variants
52
- // =============================================================================
53
-
54
- export const Desktop: Story = {
55
- render: () => (
56
- <Tout
57
- headline="Brand-Large/Headline/Small"
58
- body="A river pattern stacks content in a simple vertical flow: one clear heading, a short block of copy, then the next step. It's ideal for guiding citizens through a process or story, keeping focus moving straight down the page with minimal choices and well-timed calls to action."
59
- primaryAction={<Button>Primary</Button>}
60
- secondaryAction={<Button variant="secondary-outline">Secondary</Button>}
61
- backgroundMedia={<PlaceholderBackground />}
62
- />
63
- ),
64
- globals: {
65
- viewport: { value: "lg", isRotated: false },
66
- },
67
- };
68
-
69
- export const Tablet: Story = {
70
- render: () => (
71
- <Tout
72
- headline="Brand-Large/Headline/Small"
73
- body="A river pattern stacks content in a simple vertical flow: one clear heading, a short block of copy, then the next step. It's ideal for guiding citizens through a process or story, keeping focus moving straight down the page with minimal choices and well-timed calls to action."
74
- primaryAction={<Button>Primary</Button>}
75
- secondaryAction={<Button variant="secondary-outline">Secondary</Button>}
76
- backgroundMedia={<PlaceholderBackground />}
77
- />
78
- ),
79
- globals: {
80
- viewport: { value: "md", isRotated: false },
81
- },
82
- };
83
-
84
- export const Mobile: Story = {
85
- render: () => (
86
- <Tout
87
- headline="Brand-Large/Headline/Small"
88
- body="A river pattern stacks content in a simple vertical flow: one clear heading, a short block of copy, then the next step. It's ideal for guiding citizens through a process or story, keeping focus moving straight down the page with minimal choices and well-timed calls to action."
89
- primaryAction={<Button size="sm">Primary</Button>}
90
- secondaryAction={
91
- <Button size="sm" variant="secondary-outline">
92
- Secondary
93
- </Button>
94
- }
95
- backgroundMedia={<PlaceholderBackground />}
96
- />
97
- ),
98
- globals: {
99
- viewport: { value: "sm", isRotated: false },
100
- },
101
- };
102
-
103
- // =============================================================================
104
- // Examples
105
- // =============================================================================
106
-
107
- /**
108
- * With actual background image
109
- */
110
- export const WithImage: Story = {
111
- render: () => (
112
- <Tout
113
- headline="Work with Purpose"
114
- body="Join a team that's building the future of government services. We're looking for passionate individuals who want to make a difference."
115
- primaryAction={<Button>View Careers</Button>}
116
- secondaryAction={<Button variant="secondary-outline">Learn More</Button>}
117
- backgroundMedia={<ImageBackground />}
118
- />
119
- ),
120
- };
121
-
122
- /**
123
- * Without secondary action
124
- */
125
- export const SingleAction: Story = {
126
- render: () => (
127
- <Tout
128
- headline="Get Started Today"
129
- body="Begin your journey with our comprehensive onboarding process designed to help you succeed from day one."
130
- primaryAction={<Button>Start Now</Button>}
131
- backgroundMedia={<PlaceholderBackground />}
132
- />
133
- ),
134
- };
135
-
136
- /**
137
- * With video background (placeholder)
138
- */
139
- export const WithVideoPlaceholder: Story = {
140
- render: () => (
141
- <Tout
142
- headline="Experience Innovation"
143
- body="See how modern technology is transforming the way government serves its citizens."
144
- primaryAction={<Button>Watch Video</Button>}
145
- secondaryAction={<Button variant="secondary-outline">Learn More</Button>}
146
- backgroundMedia={
147
- <div className="absolute inset-0 bg-gray-800 flex items-center justify-center">
148
- <span className="text-gray-400 typography-body-small">
149
- Video Background
150
- </span>
151
- </div>
152
- }
153
- />
154
- ),
155
- };
156
-
157
- /**
158
- * With NdstudioFooter - shows the National Design Studio branding at the bottom
159
- */
160
- export const WithNdstudioFooter: Story = {
161
- render: () => (
162
- <Tout
163
- headline="Work with Purpose"
164
- body="Join a team that's building the future of government services. We're looking for passionate individuals who want to make a difference."
165
- primaryAction={<Button>View Careers</Button>}
166
- secondaryAction={<Button variant="secondary-outline">Learn More</Button>}
167
- backgroundMedia={<ImageBackground />}
168
- footer={<NdstudioFooter />}
169
- />
170
- ),
171
- };
@@ -1,242 +0,0 @@
1
- import { describe, expect, test } from "vitest";
2
- import { page } from "vitest/browser";
3
- import { render } from "vitest-browser-react";
4
- import { Tout } from "./tout";
5
-
6
- const PlaceholderBackground = () => (
7
- <div data-testid="background" className="absolute inset-0 bg-gray-300" />
8
- );
9
-
10
- describe("Tout", () => {
11
- describe("Accessibility", () => {
12
- test("renders as section landmark", async () => {
13
- render(
14
- <Tout
15
- headline="Test Headline"
16
- body="Test body"
17
- primaryAction={<button type="button">Action</button>}
18
- backgroundMedia={<PlaceholderBackground />}
19
- data-testid="tout"
20
- />,
21
- );
22
-
23
- const tout = page.getByTestId("tout");
24
- await expect.element(tout).toBeInTheDocument();
25
- });
26
-
27
- test("headline renders as h2", async () => {
28
- render(
29
- <Tout
30
- headline="Tout Headline"
31
- body="Test body"
32
- primaryAction={<button type="button">Action</button>}
33
- backgroundMedia={<PlaceholderBackground />}
34
- />,
35
- );
36
-
37
- await expect
38
- .element(page.getByRole("heading", { level: 2, name: "Tout Headline" }))
39
- .toBeInTheDocument();
40
- });
41
-
42
- test("body text is accessible", async () => {
43
- render(
44
- <Tout
45
- headline="Test"
46
- body="Accessible body text"
47
- primaryAction={<button type="button">Action</button>}
48
- backgroundMedia={<PlaceholderBackground />}
49
- />,
50
- );
51
-
52
- await expect
53
- .element(page.getByText("Accessible body text"))
54
- .toBeInTheDocument();
55
- });
56
-
57
- test("background is hidden from screen readers", async () => {
58
- render(
59
- <Tout
60
- headline="Test"
61
- body="Test"
62
- primaryAction={<button type="button">Action</button>}
63
- backgroundMedia={<PlaceholderBackground />}
64
- data-testid="tout"
65
- />,
66
- );
67
-
68
- const tout = page.getByTestId("tout");
69
- await expect.element(tout).toBeInTheDocument();
70
- });
71
- });
72
-
73
- describe("Props", () => {
74
- test("renders with required props", async () => {
75
- render(
76
- <Tout
77
- headline="Required Headline"
78
- body="Required body"
79
- primaryAction={<button type="button">Primary</button>}
80
- backgroundMedia={<PlaceholderBackground />}
81
- />,
82
- );
83
-
84
- await expect
85
- .element(page.getByText("Required Headline"))
86
- .toBeInTheDocument();
87
- await expect.element(page.getByText("Required body")).toBeInTheDocument();
88
- await expect
89
- .element(page.getByRole("button", { name: "Primary" }))
90
- .toBeInTheDocument();
91
- await expect.element(page.getByTestId("background")).toBeInTheDocument();
92
- });
93
-
94
- test("renders secondary action when provided", async () => {
95
- render(
96
- <Tout
97
- headline="Test"
98
- body="Test"
99
- primaryAction={<button type="button">Primary</button>}
100
- secondaryAction={<button type="button">Secondary</button>}
101
- backgroundMedia={<PlaceholderBackground />}
102
- />,
103
- );
104
-
105
- await expect
106
- .element(page.getByRole("button", { name: "Primary" }))
107
- .toBeInTheDocument();
108
- await expect
109
- .element(page.getByRole("button", { name: "Secondary" }))
110
- .toBeInTheDocument();
111
- });
112
-
113
- test("does not render secondary action when not provided", async () => {
114
- render(
115
- <Tout
116
- headline="Test"
117
- body="Test"
118
- primaryAction={<button type="button">Primary</button>}
119
- backgroundMedia={<PlaceholderBackground />}
120
- />,
121
- );
122
-
123
- await expect
124
- .element(page.getByRole("button", { name: "Primary" }))
125
- .toBeInTheDocument();
126
- // Should only have one button
127
- const buttons = page.getByRole("button");
128
- await expect.element(buttons).toBeInTheDocument();
129
- });
130
-
131
- test("supports custom className", async () => {
132
- render(
133
- <Tout
134
- headline="Test"
135
- body="Test"
136
- primaryAction={<button type="button">Action</button>}
137
- backgroundMedia={<PlaceholderBackground />}
138
- className="custom-class"
139
- data-testid="tout"
140
- />,
141
- );
142
-
143
- const tout = page.getByTestId("tout");
144
- await expect.element(tout).toHaveClass(/custom-class/);
145
- });
146
-
147
- test("spreads additional props to section element", async () => {
148
- render(
149
- <Tout
150
- headline="Test"
151
- body="Test"
152
- primaryAction={<button type="button">Action</button>}
153
- backgroundMedia={<PlaceholderBackground />}
154
- data-testid="tout"
155
- aria-label="Tout section"
156
- />,
157
- );
158
-
159
- const tout = page.getByTestId("tout");
160
- await expect.element(tout).toHaveAttribute("aria-label", "Tout section");
161
- });
162
- });
163
-
164
- describe("Styling", () => {
165
- test("applies full width class", async () => {
166
- render(
167
- <Tout
168
- headline="Test"
169
- body="Test"
170
- primaryAction={<button type="button">Action</button>}
171
- backgroundMedia={<PlaceholderBackground />}
172
- data-testid="tout"
173
- />,
174
- );
175
-
176
- const tout = page.getByTestId("tout");
177
- await expect.element(tout).toHaveClass(/w-full/);
178
- });
179
-
180
- test("applies responsive height classes", async () => {
181
- render(
182
- <Tout
183
- headline="Test"
184
- body="Test"
185
- primaryAction={<button type="button">Action</button>}
186
- backgroundMedia={<PlaceholderBackground />}
187
- data-testid="tout"
188
- />,
189
- );
190
-
191
- const tout = page.getByTestId("tout");
192
- await expect.element(tout).toHaveClass(/h-\[600px\]/);
193
- });
194
-
195
- test("applies relative positioning for z-index context", async () => {
196
- render(
197
- <Tout
198
- headline="Test"
199
- body="Test"
200
- primaryAction={<button type="button">Action</button>}
201
- backgroundMedia={<PlaceholderBackground />}
202
- data-testid="tout"
203
- />,
204
- );
205
-
206
- const tout = page.getByTestId("tout");
207
- await expect.element(tout).toHaveClass(/relative/);
208
- });
209
- });
210
-
211
- describe("Content", () => {
212
- test("headline has correct styling", async () => {
213
- render(
214
- <Tout
215
- headline="Styled Headline"
216
- body="Test"
217
- primaryAction={<button type="button">Action</button>}
218
- backgroundMedia={<PlaceholderBackground />}
219
- />,
220
- );
221
-
222
- const headline = page.getByRole("heading", { level: 2 });
223
- await expect.element(headline).toHaveClass(/typography-h4/);
224
- await expect.element(headline).toHaveClass(/text-gray-900/);
225
- });
226
-
227
- test("body has correct styling", async () => {
228
- render(
229
- <Tout
230
- headline="Test"
231
- body="Styled body text"
232
- primaryAction={<button type="button">Action</button>}
233
- backgroundMedia={<PlaceholderBackground />}
234
- />,
235
- );
236
-
237
- const body = page.getByText("Styled body text");
238
- await expect.element(body).toHaveClass(/typography-body-small/);
239
- await expect.element(body).toHaveClass(/text-gray-800/);
240
- });
241
- });
242
- });
@@ -1,5 +0,0 @@
1
- export {
2
- TwoColumnSection,
3
- type TwoColumnSectionProps,
4
- twoColumnSectionVariants,
5
- } from "./two-column-section";