Skip to content

Commit 24afddb

Browse files
committed
refactor: DropdownMenu reuse the menu component
1 parent da0f28c commit 24afddb

25 files changed

+229
-805
lines changed

packages/ui/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@
2929
"@radix-ui/react-checkbox": "1.3.2",
3030
"@radix-ui/react-collapsible": "^1.1.11",
3131
"@radix-ui/react-compose-refs": "1.1.2",
32+
"@radix-ui/react-context-menu": "^2.2.15",
3233
"@radix-ui/react-dropdown-menu": "^2.1.15",
3334
"@radix-ui/react-label": "2.1.7",
35+
"@radix-ui/react-menu": "^2.1.15",
3436
"@radix-ui/react-popover": "1.1.14",
3537
"@radix-ui/react-scroll-area": "1.2.9",
3638
"@radix-ui/react-separator": "1.1.7",
@@ -39,6 +41,7 @@
3941
"@radix-ui/react-tabs": "1.1.12",
4042
"@soybean-react-ui/tailwind-plugin": "workspace:*",
4143
"clsx": "2.1.1",
44+
"cmdk": "^1.1.1",
4245
"embla-carousel-react": "8.6.0",
4346
"lucide-react": "0.525.0",
4447
"next-themes": "0.4.6",

packages/ui/src/components/dropdown-menu/DropdownMenu.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Root, Trigger } from '@radix-ui/react-dropdown-menu';
22

3+
import DropdownMenuContent from './DropdownMenuContent';
34
import DropdownMenuOption from './DropdownMenuOption';
4-
import DropdownMenuPortalContent from './DropdownMenuPortalContent';
55
import type { DropdownMenuProps } from './types';
66

77
const DropdownMenu = (props: DropdownMenuProps) => {
@@ -17,7 +17,7 @@ const DropdownMenu = (props: DropdownMenuProps) => {
1717
>
1818
<Trigger asChild>{children}</Trigger>
1919

20-
<DropdownMenuPortalContent {...contentProps}>
20+
<DropdownMenuContent {...contentProps}>
2121
{items.map((item, index) => {
2222
return (
2323
<DropdownMenuOption
@@ -28,7 +28,7 @@ const DropdownMenu = (props: DropdownMenuProps) => {
2828
/>
2929
);
3030
})}
31-
</DropdownMenuPortalContent>
31+
</DropdownMenuContent>
3232
</Root>
3333
);
3434
};
Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,16 @@
11
import { Arrow } from '@radix-ui/react-dropdown-menu';
2-
import type { ComponentRef } from 'react';
3-
import { forwardRef } from 'react';
42

5-
import { cn } from '@/lib';
3+
import MenuArrow from '../menu/MenuArrow';
64

7-
import { menuVariants } from './dropdown-menu-variants';
85
import type { DropdownMenuArrowProps } from './types';
96

10-
const DropdownMenuArrow = forwardRef<ComponentRef<typeof Arrow>, DropdownMenuArrowProps>((props, ref) => {
11-
const { className, ...rest } = props;
12-
13-
const { arrow } = menuVariants();
14-
15-
const mergedCls = cn(arrow(), className);
16-
7+
const DropdownMenuArrow = (props: DropdownMenuArrowProps) => {
178
return (
18-
<Arrow
19-
className={mergedCls}
20-
ref={ref}
21-
{...rest}
9+
<MenuArrow
10+
{...props}
11+
component={Arrow as typeof MenuArrow}
2212
/>
2313
);
24-
});
25-
26-
DropdownMenuArrow.displayName = 'DropdownMenuArrow';
14+
};
2715

2816
export default DropdownMenuArrow;

packages/ui/src/components/dropdown-menu/DropdownMenuCheckbox.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Root, Trigger } from '@radix-ui/react-dropdown-menu';
22

33
import DropdownMenuCheckboxGroup from './DropdownMenuCheckboxGroup';
4-
import DropdownMenuPortalContent from './DropdownMenuPortalContent';
4+
import DropdownMenuContent from './DropdownMenuContent';
55
import type { DropdownMenuCheckboxProps } from './types';
66

77
const DropdownMenuCheckbox = (props: DropdownMenuCheckboxProps) => {
@@ -18,7 +18,7 @@ const DropdownMenuCheckbox = (props: DropdownMenuCheckboxProps) => {
1818
>
1919
<Trigger asChild>{children}</Trigger>
2020

21-
<DropdownMenuPortalContent
21+
<DropdownMenuContent
2222
arrowClass={classNames?.arrow}
2323
className={className || classNames?.content}
2424
size={size}
@@ -29,7 +29,7 @@ const DropdownMenuCheckbox = (props: DropdownMenuCheckboxProps) => {
2929
size={size}
3030
{...rest}
3131
/>
32-
</DropdownMenuPortalContent>
32+
</DropdownMenuContent>
3333
</Root>
3434
);
3535
};
Lines changed: 12 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,24 @@
11
'use client';
22

33
import { Group } from '@radix-ui/react-dropdown-menu';
4-
import type { ComponentRef } from 'react';
5-
import { forwardRef } from 'react';
64

7-
import { cn } from '@/lib';
5+
import MenuCheckboxGroup from '../menu/MenuCheckboxGroup';
86

97
import DropdownMenuCheckboxItem from './DropdownMenuCheckboxItem';
108
import DropdownMenuLabel from './DropdownMenuLabel';
119
import DropdownMenuSeparator from './DropdownMenuSeparator';
12-
import { isLabel, isSeparator } from './shared';
1310
import type { DropdownMenuCheckboxGroupProps } from './types';
1411

15-
const DropdownMenuCheckboxGroup = forwardRef<ComponentRef<typeof Group>, DropdownMenuCheckboxGroupProps>(
16-
(props, ref) => {
17-
const { checks, className, classNames, items, onChecksChange, size, ...rest } = props;
18-
19-
return (
20-
<Group
21-
className={cn(className || classNames?.group)}
22-
ref={ref}
23-
{...rest}
24-
>
25-
{items.map((item, index) => {
26-
if (isLabel(item)) {
27-
return (
28-
<DropdownMenuLabel
29-
classNames={classNames}
30-
key={String(index)}
31-
size={size}
32-
{...item}
33-
>
34-
{item.label}
35-
</DropdownMenuLabel>
36-
);
37-
}
38-
39-
if (isSeparator(item)) {
40-
return (
41-
<DropdownMenuSeparator
42-
className={classNames?.separator}
43-
key={String(index)}
44-
size={size}
45-
/>
46-
);
47-
}
48-
49-
return (
50-
<DropdownMenuCheckboxItem
51-
key={String(index)}
52-
{...item}
53-
checked={checks?.includes(item?.textValue || '')}
54-
classNames={classNames}
55-
size={size}
56-
onCheckedChange={checked => {
57-
item.onCheckedChange?.(checked);
58-
59-
if (checked) {
60-
onChecksChange?.([...(checks || []), item?.textValue || '']);
61-
} else {
62-
onChecksChange?.([...(checks || []).filter(check => check !== item?.textValue)]);
63-
}
64-
}}
65-
>
66-
{item.label}
67-
</DropdownMenuCheckboxItem>
68-
);
69-
})}
70-
</Group>
71-
);
72-
}
73-
);
74-
75-
DropdownMenuCheckboxGroup.displayName = 'DropdownMenuCheckboxGroup';
12+
const DropdownMenuCheckboxGroup = (props: DropdownMenuCheckboxGroupProps) => {
13+
return (
14+
<MenuCheckboxGroup
15+
component={DropdownMenuCheckboxItem}
16+
groupComponent={Group}
17+
labelComponent={DropdownMenuLabel}
18+
separatorComponent={DropdownMenuSeparator}
19+
{...props}
20+
/>
21+
);
22+
};
7623

7724
export default DropdownMenuCheckboxGroup;
Lines changed: 10 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,18 @@
11
import { CheckboxItem } from '@radix-ui/react-dropdown-menu';
2-
import { Check } from 'lucide-react';
3-
import type { ComponentRef } from 'react';
4-
import { forwardRef } from 'react';
52

6-
import { cn } from '@/lib';
3+
import MenuCheckboxItem from '../menu/MenuCheckboxItem';
74

85
import DropdownMenuItemIndicator from './DropdownMenuItemIndicator';
9-
import DropdownMenuShortcut from './DropdownMenuShortcut';
10-
import { menuVariants } from './dropdown-menu-variants';
116
import type { DropdownMenuCheckboxItemProps } from './types';
127

13-
const DropdownMenuCheckboxItem = forwardRef<ComponentRef<typeof CheckboxItem>, DropdownMenuCheckboxItemProps>(
14-
(props, ref) => {
15-
const { children, className, classNames, indicatorIcon, leading, shortcut, size, trailing, ...rest } = props;
16-
17-
const { checkboxItem } = menuVariants({ size });
18-
19-
const mergedCls = cn(checkboxItem(), className || classNames?.item);
20-
21-
return (
22-
<CheckboxItem
23-
className={mergedCls}
24-
ref={ref}
25-
{...rest}
26-
>
27-
<DropdownMenuItemIndicator
28-
className={classNames?.itemIndicator}
29-
size={size}
30-
>
31-
{indicatorIcon || <Check />}
32-
</DropdownMenuItemIndicator>
33-
34-
{leading}
35-
36-
{children}
37-
38-
{trailing}
39-
40-
{shortcut && (
41-
<DropdownMenuShortcut
42-
className={classNames?.shortcut}
43-
size={size}
44-
value={shortcut}
45-
/>
46-
)}
47-
</CheckboxItem>
48-
);
49-
}
50-
);
51-
52-
DropdownMenuCheckboxItem.displayName = 'DropdownMenuCheckboxItem';
8+
const DropdownMenuCheckboxItem = (props: DropdownMenuCheckboxItemProps) => {
9+
return (
10+
<MenuCheckboxItem
11+
component={CheckboxItem as typeof MenuCheckboxItem}
12+
indicatorComponent={DropdownMenuItemIndicator}
13+
{...props}
14+
/>
15+
);
16+
};
5317

5418
export default DropdownMenuCheckboxItem;

packages/ui/src/components/dropdown-menu/DropdownMenuContent.tsx

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
1-
import { Content } from '@radix-ui/react-dropdown-menu';
1+
import { Content, Portal } from '@radix-ui/react-dropdown-menu';
22
import type { ComponentRef } from 'react';
33
import { forwardRef } from 'react';
44

5-
import { cn } from '@/lib';
5+
import MenuContent from '../menu/MenuContent';
66

7-
import { menuVariants } from './dropdown-menu-variants';
7+
import DropdownMenuArrow from './DropdownMenuArrow';
88
import type { DropdownMenuContentProps } from './types';
99

1010
const DropdownMenuContent = forwardRef<ComponentRef<typeof Content>, DropdownMenuContentProps>((props, ref) => {
11-
const { className, size, ...rest } = props;
12-
13-
const { content } = menuVariants({ size });
14-
15-
const mergedCls = cn(content(), className);
16-
1711
return (
18-
<Content
19-
className={mergedCls}
12+
<MenuContent
13+
arrowComponent={DropdownMenuArrow}
14+
component={Content as typeof MenuContent}
15+
portalComponent={Portal}
2016
ref={ref}
21-
{...rest}
17+
{...props}
2218
/>
2319
);
2420
});
Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,16 @@
11
import { Item } from '@radix-ui/react-dropdown-menu';
2-
import type { ComponentRef } from 'react';
3-
import { forwardRef } from 'react';
42

5-
import { cn } from '@/lib';
3+
import MenuItem from '../menu/MenuItem';
64

7-
import DropdownMenuShortcut from './DropdownMenuShortcut';
8-
import { menuVariants } from './dropdown-menu-variants';
95
import type { DropdownMenuItemProps } from './types';
106

11-
const DropdownMenuItem = forwardRef<ComponentRef<typeof Item>, DropdownMenuItemProps>((props, ref) => {
12-
const { children, className, classNames, leading, shortcut, size, trailing, ...rest } = props;
13-
14-
const { item } = menuVariants({ size });
15-
16-
const mergedCls = cn(item(), className);
17-
7+
const DropdownMenuItem = (props: DropdownMenuItemProps) => {
188
return (
19-
<Item
20-
className={mergedCls}
21-
ref={ref}
22-
{...rest}
23-
>
24-
{leading}
25-
26-
<span>{children}</span>
27-
28-
{trailing}
29-
30-
{shortcut && (
31-
<DropdownMenuShortcut
32-
className={classNames?.shortcut}
33-
size={size}
34-
value={shortcut}
35-
/>
36-
)}
37-
</Item>
9+
<MenuItem
10+
{...props}
11+
component={Item as typeof MenuItem}
12+
/>
3813
);
39-
});
40-
41-
DropdownMenuItem.displayName = 'DropdownMenuItem';
14+
};
4215

4316
export default DropdownMenuItem;
Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,16 @@
11
import { ItemIndicator } from '@radix-ui/react-dropdown-menu';
2-
import type { ComponentRef } from 'react';
3-
import { forwardRef } from 'react';
42

5-
import { cn } from '@/lib';
3+
import MenuItemIndicator from '../menu/MenuItemIndicator';
64

7-
import { menuVariants } from './dropdown-menu-variants';
85
import type { DropdownMenuItemIndicatorProps } from './types';
96

10-
const DropdownMenuItemIndicator = forwardRef<ComponentRef<typeof ItemIndicator>, DropdownMenuItemIndicatorProps>(
11-
(props, ref) => {
12-
const { className, size, ...rest } = props;
13-
14-
const { itemIndicator } = menuVariants({ size });
15-
16-
const mergedCls = cn(itemIndicator(), className);
17-
18-
return (
19-
<ItemIndicator
20-
className={mergedCls}
21-
ref={ref}
22-
{...rest}
23-
/>
24-
);
25-
}
26-
);
27-
28-
DropdownMenuItemIndicator.displayName = 'DropdownMenuItemIndicator';
7+
const DropdownMenuItemIndicator = (props: DropdownMenuItemIndicatorProps) => {
8+
return (
9+
<MenuItemIndicator
10+
component={ItemIndicator as typeof MenuItemIndicator}
11+
{...props}
12+
/>
13+
);
14+
};
2915

3016
export default DropdownMenuItemIndicator;

0 commit comments

Comments
 (0)