@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.
Files changed (177) hide show
  1. package/README.md +25 -0
  2. package/dist/icon-names.cjs +18 -0
  3. package/dist/icon-names.cjs.map +1 -0
  4. package/dist/icon-names.js +16 -0
  5. package/dist/icon-names.js.map +1 -0
  6. package/dist/icons.cjs +731 -0
  7. package/dist/icons.cjs.map +1 -0
  8. package/dist/icons.js +29 -0
  9. package/dist/icons.js.map +1 -0
  10. package/dist/index.cjs +14728 -0
  11. package/dist/index.cjs.map +1 -0
  12. package/dist/index.js +14553 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/markdown-editor.cjs +4440 -0
  15. package/dist/markdown-editor.cjs.map +1 -0
  16. package/dist/markdown-editor.js +4413 -0
  17. package/dist/markdown-editor.js.map +1 -0
  18. package/dist/mermaid.cjs +1011 -0
  19. package/dist/mermaid.cjs.map +1 -0
  20. package/dist/mermaid.js +1005 -0
  21. package/dist/mermaid.js.map +1 -0
  22. package/dist/styles.css +1 -0
  23. package/package.json +10 -3
  24. package/src/blocks/AIKit/CollapsibleStepHeader.tsx +7 -8
  25. package/src/blocks/AIKit/InlineStepLabel.tsx +7 -7
  26. package/src/blocks/AIKit/MessageBubble.stories.tsx +11 -3
  27. package/src/blocks/AIKit/MessageBubble.tsx +1 -1
  28. package/src/blocks/AIKit/PlanApproval.tsx +9 -8
  29. package/src/blocks/AIKit/PlanRewritingIndicator.tsx +2 -2
  30. package/src/blocks/AIKit/PromptInput.stories.tsx +10 -2
  31. package/src/blocks/AIKit/PromptInputSubmit.tsx +12 -8
  32. package/src/blocks/AIKit/Question.tsx +8 -9
  33. package/src/blocks/AIKit/SuggestedPrompt.tsx +12 -5
  34. package/src/blocks/AIKit/ThinkingIndicator.tsx +2 -2
  35. package/src/blocks/AutoSaveTextarea/AutoSaveTextarea.tsx +4 -4
  36. package/src/blocks/ClipboardButton/ClipboardButton.tsx +7 -5
  37. package/src/blocks/ClipboardButton/ClipboardInline.tsx +2 -3
  38. package/src/blocks/ColorInput/ColorInput.tsx +4 -2
  39. package/src/blocks/ColorInput/ColorPicker.tsx +5 -2
  40. package/src/blocks/EmptyState/EmptyState.tsx +16 -0
  41. package/src/blocks/ErrorState/ErrorState.tsx +15 -0
  42. package/src/blocks/Form/formHook.ts +15 -0
  43. package/src/blocks/MultiActionButtonGroup/MultiActionButton.stories.tsx +12 -11
  44. package/src/blocks/MultiActionButtonGroup/MultiActionButton.tsx +5 -4
  45. package/src/blocks/MultiCombobox/MultiCombobox.tsx +28 -12
  46. package/src/blocks/PageHeader/AGENTS.md +63 -3
  47. package/src/blocks/PageHeader/PageHeader.stories.tsx +124 -28
  48. package/src/blocks/PageHeader/PageHeader.tsx +15 -0
  49. package/src/blocks/PageHeader/PageHeaderDetail.tsx +23 -1
  50. package/src/blocks/PageHeader/PageHeaderIndex.tsx +20 -1
  51. package/src/blocks/PageLayout/PageLayout.tsx +26 -0
  52. package/src/blocks/PageToolbar/PageToolbar.stories.tsx +348 -0
  53. package/src/blocks/PageToolbar/PageToolbar.tsx +119 -0
  54. package/src/blocks/PageToolbar/index.ts +1 -0
  55. package/src/blocks/PasswordInput/PasswordInput.tsx +10 -10
  56. package/src/blocks/SearchInput/SearchInput.tsx +30 -4
  57. package/src/blocks/SearchInputWithNavigation/SearchInputWithNavigation.tsx +9 -6
  58. package/src/blocks/SplitButton/SplitButton.stories.tsx +7 -4
  59. package/src/blocks/SplitButton/SplitButton.tsx +17 -4
  60. package/src/blocks/Tagger/TagItem.tsx +4 -1
  61. package/src/blocks/Tagger/TagSelectPopover/TagSelectCreateItem.tsx +3 -1
  62. package/src/blocks/Tagger/TagSelectPopover/TagSelectList.tsx +2 -2
  63. package/src/blocks/Tagger/Tagger.tsx +2 -2
  64. package/src/components/Alert/Alert.stories.tsx +11 -3
  65. package/src/components/Alert/Alert.tsx +19 -1
  66. package/src/components/Alert/AlertCollapsibleIcon.tsx +3 -4
  67. package/src/components/Alert/AlertIcon.tsx +18 -21
  68. package/src/components/Badge/Badge.stories.tsx +22 -4
  69. package/src/components/Badge/Badge.tsx +16 -0
  70. package/src/components/Badge/BadgeButton.tsx +7 -6
  71. package/src/components/Breadcrumb/BreadcrumbEllipsis.tsx +2 -2
  72. package/src/components/Breadcrumb/BreadcrumbSeparator.tsx +2 -2
  73. package/src/components/Button/Button.stories.tsx +14 -2
  74. package/src/components/Button/Button.tsx +42 -5
  75. package/src/components/Button/styles.ts +4 -6
  76. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +32 -10
  77. package/src/components/Card/Card.tsx +17 -0
  78. package/src/components/Checkbox/Checkbox.tsx +3 -6
  79. package/src/components/CodeEditor/highlighting.ts +1 -1
  80. package/src/components/CollapsiblePanel.tsx +2 -5
  81. package/src/components/Combobox/Combobox.tsx +12 -14
  82. package/src/components/Combobox/ComboboxChips.tsx +6 -1
  83. package/src/components/Combobox/ComboboxItem.tsx +3 -4
  84. package/src/components/Combobox/ComboboxItemIndicator.tsx +6 -4
  85. package/src/components/Combobox/types.ts +2 -6
  86. package/src/components/Command/Command.stories.tsx +47 -56
  87. package/src/components/Command/CommandItem/CheckIndicator.tsx +26 -14
  88. package/src/components/Command/CommandItem/CommandItem.tsx +6 -3
  89. package/src/components/DropdownMenu/DropdownMenu.stories.tsx +8 -4
  90. package/src/components/DropdownMenu/DropdownMenuCheckboxItem.tsx +4 -1
  91. package/src/components/DropdownMenu/DropdownMenuItem.tsx +12 -6
  92. package/src/components/DropdownMenu/DropdownMenuItemIndicator.tsx +12 -6
  93. package/src/components/DropdownMenu/DropdownMenuRadioGroup/DropdownMenuRadioItem.tsx +8 -5
  94. package/src/components/DropdownMenu/DropdownMenuSub/DropdownMenuSubTrigger.tsx +2 -2
  95. package/src/components/DropdownMenu/ItemIcon.tsx +16 -8
  96. package/src/components/FormGroup/FormGroup.tsx +15 -0
  97. package/src/components/FullScreenModal/FullScreenModalHeader.tsx +4 -1
  98. package/src/components/Input/DateInput/DateInput.tsx +4 -1
  99. package/src/components/Input/DateRangeInput/DateRangeInput.tsx +4 -6
  100. package/src/components/Input/Input.tsx +18 -2
  101. package/src/components/Input/TextInput/TextInput.tsx +16 -0
  102. package/src/components/Input/TimeInput/TimeInput.tsx +4 -1
  103. package/src/components/InputGroup/InputGroup.stories.tsx +11 -3
  104. package/src/components/MarkdownEditor/MarkdownEditor.stories.tsx +63 -1
  105. package/src/components/MarkdownEditor/MarkdownEditor.tsx +105 -15
  106. package/src/components/MarkdownEditor/nodes/ImageNode.tsx +10 -10
  107. package/src/components/MarkdownEditor/nodes/MermaidNode.tsx +8 -8
  108. package/src/components/MarkdownEditor/plugins/KeyboardPlugin.tsx +47 -3
  109. package/src/components/MarkdownEditor/plugins/MarkdownSyncPlugin.tsx +12 -3
  110. package/src/components/MarkdownEditor/plugins/ToolbarPlugin.tsx +20 -10
  111. package/src/components/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx +20 -14
  112. package/src/components/MarkdownEditor/plugins/toolbar/BlockTypeDropdown.tsx +25 -16
  113. package/src/components/MarkdownEditor/plugins/toolbar/LinkPanel.tsx +3 -3
  114. package/src/components/MarkdownEditor/transformers.ts +10 -0
  115. package/src/components/MergeEditor/AcceptControls/AcceptButton.tsx +9 -4
  116. package/src/components/MergeEditor/AcceptControls/AcceptControls.tsx +25 -14
  117. package/src/components/MergeEditor/ConflictStatus/ConflictStatusIndicator.tsx +2 -2
  118. package/src/components/MergeEditor/MergeEditor.stories.tsx +15 -0
  119. package/src/components/MergeEditor/MergeEditor.tsx +9 -0
  120. package/src/components/MergeEditor/MergePane.tsx +22 -4
  121. package/src/components/MergeEditor/decorations.ts +2 -2
  122. package/src/components/Modal/Modal.stories.tsx +6 -4
  123. package/src/components/Modal/Modal.tsx +26 -0
  124. package/src/components/Modal/ModalBody.tsx +5 -0
  125. package/src/components/Modal/ModalCloseIcon.tsx +2 -3
  126. package/src/components/Modal/ModalContent.tsx +8 -0
  127. package/src/components/Modal/ModalFooter.tsx +5 -0
  128. package/src/components/Modal/ModalHeader.tsx +11 -0
  129. package/src/components/Modal/ModalIcon.tsx +45 -19
  130. package/src/components/Navbar/Navbar.stories.tsx +26 -13
  131. package/src/components/Navbar/NavbarMenuButton.tsx +11 -10
  132. package/src/components/Pagination/PaginationEllipsis.tsx +2 -2
  133. package/src/components/Pagination/PaginationNext.tsx +2 -1
  134. package/src/components/Pagination/PaginationPrevious.tsx +4 -1
  135. package/src/components/PanelWithDetails.tsx +3 -4
  136. package/src/components/Popconfirm/Popconfirm.stories.tsx +13 -5
  137. package/src/components/RadioGroup/Radio.tsx +6 -12
  138. package/src/components/Search/ClearButton.tsx +2 -2
  139. package/src/components/Search/Search.tsx +3 -3
  140. package/src/components/Select/Select.tsx +16 -5
  141. package/src/components/Select/SelectContent.tsx +13 -4
  142. package/src/components/Select/SelectItem.tsx +6 -5
  143. package/src/components/Select/SelectTrigger.tsx +2 -2
  144. package/src/components/Sidebar/Sidebar.stories.tsx +55 -19
  145. package/src/components/Sidebar/SidebarGroup/SidebarGroupAction.tsx +8 -4
  146. package/src/components/Sidebar/SidebarMenu/SidebarMenuButton.tsx +4 -2
  147. package/src/components/Sidebar/SidebarMenu/SidebarMenuCard.tsx +3 -2
  148. package/src/components/Sidebar/SidebarMenu/SidebarMenuIcon.tsx +12 -12
  149. package/src/components/Sidebar/SidebarMenu/SidebarMenuSub.tsx +3 -7
  150. package/src/components/Sidebar/SidebarMenu/SidebarSearchInput.tsx +3 -5
  151. package/src/components/Skeleton/Skeleton.stories.tsx +52 -0
  152. package/src/components/Skeleton/Skeleton.tsx +24 -1
  153. package/src/components/Table/Table.stories.tsx +223 -1
  154. package/src/components/Table/Table.tsx +17 -0
  155. package/src/components/Tabs.tsx +25 -2
  156. package/src/components/Toast/ToastDismiss.tsx +3 -3
  157. package/src/components/Toast/ToastRoot.tsx +24 -19
  158. package/src/components/Toggle/Toggle.tsx +11 -6
  159. package/src/components/Tooltip/Tooltip.tsx +23 -0
  160. package/src/components/ZoomableSvg/ZoomableSvg.tsx +8 -6
  161. package/src/icons/Keboola.tsx +28 -0
  162. package/src/icons/icons.stories.tsx +174 -0
  163. package/src/icons/index.ts +180 -0
  164. package/src/index.ts +1 -0
  165. package/src/patterns/AlertWithAction.stories.tsx +30 -0
  166. package/src/patterns/CardWithEmptyState.stories.tsx +66 -0
  167. package/src/patterns/ConfirmDialog.stories.tsx +72 -0
  168. package/src/patterns/CreatableMultiCombobox.stories.tsx +33 -0
  169. package/src/patterns/DataCardWithSkeleton.stories.tsx +48 -0
  170. package/src/patterns/DisabledButtonTooltip.stories.tsx +30 -0
  171. package/src/patterns/FilterToolbar.stories.tsx +71 -0
  172. package/src/patterns/InfoTooltip.stories.tsx +56 -0
  173. package/src/patterns/ListDetail.stories.tsx +65 -0
  174. package/src/patterns/ModalForm.stories.tsx +59 -0
  175. package/src/patterns/PageHeaderTabs.stories.tsx +48 -0
  176. package/src/styles.css +16 -8
  177. package/src/utils/legacyIcon.tsx +28 -0
@@ -1,6 +1,8 @@
1
1
  import type { ComponentProps } from 'react';
2
2
  import type { Meta, StoryObj } from '@storybook/react-vite';
3
3
 
4
+ import { ArrowLeft, ArrowRight, ChevronLeft, ChevronRight, Plus } from '@keboola/design/icons';
5
+
4
6
  import { Button } from '../Button';
5
7
 
6
8
  import { ButtonGroup } from './ButtonGroup';
@@ -61,11 +63,17 @@ export const BlockWithIcons: Story = {
61
63
  variant: 'block',
62
64
  children: (
63
65
  <>
64
- <Button variant="outline" icon="chevron-left" size="icon" aria-label="Left" />
66
+ <Button variant="outline" size="icon" aria-label="Left">
67
+ <ChevronLeft className="tw-size-5" />
68
+ </Button>
65
69
  <Button variant="outline">Left button</Button>
66
- <Button variant="outline" icon="plus" size="icon" aria-label="Plus" />
70
+ <Button variant="outline" size="icon" aria-label="Plus">
71
+ <Plus className="tw-size-4" />
72
+ </Button>
67
73
  <Button>Right Button</Button>
68
- <Button variant="outline" icon="chevron-right" size="icon" aria-label="Right" />
74
+ <Button variant="outline" size="icon" aria-label="Right">
75
+ <ChevronRight className="tw-size-5" />
76
+ </Button>
69
77
  </>
70
78
  ),
71
79
  },
@@ -77,15 +85,21 @@ export const ArgoBlock: Story = {
77
85
  variant: 'block',
78
86
  children: (
79
87
  <>
80
- <Button argo icon="chevron-left" size="icon" variant="outline" aria-label="move-left" />
88
+ <Button argo size="icon" variant="outline" aria-label="move-left">
89
+ <ChevronLeft className="tw-size-5" />
90
+ </Button>
81
91
  <Button argo variant="primary">
82
92
  Left button
83
93
  </Button>
84
- <Button argo icon="plus" size="icon" variant="outline" aria-label="add" />
94
+ <Button argo size="icon" variant="outline" aria-label="add">
95
+ <Plus className="tw-size-4" />
96
+ </Button>
85
97
  <Button argo variant="danger">
86
98
  Right Button
87
99
  </Button>
88
- <Button argo icon="chevron-right" size="icon" variant="outline" aria-label="move-right" />
100
+ <Button argo size="icon" variant="outline" aria-label="move-right">
101
+ <ChevronRight className="tw-size-5" />
102
+ </Button>
89
103
  </>
90
104
  ),
91
105
  },
@@ -96,9 +110,13 @@ export const Compact: Story = {
96
110
  space: 'compact',
97
111
  children: (
98
112
  <>
99
- <Button variant="outline" icon="arrow-left" size="icon" aria-label="Left" />
113
+ <Button variant="outline" size="icon" aria-label="Left">
114
+ <ArrowLeft className="tw-size-4" />
115
+ </Button>
100
116
  <Button variant="outline">Submit</Button>
101
- <Button variant="outline" icon="arrow-right" size="icon" aria-label="Right" />
117
+ <Button variant="outline" size="icon" aria-label="Right">
118
+ <ArrowRight className="tw-size-4" />
119
+ </Button>
102
120
  </>
103
121
  ),
104
122
  },
@@ -109,9 +127,13 @@ export const ArgoCompact: Story = {
109
127
  space: 'compact',
110
128
  children: (
111
129
  <>
112
- <Button argo size="icon" icon="arrow-left" aria-label="move-right" />
130
+ <Button argo size="icon" aria-label="move-right">
131
+ <ArrowLeft className="tw-size-4" />
132
+ </Button>
113
133
  <Button argo>Submit</Button>
114
- <Button argo size="icon" icon="arrow-right" aria-label="move-right" />
134
+ <Button argo size="icon" aria-label="move-right">
135
+ <ArrowRight className="tw-size-4" />
136
+ </Button>
115
137
  </>
116
138
  ),
117
139
  },
@@ -6,8 +6,25 @@ import { CardHeader } from './CardHeader';
6
6
  import { CardTitle } from './CardTitle';
7
7
  import { cardClassnames } from './styles';
8
8
 
9
+ /**
10
+ * Props for `Card`. `padding` controls internal spacing; `bordered` adds a subtle border.
11
+ * All standard `<div>` attributes pass through.
12
+ */
9
13
  type Props = HTMLAttributes<HTMLDivElement> & VariantProps<typeof cardClassnames>;
10
14
 
15
+ /**
16
+ * Semantic content surface — a panel with its own padding, optional border, and header / content slots.
17
+ *
18
+ * **When to use:** wrapping a conceptually-distinct chunk of content (a config section, a stats panel,
19
+ * a list of heterogeneous items). Each `Card` is a self-contained surface inside `PageLayout.Content`.
20
+ * **When NOT to use:** for tabular data use `Table`; for ad-hoc layout grids use Tailwind utility classes
21
+ * directly; for empty / error placeholders use `EmptyState` / `ErrorState`.
22
+ * **Composition:** nest `Card.Header` + `Card.Title` for the header row, then `Card.Content` for the body.
23
+ * Multiple cards usually share a `tw-grid` or `tw-flex tw-flex-col tw-gap-4` parent.
24
+ *
25
+ * @see RECIPES.md#card-with-empty-state — for an empty card placeholder pattern
26
+ * @see RECIPES.md#data-card-with-skeleton — for a loading card with `Skeleton` placeholders
27
+ */
11
28
  export const Card = ({
12
29
  children,
13
30
  className,
@@ -4,10 +4,10 @@ import type { CheckedState } from '@radix-ui/react-checkbox';
4
4
  import { Indicator, Root } from '@radix-ui/react-checkbox';
5
5
  import type { VariantProps } from 'class-variance-authority';
6
6
 
7
+ import { Check, Minus } from '../../icons';
7
8
  import { cn } from '../../utils';
8
9
  import { FieldBox } from '../FieldBox';
9
10
  import type { fieldBoxVariants } from '../FieldBox/styles';
10
- import { Icon } from '../Icon';
11
11
  import type { Props as TooltipProps } from '../Tooltip';
12
12
  import { Tooltip } from '../Tooltip';
13
13
 
@@ -58,11 +58,8 @@ export function Checkbox({
58
58
  const checkboxElement = (
59
59
  <Root id={id} {...rest} className={cn(rootVariants({ variant: styleVariant, className }))}>
60
60
  <Indicator className={cn(indicatorVariants({ variant: styleVariant }))}>
61
- <Icon icon="check" className="tw-hidden tw-size-3 group-data-[state=checked]:tw-block" />
62
- <Icon
63
- icon="minus"
64
- className="tw-hidden tw-size-3 group-data-[state=indeterminate]:tw-block"
65
- />
61
+ <Check className="tw-hidden tw-size-3 tw-stroke-[4px] group-data-[state=checked]:tw-block" />
62
+ <Minus className="tw-hidden tw-size-3 tw-stroke-[4px] group-data-[state=indeterminate]:tw-block" />
66
63
  </Indicator>
67
64
  </Root>
68
65
  );
@@ -15,7 +15,7 @@ export type HighlightedLines = {
15
15
 
16
16
  // Gutter markers for highlighting
17
17
  class HighlightMarker extends GutterMarker {
18
- toDOM() {
18
+ override toDOM() {
19
19
  const marker = document.createElement('div');
20
20
  marker.className = 'cm-highlight-marker';
21
21
  return marker;
@@ -2,8 +2,8 @@ import { useState } from 'react';
2
2
  import type { KeyboardEvent, MouseEvent, ReactNode } from 'react';
3
3
  import { cva } from 'class-variance-authority';
4
4
 
5
- import { Icon } from '../components/Icon';
6
5
  import { keyCodes } from '../constants/keyCodes';
6
+ import { ChevronDown } from '../icons';
7
7
  import { cn } from '../utils';
8
8
 
9
9
  import { Collapse } from './Collapse';
@@ -115,10 +115,7 @@ export const CollapsiblePanel = ({
115
115
  </div>
116
116
  {!isDisabled && (
117
117
  <div className="tw-ml-auto tw-shrink-0">
118
- <Icon
119
- icon="chevron-down"
120
- className={cn('tw-text-xs group-data-[state=open]:tw-rotate-180')}
121
- />
118
+ <ChevronDown className={cn('tw-size-5 group-data-[state=open]:tw-rotate-180')} />
122
119
  </div>
123
120
  )}
124
121
  </div>
@@ -1,7 +1,7 @@
1
1
  import { type ComponentProps, type ReactNode, useEffect, useRef, useState } from 'react';
2
2
  import { Combobox as BaseCombobox } from '@base-ui/react/combobox';
3
3
 
4
- import type { Icon } from '../Icon';
4
+ import { ChevronDown, Plus, X } from '../../icons';
5
5
  import { InputGroup } from '../InputGroup';
6
6
 
7
7
  import { ComboboxChips } from './ComboboxChips';
@@ -35,7 +35,6 @@ type ComboboxInputProps = ComponentProps<typeof ComboboxInput>;
35
35
  type ComboboxInputGroupProps = ComponentProps<typeof ComboboxInputGroup>;
36
36
  type ComboboxItemProps = ComponentProps<typeof ComboboxItem>;
37
37
 
38
- type IconName = ComponentProps<typeof Icon>['icon'];
39
38
  type Indicator = NonNullable<ComboboxItemProps['indicator']>;
40
39
 
41
40
  type PublicComboboxInputProps = Pick<ComboboxInputProps, 'placeholder' | 'id'> &
@@ -74,7 +73,7 @@ type Props<Value, GroupShape extends Group<Value> = Group<Value>> = PublicCombob
74
73
 
75
74
  // item specific
76
75
  itemToLabel?: (item: Value) => ReactNode;
77
- itemToIcon?: (item: Value) => IconName | undefined;
76
+ itemToIcon?: (item: Value) => ReactNode;
78
77
  itemToDisabled?: (item: Value) => boolean;
79
78
 
80
79
  // group specific
@@ -273,17 +272,16 @@ export const Combobox = <Value, GroupShape extends Group<Value> = Group<Value>>(
273
272
  <ComboboxInput id={id} placeholder={placeholder} disabled={disabled} />
274
273
  <InputGroup.Addon align="inline-end">
275
274
  {allowClear && (
276
- <InputGroup.Button asChild icon="xmark" aria-label="Clear" disabled={disabled}>
277
- <BaseCombobox.Clear />
275
+ <InputGroup.Button asChild aria-label="Clear" disabled={disabled}>
276
+ <BaseCombobox.Clear>
277
+ <X className="tw-size-4" />
278
+ </BaseCombobox.Clear>
278
279
  </InputGroup.Button>
279
280
  )}
280
- <InputGroup.Button
281
- disabled={disabled}
282
- asChild
283
- icon="chevron-down"
284
- aria-label="Open combobox"
285
- >
286
- <BaseCombobox.Trigger />
281
+ <InputGroup.Button disabled={disabled} asChild aria-label="Open combobox">
282
+ <BaseCombobox.Trigger>
283
+ <ChevronDown className="tw-size-4" />
284
+ </BaseCombobox.Trigger>
287
285
  </InputGroup.Button>
288
286
  </InputGroup.Addon>
289
287
  </ComboboxInputGroup>
@@ -293,7 +291,7 @@ export const Combobox = <Value, GroupShape extends Group<Value> = Group<Value>>(
293
291
  {(itemOrGroup: Value | GroupShape) => {
294
292
  if (isCreatableItem(itemOrGroup))
295
293
  return (
296
- <Combobox.Item value={itemOrGroup} icon="plus">
294
+ <Combobox.Item value={itemOrGroup} icon={<Plus />}>
297
295
  {queryToCreateLabel(itemOrGroup.value)}
298
296
  </Combobox.Item>
299
297
  );
@@ -303,7 +301,7 @@ export const Combobox = <Value, GroupShape extends Group<Value> = Group<Value>>(
303
301
 
304
302
  if (isCreatableItem(maybeCreatable)) {
305
303
  return (
306
- <Combobox.Item value={maybeCreatable} icon="plus">
304
+ <Combobox.Item value={maybeCreatable} icon={<Plus />}>
307
305
  {queryToCreateLabel(maybeCreatable.value)}
308
306
  </Combobox.Item>
309
307
  );
@@ -1,6 +1,7 @@
1
1
  import type { ComponentProps, ReactNode } from 'react';
2
2
  import { Combobox as BaseCombobox } from '@base-ui/react/combobox';
3
3
 
4
+ import { X } from '../../icons';
4
5
  import { Badge } from '../Badge';
5
6
 
6
7
  import { defaultItemToLabel } from './utils';
@@ -45,7 +46,11 @@ export const ComboboxChips = <Value,>({
45
46
  <Badge.Label>{itemToChipLabel(value)}</Badge.Label>
46
47
  <Badge.Addon variant="inline" align="inline-end">
47
48
  <BaseCombobox.ChipRemove
48
- render={<Badge.Button icon="xmark" aria-label="Remove value" />}
49
+ render={
50
+ <Badge.Button aria-label="Remove value">
51
+ <X className="tw-size-3" />
52
+ </Badge.Button>
53
+ }
49
54
  />
50
55
  </Badge.Addon>
51
56
  </BaseCombobox.Chip>
@@ -1,14 +1,13 @@
1
- import type { ComponentProps, ElementRef, Ref } from 'react';
1
+ import type { ComponentProps, ElementRef, ReactNode, Ref } from 'react';
2
2
  import { Combobox as BaseCombobox } from '@base-ui/react/combobox';
3
3
 
4
4
  import { cn } from '../../utils';
5
- import { Icon } from '../Icon';
6
5
 
7
6
  import { ComboboxItemIndicator } from './ComboboxItemIndicator';
8
7
 
9
8
  type Props = Omit<ComponentProps<typeof BaseCombobox.Item>, 'className'> & {
10
9
  className?: string;
11
- icon?: ComponentProps<typeof Icon>['icon'];
10
+ icon?: ReactNode;
12
11
  indicator?: ComponentProps<typeof ComboboxItemIndicator>['variant'];
13
12
  };
14
13
 
@@ -65,7 +64,7 @@ export const ComboboxItem = ({
65
64
  )}
66
65
  >
67
66
  {<ComboboxItemIndicator variant={variant} />}
68
- {icon && <Icon icon={icon} />}
67
+ {icon}
69
68
  <span className="tw-truncate">{children}</span>
70
69
  </BaseCombobox.Item>
71
70
  );
@@ -1,8 +1,8 @@
1
1
  import type { ComponentProps, ElementRef, Ref } from 'react';
2
2
  import { Combobox as BaseCombobox } from '@base-ui/react/combobox';
3
3
 
4
+ import { Check } from '../../icons';
4
5
  import { cn } from '../../utils';
5
- import { Icon } from '../Icon';
6
6
 
7
7
  type Variant = 'check' | 'checkbox';
8
8
 
@@ -42,11 +42,11 @@ export const ComboboxItemIndicator = ({
42
42
  )}
43
43
  {...props}
44
44
  >
45
- <Icon
46
- icon="check"
45
+ <Check
47
46
  className={cn(
48
47
  'tw-hidden',
49
48
  'tw-size-3',
49
+ 'tw-stroke-[4px]',
50
50
  '!tw-text-white',
51
51
  'group-data-[selected]/combobox-item-indicator:tw-block',
52
52
  )}
@@ -65,12 +65,14 @@ export const ComboboxItemIndicator = ({
65
65
  'tw-right-2',
66
66
 
67
67
  'group-data-[variant=default]/combobox-content:tw-right-4',
68
+ // Lucide SVGs default to 24×24 — constrain the rendered child so the
69
+ // 16px indicator slot owns the actual size.
68
70
  '[&_svg]:tw-size-4',
69
71
  'group-data-[highlighted]/combobox-item:tw-text-accent-foreground',
70
72
  'group-data-[variant=default]/combobox-content:group-data-[highlighted]/combobox-item:tw-text-foreground',
71
73
  className,
72
74
  )}
73
- render={<Icon icon="check" />}
75
+ render={<Check />}
74
76
  />
75
77
  );
76
78
  };
@@ -1,8 +1,4 @@
1
- import type { ComponentProps } from 'react';
2
-
3
- import type { Icon } from '../../components/Icon';
4
-
5
- export type IconName = ComponentProps<typeof Icon>['icon'];
1
+ import type { ReactNode } from 'react';
6
2
 
7
3
  // Mirrors Base UI's internal `Group<Item>` interface from
8
4
  // `@base-ui/react/internals/resolveValueLabel`. Any object with an `items`
@@ -17,7 +13,7 @@ export type Group<Item = unknown> = {
17
13
  export type LabeledItem = {
18
14
  value: string;
19
15
  label: string;
20
- icon?: IconName;
16
+ icon?: ReactNode;
21
17
  disabled?: boolean;
22
18
  };
23
19
 
@@ -1,9 +1,24 @@
1
1
  import { useState } from 'react';
2
- import type { ComponentProps } from 'react';
2
+ import type { ComponentProps, ReactNode } from 'react';
3
3
  import type { Meta, StoryObj } from '@storybook/react-vite';
4
4
 
5
+ import {
6
+ ArrowLeft,
7
+ Copy,
8
+ Eye,
9
+ Gauge,
10
+ Gift,
11
+ Layers,
12
+ Link as LinkIcon,
13
+ Plus,
14
+ Search,
15
+ Settings,
16
+ Star,
17
+ Wrench,
18
+ Zap,
19
+ } from '@keboola/design/icons';
20
+
5
21
  import { Button } from '../Button';
6
- import { Icon } from '../Icon';
7
22
  import { Modal } from '../Modal';
8
23
  import { Popover } from '../Popover';
9
24
 
@@ -12,48 +27,20 @@ import { Command } from './Command';
12
27
  type Item = {
13
28
  value: string;
14
29
  label: string;
15
- icon?: ComponentProps<typeof Icon>['icon'];
30
+ icon?: ReactNode;
16
31
  };
17
32
 
18
33
  const planets: Item[] = [
19
- {
20
- icon: 'gift',
21
- value: 'earth',
22
- label: 'Earth',
23
- },
24
- {
25
- icon: 'eye',
26
- value: 'saturn',
27
- label: 'Saturn',
28
- },
29
- {
30
- icon: 'wrench',
31
- value: 'jupiter',
32
- label: 'Jupiter',
33
- },
34
- {
35
- value: 'mars',
36
- label: 'Mars',
37
- icon: 'bolt',
38
- },
34
+ { icon: <Gift />, value: 'earth', label: 'Earth' },
35
+ { icon: <Eye />, value: 'saturn', label: 'Saturn' },
36
+ { icon: <Wrench />, value: 'jupiter', label: 'Jupiter' },
37
+ { value: 'mars', label: 'Mars', icon: <Zap /> },
39
38
  ];
40
39
 
41
40
  const colors: Item[] = [
42
- {
43
- icon: 'cog',
44
- value: 'red',
45
- label: 'Red',
46
- },
47
- {
48
- icon: 'chain',
49
- value: 'green',
50
- label: 'Green',
51
- },
52
- {
53
- icon: 'arrow-left',
54
- value: 'blue',
55
- label: 'Blue',
56
- },
41
+ { icon: <Settings />, value: 'red', label: 'Red' },
42
+ { icon: <LinkIcon />, value: 'green', label: 'Green' },
43
+ { icon: <ArrowLeft />, value: 'blue', label: 'Blue' },
57
44
  ];
58
45
 
59
46
  /**
@@ -225,7 +212,7 @@ export const AsSearchableMenu: Story = {
225
212
  <Command {...args}>
226
213
  <Command.Input
227
214
  focusVariant="off"
228
- prefix={<Icon icon="search" className="tw-text-neutral-400" />}
215
+ prefix={<Search className="tw-text-neutral-400" />}
229
216
  variant="secondary"
230
217
  placeholder="Search"
231
218
  />
@@ -264,7 +251,7 @@ export const AsGlobalSearch: Story = {
264
251
  <Command {...args}>
265
252
  <Command.Input
266
253
  focusVariant="off"
267
- prefix={<Icon icon="search" className="tw-text-neutral-400" />}
254
+ prefix={<Search className="tw-text-neutral-400" />}
268
255
  variant="secondary"
269
256
  placeholder="Search"
270
257
  />
@@ -275,16 +262,22 @@ export const AsGlobalSearch: Story = {
275
262
 
276
263
  <Command.List>
277
264
  <Command.Group heading="Link">
278
- <Command.Item icon="gauge">Go to Dashboard</Command.Item>
279
- <Command.Item icon="layer-group">Go to Workspaces</Command.Item>
280
- <Command.Item icon="copy">Go to Transformation</Command.Item>
281
- <Command.Item icon="eye">Go to App</Command.Item>
265
+ <Command.Item icon={<Gauge className="tw-size-4" />}>Go to Dashboard</Command.Item>
266
+ <Command.Item icon={<Layers className="tw-size-4" />}>
267
+ Go to Workspaces
268
+ </Command.Item>
269
+ <Command.Item icon={<Copy className="tw-size-4" />}>
270
+ Go to Transformation
271
+ </Command.Item>
272
+ <Command.Item icon={<Eye className="tw-size-4" />}>Go to App</Command.Item>
282
273
  </Command.Group>
283
274
 
284
275
  <Command.Group heading="Actions">
285
- <Command.Item icon="plus">Create Workspace</Command.Item>
286
- <Command.Item icon="plus">Create App</Command.Item>
287
- <Command.Item icon="plus">Create Transformation</Command.Item>
276
+ <Command.Item icon={<Plus className="tw-size-4" />}>Create Workspace</Command.Item>
277
+ <Command.Item icon={<Plus className="tw-size-4" />}>Create App</Command.Item>
278
+ <Command.Item icon={<Plus className="tw-size-4" />}>
279
+ Create Transformation
280
+ </Command.Item>
288
281
  </Command.Group>
289
282
  </Command.List>
290
283
  </Command>
@@ -309,7 +302,7 @@ export const ArgoAppearance: Story = {
309
302
  <div className="tw-mb-1 tw-px-4 tw-pb-0 tw-pt-4">
310
303
  <Command.Input
311
304
  variant="secondary"
312
- prefix={<Icon icon="search" className="tw-size-4 tw-text-neutral-400" />}
305
+ prefix={<Search className="tw-size-4 tw-text-neutral-400" />}
313
306
  placeholder="Search..."
314
307
  allowClear
315
308
  focusVariant="off"
@@ -334,13 +327,9 @@ export const ArgoAppearance: Story = {
334
327
  disabled={isDisabled}
335
328
  actions={
336
329
  isDisabled ? undefined : (
337
- <Button
338
- argo
339
- variant="outline"
340
- icon="star"
341
- aria-label="Favorite"
342
- size="icon-sm"
343
- />
330
+ <Button argo variant="outline" aria-label="Favorite" size="icon-sm">
331
+ <Star className="tw-size-4" />
332
+ </Button>
344
333
  )
345
334
  }
346
335
  >
@@ -362,7 +351,9 @@ export const ArgoAppearance: Story = {
362
351
  onSelect={handleOnSelect}
363
352
  checked={item.value === value}
364
353
  actions={
365
- <Button argo variant="outline" icon="star" aria-label="Favorite" size="icon-sm" />
354
+ <Button argo variant="outline" aria-label="Favorite" size="icon-sm">
355
+ <Star className="tw-size-4" />
356
+ </Button>
366
357
  }
367
358
  >
368
359
  {item.label}
@@ -1,5 +1,5 @@
1
+ import { Check, Circle } from '../../../icons';
1
2
  import { cn } from '../../../utils';
2
- import { Icon } from '../../Icon';
3
3
 
4
4
  type Props = {
5
5
  variant?: 'checkbox' | 'radio' | 'argo' | 'default';
@@ -10,8 +10,7 @@ export const CheckIndicator = ({ variant = 'default' }: Props) => {
10
10
 
11
11
  if (variant === 'argo') {
12
12
  return (
13
- <Icon
14
- icon="check"
13
+ <Check
15
14
  className={cn(
16
15
  // visibility
17
16
  'tw-hidden',
@@ -58,17 +57,30 @@ export const CheckIndicator = ({ variant = 'default' }: Props) => {
58
57
  'tw-shrink-0',
59
58
  )}
60
59
  >
61
- <Icon
62
- className={cn(
63
- 'tw-hidden',
64
- 'group-data-[checked=true]/command-item:tw-block',
65
-
66
- 'group-data-[variant=checkbox]/check-indicator:tw-text-white',
67
- 'group-data-[variant=radio]/check-indicator:tw-text-secondary-500',
68
- 'group-data-[variant=radio]/check-indicator:tw-size-3',
69
- )}
70
- icon={variant === 'checkbox' ? 'check' : 'circle'}
71
- />
60
+ {variant === 'checkbox' ? (
61
+ <Check
62
+ className={cn(
63
+ 'tw-hidden',
64
+ // Lucide SVGs default to 24×24; constrain to the 16px indicator slot.
65
+ 'tw-size-3',
66
+ 'tw-stroke-[4px]',
67
+ 'group-data-[checked=true]/command-item:tw-block',
68
+ 'group-data-[variant=checkbox]/check-indicator:tw-text-white',
69
+ )}
70
+ />
71
+ ) : (
72
+ <Circle
73
+ className={cn(
74
+ 'tw-hidden',
75
+ // Lucide Circle is stroke-only — force fill to match the stroke so
76
+ // the indicator reads as a solid dot.
77
+ 'tw-size-3',
78
+ 'tw-fill-current',
79
+ 'group-data-[checked=true]/command-item:tw-block',
80
+ 'group-data-[variant=radio]/check-indicator:tw-text-secondary-500',
81
+ )}
82
+ />
83
+ )}
72
84
  </span>
73
85
  );
74
86
  };
@@ -2,12 +2,11 @@ import type { ComponentProps, ReactNode } from 'react';
2
2
  import { Command as CommandPrimitive } from 'cmdk';
3
3
 
4
4
  import { cn } from '../../../utils';
5
- import { Icon } from '../../Icon';
6
5
 
7
6
  import { CheckIndicator } from './CheckIndicator';
8
7
 
9
8
  type Props = ComponentProps<typeof CommandPrimitive.Item> & {
10
- icon?: ComponentProps<typeof Icon>['icon'];
9
+ icon?: ReactNode;
11
10
  checked?: boolean;
12
11
  variant?: ComponentProps<typeof CheckIndicator>['variant'];
13
12
  actions?: ReactNode;
@@ -69,7 +68,11 @@ export const CommandItem = ({
69
68
  )}
70
69
  >
71
70
  <CheckIndicator variant={variant} />
72
- {icon && <Icon icon={icon} className="tw-size-4 tw-shrink-0 tw-text-neutral-400" />}
71
+ {icon && (
72
+ <span className="tw-inline-flex tw-size-4 tw-shrink-0 tw-items-center tw-justify-center tw-text-neutral-400 [&_svg]:tw-size-4">
73
+ {icon}
74
+ </span>
75
+ )}
73
76
  {children}
74
77
  </CommandPrimitive.Item>
75
78
 
@@ -1,6 +1,8 @@
1
1
  import { type ComponentProps, useState } from 'react';
2
2
  import type { Meta, StoryObj } from '@storybook/react-vite';
3
3
 
4
+ import { Settings } from '@keboola/design/icons';
5
+
4
6
  import { Button } from '../Button';
5
7
 
6
8
  import { DropdownMenu } from './DropdownMenu';
@@ -51,13 +53,15 @@ export const MenuItems: Story = {
51
53
 
52
54
  <DropdownMenu.Content>
53
55
  <DropdownMenu.Item>Default</DropdownMenu.Item>
54
- <DropdownMenu.Item icon="cog">Default - Icon</DropdownMenu.Item>
56
+ <DropdownMenu.Item icon={<Settings className="tw-size-4" />}>
57
+ Default - Icon
58
+ </DropdownMenu.Item>
55
59
  <DropdownMenu.Item disabled>Default - Disabled</DropdownMenu.Item>
56
- <DropdownMenu.Item icon="cog" disabled>
60
+ <DropdownMenu.Item disabled icon={<Settings className="tw-size-4" />}>
57
61
  Default - Icon- Disabled
58
62
  </DropdownMenu.Item>
59
63
  <DropdownMenu.Item isLoading>Default - Loading</DropdownMenu.Item>
60
- <DropdownMenu.Item icon="cog" isLoading>
64
+ <DropdownMenu.Item isLoading icon={<Settings className="tw-size-4" />}>
61
65
  Default - Icon - Loading
62
66
  </DropdownMenu.Item>
63
67
  <DropdownMenu.Item>Default - Selected</DropdownMenu.Item>
@@ -68,7 +72,7 @@ export const MenuItems: Story = {
68
72
  <a href="#">Anchor</a>
69
73
  </DropdownMenu.Item>
70
74
 
71
- <DropdownMenu.Item asChild icon="cog">
75
+ <DropdownMenu.Item asChild icon={<Settings className="tw-size-4" />}>
72
76
  {/* oxlint-disable-next-line jsx-a11y/anchor-is-valid */}
73
77
  <a href="#">Anchor - Icon</a>
74
78
  </DropdownMenu.Item>
@@ -1,6 +1,7 @@
1
1
  import type { ComponentProps } from 'react';
2
2
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
3
3
 
4
+ import { Loader2 } from '../../icons';
4
5
  import { cn } from '../../utils';
5
6
 
6
7
  import { DropdownMenuItemIndicator } from './DropdownMenuItemIndicator';
@@ -27,7 +28,9 @@ export const DropdownMenuCheckboxItem = ({
27
28
  }: Props) => {
28
29
  const isAtStart = indicatorAlign === 'start';
29
30
  const indicatorEle = isLoading ? (
30
- <ItemIcon spin icon="spinner" className={isAtStart ? '' : 'tw-ml-auto'} />
31
+ <ItemIcon className={isAtStart ? '' : 'tw-ml-auto'}>
32
+ <Loader2 className="tw-animate-spin" />
33
+ </ItemIcon>
31
34
  ) : (
32
35
  <DropdownMenuItemIndicator variant={indicator} className={isAtStart ? '' : 'tw-ml-auto'} />
33
36
  );