@nationaldesignstudio/react 0.0.10 → 0.0.12

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 (169) hide show
  1. package/dist/component-registry.md +2405 -0
  2. package/dist/components/atoms/accordion/accordion.d.ts +44 -3
  3. package/dist/components/atoms/button/button.d.ts +155 -11
  4. package/dist/components/atoms/button/icon-button.d.ts +114 -5
  5. package/dist/components/atoms/ndstudio-footer/ndstudio-footer.d.ts +30 -0
  6. package/dist/components/atoms/pager-control/pager-control.d.ts +116 -9
  7. package/dist/components/dev-tools/dev-toolbar/dev-toolbar.d.ts +4 -0
  8. package/dist/components/dev-tools/grid-overlay/grid-overlay.d.ts +6 -0
  9. package/dist/components/organisms/card/card.d.ts +40 -4
  10. package/dist/components/sections/banner/banner.d.ts +39 -6
  11. package/dist/components/sections/card-grid/card-grid.d.ts +37 -4
  12. package/dist/components/sections/faq-section/faq-section.d.ts +2 -2
  13. package/dist/components/sections/hero/hero.d.ts +167 -16
  14. package/dist/components/sections/river/river.d.ts +37 -4
  15. package/dist/components/sections/tout/tout.d.ts +86 -6
  16. package/dist/components/sections/two-column-section/two-column-section.d.ts +80 -6
  17. package/dist/hooks/index.d.ts +1 -0
  18. package/dist/hooks/use-event-listener.d.ts +24 -0
  19. package/dist/index.d.ts +9 -2
  20. package/dist/index.js +12034 -5934
  21. package/dist/index.js.map +1 -1
  22. package/dist/lib/theme.d.ts +330 -0
  23. package/dist/tokens.css +13930 -6368
  24. package/package.json +14 -24
  25. package/src/App.css +0 -0
  26. package/src/App.tsx +0 -7
  27. package/src/assets/fonts/PPNeueMontreal-Variable.woff2 +0 -0
  28. package/src/assets/react.svg +0 -1
  29. package/src/components/atoms/accordion/accordion.stories.tsx +0 -228
  30. package/src/components/atoms/accordion/accordion.tsx +0 -137
  31. package/src/components/atoms/accordion/index.ts +0 -6
  32. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-chromium-darwin.png +0 -0
  33. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-chromium-linux.png +0 -0
  34. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-chromium-darwin.png +0 -0
  35. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-chromium-linux.png +0 -0
  36. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-quiet-chromium-darwin.png +0 -0
  37. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-quiet-chromium-linux.png +0 -0
  38. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-disabled-chromium-darwin.png +0 -0
  39. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-disabled-chromium-linux.png +0 -0
  40. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-chromium-darwin.png +0 -0
  41. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-chromium-linux.png +0 -0
  42. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-chromium-darwin.png +0 -0
  43. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-chromium-linux.png +0 -0
  44. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-quiet-chromium-darwin.png +0 -0
  45. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-quiet-chromium-linux.png +0 -0
  46. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-large-chromium-darwin.png +0 -0
  47. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-large-chromium-linux.png +0 -0
  48. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-medium-chromium-darwin.png +0 -0
  49. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-medium-chromium-linux.png +0 -0
  50. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-small-chromium-darwin.png +0 -0
  51. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-small-chromium-linux.png +0 -0
  52. package/src/components/atoms/button/button.stories.tsx +0 -84
  53. package/src/components/atoms/button/button.test.tsx +0 -141
  54. package/src/components/atoms/button/button.tsx +0 -95
  55. package/src/components/atoms/button/button.visual.test.tsx +0 -102
  56. package/src/components/atoms/button/icon-button.stories.tsx +0 -166
  57. package/src/components/atoms/button/icon-button.tsx +0 -125
  58. package/src/components/atoms/button/index.ts +0 -6
  59. package/src/components/atoms/pager-control/index.ts +0 -5
  60. package/src/components/atoms/pager-control/pager-control.stories.tsx +0 -209
  61. package/src/components/atoms/pager-control/pager-control.test.tsx +0 -149
  62. package/src/components/atoms/pager-control/pager-control.tsx +0 -328
  63. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-default-vertical-chromium-darwin.png +0 -0
  64. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-default-vertical-chromium-linux.png +0 -0
  65. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-horizontal-chromium-darwin.png +0 -0
  66. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-horizontal-chromium-linux.png +0 -0
  67. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-minimal-chromium-darwin.png +0 -0
  68. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-minimal-chromium-linux.png +0 -0
  69. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-actions-chromium-darwin.png +0 -0
  70. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-actions-chromium-linux.png +0 -0
  71. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-eyebrow-chromium-darwin.png +0 -0
  72. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-eyebrow-chromium-linux.png +0 -0
  73. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-image-chromium-darwin.png +0 -0
  74. package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-image-chromium-linux.png +0 -0
  75. package/src/components/organisms/card/card.stories.tsx +0 -293
  76. package/src/components/organisms/card/card.test.tsx +0 -245
  77. package/src/components/organisms/card/card.tsx +0 -227
  78. package/src/components/organisms/card/card.visual.test.tsx +0 -197
  79. package/src/components/organisms/card/index.ts +0 -19
  80. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-active-link-chromium-darwin.png +0 -0
  81. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-active-link-chromium-linux.png +0 -0
  82. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-brand-only-chromium-darwin.png +0 -0
  83. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-brand-only-chromium-linux.png +0 -0
  84. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-default-chromium-darwin.png +0 -0
  85. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-default-chromium-linux.png +0 -0
  86. package/src/components/organisms/navbar/index.ts +0 -18
  87. package/src/components/organisms/navbar/navbar.stories.tsx +0 -313
  88. package/src/components/organisms/navbar/navbar.test.tsx +0 -190
  89. package/src/components/organisms/navbar/navbar.tsx +0 -317
  90. package/src/components/organisms/navbar/navbar.visual.test.tsx +0 -85
  91. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-icon-chromium-darwin.png +0 -0
  92. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-icon-chromium-linux.png +0 -0
  93. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-text-chromium-darwin.png +0 -0
  94. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-text-chromium-linux.png +0 -0
  95. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-default-chromium-darwin.png +0 -0
  96. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-default-chromium-linux.png +0 -0
  97. package/src/components/organisms/us-gov-banner/index.ts +0 -1
  98. package/src/components/organisms/us-gov-banner/us-gov-banner.stories.tsx +0 -35
  99. package/src/components/organisms/us-gov-banner/us-gov-banner.test.tsx +0 -107
  100. package/src/components/organisms/us-gov-banner/us-gov-banner.tsx +0 -73
  101. package/src/components/organisms/us-gov-banner/us-gov-banner.visual.test.tsx +0 -46
  102. package/src/components/sections/banner/banner.stories.tsx +0 -150
  103. package/src/components/sections/banner/banner.test.tsx +0 -185
  104. package/src/components/sections/banner/banner.tsx +0 -130
  105. package/src/components/sections/banner/index.ts +0 -2
  106. package/src/components/sections/card-grid/card-grid.stories.tsx +0 -351
  107. package/src/components/sections/card-grid/card-grid.tsx +0 -118
  108. package/src/components/sections/card-grid/index.ts +0 -1
  109. package/src/components/sections/faq-section/faq-section.tsx +0 -77
  110. package/src/components/sections/faq-section/index.ts +0 -2
  111. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-desktop-chromium-darwin.png +0 -0
  112. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-desktop-chromium-linux.png +0 -0
  113. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-mobile-chromium-darwin.png +0 -0
  114. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-mobile-chromium-linux.png +0 -0
  115. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-tablet-chromium-darwin.png +0 -0
  116. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-tablet-chromium-linux.png +0 -0
  117. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-desktop-chromium-darwin.png +0 -0
  118. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-desktop-chromium-linux.png +0 -0
  119. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-mobile-chromium-darwin.png +0 -0
  120. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-mobile-chromium-linux.png +0 -0
  121. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-tablet-chromium-darwin.png +0 -0
  122. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-tablet-chromium-linux.png +0 -0
  123. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-desktop-chromium-darwin.png +0 -0
  124. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-desktop-chromium-linux.png +0 -0
  125. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-mobile-chromium-darwin.png +0 -0
  126. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-mobile-chromium-linux.png +0 -0
  127. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-tablet-chromium-darwin.png +0 -0
  128. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-tablet-chromium-linux.png +0 -0
  129. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-custom-class-chromium-darwin.png +0 -0
  130. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-custom-class-chromium-linux.png +0 -0
  131. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-default-chromium-linux.png +0 -0
  132. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-long-title-chromium-darwin.png +0 -0
  133. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-long-title-chromium-linux.png +0 -0
  134. package/src/components/sections/hero/hero.stories.tsx +0 -145
  135. package/src/components/sections/hero/hero.test.tsx +0 -135
  136. package/src/components/sections/hero/hero.tsx +0 -191
  137. package/src/components/sections/hero/hero.visual.test.tsx +0 -140
  138. package/src/components/sections/hero/index.ts +0 -1
  139. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-h3-heading-chromium-darwin.png +0 -0
  140. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-h3-heading-chromium-linux.png +0 -0
  141. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-paragraphs-chromium-darwin.png +0 -0
  142. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-paragraphs-chromium-linux.png +0 -0
  143. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-sections-chromium-darwin.png +0 -0
  144. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-sections-chromium-linux.png +0 -0
  145. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-single-section-chromium-darwin.png +0 -0
  146. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-single-section-chromium-linux.png +0 -0
  147. package/src/components/sections/prose/index.ts +0 -6
  148. package/src/components/sections/prose/prose.stories.tsx +0 -144
  149. package/src/components/sections/prose/prose.test.tsx +0 -178
  150. package/src/components/sections/prose/prose.tsx +0 -88
  151. package/src/components/sections/prose/prose.visual.test.tsx +0 -105
  152. package/src/components/sections/river/index.ts +0 -1
  153. package/src/components/sections/river/river.stories.tsx +0 -237
  154. package/src/components/sections/river/river.test.tsx +0 -268
  155. package/src/components/sections/river/river.tsx +0 -175
  156. package/src/components/sections/tout/index.ts +0 -1
  157. package/src/components/sections/tout/tout.stories.tsx +0 -154
  158. package/src/components/sections/tout/tout.test.tsx +0 -242
  159. package/src/components/sections/tout/tout.tsx +0 -206
  160. package/src/components/sections/two-column-section/index.ts +0 -5
  161. package/src/components/sections/two-column-section/two-column-section.stories.tsx +0 -285
  162. package/src/components/sections/two-column-section/two-column-section.tsx +0 -152
  163. package/src/index.ts +0 -98
  164. package/src/lib/utils.ts +0 -6
  165. package/src/main.tsx +0 -13
  166. package/src/stories/Introduction.mdx +0 -114
  167. package/src/stories/TokenShowcase.stories.tsx +0 -92
  168. package/src/stories/TokenShowcase.tsx +0 -1352
  169. package/src/styles.css +0 -11
@@ -1,293 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/react-vite";
2
- import { Button } from "../../atoms/button";
3
- import {
4
- Card,
5
- CardActions,
6
- CardBody,
7
- CardContent,
8
- CardDescription,
9
- CardEyebrow,
10
- CardImage,
11
- CardTitle,
12
- } from ".";
13
-
14
- const meta: Meta<typeof Card> = {
15
- title: "Organisms/Card",
16
- component: Card,
17
- parameters: {
18
- layout: "centered",
19
- },
20
- } as Meta<typeof Card>;
21
-
22
- export default meta;
23
- type Story = StoryObj<typeof Card>;
24
-
25
- // =============================================================================
26
- // Default
27
- // =============================================================================
28
-
29
- export const Default: Story = {
30
- render: () => (
31
- <div className="w-[418px]">
32
- <Card>
33
- <CardImage />
34
- <CardContent>
35
- <CardBody>
36
- <CardEyebrow>Optional Eyebrow</CardEyebrow>
37
- <div className="flex flex-col gap-[6px]">
38
- <CardTitle>Card Title</CardTitle>
39
- <CardDescription>
40
- Use cards when citizens need to scan items at a glance, either
41
- to jump to a more detailed page or absorb short information.
42
- </CardDescription>
43
- </div>
44
- </CardBody>
45
- <CardActions>
46
- <Button size="default" variant="charcoal">
47
- Primary
48
- </Button>
49
- <Button size="default" variant="charcoalOutline">
50
- Secondary
51
- </Button>
52
- </CardActions>
53
- </CardContent>
54
- </Card>
55
- </div>
56
- ),
57
- };
58
-
59
- // =============================================================================
60
- // Layouts
61
- // =============================================================================
62
-
63
- export const Vertical: Story = {
64
- render: () => (
65
- <div className="w-[418px]">
66
- <Card layout="vertical">
67
- <CardImage />
68
- <CardContent>
69
- <CardBody>
70
- <CardEyebrow>Optional Eyebrow</CardEyebrow>
71
- <div className="flex flex-col gap-[6px]">
72
- <CardTitle>Card Title</CardTitle>
73
- <CardDescription>
74
- Use cards when citizens need to scan items at a glance, either
75
- to jump to a more detailed page or absorb short information.
76
- </CardDescription>
77
- </div>
78
- </CardBody>
79
- <CardActions>
80
- <Button size="default" variant="charcoal">
81
- Primary
82
- </Button>
83
- <Button size="default" variant="charcoalOutline">
84
- Secondary
85
- </Button>
86
- </CardActions>
87
- </CardContent>
88
- </Card>
89
- </div>
90
- ),
91
- };
92
-
93
- export const Horizontal: Story = {
94
- render: () => (
95
- <div className="w-[700px]">
96
- <Card layout="horizontal">
97
- <CardImage />
98
- <CardContent>
99
- <CardBody>
100
- <CardEyebrow>Eyebrow</CardEyebrow>
101
- <div className="flex flex-col gap-[9px]">
102
- <CardTitle>
103
- Cards can support multi line headings easily.
104
- </CardTitle>
105
- <CardDescription>
106
- Use cards when citizens need to scan items at a glance, either
107
- to jump to a more detailed page or absorb short information.
108
- </CardDescription>
109
- </div>
110
- </CardBody>
111
- <CardActions>
112
- <Button size="sm" variant="charcoal">
113
- Primary
114
- </Button>
115
- <Button size="sm" variant="charcoalOutline">
116
- Secondary
117
- </Button>
118
- </CardActions>
119
- </CardContent>
120
- </Card>
121
- </div>
122
- ),
123
- };
124
-
125
- // =============================================================================
126
- // Variations
127
- // =============================================================================
128
-
129
- export const WithoutImage: Story = {
130
- render: () => (
131
- <div className="w-[418px]">
132
- <Card>
133
- <CardContent>
134
- <CardBody>
135
- <CardEyebrow>Category</CardEyebrow>
136
- <div className="flex flex-col gap-[6px]">
137
- <CardTitle>Card Without Image</CardTitle>
138
- <CardDescription>
139
- Cards can be used without images for text-focused content.
140
- </CardDescription>
141
- </div>
142
- </CardBody>
143
- <CardActions>
144
- <Button size="default" variant="charcoal">
145
- Learn More
146
- </Button>
147
- </CardActions>
148
- </CardContent>
149
- </Card>
150
- </div>
151
- ),
152
- };
153
-
154
- export const WithoutEyebrow: Story = {
155
- render: () => (
156
- <div className="w-[418px]">
157
- <Card>
158
- <CardImage />
159
- <CardContent>
160
- <CardBody>
161
- <div className="flex flex-col gap-[6px]">
162
- <CardTitle>Card Title</CardTitle>
163
- <CardDescription>
164
- The eyebrow is optional and can be omitted when not needed.
165
- </CardDescription>
166
- </div>
167
- </CardBody>
168
- <CardActions>
169
- <Button size="default" variant="charcoal">
170
- Primary
171
- </Button>
172
- </CardActions>
173
- </CardContent>
174
- </Card>
175
- </div>
176
- ),
177
- };
178
-
179
- export const WithoutActions: Story = {
180
- render: () => (
181
- <div className="w-[418px]">
182
- <Card>
183
- <CardImage />
184
- <CardContent>
185
- <CardBody>
186
- <CardEyebrow>Information</CardEyebrow>
187
- <div className="flex flex-col gap-[6px]">
188
- <CardTitle>Informational Card</CardTitle>
189
- <CardDescription>
190
- Cards without actions can be used for purely informational
191
- content that doesn't require user interaction.
192
- </CardDescription>
193
- </div>
194
- </CardBody>
195
- </CardContent>
196
- </Card>
197
- </div>
198
- ),
199
- };
200
-
201
- export const Minimal: Story = {
202
- render: () => (
203
- <div className="w-[418px]">
204
- <Card>
205
- <CardContent>
206
- <CardBody>
207
- <CardTitle>Minimal Card</CardTitle>
208
- <CardDescription>
209
- A minimal card with just title and description.
210
- </CardDescription>
211
- </CardBody>
212
- </CardContent>
213
- </Card>
214
- </div>
215
- ),
216
- };
217
-
218
- // =============================================================================
219
- // Grid Example
220
- // =============================================================================
221
-
222
- export const CardGrid: Story = {
223
- render: () => (
224
- <div className="grid max-w-[900px] grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
225
- {[1, 2, 3].map((i) => (
226
- <Card key={i}>
227
- <CardImage />
228
- <CardContent>
229
- <CardBody>
230
- <CardEyebrow>Category {i}</CardEyebrow>
231
- <div className="flex flex-col gap-[6px]">
232
- <CardTitle>Card Title {i}</CardTitle>
233
- <CardDescription>
234
- Brief description of the card content goes here.
235
- </CardDescription>
236
- </div>
237
- </CardBody>
238
- <CardActions>
239
- <Button size="sm" variant="charcoal">
240
- Action
241
- </Button>
242
- </CardActions>
243
- </CardContent>
244
- </Card>
245
- ))}
246
- </div>
247
- ),
248
- parameters: {
249
- layout: "padded",
250
- },
251
- };
252
-
253
- // =============================================================================
254
- // Playground
255
- // =============================================================================
256
-
257
- export const Playground: Story = {
258
- render: (args) => (
259
- <div className="w-[418px]">
260
- <Card {...args}>
261
- <CardImage />
262
- <CardContent>
263
- <CardBody>
264
- <CardEyebrow>Eyebrow</CardEyebrow>
265
- <div className="flex flex-col gap-[6px]">
266
- <CardTitle>Card Title</CardTitle>
267
- <CardDescription>
268
- Use cards when citizens need to scan items at a glance.
269
- </CardDescription>
270
- </div>
271
- </CardBody>
272
- <CardActions>
273
- <Button size="default" variant="charcoal">
274
- Primary
275
- </Button>
276
- <Button size="default" variant="charcoalOutline">
277
- Secondary
278
- </Button>
279
- </CardActions>
280
- </CardContent>
281
- </Card>
282
- </div>
283
- ),
284
- };
285
- Playground.argTypes = {
286
- layout: {
287
- control: { type: "radio" },
288
- options: ["vertical", "horizontal"],
289
- },
290
- };
291
- Playground.args = {
292
- layout: "vertical",
293
- };
@@ -1,245 +0,0 @@
1
- import { describe, expect, test } from "vitest";
2
- import { page } from "vitest/browser";
3
- import { render } from "vitest-browser-react";
4
- import { Button } from "../../atoms/button";
5
- import {
6
- Card,
7
- CardActions,
8
- CardBody,
9
- CardContent,
10
- CardDescription,
11
- CardEyebrow,
12
- CardImage,
13
- CardTitle,
14
- } from "./card";
15
-
16
- describe("Card", () => {
17
- describe("Accessibility", () => {
18
- test("CardTitle renders as h3 heading by default", async () => {
19
- render(
20
- <Card>
21
- <CardContent>
22
- <CardBody>
23
- <CardTitle>Test Title</CardTitle>
24
- </CardBody>
25
- </CardContent>
26
- </Card>,
27
- );
28
-
29
- await expect
30
- .element(page.getByRole("heading", { level: 3, name: "Test Title" }))
31
- .toBeInTheDocument();
32
- });
33
-
34
- test("CardTitle supports as prop to change heading level", async () => {
35
- render(
36
- <Card>
37
- <CardContent>
38
- <CardBody>
39
- <CardTitle as="h2">H2 Title</CardTitle>
40
- </CardBody>
41
- </CardContent>
42
- </Card>,
43
- );
44
-
45
- await expect
46
- .element(page.getByRole("heading", { level: 2, name: "H2 Title" }))
47
- .toBeInTheDocument();
48
- });
49
-
50
- test("CardImage renders img with alt text when src provided", async () => {
51
- render(
52
- <Card>
53
- <CardImage
54
- src="https://example.com/image.jpg"
55
- alt="Test image description"
56
- />
57
- <CardContent>
58
- <CardBody>
59
- <CardTitle>Card with Image</CardTitle>
60
- </CardBody>
61
- </CardContent>
62
- </Card>,
63
- );
64
-
65
- await expect
66
- .element(page.getByRole("img", { name: "Test image description" }))
67
- .toBeInTheDocument();
68
- });
69
-
70
- test("CardImage does not render img when no src provided", async () => {
71
- render(
72
- <Card>
73
- <CardImage />
74
- <CardContent>
75
- <CardBody>
76
- <CardTitle>Card without Image Source</CardTitle>
77
- </CardBody>
78
- </CardContent>
79
- </Card>,
80
- );
81
-
82
- // Should not have an img element
83
- const images = page.getByRole("img");
84
- await expect.element(images).not.toBeInTheDocument();
85
- });
86
-
87
- test("buttons in CardActions are accessible", async () => {
88
- render(
89
- <Card>
90
- <CardContent>
91
- <CardBody>
92
- <CardTitle>Card with Actions</CardTitle>
93
- </CardBody>
94
- <CardActions>
95
- <Button>Primary Action</Button>
96
- <Button variant="charcoalOutline">Secondary Action</Button>
97
- </CardActions>
98
- </CardContent>
99
- </Card>,
100
- );
101
-
102
- await expect
103
- .element(page.getByRole("button", { name: "Primary Action" }))
104
- .toBeInTheDocument();
105
- await expect
106
- .element(page.getByRole("button", { name: "Secondary Action" }))
107
- .toBeInTheDocument();
108
- });
109
-
110
- test("Card structure is semantically correct", async () => {
111
- render(
112
- <Card data-testid="card">
113
- <CardContent>
114
- <CardBody>
115
- <CardEyebrow>Eyebrow Text</CardEyebrow>
116
- <CardTitle>Card Title</CardTitle>
117
- <CardDescription>Card description text</CardDescription>
118
- </CardBody>
119
- </CardContent>
120
- </Card>,
121
- );
122
-
123
- // Verify all text content is present and readable
124
- await expect.element(page.getByText("Eyebrow Text")).toBeInTheDocument();
125
- await expect.element(page.getByText("Card Title")).toBeInTheDocument();
126
- await expect
127
- .element(page.getByText("Card description text"))
128
- .toBeInTheDocument();
129
- });
130
- });
131
-
132
- describe("Layout Variants", () => {
133
- test("vertical layout applies correct classes", async () => {
134
- render(
135
- <Card layout="vertical" data-testid="card">
136
- <CardContent>
137
- <CardBody>
138
- <CardTitle>Vertical Card</CardTitle>
139
- </CardBody>
140
- </CardContent>
141
- </Card>,
142
- );
143
-
144
- const card = page.getByTestId("card");
145
- await expect.element(card).toHaveClass(/flex-col/);
146
- });
147
-
148
- test("horizontal layout applies correct classes", async () => {
149
- render(
150
- <Card layout="horizontal" data-testid="card">
151
- <CardContent>
152
- <CardBody>
153
- <CardTitle>Horizontal Card</CardTitle>
154
- </CardBody>
155
- </CardContent>
156
- </Card>,
157
- );
158
-
159
- const card = page.getByTestId("card");
160
- await expect.element(card).toHaveClass(/flex-row/);
161
- });
162
-
163
- test("default layout is vertical", async () => {
164
- render(
165
- <Card data-testid="card">
166
- <CardContent>
167
- <CardBody>
168
- <CardTitle>Default Card</CardTitle>
169
- </CardBody>
170
- </CardContent>
171
- </Card>,
172
- );
173
-
174
- const card = page.getByTestId("card");
175
- await expect.element(card).toHaveClass(/flex-col/);
176
- });
177
- });
178
-
179
- describe("Component Composition", () => {
180
- test("renders complete card with all sub-components", async () => {
181
- render(
182
- <Card>
183
- <CardImage src="https://example.com/test.jpg" alt="Test" />
184
- <CardContent>
185
- <CardBody>
186
- <CardEyebrow>Category</CardEyebrow>
187
- <CardTitle>Full Card Example</CardTitle>
188
- <CardDescription>
189
- This is a complete card with all components.
190
- </CardDescription>
191
- </CardBody>
192
- <CardActions>
193
- <Button>Action</Button>
194
- </CardActions>
195
- </CardContent>
196
- </Card>,
197
- );
198
-
199
- await expect
200
- .element(page.getByRole("img", { name: "Test" }))
201
- .toBeInTheDocument();
202
- await expect.element(page.getByText("Category")).toBeInTheDocument();
203
- await expect
204
- .element(page.getByRole("heading", { name: "Full Card Example" }))
205
- .toBeInTheDocument();
206
- await expect
207
- .element(page.getByText("This is a complete card with all components."))
208
- .toBeInTheDocument();
209
- await expect
210
- .element(page.getByRole("button", { name: "Action" }))
211
- .toBeInTheDocument();
212
- });
213
-
214
- test("renders minimal card with only required components", async () => {
215
- render(
216
- <Card>
217
- <CardContent>
218
- <CardBody>
219
- <CardTitle>Minimal</CardTitle>
220
- </CardBody>
221
- </CardContent>
222
- </Card>,
223
- );
224
-
225
- await expect
226
- .element(page.getByRole("heading", { name: "Minimal" }))
227
- .toBeInTheDocument();
228
- });
229
-
230
- test("supports custom className on Card", async () => {
231
- render(
232
- <Card className="custom-class" data-testid="card">
233
- <CardContent>
234
- <CardBody>
235
- <CardTitle>Custom Card</CardTitle>
236
- </CardBody>
237
- </CardContent>
238
- </Card>,
239
- );
240
-
241
- const card = page.getByTestId("card");
242
- await expect.element(card).toHaveClass(/custom-class/);
243
- });
244
- });
245
- });