Skip to content

Commit 236407b

Browse files
authored
feat: add navigation menu
1 parent 4a6d617 commit 236407b

File tree

7 files changed

+656
-131
lines changed

7 files changed

+656
-131
lines changed

components/Navigation/Navigation.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const baseNavItemCss = css({
2525
color: '$navButtonText',
2626
border: 'none',
2727
minHeight: '$7',
28+
width: '100%',
2829
px: '$3',
2930
py: '$2',
3031
borderRadius: '$3',
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { GearIcon, PersonIcon } from '@radix-ui/react-icons';
2+
import { Meta, StoryFn } from '@storybook/react';
3+
import React from 'react';
4+
5+
import { modifyVariantsForStory } from '../../utils/modifyVariantsForStory';
6+
import { Container } from '../Container';
7+
import { Link } from '../Link';
8+
import { NavigationItem } from '../Navigation';
9+
import { Text } from '../Text';
10+
import {
11+
NavigationMenu,
12+
NavigationMenuContent,
13+
NavigationMenuItem,
14+
NavigationMenuLink,
15+
NavigationMenuList,
16+
NavigationMenuProps,
17+
NavigationMenuTrigger,
18+
NavigationMenuVariants,
19+
} from './NavigationMenu';
20+
21+
const BaseNavigationMenu = (props: NavigationMenuProps): JSX.Element => (
22+
<NavigationMenu {...props} />
23+
);
24+
25+
const NavigationMenuForStory = modifyVariantsForStory<NavigationMenuVariants, NavigationMenuProps>(
26+
BaseNavigationMenu,
27+
);
28+
29+
const Component: Meta<typeof NavigationMenuForStory> = {
30+
title: 'Components/NavigationMenu',
31+
component: NavigationMenuForStory,
32+
};
33+
34+
const Template: StoryFn<typeof NavigationMenuForStory> = (args) => (
35+
<Container>
36+
<NavigationMenuForStory {...args}>
37+
<NavigationMenuList>
38+
<NavigationMenuItem>
39+
<NavigationMenuTrigger>
40+
<Text css={{ cursor: 'pointer' }}>Links</Text>
41+
</NavigationMenuTrigger>
42+
<NavigationMenuContent css={{ display: 'flex', flexDirection: 'column', gap: '$1' }}>
43+
<NavigationMenuLink asChild>
44+
<Link href="#">A link</Link>
45+
</NavigationMenuLink>
46+
<NavigationMenuLink asChild>
47+
<Link href="#">Another link</Link>
48+
</NavigationMenuLink>
49+
</NavigationMenuContent>
50+
</NavigationMenuItem>
51+
52+
<NavigationMenuItem>
53+
<NavigationMenuTrigger>
54+
<Text css={{ cursor: 'pointer' }}>Navigation items</Text>
55+
</NavigationMenuTrigger>
56+
<NavigationMenuContent>
57+
<NavigationMenuLink>
58+
<NavigationItem startAdornment={<PersonIcon />}>Profile</NavigationItem>
59+
</NavigationMenuLink>
60+
<NavigationMenuLink>
61+
<NavigationItem startAdornment={<GearIcon />}>Settings</NavigationItem>
62+
</NavigationMenuLink>
63+
</NavigationMenuContent>
64+
</NavigationMenuItem>
65+
</NavigationMenuList>
66+
</NavigationMenuForStory>
67+
</Container>
68+
);
69+
70+
export const Basic: StoryFn<typeof NavigationMenuForStory> = Template.bind({});
71+
72+
export default Component;
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';
2+
import React from 'react';
3+
4+
import { CSS, styled, VariantProps } from '../../stitches.config';
5+
import { elevationVariants } from '../Elevation';
6+
import { panelStyles } from '../Panel';
7+
8+
// #region Root
9+
10+
const StyledRoot = styled(NavigationMenuPrimitive.Root, {
11+
ul: {
12+
m: 0,
13+
p: 0,
14+
listStyleType: 'none',
15+
li: {
16+
position: 'relative',
17+
display: 'inline',
18+
},
19+
},
20+
});
21+
22+
export type NavigationMenuProps = React.ComponentProps<typeof NavigationMenuPrimitive.Root> & {
23+
children: React.ReactNode;
24+
css?: CSS;
25+
};
26+
27+
export type NavigationMenuVariants = VariantProps<typeof NavigationMenu>;
28+
29+
export const NavigationMenu = React.forwardRef<
30+
React.ElementRef<typeof StyledRoot>,
31+
NavigationMenuProps
32+
>(({ children, ...props }, fowardedRef) => (
33+
<StyledRoot {...props} ref={fowardedRef}>
34+
{children}
35+
</StyledRoot>
36+
));
37+
38+
// #endregion Root
39+
40+
// #region Content
41+
42+
const StyledContent = styled(NavigationMenuPrimitive.Content, panelStyles, {
43+
position: 'absolute',
44+
left: 0,
45+
zIndex: 1,
46+
p: '$2',
47+
color: '$hiContrast',
48+
'&:focus': {
49+
outline: 'none',
50+
},
51+
variants: {
52+
elevation: elevationVariants,
53+
},
54+
defaultVariants: {
55+
elevation: 2,
56+
},
57+
});
58+
59+
type NavigationMenuPrimitiveContentProps = Omit<
60+
React.ComponentProps<typeof NavigationMenuPrimitive.Content>,
61+
'as'
62+
>;
63+
64+
export type NavigationMenuContentProps = NavigationMenuPrimitiveContentProps &
65+
VariantProps<typeof StyledContent> & {
66+
css?: CSS;
67+
};
68+
69+
export const NavigationMenuContent = React.forwardRef<
70+
React.ElementRef<typeof StyledContent>,
71+
NavigationMenuContentProps
72+
>(({ children, elevation, ...props }, fowardedRef) => (
73+
<StyledContent elevation={elevation} {...props} ref={fowardedRef}>
74+
{children}
75+
</StyledContent>
76+
));
77+
78+
// #endregion Content
79+
80+
// #region Trigger
81+
82+
const StyledTrigger = styled(NavigationMenuPrimitive.Trigger, {
83+
backgroundColor: 'transparent',
84+
border: 'none',
85+
});
86+
87+
export type NavigationMenuTriggerProps = React.ComponentProps<
88+
typeof NavigationMenuPrimitive.Trigger
89+
> &
90+
VariantProps<typeof StyledContent> & {
91+
css?: CSS;
92+
};
93+
94+
export const NavigationMenuTrigger = ({ children, ...props }: NavigationMenuTriggerProps) => (
95+
<StyledTrigger {...props}>{children}</StyledTrigger>
96+
);
97+
98+
// #endregion Trigger
99+
100+
export const NavigationMenuIndicator = NavigationMenuPrimitive.Indicator;
101+
export const NavigationMenuItem = NavigationMenuPrimitive.Item;
102+
export const NavigationMenuLink = NavigationMenuPrimitive.Link;
103+
export const NavigationMenuList = NavigationMenuPrimitive.List;
104+
export const NavigationMenuViewport = NavigationMenuPrimitive.Viewport;

components/NavigationMenu/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './NavigationMenu';

index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ export {
5959
NavigationItem,
6060
NavigationLink,
6161
} from './components/Navigation';
62+
export {
63+
NavigationMenu,
64+
NavigationMenuContent,
65+
NavigationMenuIndicator,
66+
NavigationMenuItem,
67+
NavigationMenuLink,
68+
NavigationMenuList,
69+
NavigationMenuTrigger,
70+
NavigationMenuViewport,
71+
} from './components/NavigationMenu';
6272
export {
6373
NavigationTreeDrawer,
6474
NavigationTreeContainer,

package.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"@radix-ui/react-id": "^1.0.0",
7070
"@radix-ui/react-label": "^2.0.0",
7171
"@radix-ui/react-menu": "^2.0.1",
72+
"@radix-ui/react-navigation-menu": "^1.2.0",
7273
"@radix-ui/react-popover": "^1.0.2",
7374
"@radix-ui/react-portal": "^1.0.1",
7475
"@radix-ui/react-progress": "^1.0.1",
@@ -90,13 +91,13 @@
9091
"@semantic-release/release-notes-generator": "^10.0.3",
9192
"@stitches/react": "1.2.7",
9293
"@storybook/addon-actions": "^8.2.2",
93-
"@storybook/addon-docs": "^8.2.2",
94-
"@storybook/addon-essentials": "^8.2.2",
94+
"@storybook/addon-docs": "^8.2.5",
95+
"@storybook/addon-essentials": "^8.2.5",
9596
"@storybook/addon-links": "^8.2.2",
96-
"@storybook/builder-vite": "^8.2.2",
97+
"@storybook/builder-vite": "^8.2.5",
9798
"@storybook/preview-api": "^8.2.2",
98-
"@storybook/react": "^8.2.2",
99-
"@storybook/react-vite": "^8.2.2",
99+
"@storybook/react": "^8.2.5",
100+
"@storybook/react-vite": "^8.2.5",
100101
"@storybook/theming": "^8.2.2",
101102
"@types/jest": "^27.4.1",
102103
"@types/jest-axe": "^3.5.3",
@@ -114,13 +115,13 @@
114115
"lodash.merge": "^4.6.2",
115116
"np": "^8.0.4",
116117
"patch-package": "^8.0.0",
117-
"prettier": "^2.1.2",
118+
"prettier": "^3.3.3",
118119
"react": "18.2.0",
119120
"react-dom": "18.2.0",
120121
"rollup": "^2.70.1",
121122
"rollup-plugin-typescript2": "^0.36.0",
122123
"semantic-release": "^19.0.2",
123-
"storybook": "^8.2.2",
124+
"storybook": "^8.2.5",
124125
"storybook-dark-mode": "^4.0.2",
125126
"tinycolor2": "^1.4.2",
126127
"typescript": "5.4.5",

0 commit comments

Comments
 (0)