@nationaldesignstudio/react 0.0.14 → 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.
Files changed (166) hide show
  1. package/dist/tailwind.css +15 -1
  2. package/dist/tokens.css +45 -60
  3. package/package.json +5 -10
  4. package/src/App.css +0 -0
  5. package/src/App.tsx +7 -0
  6. package/src/assets/fonts/PPNeueMontreal-Variable.woff2 +0 -0
  7. package/src/assets/react.svg +1 -0
  8. package/src/components/atoms/accordion/accordion.stories.tsx +228 -0
  9. package/src/components/atoms/accordion/accordion.tsx +219 -0
  10. package/src/components/atoms/accordion/index.ts +6 -0
  11. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-chromium-darwin.png +0 -0
  12. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-chromium-linux.png +0 -0
  13. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-chromium-darwin.png +0 -0
  14. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-chromium-linux.png +0 -0
  15. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-quiet-chromium-darwin.png +0 -0
  16. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-quiet-chromium-linux.png +0 -0
  17. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-disabled-chromium-darwin.png +0 -0
  18. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-disabled-chromium-linux.png +0 -0
  19. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-chromium-darwin.png +0 -0
  20. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-chromium-linux.png +0 -0
  21. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-chromium-darwin.png +0 -0
  22. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-chromium-linux.png +0 -0
  23. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-quiet-chromium-darwin.png +0 -0
  24. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-quiet-chromium-linux.png +0 -0
  25. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-large-chromium-darwin.png +0 -0
  26. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-large-chromium-linux.png +0 -0
  27. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-medium-chromium-darwin.png +0 -0
  28. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-medium-chromium-linux.png +0 -0
  29. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-small-chromium-darwin.png +0 -0
  30. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-small-chromium-linux.png +0 -0
  31. package/src/components/atoms/button/button.stories.tsx +102 -0
  32. package/src/components/atoms/button/button.test.tsx +135 -0
  33. package/src/components/atoms/button/button.tsx +139 -0
  34. package/src/components/atoms/button/button.visual.test.tsx +102 -0
  35. package/src/components/atoms/button/icon-button.stories.tsx +166 -0
  36. package/src/components/atoms/button/icon-button.tsx +120 -0
  37. package/src/components/atoms/button/index.ts +6 -0
  38. package/src/components/atoms/ndstudio-footer/index.ts +1 -0
  39. package/src/components/atoms/ndstudio-footer/ndstudio-footer.tsx +55 -0
  40. package/src/components/atoms/pager-control/index.ts +5 -0
  41. package/src/components/atoms/pager-control/pager-control.stories.tsx +209 -0
  42. package/src/components/atoms/pager-control/pager-control.test.tsx +130 -0
  43. package/src/components/atoms/pager-control/pager-control.tsx +329 -0
  44. package/src/components/dev-tools/dev-toolbar/dev-toolbar.stories.tsx +82 -0
  45. package/src/components/dev-tools/dev-toolbar/dev-toolbar.tsx +196 -0
  46. package/src/components/dev-tools/dev-toolbar/index.ts +1 -0
  47. package/src/components/dev-tools/grid-overlay/grid-overlay.tsx +41 -0
  48. package/src/components/dev-tools/grid-overlay/index.ts +1 -0
  49. package/src/components/dev-tools/index.ts +2 -0
  50. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-default-vertical-chromium-darwin.png +0 -0
  51. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-default-vertical-chromium-linux.png +0 -0
  52. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-horizontal-chromium-darwin.png +0 -0
  53. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-horizontal-chromium-linux.png +0 -0
  54. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-minimal-chromium-darwin.png +0 -0
  55. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-minimal-chromium-linux.png +0 -0
  56. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-actions-chromium-darwin.png +0 -0
  57. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-actions-chromium-linux.png +0 -0
  58. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-eyebrow-chromium-darwin.png +0 -0
  59. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-eyebrow-chromium-linux.png +0 -0
  60. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-image-chromium-darwin.png +0 -0
  61. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-image-chromium-linux.png +0 -0
  62. package/src/components/organisms/card/card.stories.tsx +293 -0
  63. package/src/components/organisms/card/card.test.tsx +245 -0
  64. package/src/components/organisms/card/card.tsx +225 -0
  65. package/src/components/organisms/card/card.visual.test.tsx +197 -0
  66. package/src/components/organisms/card/index.ts +19 -0
  67. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-active-link-chromium-darwin.png +0 -0
  68. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-active-link-chromium-linux.png +0 -0
  69. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-brand-only-chromium-darwin.png +0 -0
  70. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-brand-only-chromium-linux.png +0 -0
  71. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-default-chromium-darwin.png +0 -0
  72. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-default-chromium-linux.png +0 -0
  73. package/src/components/organisms/navbar/index.ts +18 -0
  74. package/src/components/organisms/navbar/navbar.stories.tsx +313 -0
  75. package/src/components/organisms/navbar/navbar.test.tsx +190 -0
  76. package/src/components/organisms/navbar/navbar.tsx +323 -0
  77. package/src/components/organisms/navbar/navbar.visual.test.tsx +85 -0
  78. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-icon-chromium-darwin.png +0 -0
  79. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-icon-chromium-linux.png +0 -0
  80. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-text-chromium-darwin.png +0 -0
  81. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-text-chromium-linux.png +0 -0
  82. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-default-chromium-darwin.png +0 -0
  83. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-default-chromium-linux.png +0 -0
  84. package/src/components/organisms/us-gov-banner/index.ts +1 -0
  85. package/src/components/organisms/us-gov-banner/us-gov-banner.stories.tsx +35 -0
  86. package/src/components/organisms/us-gov-banner/us-gov-banner.test.tsx +107 -0
  87. package/src/components/organisms/us-gov-banner/us-gov-banner.tsx +73 -0
  88. package/src/components/organisms/us-gov-banner/us-gov-banner.visual.test.tsx +46 -0
  89. package/src/components/sections/banner/banner.stories.tsx +150 -0
  90. package/src/components/sections/banner/banner.test.tsx +185 -0
  91. package/src/components/sections/banner/banner.tsx +130 -0
  92. package/src/components/sections/banner/index.ts +2 -0
  93. package/src/components/sections/card-grid/card-grid.stories.tsx +351 -0
  94. package/src/components/sections/card-grid/card-grid.tsx +116 -0
  95. package/src/components/sections/card-grid/index.ts +1 -0
  96. package/src/components/sections/faq-section/faq-section.stories.tsx +453 -0
  97. package/src/components/sections/faq-section/faq-section.tsx +84 -0
  98. package/src/components/sections/faq-section/index.ts +2 -0
  99. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-desktop-chromium-darwin.png +0 -0
  100. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-desktop-chromium-linux.png +0 -0
  101. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-mobile-chromium-darwin.png +0 -0
  102. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-mobile-chromium-linux.png +0 -0
  103. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-tablet-chromium-darwin.png +0 -0
  104. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-tablet-chromium-linux.png +0 -0
  105. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-desktop-chromium-darwin.png +0 -0
  106. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-desktop-chromium-linux.png +0 -0
  107. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-mobile-chromium-darwin.png +0 -0
  108. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-mobile-chromium-linux.png +0 -0
  109. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-tablet-chromium-darwin.png +0 -0
  110. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-tablet-chromium-linux.png +0 -0
  111. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-desktop-chromium-darwin.png +0 -0
  112. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-desktop-chromium-linux.png +0 -0
  113. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-mobile-chromium-darwin.png +0 -0
  114. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-mobile-chromium-linux.png +0 -0
  115. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-tablet-chromium-darwin.png +0 -0
  116. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-tablet-chromium-linux.png +0 -0
  117. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-custom-class-chromium-darwin.png +0 -0
  118. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-custom-class-chromium-linux.png +0 -0
  119. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-default-chromium-linux.png +0 -0
  120. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-long-title-chromium-darwin.png +0 -0
  121. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-long-title-chromium-linux.png +0 -0
  122. package/src/components/sections/hero/hero.stories.tsx +274 -0
  123. package/src/components/sections/hero/hero.test.tsx +135 -0
  124. package/src/components/sections/hero/hero.tsx +453 -0
  125. package/src/components/sections/hero/hero.visual.test.tsx +140 -0
  126. package/src/components/sections/hero/index.ts +10 -0
  127. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-h3-heading-chromium-darwin.png +0 -0
  128. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-h3-heading-chromium-linux.png +0 -0
  129. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-paragraphs-chromium-darwin.png +0 -0
  130. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-paragraphs-chromium-linux.png +0 -0
  131. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-sections-chromium-darwin.png +0 -0
  132. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-sections-chromium-linux.png +0 -0
  133. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-single-section-chromium-darwin.png +0 -0
  134. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-single-section-chromium-linux.png +0 -0
  135. package/src/components/sections/prose/index.ts +6 -0
  136. package/src/components/sections/prose/prose.stories.tsx +144 -0
  137. package/src/components/sections/prose/prose.test.tsx +178 -0
  138. package/src/components/sections/prose/prose.tsx +88 -0
  139. package/src/components/sections/prose/prose.visual.test.tsx +105 -0
  140. package/src/components/sections/river/index.ts +1 -0
  141. package/src/components/sections/river/river.stories.tsx +237 -0
  142. package/src/components/sections/river/river.test.tsx +268 -0
  143. package/src/components/sections/river/river.tsx +173 -0
  144. package/src/components/sections/tout/index.ts +1 -0
  145. package/src/components/sections/tout/tout.stories.tsx +171 -0
  146. package/src/components/sections/tout/tout.test.tsx +242 -0
  147. package/src/components/sections/tout/tout.tsx +270 -0
  148. package/src/components/sections/two-column-section/index.ts +5 -0
  149. package/src/components/sections/two-column-section/two-column-section.stories.tsx +285 -0
  150. package/src/components/sections/two-column-section/two-column-section.tsx +162 -0
  151. package/src/hooks/index.ts +1 -0
  152. package/src/hooks/use-event-listener.ts +73 -0
  153. package/src/index.ts +155 -0
  154. package/src/lib/theme.ts +1000 -0
  155. package/src/lib/utils.ts +6 -0
  156. package/src/main.tsx +13 -0
  157. package/src/stories/GridSystem.stories.tsx +84 -0
  158. package/src/stories/Introduction.mdx +114 -0
  159. package/src/stories/ThemeProvider.stories.tsx +357 -0
  160. package/src/stories/TokenShowcase.stories.tsx +92 -0
  161. package/src/stories/TokenShowcase.tsx +1429 -0
  162. package/src/styles.css +11 -0
  163. package/src/theme/ThemeProvider.tsx +297 -0
  164. package/src/theme/hooks.ts +40 -0
  165. package/src/theme/index.ts +43 -0
  166. package/src/theme/utils.ts +104 -0
@@ -0,0 +1,274 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { Hero, HeroBackground } from ".";
3
+
4
+ const meta: Meta<typeof Hero> = {
5
+ title: "Sections/Hero",
6
+ component: Hero,
7
+ parameters: {
8
+ layout: "fullscreen",
9
+ },
10
+ argTypes: {
11
+ variant: {
12
+ control: "select",
13
+ options: ["A1", "A2", "A3"],
14
+ description: "Hero variant controlling content alignment",
15
+ },
16
+ title: {
17
+ control: "text",
18
+ description: "The title text displayed in the hero",
19
+ },
20
+ background: {
21
+ control: "text",
22
+ description:
23
+ "Background color (hex/rgb) or use HeroBackground components",
24
+ },
25
+ overlayOpacity: {
26
+ control: { type: "range", min: 0, max: 1, step: 0.1 },
27
+ description: "Opacity of the overlay (0-1)",
28
+ },
29
+ overlayColor: {
30
+ control: "color",
31
+ description: "Color of the overlay",
32
+ },
33
+ },
34
+ } as Meta<typeof Hero>;
35
+
36
+ export default meta;
37
+ type Story = StoryObj<typeof Hero>;
38
+
39
+ export const Playground: Story = {
40
+ render: (args) => <Hero {...args} />,
41
+ };
42
+ Playground.args = {
43
+ title: "Hero Title",
44
+ variant: "A1",
45
+ background: "#1a1a1a",
46
+ };
47
+
48
+ // =============================================================================
49
+ // Variants
50
+ // =============================================================================
51
+
52
+ /**
53
+ * A1 variant: Content aligned at the bottom of the hero.
54
+ * This is the default variant.
55
+ */
56
+ export const A1: Story = {
57
+ render: () => <Hero variant="A1" title="Hero A1" />,
58
+ };
59
+
60
+ /**
61
+ * A2 variant: Content aligned at the top of the hero.
62
+ */
63
+ export const A2: Story = {
64
+ render: () => <Hero variant="A2" title="Hero A2" />,
65
+ };
66
+
67
+ /**
68
+ * A3 variant: Content centered vertically in the hero.
69
+ */
70
+ export const A3: Story = {
71
+ render: () => <Hero variant="A3" title="Hero A3" />,
72
+ };
73
+
74
+ // =============================================================================
75
+ // Background Types
76
+ // =============================================================================
77
+
78
+ /**
79
+ * Hero with solid color background using hex code
80
+ */
81
+ export const WithColorBackground: Story = {
82
+ render: () => (
83
+ <Hero variant="A1" title="Color Background" background="#2563eb" />
84
+ ),
85
+ };
86
+
87
+ /**
88
+ * Hero with background image using HeroBackground.Image
89
+ */
90
+ export const WithImageBackground: Story = {
91
+ render: () => (
92
+ <Hero
93
+ variant="A1"
94
+ title="Image Background"
95
+ background={
96
+ <HeroBackground.Image
97
+ src="https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=1920&q=80"
98
+ position="center"
99
+ alt="Earth from space"
100
+ />
101
+ }
102
+ overlayOpacity={0.4}
103
+ />
104
+ ),
105
+ };
106
+
107
+ /**
108
+ * Hero with HTML5 video background using HeroBackground.Video
109
+ */
110
+ export const WithVideoBackground: Story = {
111
+ render: () => (
112
+ <Hero
113
+ variant="A1"
114
+ title="Video Background"
115
+ background={
116
+ <HeroBackground.Video
117
+ src="https://storage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4"
118
+ poster="https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=1920&q=80"
119
+ />
120
+ }
121
+ overlayOpacity={0.3}
122
+ />
123
+ ),
124
+ };
125
+
126
+ /**
127
+ * Hero with Cloudflare Stream video background
128
+ *
129
+ * Note: Replace with a valid Cloudflare Stream video ID for actual use
130
+ */
131
+ export const WithCloudflareStream: Story = {
132
+ render: () => (
133
+ <Hero
134
+ variant="A1"
135
+ title="Stream Background"
136
+ background={
137
+ <HeroBackground.Stream
138
+ videoId="5d5bc37ffcf54c9b82e996823bffbb81"
139
+ muted
140
+ autoplay
141
+ loop
142
+ />
143
+ }
144
+ overlayOpacity={0.4}
145
+ />
146
+ ),
147
+ };
148
+
149
+ // =============================================================================
150
+ // Responsive Variants - A1 (Content at bottom)
151
+ // =============================================================================
152
+
153
+ export const A1Desktop: Story = {
154
+ render: () => <Hero variant="A1" title="Hero A1" />,
155
+ globals: {
156
+ viewport: { value: "lg", isRotated: false },
157
+ },
158
+ };
159
+
160
+ export const A1Tablet: Story = {
161
+ render: () => <Hero variant="A1" title="Hero A1" />,
162
+ globals: {
163
+ viewport: { value: "md", isRotated: false },
164
+ },
165
+ };
166
+
167
+ export const A1Mobile: Story = {
168
+ render: () => <Hero variant="A1" title="Hero A1" />,
169
+ globals: {
170
+ viewport: { value: "sm", isRotated: false },
171
+ },
172
+ };
173
+
174
+ // =============================================================================
175
+ // Responsive Variants - A2 (Content at top)
176
+ // =============================================================================
177
+
178
+ export const A2Desktop: Story = {
179
+ render: () => <Hero variant="A2" title="Hero A2" />,
180
+ globals: {
181
+ viewport: { value: "lg", isRotated: false },
182
+ },
183
+ };
184
+
185
+ export const A2Tablet: Story = {
186
+ render: () => <Hero variant="A2" title="Hero A2" />,
187
+ globals: {
188
+ viewport: { value: "md", isRotated: false },
189
+ },
190
+ };
191
+
192
+ export const A2Mobile: Story = {
193
+ render: () => <Hero variant="A2" title="Hero A2" />,
194
+ globals: {
195
+ viewport: { value: "sm", isRotated: false },
196
+ },
197
+ };
198
+
199
+ // =============================================================================
200
+ // Responsive Variants - A3 (Content centered)
201
+ // =============================================================================
202
+
203
+ export const A3Desktop: Story = {
204
+ render: () => <Hero variant="A3" title="Hero A3" />,
205
+ globals: {
206
+ viewport: { value: "lg", isRotated: false },
207
+ },
208
+ };
209
+
210
+ export const A3Tablet: Story = {
211
+ render: () => <Hero variant="A3" title="Hero A3" />,
212
+ globals: {
213
+ viewport: { value: "md", isRotated: false },
214
+ },
215
+ };
216
+
217
+ export const A3Mobile: Story = {
218
+ render: () => <Hero variant="A3" title="Hero A3" />,
219
+ globals: {
220
+ viewport: { value: "sm", isRotated: false },
221
+ },
222
+ };
223
+
224
+ // =============================================================================
225
+ // Examples
226
+ // =============================================================================
227
+
228
+ export const WithLongTitle: Story = {
229
+ render: () => <Hero title="A Much Longer Hero Title That Wraps" />,
230
+ };
231
+
232
+ export const WithCustomClassName: Story = {
233
+ render: () => <Hero title="Custom Background" className="bg-blue-600" />,
234
+ };
235
+
236
+ /**
237
+ * Hero with image and high overlay for better text contrast
238
+ */
239
+ export const WithHighOverlay: Story = {
240
+ render: () => (
241
+ <Hero
242
+ variant="A3"
243
+ title="High Contrast"
244
+ background={
245
+ <HeroBackground.Image
246
+ src="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=1920&q=80"
247
+ position="center bottom"
248
+ />
249
+ }
250
+ overlayOpacity={0.7}
251
+ overlayColor="#000000"
252
+ />
253
+ ),
254
+ };
255
+
256
+ /**
257
+ * Hero with gradient-style overlay color
258
+ */
259
+ export const WithColoredOverlay: Story = {
260
+ render: () => (
261
+ <Hero
262
+ variant="A1"
263
+ title="Tinted Overlay"
264
+ background={
265
+ <HeroBackground.Image
266
+ src="https://images.unsplash.com/photo-1557682250-33bd709cbe85?w=1920&q=80"
267
+ position="center"
268
+ />
269
+ }
270
+ overlayOpacity={0.5}
271
+ overlayColor="#1e3a5f"
272
+ />
273
+ ),
274
+ };
@@ -0,0 +1,135 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { page } from "vitest/browser";
3
+ import { render } from "vitest-browser-react";
4
+ import { Hero } from "./hero";
5
+
6
+ describe("Hero", () => {
7
+ describe("Accessibility", () => {
8
+ test("renders as section landmark", async () => {
9
+ render(<Hero title="Test Hero" data-testid="hero" />);
10
+
11
+ // Section is a region landmark when it has an accessible name
12
+ const hero = page.getByTestId("hero");
13
+ await expect.element(hero).toBeInTheDocument();
14
+ });
15
+
16
+ test("title renders as h1 heading", async () => {
17
+ render(<Hero title="Hero Title" />);
18
+
19
+ await expect
20
+ .element(page.getByRole("heading", { level: 1, name: "Hero Title" }))
21
+ .toBeInTheDocument();
22
+ });
23
+
24
+ test("title is accessible to screen readers", async () => {
25
+ render(<Hero title="Accessible Title" />);
26
+
27
+ await expect
28
+ .element(page.getByText("Accessible Title"))
29
+ .toBeInTheDocument();
30
+ });
31
+ });
32
+
33
+ describe("Props", () => {
34
+ test("renders with required title prop", async () => {
35
+ render(<Hero title="Required Title" />);
36
+
37
+ await expect
38
+ .element(page.getByText("Required Title"))
39
+ .toBeInTheDocument();
40
+ });
41
+
42
+ test("supports custom className", async () => {
43
+ render(
44
+ <Hero title="Custom" className="custom-class" data-testid="hero" />,
45
+ );
46
+
47
+ const hero = page.getByTestId("hero");
48
+ await expect.element(hero).toHaveClass(/custom-class/);
49
+ });
50
+
51
+ test("spreads additional props to section element", async () => {
52
+ render(
53
+ <Hero
54
+ title="Props Test"
55
+ data-testid="hero"
56
+ aria-label="Hero section"
57
+ />,
58
+ );
59
+
60
+ const hero = page.getByTestId("hero");
61
+ await expect.element(hero).toHaveAttribute("aria-label", "Hero section");
62
+ });
63
+ });
64
+
65
+ describe("Styling", () => {
66
+ test("applies default background color", async () => {
67
+ render(<Hero title="Default" data-testid="hero" />);
68
+
69
+ const hero = page.getByTestId("hero");
70
+ await expect.element(hero).toHaveClass(/bg-gray-1000/);
71
+ });
72
+
73
+ test("applies responsive height classes", async () => {
74
+ render(<Hero title="Responsive" data-testid="hero" />);
75
+
76
+ const hero = page.getByTestId("hero");
77
+ // Mobile height
78
+ await expect.element(hero).toHaveClass(/h-\[500px\]/);
79
+ });
80
+ });
81
+
82
+ describe("Variants", () => {
83
+ test("A1 variant applies items-end alignment (default)", async () => {
84
+ render(<Hero title="A1 Hero" variant="A1" data-testid="hero" />);
85
+
86
+ const hero = page.getByTestId("hero");
87
+ await expect.element(hero).toHaveClass(/items-end/);
88
+ });
89
+
90
+ test("A1 variant is default when no variant specified", async () => {
91
+ render(<Hero title="Default Hero" data-testid="hero" />);
92
+
93
+ const hero = page.getByTestId("hero");
94
+ await expect.element(hero).toHaveClass(/items-end/);
95
+ });
96
+
97
+ test("A2 variant applies items-start alignment", async () => {
98
+ render(<Hero title="A2 Hero" variant="A2" data-testid="hero" />);
99
+
100
+ const hero = page.getByTestId("hero");
101
+ await expect.element(hero).toHaveClass(/items-start/);
102
+ });
103
+
104
+ test("A3 variant applies items-center alignment", async () => {
105
+ render(<Hero title="A3 Hero" variant="A3" data-testid="hero" />);
106
+
107
+ const hero = page.getByTestId("hero");
108
+ await expect.element(hero).toHaveClass(/items-center/);
109
+ });
110
+
111
+ test("A1 variant maintains common styles", async () => {
112
+ render(<Hero title="A1 Hero" variant="A1" data-testid="hero" />);
113
+
114
+ const hero = page.getByTestId("hero");
115
+ await expect.element(hero).toHaveClass(/bg-gray-1000/);
116
+ await expect.element(hero).toHaveClass(/h-\[500px\]/);
117
+ });
118
+
119
+ test("A2 variant maintains common styles", async () => {
120
+ render(<Hero title="A2 Hero" variant="A2" data-testid="hero" />);
121
+
122
+ const hero = page.getByTestId("hero");
123
+ await expect.element(hero).toHaveClass(/bg-gray-1000/);
124
+ await expect.element(hero).toHaveClass(/h-\[500px\]/);
125
+ });
126
+
127
+ test("A3 variant maintains common styles", async () => {
128
+ render(<Hero title="A3 Hero" variant="A3" data-testid="hero" />);
129
+
130
+ const hero = page.getByTestId("hero");
131
+ await expect.element(hero).toHaveClass(/bg-gray-1000/);
132
+ await expect.element(hero).toHaveClass(/h-\[500px\]/);
133
+ });
134
+ });
135
+ });