@nationaldesignstudio/react 0.0.17 → 0.0.19
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 +181 -29
- package/dist/components/atoms/background/background.d.ts +135 -0
- package/dist/components/atoms/button/button.d.ts +64 -82
- package/dist/components/atoms/button/icon-button.d.ts +100 -66
- package/dist/components/organisms/card/card.d.ts +130 -4
- package/dist/components/organisms/us-gov-banner/us-gov-banner.d.ts +120 -2
- package/dist/components/sections/hero/hero.d.ts +166 -150
- package/dist/components/sections/quote-block/quote-block.d.ts +152 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +3868 -5978
- package/dist/index.js.map +1 -1
- package/dist/lib/utils.d.ts +1 -2
- package/dist/tokens.css +207 -16
- package/package.json +2 -4
- package/src/components/atoms/background/background.tsx +377 -0
- package/src/components/atoms/background/index.ts +22 -0
- package/src/components/atoms/button/button.stories.tsx +81 -32
- package/src/components/atoms/button/button.tsx +91 -49
- package/src/components/atoms/button/icon-button.stories.tsx +179 -28
- package/src/components/atoms/button/icon-button.tsx +111 -49
- package/src/components/organisms/card/card.tsx +82 -24
- package/src/components/organisms/card/index.ts +7 -0
- package/src/components/organisms/us-gov-banner/index.ts +5 -1
- package/src/components/organisms/us-gov-banner/us-gov-banner.tsx +72 -16
- package/src/components/sections/hero/hero.stories.tsx +124 -1
- package/src/components/sections/hero/hero.test.tsx +21 -18
- package/src/components/sections/hero/hero.tsx +188 -301
- package/src/components/sections/hero/index.ts +13 -0
- package/src/components/sections/quote-block/index.ts +5 -0
- package/src/components/sections/quote-block/quote-block.tsx +216 -0
- package/src/index.ts +40 -0
- package/src/lib/utils.ts +1 -6
- package/src/stories/ThemeProvider.stories.tsx +5 -5
|
@@ -17,70 +17,115 @@ import { tv, type VariantProps } from "tailwind-variants";
|
|
|
17
17
|
* <IconButton aria-label="Close menu">
|
|
18
18
|
* <CloseIcon />
|
|
19
19
|
* </IconButton>
|
|
20
|
-
*
|
|
21
|
-
* // Correct usage with aria-labelledby
|
|
22
|
-
* <IconButton aria-labelledby="close-label">
|
|
23
|
-
* <CloseIcon />
|
|
24
|
-
* </IconButton>
|
|
25
|
-
* <span id="close-label" className="sr-only">Close menu</span>
|
|
26
20
|
* ```
|
|
27
21
|
*
|
|
28
22
|
* Variants:
|
|
29
|
-
* -
|
|
30
|
-
* -
|
|
31
|
-
* -
|
|
32
|
-
* -
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* -
|
|
36
|
-
* -
|
|
23
|
+
* - solid: Filled button
|
|
24
|
+
* - outline: Outlined button
|
|
25
|
+
* - ghost: No background/border, just icon
|
|
26
|
+
* - subtle: Subtle outlined button
|
|
27
|
+
*
|
|
28
|
+
* Color Schemes:
|
|
29
|
+
* - dark: Dark colors for use on light backgrounds (default)
|
|
30
|
+
* - light: Light colors for use on dark backgrounds
|
|
37
31
|
*
|
|
38
32
|
* Sizes:
|
|
39
|
-
* - lg: Large (
|
|
40
|
-
* - default: Medium (
|
|
41
|
-
* - sm: Small (
|
|
33
|
+
* - lg: Large (48x48)
|
|
34
|
+
* - default: Medium (40x40)
|
|
35
|
+
* - sm: Small (32x32)
|
|
36
|
+
*
|
|
37
|
+
* Rounded:
|
|
38
|
+
* - default: Standard border radius
|
|
39
|
+
* - sm: Smaller border radius
|
|
40
|
+
* - full: Fully circular
|
|
42
41
|
*/
|
|
43
42
|
const iconButtonVariants = tv({
|
|
44
43
|
base: "inline-flex items-center justify-center whitespace-nowrap transition-colors duration-150 cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
45
44
|
variants: {
|
|
46
45
|
variant: {
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
solid: "",
|
|
47
|
+
outline: "border",
|
|
48
|
+
ghost: "",
|
|
49
|
+
subtle: "border",
|
|
50
|
+
},
|
|
51
|
+
colorScheme: {
|
|
52
|
+
dark: "",
|
|
53
|
+
light: "",
|
|
54
|
+
},
|
|
55
|
+
size: {
|
|
56
|
+
lg: "size-48",
|
|
57
|
+
default: "size-40",
|
|
58
|
+
sm: "size-32",
|
|
59
|
+
},
|
|
60
|
+
rounded: {
|
|
61
|
+
default: "rounded-radius-12",
|
|
62
|
+
sm: "rounded-radius-10",
|
|
63
|
+
full: "rounded-full",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
compoundVariants: [
|
|
67
|
+
// Solid + Dark (for light backgrounds)
|
|
68
|
+
{
|
|
69
|
+
variant: "solid",
|
|
70
|
+
colorScheme: "dark",
|
|
71
|
+
class:
|
|
49
72
|
"bg-gray-1200 text-gray-100 hover:bg-gray-1100 active:bg-gray-1000 focus-visible:ring-gray-1000",
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
73
|
+
},
|
|
74
|
+
// Solid + Light (for dark backgrounds)
|
|
75
|
+
{
|
|
76
|
+
variant: "solid",
|
|
77
|
+
colorScheme: "light",
|
|
78
|
+
class:
|
|
79
|
+
"bg-gray-50 text-gray-1000 hover:bg-gray-100 active:bg-gray-200 focus-visible:ring-gray-50 focus-visible:ring-offset-gray-1000",
|
|
80
|
+
},
|
|
81
|
+
// Outline + Dark (for light backgrounds)
|
|
82
|
+
{
|
|
83
|
+
variant: "outline",
|
|
84
|
+
colorScheme: "dark",
|
|
85
|
+
class:
|
|
86
|
+
"border-alpha-black-30 text-gray-1000 hover:bg-alpha-black-5 active:bg-alpha-black-10 focus-visible:ring-gray-1000",
|
|
87
|
+
},
|
|
88
|
+
// Outline + Light (for dark backgrounds)
|
|
89
|
+
{
|
|
90
|
+
variant: "outline",
|
|
91
|
+
colorScheme: "light",
|
|
92
|
+
class:
|
|
93
|
+
"border-gray-50 text-gray-50 hover:bg-alpha-white-10 active:bg-alpha-white-20 focus-visible:ring-gray-50 focus-visible:ring-offset-gray-1000",
|
|
94
|
+
},
|
|
95
|
+
// Ghost + Dark (for light backgrounds)
|
|
96
|
+
{
|
|
97
|
+
variant: "ghost",
|
|
98
|
+
colorScheme: "dark",
|
|
99
|
+
class:
|
|
58
100
|
"text-gray-700 hover:text-gray-900 hover:bg-alpha-black-5 active:bg-alpha-black-10 focus-visible:ring-gray-1000",
|
|
59
|
-
|
|
60
|
-
|
|
101
|
+
},
|
|
102
|
+
// Ghost + Light (for dark backgrounds)
|
|
103
|
+
{
|
|
104
|
+
variant: "ghost",
|
|
105
|
+
colorScheme: "light",
|
|
106
|
+
class:
|
|
61
107
|
"text-gray-300 hover:text-gray-100 hover:bg-alpha-white-10 active:bg-alpha-white-20 focus-visible:ring-gray-50 focus-visible:ring-offset-gray-1000",
|
|
62
|
-
// Ivory (light filled) - primary light (for dark backgrounds)
|
|
63
|
-
ivory:
|
|
64
|
-
"bg-gray-50 text-gray-1000 hover:bg-gray-100 active:bg-gray-200 focus-visible:ring-gray-50 focus-visible:ring-offset-gray-1000",
|
|
65
|
-
// Ivory Outline - outlined light (for dark backgrounds)
|
|
66
|
-
ivoryOutline:
|
|
67
|
-
"border border-gray-50 text-gray-50 hover:bg-alpha-white-10 active:bg-alpha-white-20 focus-visible:ring-gray-50 focus-visible:ring-offset-gray-1000",
|
|
68
|
-
// Ivory Outline Quiet - subtle light outline (for dark backgrounds)
|
|
69
|
-
ivoryOutlineQuiet:
|
|
70
|
-
"border border-alpha-white-20 text-alpha-white-60 hover:border-alpha-white-30 hover:text-alpha-white-80 active:bg-alpha-white-5 focus-visible:ring-gray-50 focus-visible:ring-offset-gray-1000",
|
|
71
108
|
},
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
sm: "rounded-radius-10 size-spacing-32",
|
|
109
|
+
// Subtle + Dark (for light backgrounds)
|
|
110
|
+
{
|
|
111
|
+
variant: "subtle",
|
|
112
|
+
colorScheme: "dark",
|
|
113
|
+
class:
|
|
114
|
+
"border-alpha-black-20 text-alpha-black-60 hover:border-alpha-black-30 hover:text-alpha-black-80 active:bg-alpha-black-5 focus-visible:ring-gray-1000",
|
|
79
115
|
},
|
|
80
|
-
|
|
116
|
+
// Subtle + Light (for dark backgrounds)
|
|
117
|
+
{
|
|
118
|
+
variant: "subtle",
|
|
119
|
+
colorScheme: "light",
|
|
120
|
+
class:
|
|
121
|
+
"border-alpha-white-20 text-alpha-white-60 hover:border-alpha-white-30 hover:text-alpha-white-80 active:bg-alpha-white-5 focus-visible:ring-gray-50 focus-visible:ring-offset-gray-1000",
|
|
122
|
+
},
|
|
123
|
+
],
|
|
81
124
|
defaultVariants: {
|
|
82
|
-
variant: "
|
|
125
|
+
variant: "solid",
|
|
126
|
+
colorScheme: "dark",
|
|
83
127
|
size: "default",
|
|
128
|
+
rounded: "default",
|
|
84
129
|
},
|
|
85
130
|
});
|
|
86
131
|
|
|
@@ -91,7 +136,18 @@ export interface IconButtonProps
|
|
|
91
136
|
}
|
|
92
137
|
|
|
93
138
|
const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(
|
|
94
|
-
(
|
|
139
|
+
(
|
|
140
|
+
{
|
|
141
|
+
className,
|
|
142
|
+
variant,
|
|
143
|
+
colorScheme,
|
|
144
|
+
size,
|
|
145
|
+
rounded,
|
|
146
|
+
asChild = false,
|
|
147
|
+
...props
|
|
148
|
+
},
|
|
149
|
+
ref,
|
|
150
|
+
) => {
|
|
95
151
|
// Development warning for missing accessible label
|
|
96
152
|
React.useEffect(() => {
|
|
97
153
|
if (import.meta.env?.DEV) {
|
|
@@ -108,7 +164,13 @@ const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(
|
|
|
108
164
|
const Comp = asChild ? Slot : "button";
|
|
109
165
|
return (
|
|
110
166
|
<Comp
|
|
111
|
-
className={iconButtonVariants({
|
|
167
|
+
className={iconButtonVariants({
|
|
168
|
+
variant,
|
|
169
|
+
colorScheme,
|
|
170
|
+
size,
|
|
171
|
+
rounded,
|
|
172
|
+
class: className,
|
|
173
|
+
})}
|
|
112
174
|
ref={ref}
|
|
113
175
|
{...props}
|
|
114
176
|
/>
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { tv, type VariantProps } from "tailwind-variants";
|
|
3
|
-
import { cn } from "@/lib/utils";
|
|
4
3
|
|
|
5
4
|
const cardVariants = tv({
|
|
6
|
-
base: "flex overflow-hidden rounded-surface-card bg-card-background stroke-surface-card border-border-subtle border-solid",
|
|
5
|
+
base: "relative flex overflow-hidden rounded-surface-card bg-card-background stroke-surface-card border-border-subtle border-solid",
|
|
7
6
|
variants: {
|
|
8
7
|
layout: {
|
|
9
8
|
vertical: "w-full flex-col",
|
|
10
9
|
horizontal: "w-full flex-row",
|
|
10
|
+
/**
|
|
11
|
+
* Overlay layout - content sits on top of full-bleed background.
|
|
12
|
+
* Use with Background components for images/gradients.
|
|
13
|
+
*/
|
|
14
|
+
overlay: "w-full flex-col",
|
|
11
15
|
},
|
|
12
16
|
},
|
|
13
17
|
defaultVariants: {
|
|
@@ -25,8 +29,10 @@ export interface CardProps
|
|
|
25
29
|
* Layouts:
|
|
26
30
|
* - vertical: Image on top, content below (default)
|
|
27
31
|
* - horizontal: Image on left, content on right
|
|
32
|
+
* - overlay: Full-bleed background with content on top
|
|
28
33
|
*
|
|
29
34
|
* Use with CardImage, CardContent, CardEyebrow, CardTitle, CardDescription, and CardActions.
|
|
35
|
+
* For overlay layout, use Background components for full-bleed backgrounds.
|
|
30
36
|
*/
|
|
31
37
|
const Card = React.forwardRef<HTMLDivElement, CardProps>(
|
|
32
38
|
({ className, layout, ...props }, ref) => {
|
|
@@ -41,6 +47,16 @@ const Card = React.forwardRef<HTMLDivElement, CardProps>(
|
|
|
41
47
|
);
|
|
42
48
|
Card.displayName = "Card";
|
|
43
49
|
|
|
50
|
+
const cardImageVariants = tv({
|
|
51
|
+
base: [
|
|
52
|
+
"relative shrink-0 bg-bg-muted",
|
|
53
|
+
// Vertical: full width with aspect ratio
|
|
54
|
+
"aspect-video w-full",
|
|
55
|
+
// When in horizontal card (parent has flex-row), override
|
|
56
|
+
"[.flex-row>&]:aspect-auto [.flex-row>&]:w-2/5 [.flex-row>&]:self-stretch",
|
|
57
|
+
],
|
|
58
|
+
});
|
|
59
|
+
|
|
44
60
|
export interface CardImageProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
45
61
|
/**
|
|
46
62
|
* The image source URL
|
|
@@ -61,14 +77,7 @@ const CardImage = React.forwardRef<HTMLDivElement, CardImageProps>(
|
|
|
61
77
|
return (
|
|
62
78
|
<div
|
|
63
79
|
ref={ref}
|
|
64
|
-
className={
|
|
65
|
-
"relative shrink-0 bg-gray-500",
|
|
66
|
-
// Vertical: full width with aspect ratio
|
|
67
|
-
"aspect-video w-full",
|
|
68
|
-
// When in horizontal card (parent has flex-row), override
|
|
69
|
-
"[.flex-row>&]:aspect-auto [.flex-row>&]:w-2/5 [.flex-row>&]:self-stretch",
|
|
70
|
-
className,
|
|
71
|
-
)}
|
|
80
|
+
className={cardImageVariants({ class: className })}
|
|
72
81
|
{...props}
|
|
73
82
|
>
|
|
74
83
|
{src && (
|
|
@@ -84,22 +93,47 @@ const CardImage = React.forwardRef<HTMLDivElement, CardImageProps>(
|
|
|
84
93
|
);
|
|
85
94
|
CardImage.displayName = "CardImage";
|
|
86
95
|
|
|
96
|
+
const cardContentVariants = tv({
|
|
97
|
+
base: "flex w-full flex-1 flex-col gap-spatial-card-large-gap p-spatial-card-large-padding",
|
|
98
|
+
variants: {
|
|
99
|
+
/**
|
|
100
|
+
* Vertical alignment of content within the card.
|
|
101
|
+
* Useful for overlay layouts to position content at top/center/bottom.
|
|
102
|
+
*/
|
|
103
|
+
justify: {
|
|
104
|
+
start: "justify-start",
|
|
105
|
+
center: "justify-center",
|
|
106
|
+
end: "justify-end",
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
|
|
87
111
|
export interface CardContentProps
|
|
88
|
-
extends React.HTMLAttributes<HTMLDivElement
|
|
112
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
113
|
+
VariantProps<typeof cardContentVariants> {}
|
|
89
114
|
|
|
90
115
|
/**
|
|
91
116
|
* Card content container with proper padding and spacing.
|
|
92
117
|
* Uses spatial card tokens for consistent sizing.
|
|
118
|
+
* For overlay layout, add `relative z-10` to ensure content sits above background.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```tsx
|
|
122
|
+
* // Content at bottom of overlay card
|
|
123
|
+
* <Card layout="overlay">
|
|
124
|
+
* <Background.Image src="/hero.jpg" />
|
|
125
|
+
* <CardContent justify="end" className="relative z-10">
|
|
126
|
+
* <CardTitle>Title</CardTitle>
|
|
127
|
+
* </CardContent>
|
|
128
|
+
* </Card>
|
|
129
|
+
* ```
|
|
93
130
|
*/
|
|
94
131
|
const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(
|
|
95
|
-
({ className, ...props }, ref) => {
|
|
132
|
+
({ className, justify, ...props }, ref) => {
|
|
96
133
|
return (
|
|
97
134
|
<div
|
|
98
135
|
ref={ref}
|
|
99
|
-
className={
|
|
100
|
-
"flex w-full flex-1 flex-col gap-spatial-card-large-gap p-spatial-card-large-padding",
|
|
101
|
-
className,
|
|
102
|
-
)}
|
|
136
|
+
className={cardContentVariants({ justify, class: className })}
|
|
103
137
|
{...props}
|
|
104
138
|
/>
|
|
105
139
|
);
|
|
@@ -107,6 +141,10 @@ const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(
|
|
|
107
141
|
);
|
|
108
142
|
CardContent.displayName = "CardContent";
|
|
109
143
|
|
|
144
|
+
const cardEyebrowVariants = tv({
|
|
145
|
+
base: "typography-caption-large text-text-muted",
|
|
146
|
+
});
|
|
147
|
+
|
|
110
148
|
export interface CardEyebrowProps
|
|
111
149
|
extends React.HTMLAttributes<HTMLParagraphElement> {}
|
|
112
150
|
|
|
@@ -118,7 +156,7 @@ const CardEyebrow = React.forwardRef<HTMLParagraphElement, CardEyebrowProps>(
|
|
|
118
156
|
return (
|
|
119
157
|
<p
|
|
120
158
|
ref={ref}
|
|
121
|
-
className={
|
|
159
|
+
className={cardEyebrowVariants({ class: className })}
|
|
122
160
|
{...props}
|
|
123
161
|
/>
|
|
124
162
|
);
|
|
@@ -126,6 +164,10 @@ const CardEyebrow = React.forwardRef<HTMLParagraphElement, CardEyebrowProps>(
|
|
|
126
164
|
);
|
|
127
165
|
CardEyebrow.displayName = "CardEyebrow";
|
|
128
166
|
|
|
167
|
+
const cardTitleVariants = tv({
|
|
168
|
+
base: "typography-subheading-small text-text-primary",
|
|
169
|
+
});
|
|
170
|
+
|
|
129
171
|
export interface CardTitleProps
|
|
130
172
|
extends React.HTMLAttributes<HTMLHeadingElement> {
|
|
131
173
|
/**
|
|
@@ -142,7 +184,7 @@ const CardTitle = React.forwardRef<HTMLHeadingElement, CardTitleProps>(
|
|
|
142
184
|
return (
|
|
143
185
|
<Component
|
|
144
186
|
ref={ref}
|
|
145
|
-
className={
|
|
187
|
+
className={cardTitleVariants({ class: className })}
|
|
146
188
|
{...props}
|
|
147
189
|
/>
|
|
148
190
|
);
|
|
@@ -150,6 +192,10 @@ const CardTitle = React.forwardRef<HTMLHeadingElement, CardTitleProps>(
|
|
|
150
192
|
);
|
|
151
193
|
CardTitle.displayName = "CardTitle";
|
|
152
194
|
|
|
195
|
+
const cardDescriptionVariants = tv({
|
|
196
|
+
base: "typography-body-small text-text-secondary",
|
|
197
|
+
});
|
|
198
|
+
|
|
153
199
|
export interface CardDescriptionProps
|
|
154
200
|
extends React.HTMLAttributes<HTMLParagraphElement> {}
|
|
155
201
|
|
|
@@ -163,13 +209,17 @@ const CardDescription = React.forwardRef<
|
|
|
163
209
|
return (
|
|
164
210
|
<p
|
|
165
211
|
ref={ref}
|
|
166
|
-
className={
|
|
212
|
+
className={cardDescriptionVariants({ class: className })}
|
|
167
213
|
{...props}
|
|
168
214
|
/>
|
|
169
215
|
);
|
|
170
216
|
});
|
|
171
217
|
CardDescription.displayName = "CardDescription";
|
|
172
218
|
|
|
219
|
+
const cardBodyVariants = tv({
|
|
220
|
+
base: "flex w-full flex-col gap-spatial-card-small-gap",
|
|
221
|
+
});
|
|
222
|
+
|
|
173
223
|
export interface CardBodyProps extends React.HTMLAttributes<HTMLDivElement> {}
|
|
174
224
|
|
|
175
225
|
/**
|
|
@@ -181,10 +231,7 @@ const CardBody = React.forwardRef<HTMLDivElement, CardBodyProps>(
|
|
|
181
231
|
return (
|
|
182
232
|
<div
|
|
183
233
|
ref={ref}
|
|
184
|
-
className={
|
|
185
|
-
"flex w-full flex-col gap-spatial-card-small-gap",
|
|
186
|
-
className,
|
|
187
|
-
)}
|
|
234
|
+
className={cardBodyVariants({ class: className })}
|
|
188
235
|
{...props}
|
|
189
236
|
/>
|
|
190
237
|
);
|
|
@@ -192,6 +239,10 @@ const CardBody = React.forwardRef<HTMLDivElement, CardBodyProps>(
|
|
|
192
239
|
);
|
|
193
240
|
CardBody.displayName = "CardBody";
|
|
194
241
|
|
|
242
|
+
const cardActionsVariants = tv({
|
|
243
|
+
base: "flex gap-spacing-12",
|
|
244
|
+
});
|
|
245
|
+
|
|
195
246
|
export interface CardActionsProps
|
|
196
247
|
extends React.HTMLAttributes<HTMLDivElement> {}
|
|
197
248
|
|
|
@@ -204,7 +255,7 @@ const CardActions = React.forwardRef<HTMLDivElement, CardActionsProps>(
|
|
|
204
255
|
return (
|
|
205
256
|
<div
|
|
206
257
|
ref={ref}
|
|
207
|
-
className={
|
|
258
|
+
className={cardActionsVariants({ class: className })}
|
|
208
259
|
{...props}
|
|
209
260
|
/>
|
|
210
261
|
);
|
|
@@ -216,10 +267,17 @@ export {
|
|
|
216
267
|
Card,
|
|
217
268
|
cardVariants,
|
|
218
269
|
CardImage,
|
|
270
|
+
cardImageVariants,
|
|
219
271
|
CardContent,
|
|
272
|
+
cardContentVariants,
|
|
220
273
|
CardEyebrow,
|
|
274
|
+
cardEyebrowVariants,
|
|
221
275
|
CardTitle,
|
|
276
|
+
cardTitleVariants,
|
|
222
277
|
CardDescription,
|
|
278
|
+
cardDescriptionVariants,
|
|
223
279
|
CardBody,
|
|
280
|
+
cardBodyVariants,
|
|
224
281
|
CardActions,
|
|
282
|
+
cardActionsVariants,
|
|
225
283
|
};
|
|
@@ -15,5 +15,12 @@ export {
|
|
|
15
15
|
type CardProps,
|
|
16
16
|
CardTitle,
|
|
17
17
|
type CardTitleProps,
|
|
18
|
+
cardActionsVariants,
|
|
19
|
+
cardBodyVariants,
|
|
20
|
+
cardContentVariants,
|
|
21
|
+
cardDescriptionVariants,
|
|
22
|
+
cardEyebrowVariants,
|
|
23
|
+
cardImageVariants,
|
|
24
|
+
cardTitleVariants,
|
|
18
25
|
cardVariants,
|
|
19
26
|
} from "./card";
|
|
@@ -1,7 +1,34 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { tv, type VariantProps } from "tailwind-variants";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
const usGovBannerVariants = tv({
|
|
5
|
+
slots: {
|
|
6
|
+
root: "flex w-full items-center justify-center py-spacing-12",
|
|
7
|
+
content: "flex items-center gap-spacing-8",
|
|
8
|
+
text: "text-[11px] leading-[13px] tracking-[0.17px]",
|
|
9
|
+
},
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: {
|
|
13
|
+
root: "bg-gray-50",
|
|
14
|
+
content: "opacity-70",
|
|
15
|
+
text: "text-gray-900",
|
|
16
|
+
},
|
|
17
|
+
inverted: {
|
|
18
|
+
root: "bg-transparent",
|
|
19
|
+
content: "opacity-70",
|
|
20
|
+
text: "text-text-inverted",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
defaultVariants: {
|
|
25
|
+
variant: "default",
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export interface USGovBannerProps
|
|
30
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
31
|
+
VariantProps<typeof usGovBannerVariants> {
|
|
5
32
|
/**
|
|
6
33
|
* Custom flag icon element. Defaults to a US flag SVG.
|
|
7
34
|
*/
|
|
@@ -17,31 +44,39 @@ export interface USGovBannerProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
17
44
|
* US Government official website banner.
|
|
18
45
|
* Displays the official government website notice with flag icon.
|
|
19
46
|
* Commonly placed at the very top of government websites.
|
|
47
|
+
*
|
|
48
|
+
* Variants:
|
|
49
|
+
* - default: Light background with dark text (for light pages)
|
|
50
|
+
* - inverted: Transparent background with white text/flag (for dark backgrounds/heroes)
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```tsx
|
|
54
|
+
* // Default (light)
|
|
55
|
+
* <USGovBanner />
|
|
56
|
+
*
|
|
57
|
+
* // Inverted (for dark backgrounds)
|
|
58
|
+
* <USGovBanner variant="inverted" />
|
|
59
|
+
* ```
|
|
20
60
|
*/
|
|
21
61
|
const USGovBanner = React.forwardRef<HTMLDivElement, USGovBannerProps>(
|
|
22
62
|
(
|
|
23
63
|
{
|
|
24
64
|
className,
|
|
65
|
+
variant,
|
|
25
66
|
flagIcon,
|
|
26
67
|
text = "An official website of the United States government",
|
|
27
68
|
...props
|
|
28
69
|
},
|
|
29
70
|
ref,
|
|
30
71
|
) => {
|
|
72
|
+
const styles = usGovBannerVariants({ variant });
|
|
73
|
+
const isInverted = variant === "inverted";
|
|
74
|
+
|
|
31
75
|
return (
|
|
32
|
-
<div
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
className,
|
|
37
|
-
)}
|
|
38
|
-
{...props}
|
|
39
|
-
>
|
|
40
|
-
<div className="flex items-center gap-spacing-8 opacity-70">
|
|
41
|
-
{flagIcon ?? <DefaultUSFlag />}
|
|
42
|
-
<p className="text-[11px] leading-[13px] tracking-[0.17px] text-gray-900">
|
|
43
|
-
{text}
|
|
44
|
-
</p>
|
|
76
|
+
<div ref={ref} className={styles.root({ class: className })} {...props}>
|
|
77
|
+
<div className={styles.content()}>
|
|
78
|
+
{flagIcon ?? (isInverted ? <WhiteUSFlag /> : <DefaultUSFlag />)}
|
|
79
|
+
<p className={styles.text()}>{text}</p>
|
|
45
80
|
</div>
|
|
46
81
|
</div>
|
|
47
82
|
);
|
|
@@ -70,4 +105,25 @@ function DefaultUSFlag() {
|
|
|
70
105
|
);
|
|
71
106
|
}
|
|
72
107
|
|
|
73
|
-
|
|
108
|
+
function WhiteUSFlag() {
|
|
109
|
+
return (
|
|
110
|
+
<svg
|
|
111
|
+
width="16"
|
|
112
|
+
height="12"
|
|
113
|
+
viewBox="0 0 16 12"
|
|
114
|
+
fill="none"
|
|
115
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
116
|
+
aria-hidden="true"
|
|
117
|
+
>
|
|
118
|
+
<path d="M0 0H16V12H0V0Z" fill="white" fillOpacity="0.1" />
|
|
119
|
+
<path
|
|
120
|
+
d="M0 0H16V0.923077H0V0ZM0 1.84615H16V2.76923H0V1.84615ZM0 3.69231H16V4.61538H0V3.69231ZM0 5.53846H16V6.46154H0V5.53846ZM0 7.38462H16V8.30769H0V7.38462ZM0 9.23077H16V10.1538H0V9.23077ZM0 11.0769H16V12H0V11.0769Z"
|
|
121
|
+
fill="white"
|
|
122
|
+
fillOpacity="0.8"
|
|
123
|
+
/>
|
|
124
|
+
<path d="M0 0H8V6.46154H0V0Z" fill="white" fillOpacity="0.6" />
|
|
125
|
+
</svg>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export { USGovBanner, usGovBannerVariants };
|