@nationaldesignstudio/react 0.0.7 → 0.0.8

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 (170) hide show
  1. package/README.md +0 -4
  2. package/dist/assets/fonts/PPNeueMontreal-Variable.woff2 +0 -0
  3. package/dist/assets/react.svg +1 -0
  4. package/dist/components/atoms/accordion/accordion.d.ts +50 -0
  5. package/dist/components/{button → atoms/button}/button.d.ts +5 -4
  6. package/dist/components/atoms/pager-control/pager-control.d.ts +62 -0
  7. package/dist/components/{card → organisms/card}/card.d.ts +6 -2
  8. package/dist/components/{navbar → organisms/navbar}/navbar.d.ts +27 -1
  9. package/dist/components/sections/banner/banner.d.ts +64 -0
  10. package/dist/components/sections/card-grid/card-grid.d.ts +53 -0
  11. package/dist/components/sections/faq-section/faq-section.d.ts +44 -0
  12. package/dist/components/sections/hero/hero.d.ts +73 -0
  13. package/dist/components/sections/river/river.d.ts +63 -0
  14. package/dist/components/sections/tout/tout.d.ts +73 -0
  15. package/dist/components/sections/two-column-section/two-column-section.d.ts +58 -0
  16. package/dist/index.d.ts +28 -12
  17. package/dist/index.js +3185 -813
  18. package/dist/index.js.map +1 -1
  19. package/dist/tailwind.css +23 -0
  20. package/dist/tokens.css +2009 -103
  21. package/package.json +23 -5
  22. package/src/App.css +0 -0
  23. package/src/App.tsx +7 -0
  24. package/src/assets/fonts/PPNeueMontreal-Variable.woff2 +0 -0
  25. package/src/assets/react.svg +1 -0
  26. package/src/components/atoms/accordion/accordion.stories.tsx +228 -0
  27. package/src/components/atoms/accordion/accordion.tsx +137 -0
  28. package/src/components/atoms/accordion/index.ts +6 -0
  29. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-chromium-darwin.png +0 -0
  30. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-chromium-linux.png +0 -0
  31. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-chromium-darwin.png +0 -0
  32. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-chromium-linux.png +0 -0
  33. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-quiet-chromium-darwin.png +0 -0
  34. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-quiet-chromium-linux.png +0 -0
  35. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-disabled-chromium-darwin.png +0 -0
  36. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-disabled-chromium-linux.png +0 -0
  37. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-chromium-darwin.png +0 -0
  38. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-chromium-linux.png +0 -0
  39. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-chromium-darwin.png +0 -0
  40. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-chromium-linux.png +0 -0
  41. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-quiet-chromium-darwin.png +0 -0
  42. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-quiet-chromium-linux.png +0 -0
  43. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-large-chromium-darwin.png +0 -0
  44. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-large-chromium-linux.png +0 -0
  45. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-medium-chromium-darwin.png +0 -0
  46. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-medium-chromium-linux.png +0 -0
  47. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-small-chromium-darwin.png +0 -0
  48. package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-small-chromium-linux.png +0 -0
  49. package/src/components/atoms/button/button.stories.tsx +93 -0
  50. package/src/components/atoms/button/button.test.tsx +141 -0
  51. package/src/components/atoms/button/button.tsx +95 -0
  52. package/src/components/atoms/button/button.visual.test.tsx +102 -0
  53. package/src/components/atoms/button/icon-button.stories.tsx +175 -0
  54. package/src/components/atoms/button/icon-button.tsx +90 -0
  55. package/src/components/atoms/button/index.ts +6 -0
  56. package/src/components/atoms/pager-control/index.ts +5 -0
  57. package/src/components/atoms/pager-control/pager-control.stories.tsx +212 -0
  58. package/src/components/atoms/pager-control/pager-control.test.tsx +149 -0
  59. package/src/components/atoms/pager-control/pager-control.tsx +328 -0
  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 +293 -0
  73. package/src/components/organisms/card/card.test.tsx +245 -0
  74. package/src/components/organisms/card/card.tsx +227 -0
  75. package/src/components/organisms/card/card.visual.test.tsx +197 -0
  76. package/src/components/organisms/card/index.ts +19 -0
  77. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-active-link-chromium-darwin.png +0 -0
  78. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-active-link-chromium-linux.png +0 -0
  79. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-brand-only-chromium-darwin.png +0 -0
  80. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-brand-only-chromium-linux.png +0 -0
  81. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-default-chromium-darwin.png +0 -0
  82. package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-default-chromium-linux.png +0 -0
  83. package/src/components/organisms/navbar/index.ts +18 -0
  84. package/src/components/organisms/navbar/navbar.stories.tsx +313 -0
  85. package/src/components/organisms/navbar/navbar.test.tsx +190 -0
  86. package/src/components/organisms/navbar/navbar.tsx +365 -0
  87. package/src/components/organisms/navbar/navbar.visual.test.tsx +85 -0
  88. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-icon-chromium-darwin.png +0 -0
  89. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-icon-chromium-linux.png +0 -0
  90. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-text-chromium-darwin.png +0 -0
  91. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-text-chromium-linux.png +0 -0
  92. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-default-chromium-darwin.png +0 -0
  93. package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-default-chromium-linux.png +0 -0
  94. package/src/components/organisms/us-gov-banner/index.ts +1 -0
  95. package/src/components/organisms/us-gov-banner/us-gov-banner.stories.tsx +35 -0
  96. package/src/components/organisms/us-gov-banner/us-gov-banner.test.tsx +107 -0
  97. package/src/components/organisms/us-gov-banner/us-gov-banner.tsx +73 -0
  98. package/src/components/organisms/us-gov-banner/us-gov-banner.visual.test.tsx +46 -0
  99. package/src/components/sections/banner/banner.stories.tsx +150 -0
  100. package/src/components/sections/banner/banner.test.tsx +185 -0
  101. package/src/components/sections/banner/banner.tsx +132 -0
  102. package/src/components/sections/banner/index.ts +2 -0
  103. package/src/components/sections/card-grid/card-grid.stories.tsx +351 -0
  104. package/src/components/sections/card-grid/card-grid.tsx +118 -0
  105. package/src/components/sections/card-grid/index.ts +1 -0
  106. package/src/components/sections/faq-section/faq-section.tsx +76 -0
  107. package/src/components/sections/faq-section/index.ts +2 -0
  108. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-desktop-chromium-darwin.png +0 -0
  109. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-desktop-chromium-linux.png +0 -0
  110. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-mobile-chromium-darwin.png +0 -0
  111. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-mobile-chromium-linux.png +0 -0
  112. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-tablet-chromium-darwin.png +0 -0
  113. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-tablet-chromium-linux.png +0 -0
  114. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-desktop-chromium-darwin.png +0 -0
  115. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-desktop-chromium-linux.png +0 -0
  116. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-mobile-chromium-darwin.png +0 -0
  117. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-mobile-chromium-linux.png +0 -0
  118. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-tablet-chromium-darwin.png +0 -0
  119. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-tablet-chromium-linux.png +0 -0
  120. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-desktop-chromium-darwin.png +0 -0
  121. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-desktop-chromium-linux.png +0 -0
  122. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-mobile-chromium-darwin.png +0 -0
  123. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-mobile-chromium-linux.png +0 -0
  124. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-tablet-chromium-darwin.png +0 -0
  125. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-tablet-chromium-linux.png +0 -0
  126. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-custom-class-chromium-darwin.png +0 -0
  127. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-custom-class-chromium-linux.png +0 -0
  128. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-default-chromium-linux.png +0 -0
  129. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-long-title-chromium-darwin.png +0 -0
  130. package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-long-title-chromium-linux.png +0 -0
  131. package/src/components/sections/hero/hero.stories.tsx +145 -0
  132. package/src/components/sections/hero/hero.test.tsx +135 -0
  133. package/src/components/sections/hero/hero.tsx +190 -0
  134. package/src/components/sections/hero/hero.visual.test.tsx +140 -0
  135. package/src/components/sections/hero/index.ts +1 -0
  136. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-h3-heading-chromium-darwin.png +0 -0
  137. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-h3-heading-chromium-linux.png +0 -0
  138. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-paragraphs-chromium-darwin.png +0 -0
  139. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-paragraphs-chromium-linux.png +0 -0
  140. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-sections-chromium-darwin.png +0 -0
  141. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-sections-chromium-linux.png +0 -0
  142. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-single-section-chromium-darwin.png +0 -0
  143. package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-single-section-chromium-linux.png +0 -0
  144. package/src/components/sections/prose/index.ts +6 -0
  145. package/src/components/sections/prose/prose.stories.tsx +144 -0
  146. package/src/components/sections/prose/prose.test.tsx +178 -0
  147. package/src/components/sections/prose/prose.tsx +88 -0
  148. package/src/components/sections/prose/prose.visual.test.tsx +105 -0
  149. package/src/components/sections/river/index.ts +1 -0
  150. package/src/components/sections/river/river.stories.tsx +237 -0
  151. package/src/components/sections/river/river.test.tsx +268 -0
  152. package/src/components/sections/river/river.tsx +175 -0
  153. package/src/components/sections/tout/index.ts +1 -0
  154. package/src/components/sections/tout/tout.stories.tsx +154 -0
  155. package/src/components/sections/tout/tout.test.tsx +242 -0
  156. package/src/components/sections/tout/tout.tsx +205 -0
  157. package/src/components/sections/two-column-section/index.ts +5 -0
  158. package/src/components/sections/two-column-section/two-column-section.stories.tsx +285 -0
  159. package/src/components/sections/two-column-section/two-column-section.tsx +155 -0
  160. package/src/index.ts +98 -0
  161. package/src/lib/utils.ts +6 -0
  162. package/src/main.tsx +13 -0
  163. package/src/stories/Introduction.mdx +114 -0
  164. package/src/stories/TokenShowcase.stories.tsx +92 -0
  165. package/src/stories/TokenShowcase.tsx +1352 -0
  166. package/src/styles.css +11 -0
  167. package/dist/components/hero/hero.d.ts +0 -17
  168. /package/dist/components/{button → atoms/button}/icon-button.d.ts +0 -0
  169. /package/dist/components/{us-gov-banner → organisms/us-gov-banner}/us-gov-banner.d.ts +0 -0
  170. /package/dist/components/{prose → sections/prose}/prose.d.ts +0 -0
@@ -0,0 +1,227 @@
1
+ import { cva, type VariantProps } from "class-variance-authority";
2
+ import * as React from "react";
3
+ import { cn } from "@/lib/utils";
4
+
5
+ const cardVariants = cva("flex overflow-hidden rounded-[24px] bg-white", {
6
+ variants: {
7
+ layout: {
8
+ vertical: "w-full flex-col",
9
+ horizontal: "w-full flex-row",
10
+ },
11
+ },
12
+ defaultVariants: {
13
+ layout: "vertical",
14
+ },
15
+ });
16
+
17
+ export interface CardProps
18
+ extends React.HTMLAttributes<HTMLDivElement>,
19
+ VariantProps<typeof cardVariants> {}
20
+
21
+ /**
22
+ * Card component for displaying content in a contained, scannable format.
23
+ *
24
+ * Layouts:
25
+ * - vertical: Image on top, content below (default)
26
+ * - horizontal: Image on left, content on right
27
+ *
28
+ * Use with CardImage, CardContent, CardEyebrow, CardTitle, CardDescription, and CardActions.
29
+ */
30
+ const Card = React.forwardRef<HTMLDivElement, CardProps>(
31
+ ({ className, layout, ...props }, ref) => {
32
+ return (
33
+ <div
34
+ ref={ref}
35
+ className={cn(cardVariants({ layout, className }))}
36
+ {...props}
37
+ />
38
+ );
39
+ },
40
+ );
41
+ Card.displayName = "Card";
42
+
43
+ export interface CardImageProps extends React.HTMLAttributes<HTMLDivElement> {
44
+ /**
45
+ * The image source URL
46
+ */
47
+ src?: string;
48
+ /**
49
+ * Alt text for the image
50
+ */
51
+ alt?: string;
52
+ }
53
+
54
+ /**
55
+ * Card image area. For vertical layout, displays with 16:9 aspect ratio.
56
+ * For horizontal layout, takes up ~40% width and stretches to content height.
57
+ */
58
+ const CardImage = React.forwardRef<HTMLDivElement, CardImageProps>(
59
+ ({ className, src, alt = "", ...props }, ref) => {
60
+ return (
61
+ <div
62
+ ref={ref}
63
+ className={cn(
64
+ "relative shrink-0 bg-gray-500",
65
+ // Vertical: full width with aspect ratio
66
+ "aspect-video w-full",
67
+ // When in horizontal card (parent has flex-row), override
68
+ "[.flex-row>&]:aspect-auto [.flex-row>&]:w-2/5 [.flex-row>&]:self-stretch",
69
+ className,
70
+ )}
71
+ {...props}
72
+ >
73
+ {src && (
74
+ <img
75
+ src={src}
76
+ alt={alt}
77
+ className="absolute inset-0 size-full object-cover"
78
+ />
79
+ )}
80
+ </div>
81
+ );
82
+ },
83
+ );
84
+ CardImage.displayName = "CardImage";
85
+
86
+ export interface CardContentProps
87
+ extends React.HTMLAttributes<HTMLDivElement> {}
88
+
89
+ /**
90
+ * Card content container with proper padding and spacing.
91
+ */
92
+ const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(
93
+ ({ className, ...props }, ref) => {
94
+ return (
95
+ <div
96
+ ref={ref}
97
+ className={cn(
98
+ "flex w-full flex-1 flex-col gap-spacing-24 p-spacing-24",
99
+ className,
100
+ )}
101
+ {...props}
102
+ />
103
+ );
104
+ },
105
+ );
106
+ CardContent.displayName = "CardContent";
107
+
108
+ export interface CardEyebrowProps
109
+ extends React.HTMLAttributes<HTMLParagraphElement> {}
110
+
111
+ /**
112
+ * Optional eyebrow text above the card title.
113
+ */
114
+ const CardEyebrow = React.forwardRef<HTMLParagraphElement, CardEyebrowProps>(
115
+ ({ className, ...props }, ref) => {
116
+ return (
117
+ <p
118
+ ref={ref}
119
+ className={cn(
120
+ "typography-brand-large-caption-large text-gray-500",
121
+ className,
122
+ )}
123
+ {...props}
124
+ />
125
+ );
126
+ },
127
+ );
128
+ CardEyebrow.displayName = "CardEyebrow";
129
+
130
+ export interface CardTitleProps
131
+ extends React.HTMLAttributes<HTMLHeadingElement> {
132
+ /**
133
+ * The heading level to render (h1-h6). Defaults to h3.
134
+ */
135
+ as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
136
+ }
137
+
138
+ /**
139
+ * Card title/heading. Use the `as` prop to change the heading level.
140
+ */
141
+ const CardTitle = React.forwardRef<HTMLHeadingElement, CardTitleProps>(
142
+ ({ className, as: Component = "h3", ...props }, ref) => {
143
+ return (
144
+ <Component
145
+ ref={ref}
146
+ className={cn(
147
+ "typography-brand-large-subheading-small text-gray-1100",
148
+ className,
149
+ )}
150
+ {...props}
151
+ />
152
+ );
153
+ },
154
+ );
155
+ CardTitle.displayName = "CardTitle";
156
+
157
+ export interface CardDescriptionProps
158
+ extends React.HTMLAttributes<HTMLParagraphElement> {}
159
+
160
+ /**
161
+ * Card body/description text.
162
+ */
163
+ const CardDescription = React.forwardRef<
164
+ HTMLParagraphElement,
165
+ CardDescriptionProps
166
+ >(({ className, ...props }, ref) => {
167
+ return (
168
+ <p
169
+ ref={ref}
170
+ className={cn(
171
+ "typography-brand-large-body-small text-gray-800",
172
+ className,
173
+ )}
174
+ {...props}
175
+ />
176
+ );
177
+ });
178
+ CardDescription.displayName = "CardDescription";
179
+
180
+ export interface CardBodyProps extends React.HTMLAttributes<HTMLDivElement> {}
181
+
182
+ /**
183
+ * Container for card text content (eyebrow, title, description).
184
+ */
185
+ const CardBody = React.forwardRef<HTMLDivElement, CardBodyProps>(
186
+ ({ className, ...props }, ref) => {
187
+ return (
188
+ <div
189
+ ref={ref}
190
+ className={cn("flex w-full flex-col gap-spacing-14", className)}
191
+ {...props}
192
+ />
193
+ );
194
+ },
195
+ );
196
+ CardBody.displayName = "CardBody";
197
+
198
+ export interface CardActionsProps
199
+ extends React.HTMLAttributes<HTMLDivElement> {}
200
+
201
+ /**
202
+ * Container for card action buttons.
203
+ */
204
+ const CardActions = React.forwardRef<HTMLDivElement, CardActionsProps>(
205
+ ({ className, ...props }, ref) => {
206
+ return (
207
+ <div
208
+ ref={ref}
209
+ className={cn("flex gap-spacing-11", className)}
210
+ {...props}
211
+ />
212
+ );
213
+ },
214
+ );
215
+ CardActions.displayName = "CardActions";
216
+
217
+ export {
218
+ Card,
219
+ cardVariants,
220
+ CardImage,
221
+ CardContent,
222
+ CardEyebrow,
223
+ CardTitle,
224
+ CardDescription,
225
+ CardBody,
226
+ CardActions,
227
+ };
@@ -0,0 +1,197 @@
1
+ import { render } from "@testing-library/react";
2
+ import { describe, expect, test } from "vitest";
3
+ import { page } from "vitest/browser";
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 Visual Regression", () => {
17
+ test("default vertical layout renders correctly", async () => {
18
+ render(
19
+ <div
20
+ style={{ width: "418px", backgroundColor: "#1a1a1a", padding: "20px" }}
21
+ >
22
+ <Card data-testid="card">
23
+ <CardImage />
24
+ <CardContent>
25
+ <CardBody>
26
+ <CardEyebrow>Optional Eyebrow</CardEyebrow>
27
+ <div className="flex flex-col gap-[6px]">
28
+ <CardTitle>Card Title</CardTitle>
29
+ <CardDescription>
30
+ Use cards when citizens need to scan items at a glance.
31
+ </CardDescription>
32
+ </div>
33
+ </CardBody>
34
+ <CardActions>
35
+ <Button size="default" variant="charcoal">
36
+ Primary
37
+ </Button>
38
+ <Button size="default" variant="charcoalOutline">
39
+ Secondary
40
+ </Button>
41
+ </CardActions>
42
+ </CardContent>
43
+ </Card>
44
+ </div>,
45
+ );
46
+
47
+ await expect(page.getByTestId("card")).toMatchScreenshot(
48
+ "card-default-vertical",
49
+ );
50
+ });
51
+
52
+ test("horizontal layout renders correctly", async () => {
53
+ render(
54
+ <div
55
+ style={{ width: "700px", backgroundColor: "#1a1a1a", padding: "20px" }}
56
+ >
57
+ <Card layout="horizontal" data-testid="card">
58
+ <CardImage />
59
+ <CardContent>
60
+ <CardBody>
61
+ <CardEyebrow>Eyebrow</CardEyebrow>
62
+ <div className="flex flex-col gap-[9px]">
63
+ <CardTitle>
64
+ Cards can support multi line headings easily.
65
+ </CardTitle>
66
+ <CardDescription>
67
+ Use cards when citizens need to scan items at a glance.
68
+ </CardDescription>
69
+ </div>
70
+ </CardBody>
71
+ <CardActions>
72
+ <Button size="sm" variant="charcoal">
73
+ Primary
74
+ </Button>
75
+ <Button size="sm" variant="charcoalOutline">
76
+ Secondary
77
+ </Button>
78
+ </CardActions>
79
+ </CardContent>
80
+ </Card>
81
+ </div>,
82
+ );
83
+
84
+ await expect(page.getByTestId("card")).toMatchScreenshot("card-horizontal");
85
+ });
86
+
87
+ test("without image renders correctly", async () => {
88
+ render(
89
+ <div
90
+ style={{ width: "418px", backgroundColor: "#1a1a1a", padding: "20px" }}
91
+ >
92
+ <Card data-testid="card">
93
+ <CardContent>
94
+ <CardBody>
95
+ <CardEyebrow>Category</CardEyebrow>
96
+ <div className="flex flex-col gap-[6px]">
97
+ <CardTitle>Card Without Image</CardTitle>
98
+ <CardDescription>
99
+ Cards can be used without images for text-focused content.
100
+ </CardDescription>
101
+ </div>
102
+ </CardBody>
103
+ <CardActions>
104
+ <Button size="default" variant="charcoal">
105
+ Learn More
106
+ </Button>
107
+ </CardActions>
108
+ </CardContent>
109
+ </Card>
110
+ </div>,
111
+ );
112
+
113
+ await expect(page.getByTestId("card")).toMatchScreenshot(
114
+ "card-without-image",
115
+ );
116
+ });
117
+
118
+ test("without eyebrow renders correctly", async () => {
119
+ render(
120
+ <div
121
+ style={{ width: "418px", backgroundColor: "#1a1a1a", padding: "20px" }}
122
+ >
123
+ <Card data-testid="card">
124
+ <CardImage />
125
+ <CardContent>
126
+ <CardBody>
127
+ <div className="flex flex-col gap-[6px]">
128
+ <CardTitle>Card Title</CardTitle>
129
+ <CardDescription>
130
+ The eyebrow is optional and can be omitted when not needed.
131
+ </CardDescription>
132
+ </div>
133
+ </CardBody>
134
+ <CardActions>
135
+ <Button size="default" variant="charcoal">
136
+ Primary
137
+ </Button>
138
+ </CardActions>
139
+ </CardContent>
140
+ </Card>
141
+ </div>,
142
+ );
143
+
144
+ await expect(page.getByTestId("card")).toMatchScreenshot(
145
+ "card-without-eyebrow",
146
+ );
147
+ });
148
+
149
+ test("without actions renders correctly", async () => {
150
+ render(
151
+ <div
152
+ style={{ width: "418px", backgroundColor: "#1a1a1a", padding: "20px" }}
153
+ >
154
+ <Card data-testid="card">
155
+ <CardImage />
156
+ <CardContent>
157
+ <CardBody>
158
+ <CardEyebrow>Information</CardEyebrow>
159
+ <div className="flex flex-col gap-[6px]">
160
+ <CardTitle>Informational Card</CardTitle>
161
+ <CardDescription>
162
+ Cards without actions can be used for purely informational
163
+ content.
164
+ </CardDescription>
165
+ </div>
166
+ </CardBody>
167
+ </CardContent>
168
+ </Card>
169
+ </div>,
170
+ );
171
+
172
+ await expect(page.getByTestId("card")).toMatchScreenshot(
173
+ "card-without-actions",
174
+ );
175
+ });
176
+
177
+ test("minimal card renders correctly", async () => {
178
+ render(
179
+ <div
180
+ style={{ width: "418px", backgroundColor: "#1a1a1a", padding: "20px" }}
181
+ >
182
+ <Card data-testid="card">
183
+ <CardContent>
184
+ <CardBody>
185
+ <CardTitle>Minimal Card</CardTitle>
186
+ <CardDescription>
187
+ A minimal card with just title and description.
188
+ </CardDescription>
189
+ </CardBody>
190
+ </CardContent>
191
+ </Card>
192
+ </div>,
193
+ );
194
+
195
+ await expect(page.getByTestId("card")).toMatchScreenshot("card-minimal");
196
+ });
197
+ });
@@ -0,0 +1,19 @@
1
+ export {
2
+ Card,
3
+ CardActions,
4
+ type CardActionsProps,
5
+ CardBody,
6
+ type CardBodyProps,
7
+ CardContent,
8
+ type CardContentProps,
9
+ CardDescription,
10
+ type CardDescriptionProps,
11
+ CardEyebrow,
12
+ type CardEyebrowProps,
13
+ CardImage,
14
+ type CardImageProps,
15
+ type CardProps,
16
+ CardTitle,
17
+ type CardTitleProps,
18
+ cardVariants,
19
+ } from "./card";
@@ -0,0 +1,18 @@
1
+ export {
2
+ Navbar,
3
+ NavbarActions,
4
+ type NavbarActionsProps,
5
+ NavbarBrand,
6
+ type NavbarBrandProps,
7
+ NavbarLink,
8
+ type NavbarLinkProps,
9
+ NavbarLinks,
10
+ type NavbarLinksProps,
11
+ NavbarMobileMenu,
12
+ NavbarMobileMenuButton,
13
+ type NavbarMobileMenuButtonProps,
14
+ NavbarMobileMenuLink,
15
+ type NavbarMobileMenuLinkProps,
16
+ type NavbarMobileMenuProps,
17
+ type NavbarProps,
18
+ } from "./navbar";