@keboola/design 1.2.1 → 1.3.1
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/README.md +25 -0
- package/dist/icon-names.cjs +18 -0
- package/dist/icon-names.cjs.map +1 -0
- package/dist/icon-names.js +16 -0
- package/dist/icon-names.js.map +1 -0
- package/dist/icons.cjs +731 -0
- package/dist/icons.cjs.map +1 -0
- package/dist/icons.js +29 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.cjs +14728 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +14553 -0
- package/dist/index.js.map +1 -0
- package/dist/markdown-editor.cjs +4440 -0
- package/dist/markdown-editor.cjs.map +1 -0
- package/dist/markdown-editor.js +4413 -0
- package/dist/markdown-editor.js.map +1 -0
- package/dist/mermaid.cjs +1011 -0
- package/dist/mermaid.cjs.map +1 -0
- package/dist/mermaid.js +1005 -0
- package/dist/mermaid.js.map +1 -0
- package/dist/styles.css +1 -0
- package/package.json +10 -3
- package/src/blocks/AIKit/CollapsibleStepHeader.tsx +7 -8
- package/src/blocks/AIKit/InlineStepLabel.tsx +7 -7
- package/src/blocks/AIKit/MessageBubble.stories.tsx +11 -3
- package/src/blocks/AIKit/MessageBubble.tsx +1 -1
- package/src/blocks/AIKit/PlanApproval.tsx +9 -8
- package/src/blocks/AIKit/PlanRewritingIndicator.tsx +2 -2
- package/src/blocks/AIKit/PromptInput.stories.tsx +10 -2
- package/src/blocks/AIKit/PromptInputSubmit.tsx +12 -8
- package/src/blocks/AIKit/Question.tsx +8 -9
- package/src/blocks/AIKit/SuggestedPrompt.tsx +12 -5
- package/src/blocks/AIKit/ThinkingIndicator.tsx +2 -2
- package/src/blocks/AutoSaveTextarea/AutoSaveTextarea.tsx +4 -4
- package/src/blocks/ClipboardButton/ClipboardButton.tsx +7 -5
- package/src/blocks/ClipboardButton/ClipboardInline.tsx +2 -3
- package/src/blocks/ColorInput/ColorInput.tsx +4 -2
- package/src/blocks/ColorInput/ColorPicker.tsx +5 -2
- package/src/blocks/EmptyState/EmptyState.tsx +16 -0
- package/src/blocks/ErrorState/ErrorState.tsx +15 -0
- package/src/blocks/Form/formHook.ts +15 -0
- package/src/blocks/MultiActionButtonGroup/MultiActionButton.stories.tsx +12 -11
- package/src/blocks/MultiActionButtonGroup/MultiActionButton.tsx +5 -4
- package/src/blocks/MultiCombobox/MultiCombobox.tsx +28 -12
- package/src/blocks/PageHeader/AGENTS.md +63 -3
- package/src/blocks/PageHeader/PageHeader.stories.tsx +124 -28
- package/src/blocks/PageHeader/PageHeader.tsx +15 -0
- package/src/blocks/PageHeader/PageHeaderDetail.tsx +23 -1
- package/src/blocks/PageHeader/PageHeaderIndex.tsx +20 -1
- package/src/blocks/PageLayout/PageLayout.tsx +26 -0
- package/src/blocks/PageToolbar/PageToolbar.stories.tsx +348 -0
- package/src/blocks/PageToolbar/PageToolbar.tsx +119 -0
- package/src/blocks/PageToolbar/index.ts +1 -0
- package/src/blocks/PasswordInput/PasswordInput.tsx +10 -10
- package/src/blocks/SearchInput/SearchInput.tsx +30 -4
- package/src/blocks/SearchInputWithNavigation/SearchInputWithNavigation.tsx +9 -6
- package/src/blocks/SplitButton/SplitButton.stories.tsx +7 -4
- package/src/blocks/SplitButton/SplitButton.tsx +17 -4
- package/src/blocks/Tagger/TagItem.tsx +4 -1
- package/src/blocks/Tagger/TagSelectPopover/TagSelectCreateItem.tsx +3 -1
- package/src/blocks/Tagger/TagSelectPopover/TagSelectList.tsx +2 -2
- package/src/blocks/Tagger/Tagger.tsx +2 -2
- package/src/components/Alert/Alert.stories.tsx +11 -3
- package/src/components/Alert/Alert.tsx +19 -1
- package/src/components/Alert/AlertCollapsibleIcon.tsx +3 -4
- package/src/components/Alert/AlertIcon.tsx +18 -21
- package/src/components/Badge/Badge.stories.tsx +22 -4
- package/src/components/Badge/Badge.tsx +16 -0
- package/src/components/Badge/BadgeButton.tsx +7 -6
- package/src/components/Breadcrumb/BreadcrumbEllipsis.tsx +2 -2
- package/src/components/Breadcrumb/BreadcrumbSeparator.tsx +2 -2
- package/src/components/Button/Button.stories.tsx +14 -2
- package/src/components/Button/Button.tsx +42 -5
- package/src/components/Button/styles.ts +4 -6
- package/src/components/ButtonGroup/ButtonGroup.stories.tsx +32 -10
- package/src/components/Card/Card.tsx +17 -0
- package/src/components/Checkbox/Checkbox.tsx +3 -6
- package/src/components/CodeEditor/highlighting.ts +1 -1
- package/src/components/CollapsiblePanel.tsx +2 -5
- package/src/components/Combobox/Combobox.tsx +12 -14
- package/src/components/Combobox/ComboboxChips.tsx +6 -1
- package/src/components/Combobox/ComboboxItem.tsx +3 -4
- package/src/components/Combobox/ComboboxItemIndicator.tsx +6 -4
- package/src/components/Combobox/types.ts +2 -6
- package/src/components/Command/Command.stories.tsx +47 -56
- package/src/components/Command/CommandItem/CheckIndicator.tsx +26 -14
- package/src/components/Command/CommandItem/CommandItem.tsx +6 -3
- package/src/components/DropdownMenu/DropdownMenu.stories.tsx +8 -4
- package/src/components/DropdownMenu/DropdownMenuCheckboxItem.tsx +4 -1
- package/src/components/DropdownMenu/DropdownMenuItem.tsx +12 -6
- package/src/components/DropdownMenu/DropdownMenuItemIndicator.tsx +12 -6
- package/src/components/DropdownMenu/DropdownMenuRadioGroup/DropdownMenuRadioItem.tsx +8 -5
- package/src/components/DropdownMenu/DropdownMenuSub/DropdownMenuSubTrigger.tsx +2 -2
- package/src/components/DropdownMenu/ItemIcon.tsx +16 -8
- package/src/components/FormGroup/FormGroup.tsx +15 -0
- package/src/components/FullScreenModal/FullScreenModalHeader.tsx +4 -1
- package/src/components/Input/DateInput/DateInput.tsx +4 -1
- package/src/components/Input/DateRangeInput/DateRangeInput.tsx +4 -6
- package/src/components/Input/Input.tsx +18 -2
- package/src/components/Input/TextInput/TextInput.tsx +16 -0
- package/src/components/Input/TimeInput/TimeInput.tsx +4 -1
- package/src/components/InputGroup/InputGroup.stories.tsx +11 -3
- package/src/components/MarkdownEditor/MarkdownEditor.stories.tsx +63 -1
- package/src/components/MarkdownEditor/MarkdownEditor.tsx +105 -15
- package/src/components/MarkdownEditor/nodes/ImageNode.tsx +10 -10
- package/src/components/MarkdownEditor/nodes/MermaidNode.tsx +8 -8
- package/src/components/MarkdownEditor/plugins/KeyboardPlugin.tsx +47 -3
- package/src/components/MarkdownEditor/plugins/MarkdownSyncPlugin.tsx +12 -3
- package/src/components/MarkdownEditor/plugins/ToolbarPlugin.tsx +20 -10
- package/src/components/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx +20 -14
- package/src/components/MarkdownEditor/plugins/toolbar/BlockTypeDropdown.tsx +25 -16
- package/src/components/MarkdownEditor/plugins/toolbar/LinkPanel.tsx +3 -3
- package/src/components/MarkdownEditor/transformers.ts +10 -0
- package/src/components/MergeEditor/AcceptControls/AcceptButton.tsx +9 -4
- package/src/components/MergeEditor/AcceptControls/AcceptControls.tsx +25 -14
- package/src/components/MergeEditor/ConflictStatus/ConflictStatusIndicator.tsx +2 -2
- package/src/components/MergeEditor/MergeEditor.stories.tsx +15 -0
- package/src/components/MergeEditor/MergeEditor.tsx +9 -0
- package/src/components/MergeEditor/MergePane.tsx +22 -4
- package/src/components/MergeEditor/decorations.ts +2 -2
- package/src/components/Modal/Modal.stories.tsx +6 -4
- package/src/components/Modal/Modal.tsx +26 -0
- package/src/components/Modal/ModalBody.tsx +5 -0
- package/src/components/Modal/ModalCloseIcon.tsx +2 -3
- package/src/components/Modal/ModalContent.tsx +8 -0
- package/src/components/Modal/ModalFooter.tsx +5 -0
- package/src/components/Modal/ModalHeader.tsx +11 -0
- package/src/components/Modal/ModalIcon.tsx +45 -19
- package/src/components/Navbar/Navbar.stories.tsx +26 -13
- package/src/components/Navbar/NavbarMenuButton.tsx +11 -10
- package/src/components/Pagination/PaginationEllipsis.tsx +2 -2
- package/src/components/Pagination/PaginationNext.tsx +2 -1
- package/src/components/Pagination/PaginationPrevious.tsx +4 -1
- package/src/components/PanelWithDetails.tsx +3 -4
- package/src/components/Popconfirm/Popconfirm.stories.tsx +13 -5
- package/src/components/RadioGroup/Radio.tsx +6 -12
- package/src/components/Search/ClearButton.tsx +2 -2
- package/src/components/Search/Search.tsx +3 -3
- package/src/components/Select/Select.tsx +16 -5
- package/src/components/Select/SelectContent.tsx +13 -4
- package/src/components/Select/SelectItem.tsx +6 -5
- package/src/components/Select/SelectTrigger.tsx +2 -2
- package/src/components/Sidebar/Sidebar.stories.tsx +55 -19
- package/src/components/Sidebar/SidebarGroup/SidebarGroupAction.tsx +8 -4
- package/src/components/Sidebar/SidebarMenu/SidebarMenuButton.tsx +4 -2
- package/src/components/Sidebar/SidebarMenu/SidebarMenuCard.tsx +3 -2
- package/src/components/Sidebar/SidebarMenu/SidebarMenuIcon.tsx +12 -12
- package/src/components/Sidebar/SidebarMenu/SidebarMenuSub.tsx +3 -7
- package/src/components/Sidebar/SidebarMenu/SidebarSearchInput.tsx +3 -5
- package/src/components/Skeleton/Skeleton.stories.tsx +52 -0
- package/src/components/Skeleton/Skeleton.tsx +24 -1
- package/src/components/Table/Table.stories.tsx +223 -1
- package/src/components/Table/Table.tsx +17 -0
- package/src/components/Tabs.tsx +25 -2
- package/src/components/Toast/ToastDismiss.tsx +3 -3
- package/src/components/Toast/ToastRoot.tsx +24 -19
- package/src/components/Toggle/Toggle.tsx +11 -6
- package/src/components/Tooltip/Tooltip.tsx +23 -0
- package/src/components/ZoomableSvg/ZoomableSvg.tsx +8 -6
- package/src/icons/Keboola.tsx +28 -0
- package/src/icons/icons.stories.tsx +174 -0
- package/src/icons/index.ts +180 -0
- package/src/index.ts +1 -0
- package/src/patterns/AlertWithAction.stories.tsx +30 -0
- package/src/patterns/CardWithEmptyState.stories.tsx +66 -0
- package/src/patterns/ConfirmDialog.stories.tsx +72 -0
- package/src/patterns/CreatableMultiCombobox.stories.tsx +33 -0
- package/src/patterns/DataCardWithSkeleton.stories.tsx +48 -0
- package/src/patterns/DisabledButtonTooltip.stories.tsx +30 -0
- package/src/patterns/FilterToolbar.stories.tsx +71 -0
- package/src/patterns/InfoTooltip.stories.tsx +56 -0
- package/src/patterns/ListDetail.stories.tsx +65 -0
- package/src/patterns/ModalForm.stories.tsx +59 -0
- package/src/patterns/PageHeaderTabs.stories.tsx +48 -0
- package/src/styles.css +16 -8
- package/src/utils/legacyIcon.tsx +28 -0
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
3
|
|
|
4
4
|
import { cn } from '../../utils';
|
|
5
|
+
import { isFAIconValue } from '../../utils/legacyIcon';
|
|
5
6
|
import { Icon } from '../Icon';
|
|
6
7
|
|
|
7
8
|
type NamedColor = 'orange' | 'blue' | 'red' | 'green' | 'gray' | 'violet';
|
|
8
9
|
|
|
9
|
-
type IconProps =
|
|
10
|
+
type IconProps = {
|
|
10
11
|
color: NamedColor | (string & {});
|
|
12
|
+
/**
|
|
13
|
+
* Pass a Lucide icon node. Legacy FontAwesome `"name"` / `[prefix, name]`
|
|
14
|
+
* string values are still accepted during the C2 deprecation window and
|
|
15
|
+
* rendered via the legacy `<Icon>` wrapper.
|
|
16
|
+
*/
|
|
17
|
+
icon: ReactNode;
|
|
18
|
+
/**
|
|
19
|
+
* @deprecated FA-icon `spin` pass-through kept only for the legacy
|
|
20
|
+
* `<Modal.Icon icon="spinner" spin />` callsite during the kbc-ui sweep.
|
|
21
|
+
* New code should render an animated Lucide loader as the `icon` node.
|
|
22
|
+
*/
|
|
23
|
+
spin?: boolean;
|
|
11
24
|
iconUrl?: never;
|
|
12
25
|
iconAlt?: never;
|
|
13
26
|
};
|
|
@@ -17,13 +30,24 @@ type ImageProps = {
|
|
|
17
30
|
iconUrl: string;
|
|
18
31
|
iconAlt?: string;
|
|
19
32
|
icon?: never;
|
|
33
|
+
spin?: never;
|
|
20
34
|
};
|
|
21
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Discriminated props for `Modal.Icon` — either an `icon` slot (a Lucide icon)
|
|
38
|
+
* with a categorical `color`, or a remote `iconUrl` (renders an `<img>`).
|
|
39
|
+
* The two shapes are mutually exclusive.
|
|
40
|
+
*/
|
|
22
41
|
type Props = IconProps | ImageProps;
|
|
23
42
|
|
|
24
43
|
const NAMED_COLORS = new Set<string>(['orange', 'blue', 'red', 'green', 'gray', 'violet']);
|
|
25
44
|
|
|
26
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Status-coloured icon docked to the top-left of `Modal.Content`. Use the categorical `color`
|
|
47
|
+
* (`red` destructive, `orange` warning, `green` success, `blue` info, `gray` neutral, `violet` agent)
|
|
48
|
+
* to encode meaning. The colour palette is categorical and stays fixed across brand themes.
|
|
49
|
+
*/
|
|
50
|
+
export const ModalIcon = (props: Props) => {
|
|
27
51
|
const [hasImageError, setHasImageError] = useState(false);
|
|
28
52
|
|
|
29
53
|
if ('iconUrl' in props && hasImageError) {
|
|
@@ -44,16 +68,19 @@ export const ModalIcon = ({ color, ...props }: Props) => {
|
|
|
44
68
|
) : (
|
|
45
69
|
<div
|
|
46
70
|
className={cn('tw-relative', 'tw-rounded-full', 'tw-size-12', {
|
|
47
|
-
'tw-bg-warning-500': color === 'orange',
|
|
48
|
-
'tw-bg-secondary-500': color === 'blue',
|
|
49
|
-
'tw-bg-primary-500': color === 'green',
|
|
50
|
-
'tw-bg-error-500': color === 'red',
|
|
51
|
-
'tw-bg-neutral-150': color === 'gray',
|
|
52
|
-
'tw-bg-purple-100': color === 'violet',
|
|
71
|
+
'tw-bg-warning-500': props.color === 'orange',
|
|
72
|
+
'tw-bg-secondary-500': props.color === 'blue',
|
|
73
|
+
'tw-bg-primary-500': props.color === 'green',
|
|
74
|
+
'tw-bg-error-500': props.color === 'red',
|
|
75
|
+
'tw-bg-neutral-150': props.color === 'gray',
|
|
76
|
+
'tw-bg-purple-100': props.color === 'violet',
|
|
53
77
|
})}
|
|
54
|
-
style={
|
|
78
|
+
style={
|
|
79
|
+
props.color && !NAMED_COLORS.has(props.color)
|
|
80
|
+
? { backgroundColor: props.color }
|
|
81
|
+
: undefined
|
|
82
|
+
}
|
|
55
83
|
>
|
|
56
|
-
{/* Icon spinning uses CSS transforms, which conflict with center positioning, so a wrapper should be used */}
|
|
57
84
|
<span
|
|
58
85
|
className={cn(
|
|
59
86
|
'tw-absolute',
|
|
@@ -65,16 +92,15 @@ export const ModalIcon = ({ color, ...props }: Props) => {
|
|
|
65
92
|
'tw-left-1/2',
|
|
66
93
|
'-tw-translate-x-1/2',
|
|
67
94
|
'-tw-translate-y-1/2',
|
|
95
|
+
{
|
|
96
|
+
'tw-text-white': props.color !== 'violet',
|
|
97
|
+
'tw-text-purple-500': props.color === 'violet',
|
|
98
|
+
},
|
|
99
|
+
'[&_svg]:tw-size-6',
|
|
100
|
+
'[&_svg]:tw-aspect-square',
|
|
68
101
|
)}
|
|
69
102
|
>
|
|
70
|
-
<Icon
|
|
71
|
-
className={cn(
|
|
72
|
-
{ 'tw-text-white': color !== 'violet', 'tw-text-purple-500': color === 'violet' },
|
|
73
|
-
'tw-size-6',
|
|
74
|
-
'tw-aspect-square',
|
|
75
|
-
)}
|
|
76
|
-
{...props}
|
|
77
|
-
/>
|
|
103
|
+
{isFAIconValue(props.icon) ? <Icon icon={props.icon} spin={props.spin} /> : props.icon}
|
|
78
104
|
</span>
|
|
79
105
|
</div>
|
|
80
106
|
)}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ComponentProps } from 'react';
|
|
2
2
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
3
|
|
|
4
|
+
import { Bell, Diamond, Keboola, Search } from '../../icons';
|
|
4
5
|
import { Icon } from '../Icon';
|
|
5
6
|
|
|
6
7
|
import { Navbar } from './Navbar';
|
|
@@ -44,20 +45,20 @@ export const Default: Story = {
|
|
|
44
45
|
<Navbar {...props}>
|
|
45
46
|
<Navbar.Header>
|
|
46
47
|
<Navbar.MenuItemAdornment variant="icon" asChild>
|
|
47
|
-
<
|
|
48
|
+
<Keboola className="!tw-size-8 tw-shrink-0 !tw-p-0" />
|
|
48
49
|
</Navbar.MenuItemAdornment>
|
|
49
50
|
</Navbar.Header>
|
|
50
51
|
|
|
51
52
|
<Navbar.Content>
|
|
52
53
|
<Navbar.Menu marker="forward-slash">
|
|
53
54
|
<Navbar.MenuItem>
|
|
54
|
-
<Navbar.MenuButton variant="emphasized" icon={
|
|
55
|
+
<Navbar.MenuButton variant="emphasized" icon={<Diamond className="tw-size-4" />}>
|
|
55
56
|
Project
|
|
56
57
|
<Icon icon={['far', 'angles-up-down']} />
|
|
57
58
|
</Navbar.MenuButton>
|
|
58
59
|
</Navbar.MenuItem>
|
|
59
60
|
<Navbar.MenuItem>
|
|
60
|
-
<Navbar.MenuButton icon={
|
|
61
|
+
<Navbar.MenuButton icon={<Diamond className="tw-size-4" />}>
|
|
61
62
|
Branch
|
|
62
63
|
<Icon icon={['far', 'angles-up-down']} />
|
|
63
64
|
</Navbar.MenuButton>
|
|
@@ -67,14 +68,18 @@ export const Default: Story = {
|
|
|
67
68
|
<Navbar.Footer>
|
|
68
69
|
<Navbar.Menu>
|
|
69
70
|
<Navbar.MenuItem>
|
|
70
|
-
<Navbar.MenuButton variant="search" icon="
|
|
71
|
+
<Navbar.MenuButton variant="search" icon={<Search className="tw-size-4" />}>
|
|
71
72
|
Search
|
|
72
73
|
<Navbar.MenuItemAdornment variant="shortcut">/</Navbar.MenuItemAdornment>
|
|
73
74
|
</Navbar.MenuButton>
|
|
74
75
|
</Navbar.MenuItem>
|
|
75
76
|
|
|
76
77
|
<Navbar.MenuItem>
|
|
77
|
-
<Navbar.MenuButton
|
|
78
|
+
<Navbar.MenuButton
|
|
79
|
+
variant="icon"
|
|
80
|
+
aria-label="Notifications"
|
|
81
|
+
icon={<Bell className="tw-size-4" />}
|
|
82
|
+
/>
|
|
78
83
|
</Navbar.MenuItem>
|
|
79
84
|
|
|
80
85
|
<Navbar.MenuItem>
|
|
@@ -94,7 +99,7 @@ export const ContentScrolling: Story = {
|
|
|
94
99
|
<Navbar.Header>
|
|
95
100
|
<Navbar.Menu>
|
|
96
101
|
<Navbar.MenuItem>
|
|
97
|
-
<
|
|
102
|
+
<Keboola className="tw-mx-2 !tw-size-8 tw-shrink-0 tw-text-secondary-500" />
|
|
98
103
|
</Navbar.MenuItem>
|
|
99
104
|
</Navbar.Menu>
|
|
100
105
|
</Navbar.Header>
|
|
@@ -102,7 +107,7 @@ export const ContentScrolling: Story = {
|
|
|
102
107
|
<Navbar.Menu marker="forward-slash">
|
|
103
108
|
{items.map((item) => (
|
|
104
109
|
<Navbar.MenuItem key={item}>
|
|
105
|
-
<Navbar.MenuButton icon={
|
|
110
|
+
<Navbar.MenuButton icon={<Diamond className="tw-size-4" />}>
|
|
106
111
|
{item}
|
|
107
112
|
<Icon icon={['far', 'angles-up-down']} />
|
|
108
113
|
</Navbar.MenuButton>
|
|
@@ -130,34 +135,42 @@ export const MenuItems: Story = {
|
|
|
130
135
|
<Navbar.Content>
|
|
131
136
|
<Navbar.Menu>
|
|
132
137
|
<Navbar.MenuItem>
|
|
133
|
-
<Navbar.MenuButton icon={
|
|
138
|
+
<Navbar.MenuButton icon={<Diamond className="tw-size-4" />}>Default</Navbar.MenuButton>
|
|
134
139
|
</Navbar.MenuItem>
|
|
135
140
|
<Navbar.MenuItem>
|
|
136
|
-
<Navbar.MenuButton icon={
|
|
141
|
+
<Navbar.MenuButton asChild icon={<Diamond className="tw-size-4" />}>
|
|
137
142
|
<a href="https://www.keboola.com">Default - Anchor</a>
|
|
138
143
|
</Navbar.MenuButton>
|
|
139
144
|
</Navbar.MenuItem>
|
|
140
145
|
|
|
141
146
|
<Navbar.MenuItem>
|
|
142
|
-
<Navbar.MenuButton disabled icon={
|
|
147
|
+
<Navbar.MenuButton disabled icon={<Diamond className="tw-size-4" />}>
|
|
143
148
|
Default - Disabled
|
|
144
149
|
</Navbar.MenuButton>
|
|
145
150
|
</Navbar.MenuItem>
|
|
146
151
|
|
|
147
152
|
<Navbar.MenuItem>
|
|
148
|
-
<Navbar.MenuButton variant="emphasized" icon={
|
|
153
|
+
<Navbar.MenuButton variant="emphasized" icon={<Diamond className="tw-size-4" />}>
|
|
149
154
|
Emphasized
|
|
150
155
|
</Navbar.MenuButton>
|
|
151
156
|
</Navbar.MenuItem>
|
|
152
157
|
|
|
153
158
|
<Navbar.MenuItem>
|
|
154
|
-
<Navbar.MenuButton
|
|
159
|
+
<Navbar.MenuButton
|
|
160
|
+
variant="emphasized"
|
|
161
|
+
asChild
|
|
162
|
+
icon={<Diamond className="tw-size-4" />}
|
|
163
|
+
>
|
|
155
164
|
<a href="https://www.keboola.com">Emphasized - Anchor</a>
|
|
156
165
|
</Navbar.MenuButton>
|
|
157
166
|
</Navbar.MenuItem>
|
|
158
167
|
|
|
159
168
|
<Navbar.MenuItem>
|
|
160
|
-
<Navbar.MenuButton
|
|
169
|
+
<Navbar.MenuButton
|
|
170
|
+
disabled
|
|
171
|
+
variant="emphasized"
|
|
172
|
+
icon={<Diamond className="tw-size-4" />}
|
|
173
|
+
>
|
|
161
174
|
Emphasized - Disabled
|
|
162
175
|
</Navbar.MenuButton>
|
|
163
176
|
</Navbar.MenuItem>
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import type { ComponentProps, ElementRef, Ref } from 'react';
|
|
1
|
+
import type { ComponentProps, ElementRef, ReactNode, Ref } from 'react';
|
|
2
2
|
import { Root, Slottable } from '@radix-ui/react-slot';
|
|
3
3
|
import type { VariantProps } from 'class-variance-authority';
|
|
4
4
|
import { cva } from 'class-variance-authority';
|
|
5
5
|
|
|
6
|
-
import { cn
|
|
6
|
+
import { cn } from '@keboola/design';
|
|
7
|
+
import { Search } from '@keboola/design/icons';
|
|
8
|
+
|
|
9
|
+
import { renderLegacyIcon } from '../../utils/legacyIcon';
|
|
7
10
|
|
|
8
11
|
import { NavbarMenuItemAdornment } from './NavbarMenuItemAdornment';
|
|
9
12
|
|
|
@@ -87,9 +90,9 @@ const variants = cva(
|
|
|
87
90
|
},
|
|
88
91
|
);
|
|
89
92
|
|
|
90
|
-
type Icon = ComponentProps<typeof Icon>['icon'];
|
|
91
93
|
type Props = ComponentProps<'button'> & {
|
|
92
|
-
icon
|
|
94
|
+
/** Optional leading-icon slot. Pass a Lucide icon node to render an adornment before children. */
|
|
95
|
+
icon?: ReactNode;
|
|
93
96
|
asChild?: boolean;
|
|
94
97
|
} & VariantProps<typeof variants>;
|
|
95
98
|
|
|
@@ -98,7 +101,7 @@ export const NavbarMenuButton = ({
|
|
|
98
101
|
className,
|
|
99
102
|
type = 'button',
|
|
100
103
|
children,
|
|
101
|
-
icon
|
|
104
|
+
icon,
|
|
102
105
|
asChild = false,
|
|
103
106
|
variant = 'default',
|
|
104
107
|
...rest
|
|
@@ -106,7 +109,7 @@ export const NavbarMenuButton = ({
|
|
|
106
109
|
const Comp = asChild ? Root : 'button';
|
|
107
110
|
const isSearchVariant = variant === 'search';
|
|
108
111
|
const isEmphasizedVariant = variant === 'emphasized';
|
|
109
|
-
const
|
|
112
|
+
const adornment = isSearchVariant ? <Search /> : renderLegacyIcon(icon);
|
|
110
113
|
|
|
111
114
|
const adornmentVariant: ComponentProps<typeof NavbarMenuItemAdornment>['variant'] = (() => {
|
|
112
115
|
if (isSearchVariant || variant === 'icon') return 'icon-button';
|
|
@@ -122,10 +125,8 @@ export const NavbarMenuButton = ({
|
|
|
122
125
|
data-variant={variant}
|
|
123
126
|
className={cn(variants({ className, variant }))}
|
|
124
127
|
>
|
|
125
|
-
{
|
|
126
|
-
<NavbarMenuItemAdornment
|
|
127
|
-
<Icon icon={icon} />
|
|
128
|
-
</NavbarMenuItemAdornment>
|
|
128
|
+
{adornment && (
|
|
129
|
+
<NavbarMenuItemAdornment variant={adornmentVariant}>{adornment}</NavbarMenuItemAdornment>
|
|
129
130
|
)}
|
|
130
131
|
|
|
131
132
|
<Slottable>{children}</Slottable>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComponentProps } from 'react';
|
|
2
2
|
|
|
3
|
+
import { Ellipsis } from '../../icons';
|
|
3
4
|
import { cn } from '../../utils';
|
|
4
|
-
import { Icon } from '../Icon';
|
|
5
5
|
|
|
6
6
|
type Props = ComponentProps<'span'>;
|
|
7
7
|
|
|
@@ -21,6 +21,6 @@ export const PaginationEllipsis = ({ className, ...props }: Props) => (
|
|
|
21
21
|
)}
|
|
22
22
|
{...props}
|
|
23
23
|
>
|
|
24
|
-
<
|
|
24
|
+
<Ellipsis />
|
|
25
25
|
</span>
|
|
26
26
|
);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ComponentProps } from 'react';
|
|
2
2
|
|
|
3
|
+
import { ChevronRight } from '../../icons';
|
|
3
4
|
import { cn } from '../../utils';
|
|
4
5
|
|
|
5
6
|
import { PaginationButton } from './PaginationButton';
|
|
@@ -10,10 +11,10 @@ export const PaginationNext = ({ children, className, ...props }: Props) => (
|
|
|
10
11
|
<PaginationButton
|
|
11
12
|
{...props}
|
|
12
13
|
aria-label="Go to next page"
|
|
13
|
-
icon="chevron-right"
|
|
14
14
|
size="medium"
|
|
15
15
|
className={cn('tw-flex-row-reverse', className)}
|
|
16
16
|
>
|
|
17
|
+
<ChevronRight className="tw-size-5" />
|
|
17
18
|
{children ?? 'Next'}
|
|
18
19
|
</PaginationButton>
|
|
19
20
|
);
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { ComponentProps } from 'react';
|
|
2
2
|
|
|
3
|
+
import { ChevronLeft } from '../../icons';
|
|
4
|
+
|
|
3
5
|
import { PaginationButton } from './PaginationButton';
|
|
4
6
|
|
|
5
7
|
type Props = ComponentProps<typeof PaginationButton>;
|
|
6
8
|
|
|
7
9
|
export const PaginationPrevious = ({ children, ...props }: Props) => (
|
|
8
|
-
<PaginationButton {...props} size="medium" aria-label="Go to previous page"
|
|
10
|
+
<PaginationButton {...props} size="medium" aria-label="Go to previous page">
|
|
11
|
+
<ChevronLeft className="tw-size-5" />
|
|
9
12
|
{children ?? 'Previous'}
|
|
10
13
|
</PaginationButton>
|
|
11
14
|
);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
2
|
import type { KeyboardEvent, PropsWithChildren } from 'react';
|
|
3
3
|
|
|
4
|
-
import { Icon } from '../components/Icon';
|
|
5
4
|
import { keyCodes } from '../constants/keyCodes';
|
|
5
|
+
import { ChevronDown } from '../icons';
|
|
6
6
|
import { cn } from '../utils';
|
|
7
7
|
|
|
8
8
|
import { Collapse } from './Collapse';
|
|
@@ -47,10 +47,9 @@ export const PanelWithDetails = ({
|
|
|
47
47
|
onKeyUp={handleKeyUp}
|
|
48
48
|
>
|
|
49
49
|
<div className="tw-mr-2 tw-flex tw-shrink-0 tw-items-center">
|
|
50
|
-
<
|
|
51
|
-
icon="chevron-down"
|
|
50
|
+
<ChevronDown
|
|
52
51
|
className={cn(
|
|
53
|
-
'tw-
|
|
52
|
+
'tw-size-5',
|
|
54
53
|
!isOpen ? '-tw-rotate-90' : placement === 'bottom' ? 'tw-rotate-180' : '',
|
|
55
54
|
)}
|
|
56
55
|
/>
|
|
@@ -2,6 +2,8 @@ import { type ComponentProps, useState } from 'react';
|
|
|
2
2
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
3
|
import { action } from 'storybook/actions';
|
|
4
4
|
|
|
5
|
+
import { Check, Rocket, Trash2, X } from '@keboola/design/icons';
|
|
6
|
+
|
|
5
7
|
import { Button } from '../Button/Button';
|
|
6
8
|
import { DropdownMenu } from '../DropdownMenu';
|
|
7
9
|
import { Label } from '../Label';
|
|
@@ -252,11 +254,15 @@ export const CustomButtons: Story = {
|
|
|
252
254
|
|
|
253
255
|
<Popconfirm.Footer className="tw-flex tw-justify-end">
|
|
254
256
|
<Popconfirm.Cancel asChild>
|
|
255
|
-
<Button variant="outline" size="icon"
|
|
257
|
+
<Button variant="outline" size="icon">
|
|
258
|
+
<X className="tw-size-4" />
|
|
259
|
+
</Button>
|
|
256
260
|
</Popconfirm.Cancel>
|
|
257
261
|
|
|
258
262
|
<Popconfirm.Confirm asChild>
|
|
259
|
-
<Button size="icon"
|
|
263
|
+
<Button size="icon">
|
|
264
|
+
<Rocket className="tw-size-4" />
|
|
265
|
+
</Button>
|
|
260
266
|
</Popconfirm.Confirm>
|
|
261
267
|
</Popconfirm.Footer>
|
|
262
268
|
</Popconfirm.Content>
|
|
@@ -297,7 +303,9 @@ export const InModal: Story = {
|
|
|
297
303
|
<Modal.Body className="tw-flex tw-justify-center">
|
|
298
304
|
<Popconfirm {...props}>
|
|
299
305
|
<Popconfirm.Trigger asChild>
|
|
300
|
-
<Button
|
|
306
|
+
<Button variant="danger" size="icon">
|
|
307
|
+
<Trash2 className="tw-size-4" />
|
|
308
|
+
</Button>
|
|
301
309
|
</Popconfirm.Trigger>
|
|
302
310
|
<Popconfirm.Content>
|
|
303
311
|
<Popconfirm.Body>Are you sure you want to delete this branch?</Popconfirm.Body>
|
|
@@ -331,7 +339,7 @@ export const InDropdownMenu: Story = {
|
|
|
331
339
|
<DropdownMenu.Group>
|
|
332
340
|
<Popconfirm {...props} variant="danger">
|
|
333
341
|
<Popconfirm.Trigger asChild>
|
|
334
|
-
<DropdownMenu.Item icon="
|
|
342
|
+
<DropdownMenu.Item asModalTrigger icon={<Trash2 className="tw-size-4" />}>
|
|
335
343
|
Delete Task
|
|
336
344
|
</DropdownMenu.Item>
|
|
337
345
|
</Popconfirm.Trigger>
|
|
@@ -346,7 +354,7 @@ export const InDropdownMenu: Story = {
|
|
|
346
354
|
|
|
347
355
|
<Popconfirm {...props}>
|
|
348
356
|
<Popconfirm.Trigger asChild>
|
|
349
|
-
<DropdownMenu.Item asModalTrigger icon="
|
|
357
|
+
<DropdownMenu.Item asModalTrigger icon={<Check className="tw-size-4" />}>
|
|
350
358
|
Confirm
|
|
351
359
|
</DropdownMenu.Item>
|
|
352
360
|
</Popconfirm.Trigger>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ComponentProps } from 'react';
|
|
2
2
|
import { Indicator, Item } from '@radix-ui/react-radio-group';
|
|
3
3
|
|
|
4
|
+
import { Circle } from '../../icons';
|
|
4
5
|
import { cn } from '../../utils';
|
|
5
6
|
|
|
6
7
|
type Props = ComponentProps<typeof Item>;
|
|
@@ -51,17 +52,10 @@ export const Radio = ({ className, ...props }: Props) => (
|
|
|
51
52
|
className,
|
|
52
53
|
)}
|
|
53
54
|
>
|
|
54
|
-
<Indicator
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
'after:tw-content-[""]',
|
|
60
|
-
'after:tw-block',
|
|
61
|
-
'after:tw-size-2.5',
|
|
62
|
-
'after:tw-rounded-full',
|
|
63
|
-
'after:tw-bg-primary',
|
|
64
|
-
)}
|
|
65
|
-
/>
|
|
55
|
+
<Indicator className={cn('tw-flex', 'tw-items-center', 'tw-justify-center')}>
|
|
56
|
+
{/* Lucide Circle is stroke-only — force fill to match the stroke (currentColor)
|
|
57
|
+
so the indicator reads as a solid dot. */}
|
|
58
|
+
<Circle className="tw-size-2.5 tw-fill-current tw-text-primary" />
|
|
59
|
+
</Indicator>
|
|
66
60
|
</Item>
|
|
67
61
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MouseEventHandler } from 'react';
|
|
2
2
|
|
|
3
|
+
import { X } from '../../icons';
|
|
3
4
|
import { cn } from '../../utils';
|
|
4
|
-
import { Icon } from '../Icon';
|
|
5
5
|
|
|
6
6
|
type Props = {
|
|
7
7
|
onClick: MouseEventHandler<HTMLButtonElement>;
|
|
@@ -36,7 +36,7 @@ export const ClearButton = ({ onClick, testId }: Props) => {
|
|
|
36
36
|
)}
|
|
37
37
|
data-testid={testId}
|
|
38
38
|
>
|
|
39
|
-
<
|
|
39
|
+
<X className="tw-size-4" />
|
|
40
40
|
</button>
|
|
41
41
|
);
|
|
42
42
|
};
|
|
@@ -12,8 +12,8 @@ import type {
|
|
|
12
12
|
Ref,
|
|
13
13
|
} from 'react';
|
|
14
14
|
|
|
15
|
+
import { Search as SearchIcon, Sparkles } from '../../icons';
|
|
15
16
|
import { cn, debounce, noop } from '../../utils';
|
|
16
|
-
import { Icon } from '../Icon';
|
|
17
17
|
|
|
18
18
|
import { ClearButton } from './ClearButton';
|
|
19
19
|
import { searchInputClassnames, searchWrapperVariants } from './styles';
|
|
@@ -112,9 +112,9 @@ export const Search = ({
|
|
|
112
112
|
data-testid={testId.wrapper}
|
|
113
113
|
>
|
|
114
114
|
{variant === 'ai' ? (
|
|
115
|
-
<
|
|
115
|
+
<Sparkles className="tw-size-4 tw-shrink-0 [&_*]:tw-stroke-aigradient-600" />
|
|
116
116
|
) : (
|
|
117
|
-
<
|
|
117
|
+
<SearchIcon className="tw-size-4 tw-shrink-0 tw-text-neutral-400" />
|
|
118
118
|
)}
|
|
119
119
|
|
|
120
120
|
<input
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { useId } from 'react';
|
|
2
2
|
import type { ComponentProps, ReactNode } from 'react';
|
|
3
3
|
|
|
4
|
-
import type { Icon } from '../Icon';
|
|
5
|
-
|
|
6
4
|
import { SelectContent } from './SelectContent';
|
|
7
5
|
import { SelectGroup } from './SelectGroup';
|
|
8
6
|
import { SelectItem as SelectItemComponent } from './SelectItem';
|
|
@@ -11,12 +9,10 @@ import { SelectRoot } from './SelectRoot';
|
|
|
11
9
|
import { SelectSeparator } from './SelectSeparator';
|
|
12
10
|
import { SelectTrigger } from './SelectTrigger';
|
|
13
11
|
|
|
14
|
-
type IconName = ComponentProps<typeof Icon>['icon'];
|
|
15
|
-
|
|
16
12
|
export type SelectItem = {
|
|
17
13
|
value: string;
|
|
18
14
|
label: ReactNode;
|
|
19
|
-
icon?:
|
|
15
|
+
icon?: ReactNode;
|
|
20
16
|
disabled?: boolean;
|
|
21
17
|
};
|
|
22
18
|
|
|
@@ -31,6 +27,10 @@ const isGroup = (itemOrGroup: SelectItem | SelectItemGroup): itemOrGroup is Sele
|
|
|
31
27
|
type RootProps = ComponentProps<typeof SelectRoot>;
|
|
32
28
|
type TriggerProps = ComponentProps<typeof SelectTrigger>;
|
|
33
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Props for `Select`. Combines Radix `Select.Root` control props with `Select.Trigger` chrome and the
|
|
32
|
+
* convenience `items` shape (flat list, or grouped lists with optional labels).
|
|
33
|
+
*/
|
|
34
34
|
type Props = Pick<
|
|
35
35
|
RootProps,
|
|
36
36
|
| 'value'
|
|
@@ -47,6 +47,17 @@ type Props = Pick<
|
|
|
47
47
|
items?: readonly (SelectItem | SelectItemGroup)[];
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Single selection from a short enumerated list. Built on Radix Select.
|
|
52
|
+
*
|
|
53
|
+
* **When to use:** picking one value from ~10 or fewer options where search adds no value (status,
|
|
54
|
+
* region, role). Pass a flat `items` array or grouped arrays with optional labels for headings.
|
|
55
|
+
* **When NOT to use:** for longer lists with search use `Combobox`; for multi-select use `MultiCombobox`;
|
|
56
|
+
* for free-form tag entry use `Tagger`.
|
|
57
|
+
* **Composition:** wrap in `FormGroup` for label + help text, or use `useAppForm` + `field.SelectField`
|
|
58
|
+
* for forms with validation. Use the compound parts (`Select.Root`, `Select.Trigger`, `Select.Content`,
|
|
59
|
+
* `Select.Item`) for custom item layouts; the top-level `Select` covers the common cases.
|
|
60
|
+
*/
|
|
50
61
|
export const Select = ({
|
|
51
62
|
// root
|
|
52
63
|
value,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ComponentProps, ElementRef, Ref } from 'react';
|
|
2
2
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
3
3
|
|
|
4
|
+
import { ChevronDown, ChevronUp } from '../../icons';
|
|
4
5
|
import { cn } from '../../utils';
|
|
5
|
-
import { Icon } from '../Icon';
|
|
6
6
|
|
|
7
7
|
const scrollButtonStyles = cn(
|
|
8
8
|
'tw-flex',
|
|
@@ -10,16 +10,25 @@ const scrollButtonStyles = cn(
|
|
|
10
10
|
'tw-justify-center',
|
|
11
11
|
'tw-rounded-sm',
|
|
12
12
|
'tw-p-1',
|
|
13
|
-
'[&_svg]:tw-size-
|
|
13
|
+
'[&_svg]:tw-size-5',
|
|
14
14
|
);
|
|
15
15
|
|
|
16
16
|
type Variant = 'default' | 'argo';
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Props for `Select.Content`. `container` portals the listbox into a custom element (useful inside modals);
|
|
20
|
+
* `variant` switches between default and Argo styling.
|
|
21
|
+
*/
|
|
18
22
|
type Props = ComponentProps<typeof SelectPrimitive.Content> & {
|
|
19
23
|
container?: HTMLElement | null;
|
|
20
24
|
variant?: Variant;
|
|
21
25
|
};
|
|
22
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Listbox container for `Select`. Portals items into a popover sized to the trigger.
|
|
29
|
+
* Normally rendered implicitly by `Select`; use directly only when composing custom item layouts via
|
|
30
|
+
* the `Select.Root` / `Select.Trigger` / `Select.Content` compound parts.
|
|
31
|
+
*/
|
|
23
32
|
export const SelectContent = ({
|
|
24
33
|
ref,
|
|
25
34
|
className,
|
|
@@ -81,7 +90,7 @@ export const SelectContent = ({
|
|
|
81
90
|
)}
|
|
82
91
|
>
|
|
83
92
|
<SelectPrimitive.ScrollUpButton className={scrollButtonStyles}>
|
|
84
|
-
<
|
|
93
|
+
<ChevronUp />
|
|
85
94
|
</SelectPrimitive.ScrollUpButton>
|
|
86
95
|
|
|
87
96
|
<SelectPrimitive.Viewport
|
|
@@ -94,7 +103,7 @@ export const SelectContent = ({
|
|
|
94
103
|
</SelectPrimitive.Viewport>
|
|
95
104
|
|
|
96
105
|
<SelectPrimitive.ScrollDownButton className={scrollButtonStyles}>
|
|
97
|
-
<
|
|
106
|
+
<ChevronDown />
|
|
98
107
|
</SelectPrimitive.ScrollDownButton>
|
|
99
108
|
</SelectPrimitive.Content>
|
|
100
109
|
</SelectPrimitive.Portal>
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type { ComponentProps, ElementRef, Ref } from 'react';
|
|
1
|
+
import type { ComponentProps, ElementRef, ReactNode, Ref } from 'react';
|
|
2
2
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
3
3
|
|
|
4
|
+
import { Check } from '../../icons';
|
|
4
5
|
import { cn } from '../../utils';
|
|
5
|
-
import {
|
|
6
|
+
import { renderLegacyIcon } from '../../utils/legacyIcon';
|
|
6
7
|
|
|
7
8
|
type Props = ComponentProps<typeof SelectPrimitive.Item> & {
|
|
8
|
-
icon?:
|
|
9
|
+
icon?: ReactNode;
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
export const SelectItem = ({
|
|
@@ -60,12 +61,12 @@ export const SelectItem = ({
|
|
|
60
61
|
className,
|
|
61
62
|
)}
|
|
62
63
|
>
|
|
63
|
-
{icon
|
|
64
|
+
{renderLegacyIcon(icon)}
|
|
64
65
|
<span className="tw-flex-1 tw-truncate">
|
|
65
66
|
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
66
67
|
</span>
|
|
67
68
|
<SelectPrimitive.ItemIndicator className="tw-pointer-events-none">
|
|
68
|
-
<
|
|
69
|
+
<Check className="tw-size-4" />
|
|
69
70
|
</SelectPrimitive.ItemIndicator>
|
|
70
71
|
</SelectPrimitive.Item>
|
|
71
72
|
);
|
|
@@ -2,8 +2,8 @@ import type { ComponentProps, ElementRef, Ref } from 'react';
|
|
|
2
2
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
3
3
|
import { cva, type VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
|
+
import { ChevronDown } from '../../icons';
|
|
5
6
|
import { cn } from '../../utils';
|
|
6
|
-
import { Icon } from '../Icon';
|
|
7
7
|
|
|
8
8
|
const variants = cva(
|
|
9
9
|
[
|
|
@@ -155,7 +155,7 @@ export const SelectTrigger = ({
|
|
|
155
155
|
>
|
|
156
156
|
<SelectPrimitive.Value placeholder={placeholder} />
|
|
157
157
|
<SelectPrimitive.Icon asChild>
|
|
158
|
-
<
|
|
158
|
+
<ChevronDown className="tw-size-5 tw-text-muted-foreground" />
|
|
159
159
|
</SelectPrimitive.Icon>
|
|
160
160
|
</SelectPrimitive.Trigger>
|
|
161
161
|
);
|