@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.
- package/dist/component-registry.md +2405 -0
- package/dist/components/atoms/accordion/accordion.d.ts +44 -3
- package/dist/components/atoms/button/button.d.ts +155 -11
- package/dist/components/atoms/button/icon-button.d.ts +114 -5
- package/dist/components/atoms/ndstudio-footer/ndstudio-footer.d.ts +30 -0
- package/dist/components/atoms/pager-control/pager-control.d.ts +116 -9
- package/dist/components/dev-tools/dev-toolbar/dev-toolbar.d.ts +4 -0
- package/dist/components/dev-tools/grid-overlay/grid-overlay.d.ts +6 -0
- package/dist/components/organisms/card/card.d.ts +40 -4
- package/dist/components/sections/banner/banner.d.ts +39 -6
- package/dist/components/sections/card-grid/card-grid.d.ts +37 -4
- package/dist/components/sections/faq-section/faq-section.d.ts +2 -2
- package/dist/components/sections/hero/hero.d.ts +167 -16
- package/dist/components/sections/river/river.d.ts +37 -4
- package/dist/components/sections/tout/tout.d.ts +86 -6
- package/dist/components/sections/two-column-section/two-column-section.d.ts +80 -6
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/use-event-listener.d.ts +24 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.js +12034 -5934
- package/dist/index.js.map +1 -1
- package/dist/lib/theme.d.ts +330 -0
- package/dist/tokens.css +13650 -6129
- package/package.json +11 -21
- package/src/App.css +0 -0
- package/src/App.tsx +0 -7
- package/src/assets/fonts/PPNeueMontreal-Variable.woff2 +0 -0
- package/src/assets/react.svg +0 -1
- package/src/components/atoms/accordion/accordion.stories.tsx +0 -228
- package/src/components/atoms/accordion/accordion.tsx +0 -137
- package/src/components/atoms/accordion/index.ts +0 -6
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-quiet-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-quiet-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-disabled-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-disabled-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-quiet-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-quiet-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-large-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-large-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-medium-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-medium-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-small-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-small-chromium-linux.png +0 -0
- package/src/components/atoms/button/button.stories.tsx +0 -84
- package/src/components/atoms/button/button.test.tsx +0 -141
- package/src/components/atoms/button/button.tsx +0 -95
- package/src/components/atoms/button/button.visual.test.tsx +0 -102
- package/src/components/atoms/button/icon-button.stories.tsx +0 -166
- package/src/components/atoms/button/icon-button.tsx +0 -125
- package/src/components/atoms/button/index.ts +0 -6
- package/src/components/atoms/pager-control/index.ts +0 -5
- package/src/components/atoms/pager-control/pager-control.stories.tsx +0 -209
- package/src/components/atoms/pager-control/pager-control.test.tsx +0 -149
- package/src/components/atoms/pager-control/pager-control.tsx +0 -328
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-default-vertical-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-default-vertical-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-horizontal-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-horizontal-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-minimal-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-minimal-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-actions-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-actions-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-eyebrow-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-eyebrow-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-image-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-image-chromium-linux.png +0 -0
- package/src/components/organisms/card/card.stories.tsx +0 -293
- package/src/components/organisms/card/card.test.tsx +0 -245
- package/src/components/organisms/card/card.tsx +0 -227
- package/src/components/organisms/card/card.visual.test.tsx +0 -197
- package/src/components/organisms/card/index.ts +0 -19
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-active-link-chromium-darwin.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-active-link-chromium-linux.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-brand-only-chromium-darwin.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-brand-only-chromium-linux.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-default-chromium-darwin.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-default-chromium-linux.png +0 -0
- package/src/components/organisms/navbar/index.ts +0 -18
- package/src/components/organisms/navbar/navbar.stories.tsx +0 -313
- package/src/components/organisms/navbar/navbar.test.tsx +0 -190
- package/src/components/organisms/navbar/navbar.tsx +0 -317
- package/src/components/organisms/navbar/navbar.visual.test.tsx +0 -85
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-icon-chromium-darwin.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-icon-chromium-linux.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-text-chromium-darwin.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-text-chromium-linux.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-default-chromium-darwin.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-default-chromium-linux.png +0 -0
- package/src/components/organisms/us-gov-banner/index.ts +0 -1
- package/src/components/organisms/us-gov-banner/us-gov-banner.stories.tsx +0 -35
- package/src/components/organisms/us-gov-banner/us-gov-banner.test.tsx +0 -107
- package/src/components/organisms/us-gov-banner/us-gov-banner.tsx +0 -73
- package/src/components/organisms/us-gov-banner/us-gov-banner.visual.test.tsx +0 -46
- package/src/components/sections/banner/banner.stories.tsx +0 -150
- package/src/components/sections/banner/banner.test.tsx +0 -185
- package/src/components/sections/banner/banner.tsx +0 -130
- package/src/components/sections/banner/index.ts +0 -2
- package/src/components/sections/card-grid/card-grid.stories.tsx +0 -351
- package/src/components/sections/card-grid/card-grid.tsx +0 -118
- package/src/components/sections/card-grid/index.ts +0 -1
- package/src/components/sections/faq-section/faq-section.tsx +0 -77
- package/src/components/sections/faq-section/index.ts +0 -2
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-desktop-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-desktop-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-mobile-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-mobile-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-tablet-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-tablet-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-desktop-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-desktop-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-mobile-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-mobile-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-tablet-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-tablet-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-desktop-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-desktop-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-mobile-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-mobile-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-tablet-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-tablet-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-custom-class-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-custom-class-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-default-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-long-title-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-long-title-chromium-linux.png +0 -0
- package/src/components/sections/hero/hero.stories.tsx +0 -145
- package/src/components/sections/hero/hero.test.tsx +0 -135
- package/src/components/sections/hero/hero.tsx +0 -191
- package/src/components/sections/hero/hero.visual.test.tsx +0 -140
- package/src/components/sections/hero/index.ts +0 -1
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-h3-heading-chromium-darwin.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-h3-heading-chromium-linux.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-paragraphs-chromium-darwin.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-paragraphs-chromium-linux.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-sections-chromium-darwin.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-sections-chromium-linux.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-single-section-chromium-darwin.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-single-section-chromium-linux.png +0 -0
- package/src/components/sections/prose/index.ts +0 -6
- package/src/components/sections/prose/prose.stories.tsx +0 -144
- package/src/components/sections/prose/prose.test.tsx +0 -178
- package/src/components/sections/prose/prose.tsx +0 -88
- package/src/components/sections/prose/prose.visual.test.tsx +0 -105
- package/src/components/sections/river/index.ts +0 -1
- package/src/components/sections/river/river.stories.tsx +0 -237
- package/src/components/sections/river/river.test.tsx +0 -268
- package/src/components/sections/river/river.tsx +0 -175
- package/src/components/sections/tout/index.ts +0 -1
- package/src/components/sections/tout/tout.stories.tsx +0 -154
- package/src/components/sections/tout/tout.test.tsx +0 -242
- package/src/components/sections/tout/tout.tsx +0 -206
- package/src/components/sections/two-column-section/index.ts +0 -5
- package/src/components/sections/two-column-section/two-column-section.stories.tsx +0 -285
- package/src/components/sections/two-column-section/two-column-section.tsx +0 -152
- package/src/index.ts +0 -98
- package/src/lib/utils.ts +0 -6
- package/src/main.tsx +0 -13
- package/src/stories/Introduction.mdx +0 -114
- package/src/stories/TokenShowcase.stories.tsx +0 -92
- package/src/stories/TokenShowcase.tsx +0 -1352
- package/src/styles.css +0 -11
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
import { Dialog } from "@base-ui-components/react/dialog";
|
|
2
|
-
import { Slot } from "@radix-ui/react-slot";
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { cn } from "@/lib/utils";
|
|
5
|
-
|
|
6
|
-
// Context for mobile menu state
|
|
7
|
-
const NavbarContext = React.createContext<{
|
|
8
|
-
isMobileMenuOpen: boolean;
|
|
9
|
-
setIsMobileMenuOpen: (open: boolean) => void;
|
|
10
|
-
}>({
|
|
11
|
-
isMobileMenuOpen: false,
|
|
12
|
-
setIsMobileMenuOpen: () => {},
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
export interface NavbarProps extends React.HTMLAttributes<HTMLElement> {}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Main navigation bar container.
|
|
19
|
-
* Provides responsive layout for brand, links, and actions.
|
|
20
|
-
*/
|
|
21
|
-
const Navbar = React.forwardRef<HTMLElement, NavbarProps>(
|
|
22
|
-
({ className, children, ...props }, ref) => {
|
|
23
|
-
const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false);
|
|
24
|
-
const navRef = React.useRef<HTMLElement>(null);
|
|
25
|
-
|
|
26
|
-
// Set navbar height CSS variable for mobile menu positioning
|
|
27
|
-
React.useEffect(() => {
|
|
28
|
-
const updateHeight = () => {
|
|
29
|
-
if (navRef.current) {
|
|
30
|
-
const height = navRef.current.offsetHeight;
|
|
31
|
-
document.documentElement.style.setProperty(
|
|
32
|
-
"--navbar-height",
|
|
33
|
-
`${height}px`,
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
updateHeight();
|
|
39
|
-
window.addEventListener("resize", updateHeight);
|
|
40
|
-
return () => window.removeEventListener("resize", updateHeight);
|
|
41
|
-
}, []);
|
|
42
|
-
|
|
43
|
-
// Merge refs
|
|
44
|
-
const mergedRef = React.useCallback(
|
|
45
|
-
(node: HTMLElement | null) => {
|
|
46
|
-
(navRef as React.MutableRefObject<HTMLElement | null>).current = node;
|
|
47
|
-
if (typeof ref === "function") {
|
|
48
|
-
ref(node);
|
|
49
|
-
} else if (ref) {
|
|
50
|
-
ref.current = node;
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
[ref],
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<NavbarContext.Provider value={{ isMobileMenuOpen, setIsMobileMenuOpen }}>
|
|
58
|
-
<nav
|
|
59
|
-
ref={mergedRef}
|
|
60
|
-
className={cn("relative z-50 w-full bg-gray-50", className)}
|
|
61
|
-
{...props}
|
|
62
|
-
>
|
|
63
|
-
<div
|
|
64
|
-
className={cn(
|
|
65
|
-
"flex w-full items-center justify-between",
|
|
66
|
-
// Mobile
|
|
67
|
-
"px-spacing-20 py-spacing-8",
|
|
68
|
-
// Tablet
|
|
69
|
-
"md:px-spacing-32 md:py-spacing-16",
|
|
70
|
-
// Desktop
|
|
71
|
-
"xl:px-spacing-32 xl:py-spacing-24",
|
|
72
|
-
)}
|
|
73
|
-
>
|
|
74
|
-
{children}
|
|
75
|
-
</div>
|
|
76
|
-
</nav>
|
|
77
|
-
</NavbarContext.Provider>
|
|
78
|
-
);
|
|
79
|
-
},
|
|
80
|
-
);
|
|
81
|
-
Navbar.displayName = "Navbar";
|
|
82
|
-
|
|
83
|
-
export interface NavbarBrandProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
84
|
-
asChild?: boolean;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Brand/logo area of the navbar.
|
|
89
|
-
* Use asChild to render as a link.
|
|
90
|
-
*/
|
|
91
|
-
const NavbarBrand = React.forwardRef<HTMLDivElement, NavbarBrandProps>(
|
|
92
|
-
({ className, asChild = false, ...props }, ref) => {
|
|
93
|
-
const Comp = asChild ? Slot : "div";
|
|
94
|
-
return <Comp ref={ref} className={cn("shrink-0", className)} {...props} />;
|
|
95
|
-
},
|
|
96
|
-
);
|
|
97
|
-
NavbarBrand.displayName = "NavbarBrand";
|
|
98
|
-
|
|
99
|
-
export interface NavbarLinksProps
|
|
100
|
-
extends React.HTMLAttributes<HTMLDivElement> {}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Container for navigation links.
|
|
104
|
-
* Centers links on desktop, hidden on mobile (use NavbarMobileMenu instead).
|
|
105
|
-
*/
|
|
106
|
-
const NavbarLinks = React.forwardRef<HTMLDivElement, NavbarLinksProps>(
|
|
107
|
-
({ className, ...props }, ref) => {
|
|
108
|
-
return (
|
|
109
|
-
<div
|
|
110
|
-
ref={ref}
|
|
111
|
-
className={cn("hidden items-center gap-spacing-40 md:flex", className)}
|
|
112
|
-
{...props}
|
|
113
|
-
/>
|
|
114
|
-
);
|
|
115
|
-
},
|
|
116
|
-
);
|
|
117
|
-
NavbarLinks.displayName = "NavbarLinks";
|
|
118
|
-
|
|
119
|
-
export interface NavbarLinkProps
|
|
120
|
-
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
121
|
-
asChild?: boolean;
|
|
122
|
-
active?: boolean;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Individual navigation link.
|
|
127
|
-
* Use asChild to render with a router Link component.
|
|
128
|
-
*/
|
|
129
|
-
const NavbarLink = React.forwardRef<HTMLAnchorElement, NavbarLinkProps>(
|
|
130
|
-
({ className, asChild = false, active, ...props }, ref) => {
|
|
131
|
-
const Comp = asChild ? Slot : "a";
|
|
132
|
-
return (
|
|
133
|
-
<Comp
|
|
134
|
-
ref={ref}
|
|
135
|
-
className={cn(
|
|
136
|
-
"typography-brand-medium-link-small text-gray-900 transition-colors hover:text-gray-700",
|
|
137
|
-
active && "text-gray-1100",
|
|
138
|
-
className,
|
|
139
|
-
)}
|
|
140
|
-
{...props}
|
|
141
|
-
/>
|
|
142
|
-
);
|
|
143
|
-
},
|
|
144
|
-
);
|
|
145
|
-
NavbarLink.displayName = "NavbarLink";
|
|
146
|
-
|
|
147
|
-
export interface NavbarActionsProps
|
|
148
|
-
extends React.HTMLAttributes<HTMLDivElement> {}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Container for navbar action items (search, menu button, etc).
|
|
152
|
-
*/
|
|
153
|
-
const NavbarActions = React.forwardRef<HTMLDivElement, NavbarActionsProps>(
|
|
154
|
-
({ className, ...props }, ref) => {
|
|
155
|
-
return (
|
|
156
|
-
<div
|
|
157
|
-
ref={ref}
|
|
158
|
-
className={cn("flex items-center gap-spacing-8", className)}
|
|
159
|
-
{...props}
|
|
160
|
-
/>
|
|
161
|
-
);
|
|
162
|
-
},
|
|
163
|
-
);
|
|
164
|
-
NavbarActions.displayName = "NavbarActions";
|
|
165
|
-
|
|
166
|
-
export interface NavbarMobileMenuProps
|
|
167
|
-
extends React.HTMLAttributes<HTMLDivElement> {}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Mobile menu container that displays navigation links on mobile devices.
|
|
171
|
-
* Hidden on desktop (md and above). Should be used with NavbarMobileMenuButton.
|
|
172
|
-
* Built on Base UI Dialog for accessibility (focus trap, escape key, click-outside).
|
|
173
|
-
*/
|
|
174
|
-
const NavbarMobileMenu = React.forwardRef<
|
|
175
|
-
HTMLDivElement,
|
|
176
|
-
NavbarMobileMenuProps
|
|
177
|
-
>(({ className, children, ...props }, ref) => {
|
|
178
|
-
const { isMobileMenuOpen, setIsMobileMenuOpen } =
|
|
179
|
-
React.useContext(NavbarContext);
|
|
180
|
-
|
|
181
|
-
return (
|
|
182
|
-
<Dialog.Root open={isMobileMenuOpen} onOpenChange={setIsMobileMenuOpen}>
|
|
183
|
-
<Dialog.Portal>
|
|
184
|
-
<Dialog.Popup
|
|
185
|
-
ref={ref}
|
|
186
|
-
className={cn(
|
|
187
|
-
"fixed inset-0 z-50 bg-gray-50 md:hidden",
|
|
188
|
-
// Position below navbar
|
|
189
|
-
"pt-[calc(var(--navbar-height,60px)+1px)]",
|
|
190
|
-
// Smooth transition
|
|
191
|
-
"transition-opacity duration-200",
|
|
192
|
-
className,
|
|
193
|
-
)}
|
|
194
|
-
{...props}
|
|
195
|
-
>
|
|
196
|
-
<Dialog.Title className="sr-only">Navigation menu</Dialog.Title>
|
|
197
|
-
<div
|
|
198
|
-
className={cn(
|
|
199
|
-
"flex flex-col",
|
|
200
|
-
// Padding matching navbar
|
|
201
|
-
"px-spacing-20 py-spacing-16",
|
|
202
|
-
// Gap between links
|
|
203
|
-
"gap-spacing-8",
|
|
204
|
-
)}
|
|
205
|
-
>
|
|
206
|
-
{children}
|
|
207
|
-
</div>
|
|
208
|
-
</Dialog.Popup>
|
|
209
|
-
</Dialog.Portal>
|
|
210
|
-
</Dialog.Root>
|
|
211
|
-
);
|
|
212
|
-
});
|
|
213
|
-
NavbarMobileMenu.displayName = "NavbarMobileMenu";
|
|
214
|
-
|
|
215
|
-
export interface NavbarMobileMenuButtonProps
|
|
216
|
-
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
217
|
-
asChild?: boolean;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Button to toggle the mobile menu.
|
|
222
|
-
* Should be placed in NavbarActions on mobile.
|
|
223
|
-
* Use asChild to render as a custom button component (e.g., IconButton).
|
|
224
|
-
*/
|
|
225
|
-
const NavbarMobileMenuButton = React.forwardRef<
|
|
226
|
-
HTMLButtonElement,
|
|
227
|
-
NavbarMobileMenuButtonProps
|
|
228
|
-
>(({ className, asChild = false, children, ...props }, ref) => {
|
|
229
|
-
const { isMobileMenuOpen, setIsMobileMenuOpen } =
|
|
230
|
-
React.useContext(NavbarContext);
|
|
231
|
-
|
|
232
|
-
const handleClick = () => {
|
|
233
|
-
setIsMobileMenuOpen(!isMobileMenuOpen);
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
if (asChild) {
|
|
237
|
-
return (
|
|
238
|
-
<Slot
|
|
239
|
-
ref={ref}
|
|
240
|
-
aria-label="Toggle navigation menu"
|
|
241
|
-
aria-expanded={isMobileMenuOpen}
|
|
242
|
-
aria-controls="navbar-mobile-menu"
|
|
243
|
-
onClick={handleClick}
|
|
244
|
-
className={className}
|
|
245
|
-
{...props}
|
|
246
|
-
>
|
|
247
|
-
{children}
|
|
248
|
-
</Slot>
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return (
|
|
253
|
-
<button
|
|
254
|
-
ref={ref}
|
|
255
|
-
type="button"
|
|
256
|
-
aria-label="Toggle navigation menu"
|
|
257
|
-
aria-expanded={isMobileMenuOpen}
|
|
258
|
-
aria-controls="navbar-mobile-menu"
|
|
259
|
-
onClick={handleClick}
|
|
260
|
-
className={cn("transition-colors", className)}
|
|
261
|
-
{...props}
|
|
262
|
-
>
|
|
263
|
-
{children}
|
|
264
|
-
</button>
|
|
265
|
-
);
|
|
266
|
-
});
|
|
267
|
-
NavbarMobileMenuButton.displayName = "NavbarMobileMenuButton";
|
|
268
|
-
|
|
269
|
-
export interface NavbarMobileMenuLinkProps
|
|
270
|
-
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
271
|
-
asChild?: boolean;
|
|
272
|
-
active?: boolean;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Navigation link for the mobile menu.
|
|
277
|
-
* Automatically closes the mobile menu when clicked.
|
|
278
|
-
* Use asChild to render with a router Link component.
|
|
279
|
-
*/
|
|
280
|
-
const NavbarMobileMenuLink = React.forwardRef<
|
|
281
|
-
HTMLAnchorElement,
|
|
282
|
-
NavbarMobileMenuLinkProps
|
|
283
|
-
>(({ className, asChild = false, active, onClick, ...props }, ref) => {
|
|
284
|
-
const { setIsMobileMenuOpen } = React.useContext(NavbarContext);
|
|
285
|
-
const Comp = asChild ? Slot : "a";
|
|
286
|
-
|
|
287
|
-
const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
|
|
288
|
-
setIsMobileMenuOpen(false);
|
|
289
|
-
onClick?.(event);
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
return (
|
|
293
|
-
<Comp
|
|
294
|
-
ref={ref}
|
|
295
|
-
className={cn(
|
|
296
|
-
"typography-brand-medium-link-medium text-gray-900 transition-colors hover:text-gray-700",
|
|
297
|
-
"py-spacing-8",
|
|
298
|
-
active && "text-gray-1100",
|
|
299
|
-
className,
|
|
300
|
-
)}
|
|
301
|
-
onClick={handleClick}
|
|
302
|
-
{...props}
|
|
303
|
-
/>
|
|
304
|
-
);
|
|
305
|
-
});
|
|
306
|
-
NavbarMobileMenuLink.displayName = "NavbarMobileMenuLink";
|
|
307
|
-
|
|
308
|
-
export {
|
|
309
|
-
Navbar,
|
|
310
|
-
NavbarBrand,
|
|
311
|
-
NavbarLinks,
|
|
312
|
-
NavbarLink,
|
|
313
|
-
NavbarActions,
|
|
314
|
-
NavbarMobileMenu,
|
|
315
|
-
NavbarMobileMenuButton,
|
|
316
|
-
NavbarMobileMenuLink,
|
|
317
|
-
};
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "vitest";
|
|
2
|
-
import { page } from "vitest/browser";
|
|
3
|
-
import { render } from "vitest-browser-react";
|
|
4
|
-
import { Button } from "../../atoms/button";
|
|
5
|
-
import {
|
|
6
|
-
Navbar,
|
|
7
|
-
NavbarActions,
|
|
8
|
-
NavbarBrand,
|
|
9
|
-
NavbarLink,
|
|
10
|
-
NavbarLinks,
|
|
11
|
-
} from "./navbar";
|
|
12
|
-
|
|
13
|
-
describe("Navbar Visual Regression", () => {
|
|
14
|
-
test("default navbar renders correctly", async () => {
|
|
15
|
-
await page.viewport(1280, 800);
|
|
16
|
-
|
|
17
|
-
render(
|
|
18
|
-
<Navbar data-testid="navbar">
|
|
19
|
-
<NavbarBrand>
|
|
20
|
-
<span className="text-xl font-bold">Logo</span>
|
|
21
|
-
</NavbarBrand>
|
|
22
|
-
<NavbarLinks>
|
|
23
|
-
<NavbarLink href="#">Home</NavbarLink>
|
|
24
|
-
<NavbarLink href="#">About</NavbarLink>
|
|
25
|
-
<NavbarLink href="#">Services</NavbarLink>
|
|
26
|
-
<NavbarLink href="#">Contact</NavbarLink>
|
|
27
|
-
</NavbarLinks>
|
|
28
|
-
<NavbarActions>
|
|
29
|
-
<Button size="sm" variant="charcoal">
|
|
30
|
-
Sign In
|
|
31
|
-
</Button>
|
|
32
|
-
</NavbarActions>
|
|
33
|
-
</Navbar>,
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
await expect(page.getByTestId("navbar")).toMatchScreenshot(
|
|
37
|
-
"navbar-default",
|
|
38
|
-
);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test("navbar with active link renders correctly", async () => {
|
|
42
|
-
await page.viewport(1280, 800);
|
|
43
|
-
|
|
44
|
-
render(
|
|
45
|
-
<Navbar data-testid="navbar">
|
|
46
|
-
<NavbarBrand>
|
|
47
|
-
<span className="text-xl font-bold">Logo</span>
|
|
48
|
-
</NavbarBrand>
|
|
49
|
-
<NavbarLinks>
|
|
50
|
-
<NavbarLink href="#" active>
|
|
51
|
-
Home
|
|
52
|
-
</NavbarLink>
|
|
53
|
-
<NavbarLink href="#">About</NavbarLink>
|
|
54
|
-
<NavbarLink href="#">Services</NavbarLink>
|
|
55
|
-
<NavbarLink href="#">Contact</NavbarLink>
|
|
56
|
-
</NavbarLinks>
|
|
57
|
-
<NavbarActions>
|
|
58
|
-
<Button size="sm" variant="charcoal">
|
|
59
|
-
Sign In
|
|
60
|
-
</Button>
|
|
61
|
-
</NavbarActions>
|
|
62
|
-
</Navbar>,
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
await expect(page.getByTestId("navbar")).toMatchScreenshot(
|
|
66
|
-
"navbar-active-link",
|
|
67
|
-
);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test("navbar brand only renders correctly", async () => {
|
|
71
|
-
await page.viewport(1280, 800);
|
|
72
|
-
|
|
73
|
-
render(
|
|
74
|
-
<Navbar data-testid="navbar">
|
|
75
|
-
<NavbarBrand>
|
|
76
|
-
<span className="text-xl font-bold">Brand Only</span>
|
|
77
|
-
</NavbarBrand>
|
|
78
|
-
</Navbar>,
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
await expect(page.getByTestId("navbar")).toMatchScreenshot(
|
|
82
|
-
"navbar-brand-only",
|
|
83
|
-
);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { USGovBanner, type USGovBannerProps } from "./us-gov-banner";
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { USGovBanner } from ".";
|
|
3
|
-
|
|
4
|
-
const meta: Meta<typeof USGovBanner> = {
|
|
5
|
-
title: "Organisms/USGovBanner",
|
|
6
|
-
component: USGovBanner,
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: "fullscreen",
|
|
9
|
-
},
|
|
10
|
-
} as Meta<typeof USGovBanner>;
|
|
11
|
-
|
|
12
|
-
export default meta;
|
|
13
|
-
type Story = StoryObj<typeof USGovBanner>;
|
|
14
|
-
|
|
15
|
-
export const Default: Story = {
|
|
16
|
-
render: () => <USGovBanner />,
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const CustomText: Story = {
|
|
20
|
-
render: () => (
|
|
21
|
-
<USGovBanner text="An official website of the U.S. Department of State" />
|
|
22
|
-
),
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export const Playground: Story = {
|
|
26
|
-
render: (args) => <USGovBanner {...args} />,
|
|
27
|
-
};
|
|
28
|
-
Playground.argTypes = {
|
|
29
|
-
text: {
|
|
30
|
-
control: { type: "text" },
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
Playground.args = {
|
|
34
|
-
text: "An official website of the United States government",
|
|
35
|
-
};
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "vitest";
|
|
2
|
-
import { page } from "vitest/browser";
|
|
3
|
-
import { render } from "vitest-browser-react";
|
|
4
|
-
import { USGovBanner } from "./us-gov-banner";
|
|
5
|
-
|
|
6
|
-
describe("USGovBanner", () => {
|
|
7
|
-
describe("Accessibility", () => {
|
|
8
|
-
test("banner text is readable", async () => {
|
|
9
|
-
render(<USGovBanner />);
|
|
10
|
-
|
|
11
|
-
await expect
|
|
12
|
-
.element(
|
|
13
|
-
page.getByText("An official website of the United States government"),
|
|
14
|
-
)
|
|
15
|
-
.toBeInTheDocument();
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
test("flag icon is hidden from screen readers", async () => {
|
|
19
|
-
render(<USGovBanner data-testid="banner" />);
|
|
20
|
-
|
|
21
|
-
// The default flag SVG has aria-hidden="true"
|
|
22
|
-
const banner = page.getByTestId("banner");
|
|
23
|
-
await expect.element(banner).toBeInTheDocument();
|
|
24
|
-
|
|
25
|
-
// Verify the SVG is present but decorative
|
|
26
|
-
const svg = banner.element().querySelector("svg");
|
|
27
|
-
expect(svg?.getAttribute("aria-hidden")).toBe("true");
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test("custom text is readable", async () => {
|
|
31
|
-
render(<USGovBanner text="Custom government message" />);
|
|
32
|
-
|
|
33
|
-
await expect
|
|
34
|
-
.element(page.getByText("Custom government message"))
|
|
35
|
-
.toBeInTheDocument();
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
describe("Props", () => {
|
|
40
|
-
test("renders default text when no text prop provided", async () => {
|
|
41
|
-
render(<USGovBanner />);
|
|
42
|
-
|
|
43
|
-
await expect
|
|
44
|
-
.element(
|
|
45
|
-
page.getByText("An official website of the United States government"),
|
|
46
|
-
)
|
|
47
|
-
.toBeInTheDocument();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test("renders custom text when provided", async () => {
|
|
51
|
-
render(<USGovBanner text="An official California website" />);
|
|
52
|
-
|
|
53
|
-
await expect
|
|
54
|
-
.element(page.getByText("An official California website"))
|
|
55
|
-
.toBeInTheDocument();
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
test("renders custom flag icon when provided", async () => {
|
|
59
|
-
render(
|
|
60
|
-
<USGovBanner flagIcon={<span data-testid="custom-icon">🏛️</span>} />,
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
await expect.element(page.getByTestId("custom-icon")).toBeInTheDocument();
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test("supports custom className", async () => {
|
|
67
|
-
render(<USGovBanner className="custom-banner" data-testid="banner" />);
|
|
68
|
-
|
|
69
|
-
const banner = page.getByTestId("banner");
|
|
70
|
-
await expect.element(banner).toHaveClass(/custom-banner/);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test("spreads additional props", async () => {
|
|
74
|
-
render(
|
|
75
|
-
<USGovBanner data-testid="banner" aria-label="Government banner" />,
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
const banner = page.getByTestId("banner");
|
|
79
|
-
await expect
|
|
80
|
-
.element(banner)
|
|
81
|
-
.toHaveAttribute("aria-label", "Government banner");
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
describe("Styling", () => {
|
|
86
|
-
test("has light background by default", async () => {
|
|
87
|
-
render(<USGovBanner data-testid="banner" />);
|
|
88
|
-
|
|
89
|
-
const banner = page.getByTestId("banner");
|
|
90
|
-
await expect.element(banner).toHaveClass(/bg-gray-50/);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
test("is centered", async () => {
|
|
94
|
-
render(<USGovBanner data-testid="banner" />);
|
|
95
|
-
|
|
96
|
-
const banner = page.getByTestId("banner");
|
|
97
|
-
await expect.element(banner).toHaveClass(/justify-center/);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
test("spans full width", async () => {
|
|
101
|
-
render(<USGovBanner data-testid="banner" />);
|
|
102
|
-
|
|
103
|
-
const banner = page.getByTestId("banner");
|
|
104
|
-
await expect.element(banner).toHaveClass(/w-full/);
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
});
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { cn } from "@/lib/utils";
|
|
3
|
-
|
|
4
|
-
export interface USGovBannerProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
5
|
-
/**
|
|
6
|
-
* Custom flag icon element. Defaults to a US flag SVG.
|
|
7
|
-
*/
|
|
8
|
-
flagIcon?: React.ReactNode;
|
|
9
|
-
/**
|
|
10
|
-
* Banner text content
|
|
11
|
-
* @default "An official website of the United States government"
|
|
12
|
-
*/
|
|
13
|
-
text?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* US Government official website banner.
|
|
18
|
-
* Displays the official government website notice with flag icon.
|
|
19
|
-
* Commonly placed at the very top of government websites.
|
|
20
|
-
*/
|
|
21
|
-
const USGovBanner = React.forwardRef<HTMLDivElement, USGovBannerProps>(
|
|
22
|
-
(
|
|
23
|
-
{
|
|
24
|
-
className,
|
|
25
|
-
flagIcon,
|
|
26
|
-
text = "An official website of the United States government",
|
|
27
|
-
...props
|
|
28
|
-
},
|
|
29
|
-
ref,
|
|
30
|
-
) => {
|
|
31
|
-
return (
|
|
32
|
-
<div
|
|
33
|
-
ref={ref}
|
|
34
|
-
className={cn(
|
|
35
|
-
"flex w-full items-center justify-center bg-gray-50 py-spacing-12",
|
|
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>
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
);
|
|
48
|
-
},
|
|
49
|
-
);
|
|
50
|
-
USGovBanner.displayName = "USGovBanner";
|
|
51
|
-
|
|
52
|
-
function DefaultUSFlag() {
|
|
53
|
-
return (
|
|
54
|
-
<svg
|
|
55
|
-
width="16"
|
|
56
|
-
height="12"
|
|
57
|
-
viewBox="0 0 16 12"
|
|
58
|
-
fill="none"
|
|
59
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
60
|
-
aria-hidden="true"
|
|
61
|
-
>
|
|
62
|
-
<path d="M0 0H16V12H0V0Z" fill="#212121" fillOpacity="0.1" />
|
|
63
|
-
<path
|
|
64
|
-
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"
|
|
65
|
-
fill="#BF0A30"
|
|
66
|
-
fillOpacity="0.8"
|
|
67
|
-
/>
|
|
68
|
-
<path d="M0 0H8V6.46154H0V0Z" fill="#002868" fillOpacity="0.8" />
|
|
69
|
-
</svg>
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export { USGovBanner };
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "vitest";
|
|
2
|
-
import { page } from "vitest/browser";
|
|
3
|
-
import { render } from "vitest-browser-react";
|
|
4
|
-
import { USGovBanner } from "./us-gov-banner";
|
|
5
|
-
|
|
6
|
-
describe("USGovBanner Visual Regression", () => {
|
|
7
|
-
test("default banner renders correctly", async () => {
|
|
8
|
-
await page.viewport(1280, 800);
|
|
9
|
-
|
|
10
|
-
render(<USGovBanner data-testid="banner" />);
|
|
11
|
-
|
|
12
|
-
await expect(page.getByTestId("banner")).toMatchScreenshot(
|
|
13
|
-
"us-gov-banner-default",
|
|
14
|
-
);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
test("banner with custom text renders correctly", async () => {
|
|
18
|
-
await page.viewport(1280, 800);
|
|
19
|
-
|
|
20
|
-
render(
|
|
21
|
-
<USGovBanner
|
|
22
|
-
data-testid="banner"
|
|
23
|
-
text="An official website of the State of California"
|
|
24
|
-
/>,
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
await expect(page.getByTestId("banner")).toMatchScreenshot(
|
|
28
|
-
"us-gov-banner-custom-text",
|
|
29
|
-
);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test("banner with custom flag icon renders correctly", async () => {
|
|
33
|
-
await page.viewport(1280, 800);
|
|
34
|
-
|
|
35
|
-
render(
|
|
36
|
-
<USGovBanner
|
|
37
|
-
data-testid="banner"
|
|
38
|
-
flagIcon={<span aria-hidden="true">🏛️</span>}
|
|
39
|
-
/>,
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
await expect(page.getByTestId("banner")).toMatchScreenshot(
|
|
43
|
-
"us-gov-banner-custom-icon",
|
|
44
|
-
);
|
|
45
|
-
});
|
|
46
|
-
});
|