@nationaldesignstudio/react 0.1.0 → 0.2.0
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.
- package/dist/component-registry.md +46 -19
- package/dist/components/atoms/accordion/accordion.d.ts +7 -7
- package/dist/components/sections/banner/banner.d.ts +9 -9
- package/dist/components/sections/faq-section/faq-section.d.ts +1 -1
- package/dist/components/sections/hero/hero.d.ts +115 -18
- package/dist/components/sections/tout/tout.d.ts +8 -8
- package/dist/components/sections/two-column-section/two-column-section.d.ts +7 -21
- package/dist/index.js +1212 -1188
- package/dist/index.js.map +1 -1
- package/dist/tokens.css +16 -16
- package/package.json +1 -1
- package/src/components/atoms/accordion/accordion.test.tsx +18 -20
- package/src/components/atoms/accordion/accordion.tsx +19 -17
- package/src/components/atoms/background/background.test.tsx +2 -2
- package/src/components/atoms/background/background.tsx +48 -29
- package/src/components/atoms/button/button.tsx +1 -1
- package/src/components/atoms/button/icon-button.tsx +51 -16
- package/src/components/organisms/card/card.test.tsx +4 -2
- package/src/components/sections/banner/banner.stories.tsx +5 -1
- package/src/components/sections/banner/banner.tsx +10 -10
- package/src/components/sections/faq-section/faq-section.stories.tsx +7 -7
- package/src/components/sections/faq-section/faq-section.tsx +3 -3
- package/src/components/sections/hero/hero.tsx +33 -51
- package/src/components/sections/tout/tout.stories.tsx +31 -7
- package/src/components/sections/tout/tout.tsx +6 -8
- package/src/components/sections/two-column-section/two-column-section.stories.tsx +11 -11
- package/src/components/sections/two-column-section/two-column-section.tsx +16 -10
|
@@ -41,7 +41,7 @@ export interface FaqSectionProps
|
|
|
41
41
|
* </FaqSection>
|
|
42
42
|
*
|
|
43
43
|
* // With custom title
|
|
44
|
-
* <FaqSection title="Common Questions"
|
|
44
|
+
* <FaqSection title="Common Questions" colorScheme="light">
|
|
45
45
|
* ...
|
|
46
46
|
* </FaqSection>
|
|
47
47
|
* ```
|
|
@@ -50,7 +50,7 @@ const FaqSection = React.forwardRef<HTMLElement, FaqSectionProps>(
|
|
|
50
50
|
(
|
|
51
51
|
{
|
|
52
52
|
className,
|
|
53
|
-
|
|
53
|
+
colorScheme = "light",
|
|
54
54
|
title = "Frequently Asked Questions",
|
|
55
55
|
children,
|
|
56
56
|
layout,
|
|
@@ -61,7 +61,7 @@ const FaqSection = React.forwardRef<HTMLElement, FaqSectionProps>(
|
|
|
61
61
|
return (
|
|
62
62
|
<TwoColumnSection
|
|
63
63
|
ref={ref}
|
|
64
|
-
|
|
64
|
+
colorScheme={colorScheme}
|
|
65
65
|
layout={layout ?? undefined}
|
|
66
66
|
title={title}
|
|
67
67
|
className={cn(
|
|
@@ -18,56 +18,54 @@ export {
|
|
|
18
18
|
type BackgroundVideoProps as HeroBackgroundVideoProps,
|
|
19
19
|
} from "@/components/atoms/background";
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// =============================================================================
|
|
21
|
+
const DEFAULT_TITLE_TYPOGRAPHY =
|
|
22
|
+
"text-64 leading-64 tracking-64 md:text-128 md:leading-128 md:tracking-128 lg:text-192 lg:leading-192 lg:tracking-192 font-medium";
|
|
24
23
|
|
|
25
|
-
/**
|
|
26
|
-
* Hero variants based on Figma BaseKit / Heros
|
|
27
|
-
*
|
|
28
|
-
* Slots:
|
|
29
|
-
* - root: The outer container
|
|
30
|
-
* - top: Full-width slot at top for banners/nav (no padding)
|
|
31
|
-
* - content: Padded content area with alignment
|
|
32
|
-
*
|
|
33
|
-
* Variants:
|
|
34
|
-
* - A1: Content aligned at bottom (default)
|
|
35
|
-
* - A2: Content aligned at top
|
|
36
|
-
* - A3: Content centered
|
|
37
|
-
*/
|
|
38
24
|
const heroVariants = tv({
|
|
39
25
|
slots: {
|
|
40
26
|
root: "relative flex w-full flex-col overflow-hidden",
|
|
41
27
|
top: "relative z-10 w-full",
|
|
42
28
|
content: [
|
|
43
29
|
"relative z-10 mx-auto flex w-full max-w-screen-xl flex-1 flex-col",
|
|
44
|
-
// Mobile padding
|
|
45
30
|
"p-spacing-20",
|
|
46
|
-
// Tablet padding
|
|
47
31
|
"md:p-spacing-56",
|
|
48
32
|
],
|
|
33
|
+
title: DEFAULT_TITLE_TYPOGRAPHY,
|
|
49
34
|
},
|
|
50
35
|
variants: {
|
|
51
36
|
variant: {
|
|
52
|
-
// A1: Content at bottom
|
|
53
37
|
A1: {
|
|
54
38
|
root: "min-h-[80vh]",
|
|
55
39
|
content: ["justify-end", "lg:p-spacing-72"],
|
|
56
40
|
},
|
|
57
|
-
// A2: Content at top
|
|
58
41
|
A2: {
|
|
59
42
|
root: "min-h-[80vh]",
|
|
60
43
|
content: ["justify-start", "lg:p-spacing-64"],
|
|
61
44
|
},
|
|
62
|
-
// A3: Content centered
|
|
63
45
|
A3: {
|
|
64
46
|
root: "min-h-[80vh]",
|
|
65
47
|
content: ["items-center justify-center", "lg:p-spacing-64"],
|
|
66
48
|
},
|
|
67
49
|
},
|
|
50
|
+
colorScheme: {
|
|
51
|
+
dark: {
|
|
52
|
+
root: "bg-bg-page",
|
|
53
|
+
title: "text-text-primary",
|
|
54
|
+
},
|
|
55
|
+
light: {
|
|
56
|
+
root: "bg-gray-900",
|
|
57
|
+
title: "text-text-inverted",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
hasBackground: {
|
|
61
|
+
true: {
|
|
62
|
+
root: "bg-transparent",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
68
65
|
},
|
|
69
66
|
defaultVariants: {
|
|
70
67
|
variant: "A1",
|
|
68
|
+
colorScheme: "dark",
|
|
71
69
|
},
|
|
72
70
|
});
|
|
73
71
|
|
|
@@ -141,6 +139,12 @@ export interface HeroProps
|
|
|
141
139
|
* Default: "text-64 leading-64 tracking-64 md:text-128 md:leading-128 md:tracking-128 lg:text-192 lg:leading-192 lg:tracking-192"
|
|
142
140
|
*/
|
|
143
141
|
titleClassName?: string;
|
|
142
|
+
/**
|
|
143
|
+
* Color scheme for text content.
|
|
144
|
+
* - dark: Dark text for use on light backgrounds (default)
|
|
145
|
+
* - light: Light text for use on dark backgrounds
|
|
146
|
+
*/
|
|
147
|
+
colorScheme?: "dark" | "light";
|
|
144
148
|
/**
|
|
145
149
|
* Content for the top slot (full-width, no padding).
|
|
146
150
|
* Use for USGovBanner, Navigation, etc.
|
|
@@ -172,13 +176,6 @@ export interface HeroProps
|
|
|
172
176
|
theme?: ComponentTheme;
|
|
173
177
|
}
|
|
174
178
|
|
|
175
|
-
/**
|
|
176
|
-
* Default responsive typography for hero title using primitive tokens
|
|
177
|
-
* Mobile: 64px, Tablet: 128px, Desktop: 192px
|
|
178
|
-
*/
|
|
179
|
-
const DEFAULT_TITLE_TYPOGRAPHY =
|
|
180
|
-
"text-64 leading-64 tracking-64 md:text-128 md:leading-128 md:tracking-128 lg:text-192 lg:leading-192 lg:tracking-192 font-medium";
|
|
181
|
-
|
|
182
179
|
/**
|
|
183
180
|
* Checks if the background prop is a color string
|
|
184
181
|
*/
|
|
@@ -238,6 +235,7 @@ const Hero = React.forwardRef<HTMLElement, HeroProps>(
|
|
|
238
235
|
children,
|
|
239
236
|
title,
|
|
240
237
|
titleClassName,
|
|
238
|
+
colorScheme = "dark",
|
|
241
239
|
top,
|
|
242
240
|
variant,
|
|
243
241
|
background,
|
|
@@ -250,9 +248,13 @@ const Hero = React.forwardRef<HTMLElement, HeroProps>(
|
|
|
250
248
|
},
|
|
251
249
|
ref,
|
|
252
250
|
) => {
|
|
253
|
-
const styles = heroVariants({ variant });
|
|
254
251
|
const isColor = isColorString(background);
|
|
255
252
|
const hasMediaBackground = background && !isColor;
|
|
253
|
+
const styles = heroVariants({
|
|
254
|
+
variant,
|
|
255
|
+
colorScheme,
|
|
256
|
+
hasBackground: !!background,
|
|
257
|
+
});
|
|
256
258
|
const themeStyles = themeToStyleVars(theme);
|
|
257
259
|
const combinedStyles = {
|
|
258
260
|
...themeStyles,
|
|
@@ -264,22 +266,14 @@ const Hero = React.forwardRef<HTMLElement, HeroProps>(
|
|
|
264
266
|
return (
|
|
265
267
|
<section
|
|
266
268
|
ref={ref}
|
|
267
|
-
className={styles.root({
|
|
268
|
-
class: [
|
|
269
|
-
// Default background color when no background is provided
|
|
270
|
-
!background && "bg-bg-overlay",
|
|
271
|
-
className,
|
|
272
|
-
],
|
|
273
|
-
})}
|
|
269
|
+
className={styles.root({ class: className })}
|
|
274
270
|
style={
|
|
275
271
|
Object.keys(combinedStyles).length > 0 ? combinedStyles : undefined
|
|
276
272
|
}
|
|
277
273
|
{...props}
|
|
278
274
|
>
|
|
279
|
-
{/* Background slot (image, video, or stream) */}
|
|
280
275
|
{hasMediaBackground && background}
|
|
281
276
|
|
|
282
|
-
{/* Overlay */}
|
|
283
277
|
{hasMediaBackground && overlayOpacity > 0 && (
|
|
284
278
|
<BackgroundOverlay
|
|
285
279
|
opacity={overlayOpacity}
|
|
@@ -292,23 +286,11 @@ const Hero = React.forwardRef<HTMLElement, HeroProps>(
|
|
|
292
286
|
/>
|
|
293
287
|
)}
|
|
294
288
|
|
|
295
|
-
{/* Top slot - full width, no padding (for banners, nav) */}
|
|
296
289
|
{top && <div className={styles.top()}>{top}</div>}
|
|
297
290
|
|
|
298
|
-
{/* Content slot - padded area with alignment */}
|
|
299
291
|
<div className={styles.content()}>
|
|
300
|
-
{/* Title - convenience prop, renders h1 with default typography */}
|
|
301
292
|
{title && (
|
|
302
|
-
<h1
|
|
303
|
-
className={[
|
|
304
|
-
titleClassName || DEFAULT_TITLE_TYPOGRAPHY,
|
|
305
|
-
"text-text-inverted",
|
|
306
|
-
]
|
|
307
|
-
.filter(Boolean)
|
|
308
|
-
.join(" ")}
|
|
309
|
-
>
|
|
310
|
-
{title}
|
|
311
|
-
</h1>
|
|
293
|
+
<h1 className={styles.title({ class: titleClassName })}>{title}</h1>
|
|
312
294
|
)}
|
|
313
295
|
|
|
314
296
|
{/* Children - always render if provided */}
|
|
@@ -43,7 +43,11 @@ Playground.args = {
|
|
|
43
43
|
headline: "Brand-Large/Headline/Small",
|
|
44
44
|
body: "A river pattern stacks content in a simple vertical flow: one clear heading, a short block of copy, then the next step. It's ideal for guiding citizens through a process or story, keeping focus moving straight down the page with minimal choices and well-timed calls to action.",
|
|
45
45
|
primaryAction: <Button>Primary</Button>,
|
|
46
|
-
secondaryAction:
|
|
46
|
+
secondaryAction: (
|
|
47
|
+
<Button variant="outline" colorScheme="light">
|
|
48
|
+
Secondary
|
|
49
|
+
</Button>
|
|
50
|
+
),
|
|
47
51
|
backgroundMedia: <PlaceholderBackground />,
|
|
48
52
|
};
|
|
49
53
|
|
|
@@ -57,7 +61,11 @@ export const Desktop: Story = {
|
|
|
57
61
|
headline="Brand-Large/Headline/Small"
|
|
58
62
|
body="A river pattern stacks content in a simple vertical flow: one clear heading, a short block of copy, then the next step. It's ideal for guiding citizens through a process or story, keeping focus moving straight down the page with minimal choices and well-timed calls to action."
|
|
59
63
|
primaryAction={<Button>Primary</Button>}
|
|
60
|
-
secondaryAction={
|
|
64
|
+
secondaryAction={
|
|
65
|
+
<Button variant="outline" colorScheme="light">
|
|
66
|
+
Secondary
|
|
67
|
+
</Button>
|
|
68
|
+
}
|
|
61
69
|
backgroundMedia={<PlaceholderBackground />}
|
|
62
70
|
/>
|
|
63
71
|
),
|
|
@@ -72,7 +80,11 @@ export const Tablet: Story = {
|
|
|
72
80
|
headline="Brand-Large/Headline/Small"
|
|
73
81
|
body="A river pattern stacks content in a simple vertical flow: one clear heading, a short block of copy, then the next step. It's ideal for guiding citizens through a process or story, keeping focus moving straight down the page with minimal choices and well-timed calls to action."
|
|
74
82
|
primaryAction={<Button>Primary</Button>}
|
|
75
|
-
secondaryAction={
|
|
83
|
+
secondaryAction={
|
|
84
|
+
<Button variant="outline" colorScheme="light">
|
|
85
|
+
Secondary
|
|
86
|
+
</Button>
|
|
87
|
+
}
|
|
76
88
|
backgroundMedia={<PlaceholderBackground />}
|
|
77
89
|
/>
|
|
78
90
|
),
|
|
@@ -88,7 +100,7 @@ export const Mobile: Story = {
|
|
|
88
100
|
body="A river pattern stacks content in a simple vertical flow: one clear heading, a short block of copy, then the next step. It's ideal for guiding citizens through a process or story, keeping focus moving straight down the page with minimal choices and well-timed calls to action."
|
|
89
101
|
primaryAction={<Button size="sm">Primary</Button>}
|
|
90
102
|
secondaryAction={
|
|
91
|
-
<Button size="sm" variant="
|
|
103
|
+
<Button size="sm" variant="outline" colorScheme="light">
|
|
92
104
|
Secondary
|
|
93
105
|
</Button>
|
|
94
106
|
}
|
|
@@ -113,7 +125,11 @@ export const WithImage: Story = {
|
|
|
113
125
|
headline="Work with Purpose"
|
|
114
126
|
body="Join a team that's building the future of government services. We're looking for passionate individuals who want to make a difference."
|
|
115
127
|
primaryAction={<Button>View Careers</Button>}
|
|
116
|
-
secondaryAction={
|
|
128
|
+
secondaryAction={
|
|
129
|
+
<Button variant="outline" colorScheme="light">
|
|
130
|
+
Learn More
|
|
131
|
+
</Button>
|
|
132
|
+
}
|
|
117
133
|
backgroundMedia={<ImageBackground />}
|
|
118
134
|
/>
|
|
119
135
|
),
|
|
@@ -142,7 +158,11 @@ export const WithVideoPlaceholder: Story = {
|
|
|
142
158
|
headline="Experience Innovation"
|
|
143
159
|
body="See how modern technology is transforming the way government serves its citizens."
|
|
144
160
|
primaryAction={<Button>Watch Video</Button>}
|
|
145
|
-
secondaryAction={
|
|
161
|
+
secondaryAction={
|
|
162
|
+
<Button variant="outline" colorScheme="light">
|
|
163
|
+
Learn More
|
|
164
|
+
</Button>
|
|
165
|
+
}
|
|
146
166
|
backgroundMedia={
|
|
147
167
|
<div className="absolute inset-0 bg-gray-800 flex items-center justify-center">
|
|
148
168
|
<span className="text-gray-400 typography-body-small">
|
|
@@ -163,7 +183,11 @@ export const WithNdstudioFooter: Story = {
|
|
|
163
183
|
headline="Work with Purpose"
|
|
164
184
|
body="Join a team that's building the future of government services. We're looking for passionate individuals who want to make a difference."
|
|
165
185
|
primaryAction={<Button>View Careers</Button>}
|
|
166
|
-
secondaryAction={
|
|
186
|
+
secondaryAction={
|
|
187
|
+
<Button variant="outline" colorScheme="light">
|
|
188
|
+
Learn More
|
|
189
|
+
</Button>
|
|
190
|
+
}
|
|
167
191
|
backgroundMedia={<ImageBackground />}
|
|
168
192
|
footer={<NdstudioFooter />}
|
|
169
193
|
/>
|
|
@@ -16,10 +16,8 @@ const toutVariants = tv({
|
|
|
16
16
|
"h-[600px] md:h-[750px] lg:h-[900px]",
|
|
17
17
|
],
|
|
18
18
|
variants: {
|
|
19
|
-
|
|
20
|
-
// Default light content styling
|
|
19
|
+
colorScheme: {
|
|
21
20
|
light: "",
|
|
22
|
-
// Dark content styling
|
|
23
21
|
dark: "",
|
|
24
22
|
},
|
|
25
23
|
align: {
|
|
@@ -28,7 +26,7 @@ const toutVariants = tv({
|
|
|
28
26
|
},
|
|
29
27
|
},
|
|
30
28
|
defaultVariants: {
|
|
31
|
-
|
|
29
|
+
colorScheme: "light",
|
|
32
30
|
align: "left",
|
|
33
31
|
},
|
|
34
32
|
});
|
|
@@ -39,7 +37,7 @@ const toutVariants = tv({
|
|
|
39
37
|
* A full-bleed section with a background image and overlaid content.
|
|
40
38
|
* Content can be positioned on the left side or centered.
|
|
41
39
|
*
|
|
42
|
-
*
|
|
40
|
+
* Color schemes:
|
|
43
41
|
* - light: Light text styling (default)
|
|
44
42
|
* - dark: Dark text styling
|
|
45
43
|
*
|
|
@@ -121,7 +119,7 @@ const Tout = React.forwardRef<HTMLElement, ToutProps>(
|
|
|
121
119
|
(
|
|
122
120
|
{
|
|
123
121
|
className,
|
|
124
|
-
|
|
122
|
+
colorScheme = "light",
|
|
125
123
|
align = "left",
|
|
126
124
|
headline,
|
|
127
125
|
body,
|
|
@@ -136,13 +134,13 @@ const Tout = React.forwardRef<HTMLElement, ToutProps>(
|
|
|
136
134
|
ref,
|
|
137
135
|
) => {
|
|
138
136
|
const isCentered = align === "center";
|
|
139
|
-
const isDark =
|
|
137
|
+
const isDark = colorScheme === "dark";
|
|
140
138
|
const themeStyles = themeToStyleVars(theme);
|
|
141
139
|
|
|
142
140
|
return (
|
|
143
141
|
<section
|
|
144
142
|
ref={ref}
|
|
145
|
-
className={toutVariants({
|
|
143
|
+
className={toutVariants({ colorScheme, align, class: className })}
|
|
146
144
|
style={{ ...themeStyles, ...style }}
|
|
147
145
|
{...props}
|
|
148
146
|
>
|
|
@@ -8,10 +8,10 @@ const meta: Meta<typeof TwoColumnSection> = {
|
|
|
8
8
|
layout: "fullscreen",
|
|
9
9
|
},
|
|
10
10
|
argTypes: {
|
|
11
|
-
|
|
11
|
+
colorScheme: {
|
|
12
12
|
control: "select",
|
|
13
13
|
options: ["dark", "light"],
|
|
14
|
-
description: "Color
|
|
14
|
+
description: "Color scheme",
|
|
15
15
|
},
|
|
16
16
|
title: {
|
|
17
17
|
control: "text",
|
|
@@ -35,7 +35,7 @@ export const Playground: Story = {
|
|
|
35
35
|
render: (args) => <TwoColumnSection {...args} />,
|
|
36
36
|
};
|
|
37
37
|
Playground.args = {
|
|
38
|
-
|
|
38
|
+
colorScheme: "dark",
|
|
39
39
|
title: "US Tech Force",
|
|
40
40
|
lead: "The US Tech Force is recruiting an elite corps of engineers to build the next generation of government technology. Backed by the White House, Tech Force will tackle the most complex and large-scale civic and defense challenges of our era – from administering critical financial infrastructure at the Treasury Department to advancing cutting-edge programs at the Department of War – and everything in between.",
|
|
41
41
|
children: (
|
|
@@ -73,7 +73,7 @@ Playground.args = {
|
|
|
73
73
|
export const DarkVariant: Story = {
|
|
74
74
|
render: () => (
|
|
75
75
|
<TwoColumnSection
|
|
76
|
-
|
|
76
|
+
colorScheme="dark"
|
|
77
77
|
title="US Tech Force"
|
|
78
78
|
lead="The US Tech Force is recruiting an elite corps of engineers to build the next generation of government technology."
|
|
79
79
|
>
|
|
@@ -95,7 +95,7 @@ export const DarkVariant: Story = {
|
|
|
95
95
|
export const LightVariant: Story = {
|
|
96
96
|
render: () => (
|
|
97
97
|
<TwoColumnSection
|
|
98
|
-
|
|
98
|
+
colorScheme="light"
|
|
99
99
|
title="US Tech Force"
|
|
100
100
|
lead="The US Tech Force is recruiting an elite corps of engineers to build the next generation of government technology."
|
|
101
101
|
>
|
|
@@ -118,7 +118,7 @@ export const LightVariant: Story = {
|
|
|
118
118
|
export const Desktop: Story = {
|
|
119
119
|
render: () => (
|
|
120
120
|
<TwoColumnSection
|
|
121
|
-
|
|
121
|
+
colorScheme="dark"
|
|
122
122
|
title="US Tech Force"
|
|
123
123
|
lead="The US Tech Force is recruiting an elite corps of engineers to build the next generation of government technology. Backed by the White House, Tech Force will tackle the most complex and large-scale civic and defense challenges of our era."
|
|
124
124
|
>
|
|
@@ -151,7 +151,7 @@ export const Desktop: Story = {
|
|
|
151
151
|
export const Tablet: Story = {
|
|
152
152
|
render: () => (
|
|
153
153
|
<TwoColumnSection
|
|
154
|
-
|
|
154
|
+
colorScheme="dark"
|
|
155
155
|
title="US Tech Force"
|
|
156
156
|
lead="The US Tech Force is recruiting an elite corps of engineers to build the next generation of government technology. Backed by the White House, Tech Force will tackle the most complex and large-scale civic and defense challenges of our era."
|
|
157
157
|
>
|
|
@@ -184,7 +184,7 @@ export const Tablet: Story = {
|
|
|
184
184
|
export const Mobile: Story = {
|
|
185
185
|
render: () => (
|
|
186
186
|
<TwoColumnSection
|
|
187
|
-
|
|
187
|
+
colorScheme="dark"
|
|
188
188
|
title="US Tech Force"
|
|
189
189
|
lead="The US Tech Force is recruiting an elite corps of engineers to build the next generation of government technology. Backed by the White House, Tech Force will tackle the most complex and large-scale civic and defense challenges of our era."
|
|
190
190
|
>
|
|
@@ -223,7 +223,7 @@ export const Mobile: Story = {
|
|
|
223
223
|
*/
|
|
224
224
|
export const WithoutLead: Story = {
|
|
225
225
|
render: () => (
|
|
226
|
-
<TwoColumnSection
|
|
226
|
+
<TwoColumnSection colorScheme="dark" title="About the Program">
|
|
227
227
|
<p>
|
|
228
228
|
Through a two-year program, participants will work in teams reporting
|
|
229
229
|
directly to agency leadership. In collaboration with leading technology
|
|
@@ -245,7 +245,7 @@ export const WithoutLead: Story = {
|
|
|
245
245
|
export const RichLeadContent: Story = {
|
|
246
246
|
render: () => (
|
|
247
247
|
<TwoColumnSection
|
|
248
|
-
|
|
248
|
+
colorScheme="dark"
|
|
249
249
|
title="Our Mission"
|
|
250
250
|
lead={
|
|
251
251
|
<>
|
|
@@ -275,7 +275,7 @@ export const RichLeadContent: Story = {
|
|
|
275
275
|
export const ShortContent: Story = {
|
|
276
276
|
render: () => (
|
|
277
277
|
<TwoColumnSection
|
|
278
|
-
|
|
278
|
+
colorScheme="dark"
|
|
279
279
|
title="Join Us"
|
|
280
280
|
lead="Build the future of American government technology."
|
|
281
281
|
>
|
|
@@ -23,19 +23,17 @@ const twoColumnSectionVariants = tv({
|
|
|
23
23
|
"lg:px-spacing-72 lg:pt-spacing-72 lg:pb-spacing-112",
|
|
24
24
|
],
|
|
25
25
|
variants: {
|
|
26
|
-
|
|
26
|
+
colorScheme: {
|
|
27
27
|
dark: "bg-gray-1200",
|
|
28
28
|
light: "bg-white",
|
|
29
29
|
},
|
|
30
30
|
layout: {
|
|
31
|
-
/** Default 24-column grid with asymmetric split (title: 9, content: 15) */
|
|
32
31
|
asymmetric: "",
|
|
33
|
-
/** Equal 2-column layout at md+ breakpoints */
|
|
34
32
|
equal: "",
|
|
35
33
|
},
|
|
36
34
|
},
|
|
37
35
|
defaultVariants: {
|
|
38
|
-
|
|
36
|
+
colorScheme: "dark",
|
|
39
37
|
layout: "asymmetric",
|
|
40
38
|
},
|
|
41
39
|
});
|
|
@@ -86,14 +84,22 @@ export interface TwoColumnSectionProps
|
|
|
86
84
|
*/
|
|
87
85
|
const TwoColumnSection = React.forwardRef<HTMLElement, TwoColumnSectionProps>(
|
|
88
86
|
(
|
|
89
|
-
{
|
|
87
|
+
{
|
|
88
|
+
className,
|
|
89
|
+
colorScheme = "dark",
|
|
90
|
+
layout,
|
|
91
|
+
title,
|
|
92
|
+
lead,
|
|
93
|
+
children,
|
|
94
|
+
...props
|
|
95
|
+
},
|
|
90
96
|
ref,
|
|
91
97
|
) => {
|
|
92
98
|
return (
|
|
93
99
|
<section
|
|
94
100
|
ref={ref}
|
|
95
101
|
className={twoColumnSectionVariants({
|
|
96
|
-
|
|
102
|
+
colorScheme,
|
|
97
103
|
layout,
|
|
98
104
|
class: className,
|
|
99
105
|
})}
|
|
@@ -103,7 +109,7 @@ const TwoColumnSection = React.forwardRef<HTMLElement, TwoColumnSectionProps>(
|
|
|
103
109
|
<div
|
|
104
110
|
className={cn(
|
|
105
111
|
"border-t pt-spacing-36",
|
|
106
|
-
|
|
112
|
+
colorScheme === "dark" ? "border-gray-700" : "border-gray-300",
|
|
107
113
|
// Grid layout - uses primitive spacing tokens
|
|
108
114
|
"grid grid-cols-1 gap-spacing-56",
|
|
109
115
|
layout === "equal"
|
|
@@ -115,7 +121,7 @@ const TwoColumnSection = React.forwardRef<HTMLElement, TwoColumnSectionProps>(
|
|
|
115
121
|
<h2
|
|
116
122
|
className={cn(
|
|
117
123
|
"typography-subheading-medium",
|
|
118
|
-
|
|
124
|
+
colorScheme === "dark" ? "text-gray-100" : "text-gray-900",
|
|
119
125
|
// Column span based on layout
|
|
120
126
|
layout !== "equal" && "lg:col-span-9",
|
|
121
127
|
)}
|
|
@@ -135,7 +141,7 @@ const TwoColumnSection = React.forwardRef<HTMLElement, TwoColumnSectionProps>(
|
|
|
135
141
|
<div
|
|
136
142
|
className={cn(
|
|
137
143
|
"typography-body-large",
|
|
138
|
-
|
|
144
|
+
colorScheme === "dark" ? "text-gray-100" : "text-gray-900",
|
|
139
145
|
)}
|
|
140
146
|
>
|
|
141
147
|
{typeof lead === "string" ? <p>{lead}</p> : lead}
|
|
@@ -146,7 +152,7 @@ const TwoColumnSection = React.forwardRef<HTMLElement, TwoColumnSectionProps>(
|
|
|
146
152
|
<div
|
|
147
153
|
className={cn(
|
|
148
154
|
"typography-body-medium flex flex-col gap-[1em]",
|
|
149
|
-
|
|
155
|
+
colorScheme === "dark" ? "text-gray-400" : "text-gray-600",
|
|
150
156
|
)}
|
|
151
157
|
>
|
|
152
158
|
{children}
|