@nationaldesignstudio/react 0.0.10 → 0.0.11

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 +13650 -6129
  24. package/package.json +11 -21
  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,150 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/react-vite";
2
- import { Button } from "../../atoms/button";
3
- import { Banner } from ".";
4
-
5
- const meta: Meta<typeof Banner> = {
6
- title: "Sections/Banner",
7
- component: Banner,
8
- parameters: {
9
- layout: "fullscreen",
10
- },
11
- argTypes: {
12
- heading: {
13
- control: "text",
14
- description: "The heading text displayed in the banner",
15
- },
16
- description: {
17
- control: "text",
18
- description: "The description text displayed below the heading",
19
- },
20
- },
21
- } as Meta<typeof Banner>;
22
-
23
- export default meta;
24
- type Story = StoryObj<typeof Banner>;
25
-
26
- export const Playground: Story = {
27
- render: (args) => <Banner {...args} />,
28
- };
29
- Playground.args = {
30
- heading: "Important Update",
31
- description:
32
- "Use banners to surface short, important updates or a single key action without disrupting the main page content.",
33
- action: <Button>Learn More</Button>,
34
- };
35
-
36
- // =============================================================================
37
- // Default
38
- // =============================================================================
39
-
40
- /**
41
- * Default banner with heading, description, and action button.
42
- * Responsive across all breakpoints.
43
- */
44
- export const Default: Story = {
45
- render: () => (
46
- <Banner
47
- heading="Important Update"
48
- description="Use banners to surface short, important updates or a single key action without disrupting the main page content."
49
- action={<Button>Learn More</Button>}
50
- />
51
- ),
52
- };
53
-
54
- /**
55
- * Banner without an action button.
56
- */
57
- export const WithoutAction: Story = {
58
- render: () => (
59
- <Banner
60
- heading="Announcement"
61
- description="Use banners to surface short, important updates or a single key action without disrupting the main page content."
62
- />
63
- ),
64
- };
65
-
66
- // =============================================================================
67
- // Responsive Variants
68
- // =============================================================================
69
-
70
- /**
71
- * Desktop viewport (lg breakpoint, 1440px)
72
- * Horizontal layout with 72px padding
73
- */
74
- export const Desktop: Story = {
75
- render: () => (
76
- <Banner
77
- heading="Desktop Banner"
78
- description="Use banners to surface short, important updates or a single key action without disrupting the main page content."
79
- action={<Button>Learn More</Button>}
80
- />
81
- ),
82
- globals: {
83
- viewport: { value: "lg", isRotated: false },
84
- },
85
- };
86
-
87
- /**
88
- * Tablet viewport (md breakpoint, 768px)
89
- * Horizontal layout with 56px padding
90
- */
91
- export const Tablet: Story = {
92
- render: () => (
93
- <Banner
94
- heading="Tablet Banner"
95
- description="Use banners to surface short, important updates or a single key action without disrupting the main page content."
96
- action={<Button>Learn More</Button>}
97
- />
98
- ),
99
- globals: {
100
- viewport: { value: "md", isRotated: false },
101
- },
102
- };
103
-
104
- /**
105
- * Mobile viewport (sm breakpoint, 320px)
106
- * Stacked layout with 20x32px padding
107
- */
108
- export const Mobile: Story = {
109
- render: () => (
110
- <Banner
111
- heading="Mobile Banner"
112
- description="Use banners to surface short, important updates or a single key action without disruption."
113
- action={<Button size="sm">Learn More</Button>}
114
- />
115
- ),
116
- globals: {
117
- viewport: { value: "sm", isRotated: false },
118
- },
119
- };
120
-
121
- // =============================================================================
122
- // Examples
123
- // =============================================================================
124
-
125
- /**
126
- * Banner with a longer description that wraps
127
- */
128
- export const LongDescription: Story = {
129
- render: () => (
130
- <Banner
131
- heading="New Features Available"
132
- description="We've made significant improvements to our platform including enhanced security features, faster load times, improved accessibility across all components, and a redesigned dashboard experience. Check out the documentation for more details on how to take advantage of these updates."
133
- action={<Button>View Documentation</Button>}
134
- />
135
- ),
136
- };
137
-
138
- /**
139
- * Banner with custom styling
140
- */
141
- export const CustomBackground: Story = {
142
- render: () => (
143
- <Banner
144
- heading="Custom Styled Banner"
145
- description="This banner has a custom background color applied via className."
146
- action={<Button variant="ivory">Action</Button>}
147
- className="bg-gray-1000 text-gray-50 [&_h2]:text-gray-50 [&_p]:text-gray-200"
148
- />
149
- ),
150
- };
@@ -1,185 +0,0 @@
1
- import { describe, expect, test } from "vitest";
2
- import { page } from "vitest/browser";
3
- import { render } from "vitest-browser-react";
4
- import { Banner } from "./banner";
5
-
6
- describe("Banner", () => {
7
- describe("Accessibility", () => {
8
- test("renders as section landmark", async () => {
9
- render(
10
- <Banner
11
- heading="Test Banner"
12
- description="Test description"
13
- data-testid="banner"
14
- />,
15
- );
16
-
17
- const banner = page.getByTestId("banner");
18
- await expect.element(banner).toBeInTheDocument();
19
- });
20
-
21
- test("heading renders as h2", async () => {
22
- render(
23
- <Banner heading="Banner Heading" description="Test description" />,
24
- );
25
-
26
- await expect
27
- .element(
28
- page.getByRole("heading", { level: 2, name: "Banner Heading" }),
29
- )
30
- .toBeInTheDocument();
31
- });
32
-
33
- test("description is accessible to screen readers", async () => {
34
- render(
35
- <Banner heading="Test" description="Accessible description text" />,
36
- );
37
-
38
- await expect
39
- .element(page.getByText("Accessible description text"))
40
- .toBeInTheDocument();
41
- });
42
- });
43
-
44
- describe("Props", () => {
45
- test("renders with required heading and description props", async () => {
46
- render(
47
- <Banner
48
- heading="Required Heading"
49
- description="Required description"
50
- />,
51
- );
52
-
53
- await expect
54
- .element(page.getByText("Required Heading"))
55
- .toBeInTheDocument();
56
- await expect
57
- .element(page.getByText("Required description"))
58
- .toBeInTheDocument();
59
- });
60
-
61
- test("renders action when provided", async () => {
62
- render(
63
- <Banner
64
- heading="With Action"
65
- description="Description"
66
- action={<button type="button">Click Me</button>}
67
- />,
68
- );
69
-
70
- await expect
71
- .element(page.getByRole("button", { name: "Click Me" }))
72
- .toBeInTheDocument();
73
- });
74
-
75
- test("does not render action slot when not provided", async () => {
76
- render(
77
- <Banner
78
- heading="Without Action"
79
- description="Description"
80
- data-testid="banner"
81
- />,
82
- );
83
-
84
- const banner = page.getByTestId("banner");
85
- await expect.element(banner).toBeInTheDocument();
86
- // Only heading and description should be present
87
- await expect.element(page.getByRole("button")).not.toBeInTheDocument();
88
- });
89
-
90
- test("supports custom className", async () => {
91
- render(
92
- <Banner
93
- heading="Custom"
94
- description="Description"
95
- className="custom-class"
96
- data-testid="banner"
97
- />,
98
- );
99
-
100
- const banner = page.getByTestId("banner");
101
- await expect.element(banner).toHaveClass(/custom-class/);
102
- });
103
-
104
- test("spreads additional props to section element", async () => {
105
- render(
106
- <Banner
107
- heading="Props Test"
108
- description="Description"
109
- data-testid="banner"
110
- aria-label="Banner section"
111
- />,
112
- );
113
-
114
- const banner = page.getByTestId("banner");
115
- await expect
116
- .element(banner)
117
- .toHaveAttribute("aria-label", "Banner section");
118
- });
119
- });
120
-
121
- describe("Styling", () => {
122
- test("applies default background color", async () => {
123
- render(
124
- <Banner
125
- heading="Default"
126
- description="Description"
127
- data-testid="banner"
128
- />,
129
- );
130
-
131
- const banner = page.getByTestId("banner");
132
- await expect.element(banner).toHaveClass(/bg-gray-50/);
133
- });
134
-
135
- test("applies col-full for grid alignment", async () => {
136
- render(
137
- <Banner
138
- heading="Grid Test"
139
- description="Description"
140
- data-testid="banner"
141
- />,
142
- );
143
-
144
- const banner = page.getByTestId("banner");
145
- await expect.element(banner).toHaveClass(/col-full/);
146
- });
147
-
148
- test("applies responsive padding classes", async () => {
149
- render(
150
- <Banner
151
- heading="Responsive"
152
- description="Description"
153
- data-testid="banner"
154
- />,
155
- );
156
-
157
- const banner = page.getByTestId("banner");
158
- // Mobile padding
159
- await expect.element(banner).toHaveClass(/px-spacing-20/);
160
- await expect.element(banner).toHaveClass(/py-spacing-32/);
161
- });
162
- });
163
-
164
- describe("Content", () => {
165
- test("heading has correct text color", async () => {
166
- render(<Banner heading="Styled Heading" description="Description" />);
167
-
168
- const heading = page.getByRole("heading", { level: 2 });
169
- await expect.element(heading).toHaveClass(/text-gray-900/);
170
- });
171
-
172
- test("description has correct text color", async () => {
173
- render(
174
- <Banner
175
- heading="Test"
176
- description="Styled description"
177
- data-testid="banner"
178
- />,
179
- );
180
-
181
- const description = page.getByText("Styled description");
182
- await expect.element(description).toHaveClass(/text-gray-800/);
183
- });
184
- });
185
- });
@@ -1,130 +0,0 @@
1
- import { cva, type VariantProps } from "class-variance-authority";
2
- import * as React from "react";
3
- import { cn } from "@/lib/utils";
4
-
5
- /**
6
- * Banner component based on Figma BaseKit / Banners
7
- *
8
- * Used to surface short, important updates or a single key action
9
- * without disrupting the main page content.
10
- *
11
- * Responsive behavior using 24-column grid:
12
- * - Mobile (sm): Stacked layout, 20px horizontal / 32px vertical padding
13
- * - Tablet (md): Horizontal layout, 56px padding
14
- * - Desktop (lg): Horizontal layout, 72px padding
15
- *
16
- * Must be placed inside a `grid-container`. Uses `col-full` to span all columns.
17
- */
18
- const bannerVariants = cva(
19
- [
20
- // Grid alignment - full width
21
- "col-full",
22
- // Responsive padding: mobile -> tablet -> desktop
23
- "px-spacing-20 py-spacing-32",
24
- "md:p-spacing-56",
25
- "lg:px-spacing-72 lg:pb-spacing-72 lg:pt-0",
26
- ],
27
- {
28
- variants: {
29
- theme: {
30
- light: "bg-gray-50",
31
- dark: "bg-gray-1200",
32
- },
33
- },
34
- defaultVariants: {
35
- theme: "light",
36
- },
37
- },
38
- );
39
-
40
- export interface BannerProps
41
- extends React.HTMLAttributes<HTMLElement>,
42
- VariantProps<typeof bannerVariants> {
43
- /**
44
- * The heading text displayed in the banner
45
- */
46
- heading: string;
47
- /**
48
- * The description text displayed below the heading
49
- */
50
- description: string;
51
- /**
52
- * Optional action element (typically a Button component)
53
- */
54
- action?: React.ReactNode;
55
- }
56
-
57
- /**
58
- * Banner component for surfacing important updates or CTAs.
59
- *
60
- * Uses the 24-column grid system - must be placed inside a `grid-container`.
61
- * Spans full width with `col-full`.
62
- *
63
- * Responsive across breakpoints:
64
- * - Mobile: Stacked layout with smaller padding
65
- * - Tablet: Horizontal layout with medium padding
66
- * - Desktop: Horizontal layout with larger padding
67
- *
68
- * @example
69
- * ```tsx
70
- * <div className="grid-container">
71
- * <Banner
72
- * heading="Important Update"
73
- * description="Check out our new features."
74
- * action={<Button>Learn More</Button>}
75
- * />
76
- * </div>
77
- *
78
- * // Dark theme
79
- * <Banner
80
- * theme="dark"
81
- * heading="Still Have Questions?"
82
- * description="Contact us at support@example.com"
83
- * action={<Button variant="secondary">Email Us</Button>}
84
- * />
85
- * ```
86
- */
87
- const Banner = React.forwardRef<HTMLElement, BannerProps>(
88
- ({ className, theme, heading, description, action, ...props }, ref) => {
89
- return (
90
- <section
91
- ref={ref}
92
- className={cn(bannerVariants({ theme }), className)}
93
- {...props}
94
- >
95
- {/* Inner container with border-top for dark theme */}
96
- <div
97
- className={cn(
98
- "flex flex-col md:flex-row gap-spacing-20 items-start md:items-center md:justify-between",
99
- theme === "dark" && "border-t border-gray-700 py-spacing-36",
100
- )}
101
- >
102
- {/* Copy section */}
103
- <div className="flex flex-col gap-spacing-6 items-start">
104
- <h2
105
- className={cn(
106
- "typography-subheading-small",
107
- theme === "dark" ? "text-gray-100" : "text-gray-900",
108
- )}
109
- >
110
- {heading}
111
- </h2>
112
- <p
113
- className={cn(
114
- "typography-body-small",
115
- theme === "dark" ? "text-gray-500" : "text-gray-800",
116
- )}
117
- >
118
- {description}
119
- </p>
120
- </div>
121
- {/* Action slot */}
122
- {action}
123
- </div>
124
- </section>
125
- );
126
- },
127
- );
128
- Banner.displayName = "Banner";
129
-
130
- export { Banner, bannerVariants };
@@ -1,2 +0,0 @@
1
- export type { BannerProps } from "./banner";
2
- export { Banner, bannerVariants } from "./banner";