@keboola/design 1.2.1 → 1.3.0
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 +4 -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
|
@@ -3,6 +3,20 @@ import type { ComponentProps } from 'react';
|
|
|
3
3
|
import type { Decorator, Meta, StoryObj } from '@storybook/react-vite';
|
|
4
4
|
import type { InputType } from 'storybook/internal/types';
|
|
5
5
|
|
|
6
|
+
import {
|
|
7
|
+
Expand,
|
|
8
|
+
Gauge,
|
|
9
|
+
Keboola,
|
|
10
|
+
Menu,
|
|
11
|
+
Minus,
|
|
12
|
+
PanelLeft,
|
|
13
|
+
Pencil,
|
|
14
|
+
Plus,
|
|
15
|
+
Sparkles,
|
|
16
|
+
SquareTerminal,
|
|
17
|
+
Trash2,
|
|
18
|
+
} from '@keboola/design/icons';
|
|
19
|
+
|
|
6
20
|
import { cn } from '../../utils';
|
|
7
21
|
import { Button } from '../Button';
|
|
8
22
|
import { ButtonGroup } from '../ButtonGroup';
|
|
@@ -41,13 +55,15 @@ const AppContent = ({
|
|
|
41
55
|
<h3>Left Controls</h3>
|
|
42
56
|
<ButtonGroup space="compact">
|
|
43
57
|
<Sidebar.Trigger side="left">
|
|
44
|
-
<Button argo
|
|
58
|
+
<Button argo variant="primary">
|
|
59
|
+
<PanelLeft className="tw-size-4" />
|
|
45
60
|
Toggle
|
|
46
61
|
</Button>
|
|
47
62
|
</Sidebar.Trigger>
|
|
48
63
|
|
|
49
64
|
<Sidebar.FillTrigger side="left">
|
|
50
|
-
<Button argo
|
|
65
|
+
<Button argo variant="secondary">
|
|
66
|
+
<PanelLeft className="tw-size-4" />
|
|
51
67
|
Fill
|
|
52
68
|
</Button>
|
|
53
69
|
</Sidebar.FillTrigger>
|
|
@@ -60,13 +76,15 @@ const AppContent = ({
|
|
|
60
76
|
<h3>Right Controls</h3>
|
|
61
77
|
<ButtonGroup space="compact">
|
|
62
78
|
<Sidebar.FillTrigger side="right">
|
|
63
|
-
<Button argo
|
|
79
|
+
<Button argo variant="secondary">
|
|
80
|
+
<PanelLeft className="tw-size-4" />
|
|
64
81
|
Fill
|
|
65
82
|
</Button>
|
|
66
83
|
</Sidebar.FillTrigger>
|
|
67
84
|
|
|
68
85
|
<Sidebar.Trigger side="right">
|
|
69
|
-
<Button argo
|
|
86
|
+
<Button argo variant="primary">
|
|
87
|
+
<PanelLeft className="tw-size-4" />
|
|
70
88
|
Toggle
|
|
71
89
|
</Button>
|
|
72
90
|
</Sidebar.Trigger>
|
|
@@ -183,10 +201,9 @@ export const Default: Story = {
|
|
|
183
201
|
<Sidebar.Header>
|
|
184
202
|
<Sidebar.Menu>
|
|
185
203
|
<Sidebar.MenuItem>
|
|
186
|
-
<Sidebar.MenuIcon
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
/>
|
|
204
|
+
<Sidebar.MenuIcon className="!tw-size-8 tw-text-secondary-500">
|
|
205
|
+
<Keboola className="tw-size-4" />
|
|
206
|
+
</Sidebar.MenuIcon>
|
|
190
207
|
Sticky Header
|
|
191
208
|
</Sidebar.MenuItem>
|
|
192
209
|
</Sidebar.Menu>
|
|
@@ -199,7 +216,9 @@ export const Default: Story = {
|
|
|
199
216
|
<Sidebar.MenuItem>
|
|
200
217
|
<Sidebar.MenuButton tooltip="Dashboard" asChild>
|
|
201
218
|
<Link href="#">
|
|
202
|
-
<Sidebar.MenuIcon
|
|
219
|
+
<Sidebar.MenuIcon>
|
|
220
|
+
<Gauge className="tw-size-4" />
|
|
221
|
+
</Sidebar.MenuIcon>
|
|
203
222
|
Dashboard
|
|
204
223
|
</Link>
|
|
205
224
|
</Sidebar.MenuButton>
|
|
@@ -208,7 +227,9 @@ export const Default: Story = {
|
|
|
208
227
|
<Sidebar.MenuItem>
|
|
209
228
|
<Sidebar.MenuButton tooltip="AI Assistant" asChild>
|
|
210
229
|
<Link href="#">
|
|
211
|
-
<Sidebar.MenuIcon
|
|
230
|
+
<Sidebar.MenuIcon>
|
|
231
|
+
<Sparkles className="tw-size-4" />
|
|
232
|
+
</Sidebar.MenuIcon>
|
|
212
233
|
AI Assistant
|
|
213
234
|
</Link>
|
|
214
235
|
</Sidebar.MenuButton>
|
|
@@ -217,7 +238,9 @@ export const Default: Story = {
|
|
|
217
238
|
<Sidebar.MenuItem>
|
|
218
239
|
<Sidebar.MenuButton tooltip="Flows" asChild>
|
|
219
240
|
<Link href="#">
|
|
220
|
-
<Sidebar.MenuIcon
|
|
241
|
+
<Sidebar.MenuIcon>
|
|
242
|
+
<Menu className="tw-size-4" />
|
|
243
|
+
</Sidebar.MenuIcon>
|
|
221
244
|
Flows
|
|
222
245
|
</Link>
|
|
223
246
|
</Sidebar.MenuButton>
|
|
@@ -309,7 +332,8 @@ export const Default: Story = {
|
|
|
309
332
|
<div className="tw-flex tw-flex-col tw-items-center tw-p-4">
|
|
310
333
|
<h1>KAI</h1>
|
|
311
334
|
<Sidebar.FillTrigger side="right">
|
|
312
|
-
<Button block argo
|
|
335
|
+
<Button block argo variant="secondary">
|
|
336
|
+
<PanelLeft className="tw-size-4" />
|
|
313
337
|
Fill
|
|
314
338
|
</Button>
|
|
315
339
|
</Sidebar.FillTrigger>
|
|
@@ -341,12 +365,14 @@ export const Resizable: Story = {
|
|
|
341
365
|
Width: {rightWidth}px — Drag left edge to resize
|
|
342
366
|
</p>
|
|
343
367
|
<Sidebar.FillTrigger side="right">
|
|
344
|
-
<Button block argo
|
|
368
|
+
<Button block argo variant="secondary">
|
|
369
|
+
<Expand className="tw-size-4" />
|
|
345
370
|
Fullscreen
|
|
346
371
|
</Button>
|
|
347
372
|
</Sidebar.FillTrigger>
|
|
348
373
|
<Sidebar.Trigger side="right">
|
|
349
|
-
<Button block argo
|
|
374
|
+
<Button block argo variant="outline">
|
|
375
|
+
<PanelLeft className="tw-size-4" />
|
|
350
376
|
Collapse
|
|
351
377
|
</Button>
|
|
352
378
|
</Sidebar.Trigger>
|
|
@@ -446,7 +472,9 @@ export const MenuItems: Story = {
|
|
|
446
472
|
<Sidebar.MenuItem>
|
|
447
473
|
<Sidebar.MenuButton tooltip="Simple Anchor" asChild>
|
|
448
474
|
<a href="https://www.keboole.com">
|
|
449
|
-
<Sidebar.MenuIcon
|
|
475
|
+
<Sidebar.MenuIcon>
|
|
476
|
+
<SquareTerminal className="tw-size-4" />
|
|
477
|
+
</Sidebar.MenuIcon>
|
|
450
478
|
Simple Anchor
|
|
451
479
|
</a>
|
|
452
480
|
</Sidebar.MenuButton>
|
|
@@ -526,8 +554,12 @@ export const MenuAction: Story = {
|
|
|
526
554
|
|
|
527
555
|
<DropdownMenu.Content side="right" align="start">
|
|
528
556
|
<DropdownMenu.Group>
|
|
529
|
-
<DropdownMenu.Item icon="
|
|
530
|
-
|
|
557
|
+
<DropdownMenu.Item icon={<Pencil className="tw-size-4" />}>
|
|
558
|
+
Edit{' '}
|
|
559
|
+
</DropdownMenu.Item>
|
|
560
|
+
<DropdownMenu.Item icon={<Trash2 className="tw-size-4" />}>
|
|
561
|
+
Delete{' '}
|
|
562
|
+
</DropdownMenu.Item>
|
|
531
563
|
</DropdownMenu.Group>
|
|
532
564
|
</DropdownMenu.Content>
|
|
533
565
|
</DropdownMenu>
|
|
@@ -632,7 +664,9 @@ export const Group: Story = {
|
|
|
632
664
|
<Sidebar.Content>
|
|
633
665
|
<Sidebar.Group>
|
|
634
666
|
<Sidebar.GroupLabel>Group A</Sidebar.GroupLabel>
|
|
635
|
-
<Sidebar.GroupAction
|
|
667
|
+
<Sidebar.GroupAction>
|
|
668
|
+
<Plus className="tw-size-4" />
|
|
669
|
+
</Sidebar.GroupAction>
|
|
636
670
|
<Sidebar.GroupContent>
|
|
637
671
|
<Sidebar.Menu>
|
|
638
672
|
<Sidebar.MenuItem>
|
|
@@ -646,7 +680,9 @@ export const Group: Story = {
|
|
|
646
680
|
|
|
647
681
|
<Sidebar.Group>
|
|
648
682
|
<Sidebar.GroupLabel>Group B</Sidebar.GroupLabel>
|
|
649
|
-
<Sidebar.GroupAction
|
|
683
|
+
<Sidebar.GroupAction>
|
|
684
|
+
<Minus className="tw-size-4" />
|
|
685
|
+
</Sidebar.GroupAction>
|
|
650
686
|
<Sidebar.GroupContent>
|
|
651
687
|
<Sidebar.Menu>
|
|
652
688
|
<Sidebar.MenuItem>
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import type { ComponentProps, ElementRef, Ref } from 'react';
|
|
2
2
|
|
|
3
3
|
import { cn } from '../../../utils';
|
|
4
|
-
import { Icon } from '../../Icon';
|
|
5
4
|
|
|
6
|
-
type Props =
|
|
5
|
+
type Props = ComponentProps<'button'>;
|
|
7
6
|
|
|
8
7
|
export const SidebarGroupAction = ({
|
|
9
8
|
ref,
|
|
10
9
|
className,
|
|
11
10
|
type = 'button',
|
|
12
|
-
|
|
11
|
+
children,
|
|
13
12
|
...props
|
|
14
13
|
}: Props & { ref?: Ref<ElementRef<'button'>> }) => (
|
|
15
14
|
<button
|
|
@@ -34,6 +33,11 @@ export const SidebarGroupAction = ({
|
|
|
34
33
|
'tw-text-neutral-800',
|
|
35
34
|
'tw-rounded-full',
|
|
36
35
|
|
|
36
|
+
// svg defaults: size + colour
|
|
37
|
+
'[&_svg]:tw-size-3',
|
|
38
|
+
'[&_svg]:tw-text-neutral-400',
|
|
39
|
+
'hover:[&_svg]:tw-text-secondary-600',
|
|
40
|
+
|
|
37
41
|
'hover:tw-bg-neutral-100',
|
|
38
42
|
|
|
39
43
|
'focus-visible:tw-ring-4',
|
|
@@ -44,6 +48,6 @@ export const SidebarGroupAction = ({
|
|
|
44
48
|
className,
|
|
45
49
|
)}
|
|
46
50
|
>
|
|
47
|
-
|
|
51
|
+
{children}
|
|
48
52
|
</button>
|
|
49
53
|
);
|
|
@@ -2,6 +2,7 @@ import type { ComponentProps, ReactNode, Ref } from 'react';
|
|
|
2
2
|
import { Root, Slottable } from '@radix-ui/react-slot';
|
|
3
3
|
|
|
4
4
|
import { cn } from '../../../utils';
|
|
5
|
+
import { renderLegacyIcon } from '../../../utils/legacyIcon';
|
|
5
6
|
import { Tooltip } from '../../Tooltip';
|
|
6
7
|
import { useSidebarInstance } from '../SidebarInstanceContext';
|
|
7
8
|
|
|
@@ -10,7 +11,8 @@ import { SidebarMenuIcon } from './SidebarMenuIcon';
|
|
|
10
11
|
type Props = ComponentProps<'button'> & {
|
|
11
12
|
asChild?: boolean;
|
|
12
13
|
tooltip?: ReactNode;
|
|
13
|
-
|
|
14
|
+
icon?: ReactNode;
|
|
15
|
+
};
|
|
14
16
|
|
|
15
17
|
export const SidebarMenuButton = ({
|
|
16
18
|
ref,
|
|
@@ -87,7 +89,7 @@ export const SidebarMenuButton = ({
|
|
|
87
89
|
// Explicitly set the tabIndex to 0 to ensure the button is focusable; in Safari, anchors are not focusable by default.
|
|
88
90
|
tabIndex={0}
|
|
89
91
|
>
|
|
90
|
-
{icon && <SidebarMenuIcon
|
|
92
|
+
{icon && <SidebarMenuIcon>{renderLegacyIcon(icon)}</SidebarMenuIcon>}
|
|
91
93
|
<Slottable>{children}</Slottable>
|
|
92
94
|
</Component>
|
|
93
95
|
);
|
|
@@ -2,6 +2,7 @@ import { useCallback, useState } from 'react';
|
|
|
2
2
|
import type { ComponentProps, HTMLAttributes, ReactNode } from 'react';
|
|
3
3
|
|
|
4
4
|
import { cn } from '../../../utils';
|
|
5
|
+
import { renderLegacyIcon } from '../../../utils/legacyIcon';
|
|
5
6
|
import { HoverCard } from '../../HoverCard';
|
|
6
7
|
import { useSidebarInstance } from '../SidebarInstanceContext';
|
|
7
8
|
import { useSidebar } from '../SidebarProvider';
|
|
@@ -25,7 +26,7 @@ const Content = ({ children, className }: { children: ReactNode; className?: str
|
|
|
25
26
|
);
|
|
26
27
|
|
|
27
28
|
type Props = HTMLAttributes<HTMLDivElement> & {
|
|
28
|
-
icon:
|
|
29
|
+
icon: ReactNode;
|
|
29
30
|
title: ReactNode;
|
|
30
31
|
};
|
|
31
32
|
|
|
@@ -85,7 +86,7 @@ export const SidebarMenuCard = ({ children, className, icon, title, ...rest }: P
|
|
|
85
86
|
>
|
|
86
87
|
<div className="tw-flex tw-flex-col tw-gap-2">
|
|
87
88
|
<Title>
|
|
88
|
-
<SidebarMenuIcon className="tw-p-px"
|
|
89
|
+
<SidebarMenuIcon className="tw-p-px">{renderLegacyIcon(icon)}</SidebarMenuIcon>
|
|
89
90
|
{title}
|
|
90
91
|
</Title>
|
|
91
92
|
<Content className={className}>{children}</Content>
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import type { ComponentProps, ElementRef, Ref } from 'react';
|
|
2
2
|
|
|
3
3
|
import { cn } from '../../../utils';
|
|
4
|
-
import { Icon } from '../../Icon';
|
|
5
4
|
|
|
6
|
-
type Props =
|
|
7
|
-
icon: ComponentProps<typeof Icon>['icon'];
|
|
8
|
-
className?: string;
|
|
9
|
-
};
|
|
5
|
+
type Props = ComponentProps<'span'>;
|
|
10
6
|
|
|
11
7
|
export const SidebarMenuIcon = ({
|
|
12
8
|
ref,
|
|
13
9
|
className,
|
|
14
|
-
|
|
10
|
+
children,
|
|
15
11
|
...rest
|
|
16
|
-
}: Props & { ref?: Ref<ElementRef<'
|
|
17
|
-
<
|
|
12
|
+
}: Props & { ref?: Ref<ElementRef<'span'>> }) => (
|
|
13
|
+
<span
|
|
18
14
|
{...rest}
|
|
19
15
|
ref={ref}
|
|
20
|
-
icon={icon}
|
|
21
16
|
className={cn(
|
|
22
|
-
'tw-
|
|
17
|
+
'tw-inline-flex',
|
|
18
|
+
'tw-items-center',
|
|
19
|
+
'tw-justify-center',
|
|
23
20
|
'tw-aspect-square',
|
|
24
|
-
'tw-text-sidebar-primary',
|
|
25
21
|
'tw-shrink-0',
|
|
26
22
|
'tw-p-0.5',
|
|
23
|
+
'tw-text-sidebar-primary',
|
|
24
|
+
'[&_svg]:tw-size-4',
|
|
27
25
|
className,
|
|
28
26
|
)}
|
|
29
|
-
|
|
27
|
+
>
|
|
28
|
+
{children}
|
|
29
|
+
</span>
|
|
30
30
|
);
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
2
|
import type { ComponentProps, ReactNode } from 'react';
|
|
3
3
|
|
|
4
|
+
import { ChevronDown } from '../../../icons';
|
|
4
5
|
import { cn } from '../../../utils';
|
|
5
6
|
import { Collapsible } from '../../Collapsible';
|
|
6
7
|
import { DropdownMenu } from '../../DropdownMenu';
|
|
7
|
-
import { Icon } from '../../Icon';
|
|
8
8
|
import { Tooltip } from '../../Tooltip';
|
|
9
9
|
import { useSidebarInstance } from '../SidebarInstanceContext';
|
|
10
10
|
|
|
11
11
|
import { SidebarMenuButton } from './SidebarMenuButton';
|
|
12
|
-
import type { SidebarMenuIcon } from './SidebarMenuIcon';
|
|
13
12
|
|
|
14
13
|
type Props = {
|
|
15
14
|
children: ReactNode;
|
|
16
|
-
icon:
|
|
15
|
+
icon: ReactNode;
|
|
17
16
|
isActive?: boolean;
|
|
18
17
|
label: string;
|
|
19
18
|
} & Pick<ComponentProps<typeof Collapsible>, 'defaultOpen' | 'open' | 'onOpenChange'>;
|
|
@@ -109,10 +108,7 @@ export const SidebarMenuSub = ({
|
|
|
109
108
|
)}
|
|
110
109
|
>
|
|
111
110
|
{label}
|
|
112
|
-
<
|
|
113
|
-
icon={['far', 'angle-down']}
|
|
114
|
-
className="tw-ml-auto tw-transition-transform tw-duration-200 group-data-[state=open]:tw-rotate-180"
|
|
115
|
-
/>
|
|
111
|
+
<ChevronDown className="tw-ml-auto tw-size-5 tw-transition-transform tw-duration-200 group-data-[state=open]:tw-rotate-180" />
|
|
116
112
|
</SidebarMenuButton>
|
|
117
113
|
</Collapsible.Trigger>
|
|
118
114
|
<Collapsible.Content>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useRef } from 'react';
|
|
2
2
|
import type { ComponentProps, ElementRef, Ref } from 'react';
|
|
3
3
|
|
|
4
|
+
import { Search } from '../../../icons';
|
|
4
5
|
import { cn, mergeRefs } from '../../../utils';
|
|
5
|
-
import { Icon } from '../../Icon';
|
|
6
6
|
import { useSidebarInstance } from '../SidebarInstanceContext';
|
|
7
7
|
import { useSidebar } from '../SidebarProvider';
|
|
8
8
|
|
|
@@ -49,14 +49,12 @@ export const SidebarSearchInput = ({
|
|
|
49
49
|
|
|
50
50
|
return (
|
|
51
51
|
<div className={cn(wrapperClassnames, className)}>
|
|
52
|
-
<
|
|
53
|
-
icon="search"
|
|
54
|
-
fixedWidth
|
|
52
|
+
<Search
|
|
55
53
|
className={cn(
|
|
56
54
|
'tw-pointer-events-none',
|
|
57
55
|
'tw-absolute',
|
|
58
56
|
'tw-left-2',
|
|
59
|
-
'tw-
|
|
57
|
+
'tw-size-4',
|
|
60
58
|
|
|
61
59
|
'tw-text-sidebar-primary',
|
|
62
60
|
'group-data-[state=expanded]/sidebar:tw-text-neutral-400',
|
|
@@ -52,3 +52,55 @@ export const Group: Story = {
|
|
|
52
52
|
);
|
|
53
53
|
},
|
|
54
54
|
};
|
|
55
|
+
|
|
56
|
+
export const BoxLoader: Story = {
|
|
57
|
+
render: () => (
|
|
58
|
+
<div className="tw-rounded-md tw-border tw-border-border tw-bg-background tw-p-4">
|
|
59
|
+
<Skeleton height="lg" className="tw-w-full" />
|
|
60
|
+
</div>
|
|
61
|
+
),
|
|
62
|
+
parameters: {
|
|
63
|
+
docs: {
|
|
64
|
+
description: {
|
|
65
|
+
story: 'Box-shaped section placeholder — replaces the legacy `BoxLoader` card.',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const ActionLoader: Story = {
|
|
72
|
+
render: () => (
|
|
73
|
+
<div className="tw-flex tw-gap-2">
|
|
74
|
+
<Skeleton height="lg" className="tw-w-24 tw-rounded-md" />
|
|
75
|
+
<Skeleton height="lg" className="tw-w-32 tw-rounded-md" />
|
|
76
|
+
</div>
|
|
77
|
+
),
|
|
78
|
+
parameters: {
|
|
79
|
+
docs: {
|
|
80
|
+
description: {
|
|
81
|
+
story: 'Button-shaped placeholder for action rows — replaces the legacy `ActionLoader`.',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const ListOfRows: Story = {
|
|
88
|
+
render: () => (
|
|
89
|
+
<div className="tw-flex tw-flex-col tw-gap-3">
|
|
90
|
+
<Skeleton height="sm" className="tw-w-1/2" />
|
|
91
|
+
<Skeleton height="xs" className="tw-w-full" />
|
|
92
|
+
<Skeleton height="xs" className="tw-w-5/6" />
|
|
93
|
+
<Skeleton height="xs" className="tw-w-4/5" />
|
|
94
|
+
<Skeleton height="xs" className="tw-w-3/4" />
|
|
95
|
+
<Skeleton height="xs" className="tw-w-5/6" />
|
|
96
|
+
</div>
|
|
97
|
+
),
|
|
98
|
+
parameters: {
|
|
99
|
+
docs: {
|
|
100
|
+
description: {
|
|
101
|
+
story:
|
|
102
|
+
'Page-loading placeholder — heading + stacked rows. Replaces the legacy `CustomLoader`.',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
};
|
|
@@ -4,9 +4,15 @@ import { cn } from '../../utils';
|
|
|
4
4
|
|
|
5
5
|
export type Height = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Props for `Skeleton`. `height` maps to the named token (xxs 12px → 2xl 48px); `count` renders multiple
|
|
9
|
+
* stacked placeholders sharing the same shape.
|
|
10
|
+
*/
|
|
7
11
|
type SkeletonProps = {
|
|
12
|
+
/** Named height token — `xxs` (12px) through `2xl` (48px). */
|
|
8
13
|
height?: Height;
|
|
9
14
|
className?: string;
|
|
15
|
+
/** Number of stacked placeholder rows. Use for list-style loading states. */
|
|
10
16
|
count?: number;
|
|
11
17
|
};
|
|
12
18
|
|
|
@@ -40,6 +46,19 @@ const ANIMATION_CLASS_NAME = cn(
|
|
|
40
46
|
'before:tw-via-neutral-50',
|
|
41
47
|
);
|
|
42
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Animated placeholder shown in place of content that is still loading.
|
|
51
|
+
*
|
|
52
|
+
* **When to use:** during initial page or section load while the real content is fetched. Match the
|
|
53
|
+
* placeholder shape to the eventual content (one `Skeleton height="lg"` per title row, several `xs` for
|
|
54
|
+
* paragraph lines). For list shells use `count` to render N stacked placeholders.
|
|
55
|
+
* **When NOT to use:** for indeterminate background work without a layout slot use `DotsLoader` or
|
|
56
|
+
* `Button isLoading`; for empty / error states once the request resolves use `EmptyState` / `ErrorState`.
|
|
57
|
+
* **Composition:** drop directly into the slot the real content will occupy. `SkeletonList` is the typical
|
|
58
|
+
* shell for `Table` / `Card`-list pages.
|
|
59
|
+
*
|
|
60
|
+
* @see RECIPES.md#data-card-with-skeleton — for a loading card pattern
|
|
61
|
+
*/
|
|
43
62
|
export const Skeleton = ({ height = 'md', className, count = 1 }: SkeletonProps) => {
|
|
44
63
|
const prefixId = useId();
|
|
45
64
|
const keys = Array.from({ length: count }, (_, i) => `${prefixId}-${i}`);
|
|
@@ -47,7 +66,11 @@ export const Skeleton = ({ height = 'md', className, count = 1 }: SkeletonProps)
|
|
|
47
66
|
return (
|
|
48
67
|
<>
|
|
49
68
|
{keys.map((key) => (
|
|
50
|
-
<div
|
|
69
|
+
<div
|
|
70
|
+
key={key}
|
|
71
|
+
data-skeleton="true"
|
|
72
|
+
className={cn(HEIGHT_CLASS_NAME[height], ANIMATION_CLASS_NAME, className)}
|
|
73
|
+
/>
|
|
51
74
|
))}
|
|
52
75
|
</>
|
|
53
76
|
);
|