-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathdropdownItem.tsx
More file actions
123 lines (114 loc) · 4.07 KB
/
Copy pathdropdownItem.tsx
File metadata and controls
123 lines (114 loc) · 4.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import * as RadixDropdown from '@radix-ui/react-dropdown-menu';
import classNames from 'classnames';
import React, { type ComponentProps } from 'react';
import { Icon, IconType } from '../../icon';
export interface IDropdownItemProps extends Omit<ComponentProps<'div'>, 'onSelect'> {
/**
* Renders the dropdown item as selected when set to true.
*/
selected?: boolean;
/**
* Icon displayed beside the item label. Defaults to LinkExternal when the item is a link or to Checkmark when the
* selected property is set to true.
*/
icon?: IconType;
/**
* Position of the icon.
* @default right
*/
iconPosition?: 'right' | 'left';
/**
* Link of the dropdown item.
*/
href?: string;
/**
* Target of the dropdown link.
*/
target?: string;
/**
* Rel attribute of the dropdown link.
*/
rel?: string;
/**
* Form id to associate the dropdown item with a form. In this case, the dropdown item will behave as a submit button.
*/
formId?: string;
/**
* Disables the dropdown item when set to true.
*/
disabled?: boolean;
/**
* Callback when the dropdown item is selected.
*/
onSelect?: (event: Event) => void;
}
export const DropdownItem: React.FC<IDropdownItemProps> = (props) => {
const {
className,
icon,
selected,
iconPosition = 'right',
children,
disabled,
href,
target,
rel,
formId,
...otherProps
} = props;
const renderSubmitButton = formId != null;
const renderLink = href != null && href.length > 0;
let ItemWrapper: React.ElementType = React.Fragment;
let itemWrapperProps:
| React.AnchorHTMLAttributes<HTMLAnchorElement>
| React.ButtonHTMLAttributes<HTMLButtonElement>
| object = {};
if (renderLink) {
ItemWrapper = 'a';
itemWrapperProps = {
href,
target,
rel: target === '_blank' ? `noopener noreferrer ${rel ?? ''}` : rel,
};
} else if (renderSubmitButton) {
ItemWrapper = 'button';
itemWrapperProps = {
type: 'submit' as const,
form: formId,
};
}
const handleSelect = (event: Event) => {
// For submit buttons, we need to prevent the dropdown from closing immediately to allow the form submission to complete properly
if (renderSubmitButton) {
event.preventDefault();
}
props.onSelect?.(event);
};
const defaultIcon = renderLink ? IconType.LINK_EXTERNAL : selected ? IconType.CHECKMARK : undefined;
const processedIcon = icon ?? defaultIcon;
return (
<RadixDropdown.Item
disabled={disabled}
asChild={renderLink || renderSubmitButton}
className={classNames(
'flex items-center gap-3 px-4 py-3', // Layout
'cursor-pointer rounded-xl text-base leading-tight focus-visible:outline-hidden', // Style
'data-disabled:bg-neutral-0 data-disabled:pointer-events-none data-disabled:cursor-default data-disabled:text-neutral-300', // Disabled
{ 'bg-neutral-0 text-neutral-500': !selected && !disabled }, // Not selected
{ 'bg-neutral-50 text-neutral-800': selected && !disabled }, // Selected
{ 'hover:bg-neutral-50 hover:text-neutral-800': !disabled }, // Hover
{ 'data-highlighted:bg-neutral-50 data-highlighted:text-neutral-800': !disabled }, // Highlighted
{ 'flex-row justify-between': iconPosition === 'right' },
{ 'flex-row-reverse justify-end': iconPosition === 'left' && icon != null },
className,
)}
onSelect={handleSelect}
{...otherProps}
>
<ItemWrapper {...itemWrapperProps}>
<p className="truncate">{children}</p>
{processedIcon != null && <Icon icon={processedIcon} size="md" className="text-neutral-300" />}
</ItemWrapper>
</RadixDropdown.Item>
);
};