@orcestr/ui 0.0.3 → 0.1.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 (184) hide show
  1. package/dist/components/Alert/Alert.d.ts +5 -4
  2. package/dist/components/Alert/Alert.d.ts.map +1 -1
  3. package/dist/components/Alert/Alert.js +5 -2
  4. package/dist/components/AppShell/AppShell.d.ts +13 -0
  5. package/dist/components/AppShell/AppShell.d.ts.map +1 -1
  6. package/dist/components/AppShell/AppShell.js +14 -9
  7. package/dist/components/AppSidebar/AppSidebar.d.ts +36 -0
  8. package/dist/components/AppSidebar/AppSidebar.d.ts.map +1 -0
  9. package/dist/components/AppSidebar/AppSidebar.js +117 -0
  10. package/dist/components/Badge/Badge.d.ts +8 -6
  11. package/dist/components/Badge/Badge.d.ts.map +1 -1
  12. package/dist/components/Badge/Badge.js +4 -4
  13. package/dist/components/BadgeSelectMenu/BadgeSelectMenu.d.ts +22 -0
  14. package/dist/components/BadgeSelectMenu/BadgeSelectMenu.d.ts.map +1 -0
  15. package/dist/components/BadgeSelectMenu/BadgeSelectMenu.js +50 -0
  16. package/dist/components/Box/Box.d.ts +2 -0
  17. package/dist/components/Box/Box.d.ts.map +1 -1
  18. package/dist/components/Box/Box.js +15 -2
  19. package/dist/components/Button/Button.d.ts +7 -3
  20. package/dist/components/Button/Button.d.ts.map +1 -1
  21. package/dist/components/Button/Button.js +23 -3
  22. package/dist/components/Card/Card.d.ts +26 -0
  23. package/dist/components/Card/Card.d.ts.map +1 -0
  24. package/dist/components/Card/Card.js +25 -0
  25. package/dist/components/Checkbox/Checkbox.d.ts +6 -2
  26. package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
  27. package/dist/components/Checkbox/Checkbox.js +13 -4
  28. package/dist/components/Collapse/Collapse.d.ts.map +1 -1
  29. package/dist/components/Collapse/Collapse.js +5 -25
  30. package/dist/components/CommandPalette/CommandPalette.d.ts.map +1 -1
  31. package/dist/components/CommandPalette/CommandPalette.js +10 -9
  32. package/dist/components/ConfirmDialog/ConfirmDialog.d.ts.map +1 -1
  33. package/dist/components/ConfirmDialog/ConfirmDialog.js +5 -2
  34. package/dist/components/ContextMenu/ContextMenu.d.ts.map +1 -1
  35. package/dist/components/ContextMenu/ContextMenu.js +2 -2
  36. package/dist/components/CopyButton/CopyButton.d.ts +24 -0
  37. package/dist/components/CopyButton/CopyButton.d.ts.map +1 -0
  38. package/dist/components/CopyButton/CopyButton.js +81 -0
  39. package/dist/components/DatePicker/DatePicker.d.ts.map +1 -1
  40. package/dist/components/DatePicker/DatePicker.js +9 -1
  41. package/dist/components/Dialog/Dialog.d.ts +69 -1
  42. package/dist/components/Dialog/Dialog.d.ts.map +1 -1
  43. package/dist/components/Dialog/Dialog.js +48 -1
  44. package/dist/components/Drawer/Drawer.d.ts +2 -1
  45. package/dist/components/Drawer/Drawer.d.ts.map +1 -1
  46. package/dist/components/Drawer/Drawer.js +4 -4
  47. package/dist/components/EntityPicker/EntityPicker.d.ts +2 -1
  48. package/dist/components/EntityPicker/EntityPicker.d.ts.map +1 -1
  49. package/dist/components/EntityPicker/EntityPicker.js +2 -2
  50. package/dist/components/Flex/Flex.d.ts +5 -1
  51. package/dist/components/Flex/Flex.d.ts.map +1 -1
  52. package/dist/components/Flex/Flex.js +16 -3
  53. package/dist/components/Grid/Grid.d.ts +9 -2
  54. package/dist/components/Grid/Grid.d.ts.map +1 -1
  55. package/dist/components/Grid/Grid.js +22 -1
  56. package/dist/components/IconButton/IconButton.d.ts +19 -7
  57. package/dist/components/IconButton/IconButton.d.ts.map +1 -1
  58. package/dist/components/IconButton/IconButton.js +40 -5
  59. package/dist/components/IconTextButton/IconTextButton.d.ts +20 -0
  60. package/dist/components/IconTextButton/IconTextButton.d.ts.map +1 -0
  61. package/dist/components/IconTextButton/IconTextButton.js +24 -0
  62. package/dist/components/InlineEdit/InlineEdit.d.ts +63 -0
  63. package/dist/components/InlineEdit/InlineEdit.d.ts.map +1 -0
  64. package/dist/components/InlineEdit/InlineEdit.js +98 -0
  65. package/dist/components/LinkButton/LinkButton.d.ts +25 -0
  66. package/dist/components/LinkButton/LinkButton.d.ts.map +1 -0
  67. package/dist/components/LinkButton/LinkButton.js +12 -0
  68. package/dist/components/Modal/Modal.d.ts +29 -6
  69. package/dist/components/Modal/Modal.d.ts.map +1 -1
  70. package/dist/components/Modal/Modal.js +37 -13
  71. package/dist/components/Overlay/OverlayProvider.d.ts +1 -0
  72. package/dist/components/Overlay/OverlayProvider.d.ts.map +1 -1
  73. package/dist/components/Overlay/OverlayProvider.js +18 -1
  74. package/dist/components/PaginatedCombobox/PaginatedCombobox.d.ts +2 -1
  75. package/dist/components/PaginatedCombobox/PaginatedCombobox.d.ts.map +1 -1
  76. package/dist/components/PaginatedCombobox/PaginatedCombobox.js +3 -3
  77. package/dist/components/Popover/Popover.d.ts +37 -3
  78. package/dist/components/Popover/Popover.d.ts.map +1 -1
  79. package/dist/components/Popover/Popover.js +56 -9
  80. package/dist/components/ScrollArea/ScrollArea.d.ts +4 -0
  81. package/dist/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  82. package/dist/components/ScrollArea/ScrollArea.js +30 -4
  83. package/dist/components/Section/Section.d.ts +2 -0
  84. package/dist/components/Section/Section.d.ts.map +1 -1
  85. package/dist/components/SegmentedControl/SegmentedControl.d.ts +24 -1
  86. package/dist/components/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  87. package/dist/components/SegmentedControl/SegmentedControl.js +28 -2
  88. package/dist/components/Select/Select.d.ts +36 -4
  89. package/dist/components/Select/Select.d.ts.map +1 -1
  90. package/dist/components/Select/Select.js +70 -3
  91. package/dist/components/Separator/Separator.d.ts +3 -1
  92. package/dist/components/Separator/Separator.d.ts.map +1 -1
  93. package/dist/components/Separator/Separator.js +4 -2
  94. package/dist/components/SpecialModal/SpecialModal.d.ts +43 -0
  95. package/dist/components/SpecialModal/SpecialModal.d.ts.map +1 -0
  96. package/dist/components/SpecialModal/SpecialModal.js +34 -0
  97. package/dist/components/Spinner/Spinner.d.ts +3 -1
  98. package/dist/components/Spinner/Spinner.d.ts.map +1 -1
  99. package/dist/components/Spinner/Spinner.js +2 -2
  100. package/dist/components/State/State.d.ts +8 -1
  101. package/dist/components/State/State.d.ts.map +1 -1
  102. package/dist/components/State/State.js +2 -2
  103. package/dist/components/Switch/Switch.d.ts +2 -0
  104. package/dist/components/Switch/Switch.d.ts.map +1 -1
  105. package/dist/components/Switch/Switch.js +2 -1
  106. package/dist/components/Table/Table.d.ts +64 -0
  107. package/dist/components/Table/Table.d.ts.map +1 -0
  108. package/dist/components/Table/Table.js +38 -0
  109. package/dist/components/Tabs/Tabs.d.ts +33 -2
  110. package/dist/components/Tabs/Tabs.d.ts.map +1 -1
  111. package/dist/components/Tabs/Tabs.js +201 -5
  112. package/dist/components/Text/Text.d.ts +13 -3
  113. package/dist/components/Text/Text.d.ts.map +1 -1
  114. package/dist/components/Text/Text.js +16 -3
  115. package/dist/components/TextArea/TextArea.d.ts.map +1 -1
  116. package/dist/components/TextArea/TextArea.js +1 -1
  117. package/dist/components/TextField/TextField.d.ts.map +1 -1
  118. package/dist/components/TextField/TextField.js +1 -1
  119. package/dist/components/Toast/Toast.d.ts +1 -4
  120. package/dist/components/Toast/Toast.d.ts.map +1 -1
  121. package/dist/components/Toast/Toast.js +72 -37
  122. package/dist/components/Tooltip/Tooltip.d.ts +11 -3
  123. package/dist/components/Tooltip/Tooltip.d.ts.map +1 -1
  124. package/dist/components/Tooltip/Tooltip.js +58 -9
  125. package/dist/example/CodePreview.d.ts +2 -1
  126. package/dist/example/CodePreview.d.ts.map +1 -1
  127. package/dist/example/CodePreview.js +16 -51
  128. package/dist/example/ExampleActionsSection.d.ts.map +1 -1
  129. package/dist/example/ExampleActionsSection.js +3 -3
  130. package/dist/example/ExampleApplicationSection.d.ts +7 -0
  131. package/dist/example/ExampleApplicationSection.d.ts.map +1 -0
  132. package/dist/example/ExampleApplicationSection.js +88 -0
  133. package/dist/example/ExampleBasicsSections.d.ts +1 -1
  134. package/dist/example/ExampleBasicsSections.d.ts.map +1 -1
  135. package/dist/example/ExampleBasicsSections.js +15 -13
  136. package/dist/example/ExampleDataSection.d.ts.map +1 -1
  137. package/dist/example/ExampleDataSection.js +31 -30
  138. package/dist/example/ExampleFieldsSection.d.ts.map +1 -1
  139. package/dist/example/ExampleFieldsSection.js +51 -3
  140. package/dist/example/ExampleFoundationsSection.js +1 -1
  141. package/dist/example/ExampleOverlays.d.ts.map +1 -1
  142. package/dist/example/ExampleOverlays.js +7 -2
  143. package/dist/example/ExampleOverlaysSection.d.ts.map +1 -1
  144. package/dist/example/ExampleOverlaysSection.js +20 -30
  145. package/dist/example/ExampleSelectionSection.d.ts +3 -1
  146. package/dist/example/ExampleSelectionSection.d.ts.map +1 -1
  147. package/dist/example/ExampleSelectionSection.js +10 -3
  148. package/dist/example/ExampleStateSection.d.ts +3 -0
  149. package/dist/example/ExampleStateSection.d.ts.map +1 -1
  150. package/dist/example/ExampleStateSection.js +65 -9
  151. package/dist/example/ExampleThemePlayground.d.ts +84 -54
  152. package/dist/example/ExampleThemePlayground.d.ts.map +1 -1
  153. package/dist/example/ExampleThemePlayground.js +129 -63
  154. package/dist/example/UiExamplePage.d.ts.map +1 -1
  155. package/dist/example/UiExamplePage.js +39 -19
  156. package/dist/example/codeSamples.d.ts +8 -1
  157. package/dist/example/codeSamples.d.ts.map +1 -1
  158. package/dist/example/codeSamples.js +590 -119
  159. package/dist/example/exampleData.d.ts.map +1 -1
  160. package/dist/example/exampleData.js +18 -10
  161. package/dist/example/styles.css +277 -146
  162. package/dist/hooks/useFloatingPosition.js +1 -1
  163. package/dist/hooks/usePresence.d.ts.map +1 -1
  164. package/dist/hooks/usePresence.js +9 -7
  165. package/dist/index.d.ts +9 -1
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.js +9 -1
  168. package/dist/styles/orcestr-ui.css +3002 -872
  169. package/dist/theme/ThemeProvider.d.ts.map +1 -1
  170. package/dist/theme/ThemeProvider.js +109 -53
  171. package/dist/theme/defaultTheme.d.ts.map +1 -1
  172. package/dist/theme/defaultTheme.js +356 -223
  173. package/dist/theme/systemProps.d.ts +48 -28
  174. package/dist/theme/systemProps.d.ts.map +1 -1
  175. package/dist/theme/systemProps.js +103 -1
  176. package/dist/theme/themeTypes.d.ts +44 -35
  177. package/dist/theme/themeTypes.d.ts.map +1 -1
  178. package/dist/utils/slot.d.ts +11 -0
  179. package/dist/utils/slot.d.ts.map +1 -0
  180. package/dist/utils/slot.js +18 -0
  181. package/package.json +4 -1
  182. package/dist/components/Workflow/Workflow.d.ts +0 -82
  183. package/dist/components/Workflow/Workflow.d.ts.map +0 -1
  184. package/dist/components/Workflow/Workflow.js +0 -73
@@ -1,10 +1,10 @@
1
1
  export const codeSamples = {
2
- typography: `import {Badge, Box, Flex, Stack, Text} from '@orcestr/ui';
2
+ text: `import {Badge, Box, Flex, Stack, Text} from '@orcestr/ui';
3
3
 
4
4
  <Stack g={3}>
5
5
  <Stack g={1}>
6
6
  <Text as='h1' fs='28px' fw={780} lh={1.1}>
7
- Workflow review
7
+ Operations review
8
8
  </Text>
9
9
  <Text as='h2' fs='20px' fw={720} lh={1.2}>
10
10
  Review window and status
@@ -21,22 +21,22 @@ export const codeSamples = {
21
21
  </Stack>
22
22
 
23
23
  <Flex g={2} wrap>
24
- <Text tone='brand' fw={700}>Brand</Text>
24
+ <Text tone='primary' fw={700}>Primary</Text>
25
25
  <Text tone='success' fw={700}>Success</Text>
26
26
  <Text tone='warning' fw={700}>Warning</Text>
27
27
  <Text tone='danger' fw={700}>Danger</Text>
28
28
  <Text tone='info' fw={700}>Info</Text>
29
29
  </Flex>
30
30
 
31
- <Box w='100%' p={2} r={3}>
31
+ <Box w='100%' p={2} r={3} style={{background: 'var(--oui-gray-a3)'}}>
32
32
  <Text display='block' truncate>
33
- This is a long single line value that truncates cleanly.
33
+ This is a long single line value that truncates cleanly inside a constrained row.
34
34
  </Text>
35
35
  </Box>
36
36
 
37
37
  <Flex g={2} wrap>
38
38
  <Badge>Neutral</Badge>
39
- <Badge tone='brand'>Brand</Badge>
39
+ <Badge tone='primary'>Primary</Badge>
40
40
  <Badge tone='success'>Success</Badge>
41
41
  <Badge tone='warning'>Warning</Badge>
42
42
  <Badge tone='danger'>Danger</Badge>
@@ -50,57 +50,143 @@ export const codeSamples = {
50
50
  <Skeleton h={16} w='64%' />
51
51
  <Skeleton h={36} />
52
52
  </Stack>`,
53
- appShell: `import {
53
+ appShell: `import {useState} from 'react';
54
+ import {
54
55
  AppShell,
55
56
  AppShellContent,
56
57
  AppShellHeader,
57
- AppShellNav,
58
- AppShellSidebar,
58
+ type AppShellSide,
59
+ AppSidebar,
59
60
  Button,
60
- OrcestrUiProvider,
61
- Stack,
62
- Text,
61
+ Flex,
62
+ IconButton,
63
+ IconTextButton,
64
+ Menu,
65
+ PageTitleBlock,
66
+ SpecialModal,
67
+ Tooltip,
68
+ type MenuItem,
63
69
  } from '@orcestr/ui';
70
+ import {LuArrowLeft, LuArrowLeftRight, LuBell, LuBox, LuCalendar, LuCheck, LuClipboardList, LuEllipsis, LuLanguages, LuMessageSquare, LuSearch, LuTruck} from 'react-icons/lu';
64
71
 
65
- <OrcestrUiProvider surface='operations' locale='ru'>
66
- <AppShell
67
- sidebarOpen={mobileOpen}
68
- onSidebarOpenChange={setMobileOpen}
69
- header={
70
- <AppShellHeader
71
- visibility='mobile'
72
- title='Operations'
72
+ const [open, setOpen] = useState(false);
73
+ const [mobileOpen, setMobileOpen] = useState(false);
74
+ const [previewMode, setPreviewMode] = useState<'desktop' | 'phone'>('desktop');
75
+ const [sidebarSide, setSidebarSide] = useState<AppShellSide>('left');
76
+ const [activeKey, setActiveKey] = useState('requests');
77
+ const [locale, setLocale] = useState<'ru' | 'en'>('en');
78
+ const isPhone = previewMode === 'phone';
79
+ const isRight = sidebarSide === 'right';
80
+ const toggleSidebarSide = () => {
81
+ setSidebarSide((side) => side === 'left' ? 'right' : 'left');
82
+ };
83
+
84
+ const groups = [
85
+ {
86
+ key: 'demand',
87
+ items: [
88
+ {key: 'requests', label: 'Requests', icon: <LuTruck />, active: activeKey === 'requests'},
89
+ {key: 'orders', label: 'Supplier orders', icon: <LuClipboardList />, active: activeKey === 'orders'},
90
+ ],
91
+ },
92
+ {
93
+ key: 'operations',
94
+ items: [
95
+ {key: 'products', label: 'Products', icon: <LuBox />, active: activeKey === 'products'},
96
+ {key: 'calendar', label: 'Calendar', icon: <LuCalendar />, active: activeKey === 'calendar'},
97
+ ],
98
+ },
99
+ ];
100
+ const languageItems: MenuItem[] = [
101
+ {key: 'ru', label: 'RU', icon: locale === 'ru' ? <LuCheck /> : undefined, onSelect: () => setLocale('ru')},
102
+ {key: 'en', label: 'EN', icon: locale === 'en' ? <LuCheck /> : undefined, onSelect: () => setLocale('en')},
103
+ ];
104
+
105
+ <>
106
+ <Button onClick={() => setOpen(true)}>Open AppShell preview</Button>
107
+ <SpecialModal open={open} onOpenChange={setOpen} size='full' scroll='body'>
108
+ <SpecialModal.Header
109
+ title='AppShell preview'
110
+ actions={(
111
+ <>
112
+ <Button size={2} v='surface' onClick={() => setPreviewMode((mode) => mode === 'desktop' ? 'phone' : 'desktop')}>
113
+ Toggle preview
114
+ </Button>
115
+ <SpecialModal.Close />
116
+ </>
117
+ )}
118
+ />
119
+ <SpecialModal.Body>
120
+ <AppShell
121
+ sidebarMode={isPhone ? 'mobile' : 'desktop'}
122
+ sidebarSide={sidebarSide}
73
123
  sidebarOpen={mobileOpen}
124
+ desktopSidebarOpen
74
125
  onSidebarOpenChange={setMobileOpen}
75
- actions={<Button size={1}>Create</Button>}
76
- />
77
- }
78
- sidebar={
79
- <AppShellSidebar
80
- title='Operations'
81
- description='Operational module shell with themed navigation.'
82
- onClose={() => setMobileOpen(false)}
83
- footer={<Button fullWidth v='surface'>Settings</Button>}
126
+ sidebarWidth={300}
127
+ contentInset={0}
128
+ maxWidth='100%'
129
+ header={(
130
+ <AppShellHeader
131
+ visibility='always'
132
+ sidebarOpen={mobileOpen}
133
+ onSidebarOpenChange={setMobileOpen}
134
+ navigationVisibility='mobile'
135
+ actions={(
136
+ <Flex a='c' g={1}>
137
+ <IconTextButton size={2} v='soft' tone='neutral' icon={<LuSearch />}>Quick jump</IconTextButton>
138
+ <IconButton size={2} v='ghost' icon={<LuBell />} badge={64} aria-label='Notifications' />
139
+ <IconButton size={2} v='ghost' icon={<LuMessageSquare />} badge={99} aria-label='Messages' />
140
+ <Menu
141
+ align='end'
142
+ items={languageItems}
143
+ trigger={<IconButton size={2} v='ghost' icon={<LuLanguages />} aria-label={'Language: ' + locale.toUpperCase()} />}
144
+ />
145
+ </Flex>
146
+ )}
147
+ />
148
+ )}
149
+ sidebar={(
150
+ <AppSidebar
151
+ side={sidebarSide}
152
+ header={(
153
+ <>
154
+ <div className='oui-app-sidebar-brand'><span className='oui-app-sidebar-logo'>O</span><span className='oui-app-sidebar-title'>Deliveries</span></div>
155
+ <div className='oui-app-sidebar-actions'>
156
+ <Tooltip content='Back'>
157
+ <IconButton size={2} v='ghost' icon={<LuArrowLeft />} aria-label='Back' />
158
+ </Tooltip>
159
+ <Tooltip content={isRight ? 'Move sidebar left' : 'Move sidebar right'}>
160
+ <IconButton size={2} v='ghost' icon={<LuArrowLeftRight />} aria-label={isRight ? 'Move sidebar left' : 'Move sidebar right'} onClick={toggleSidebarSide} />
161
+ </Tooltip>
162
+ <IconButton size={2} v='ghost' icon={<LuEllipsis />} aria-label='Sidebar actions' />
163
+ </div>
164
+ </>
165
+ )}
166
+ itemH={38}
167
+ onNavigate={(item) => setActiveKey(item.key)}
168
+ groups={groups}
169
+ />
170
+ )}
84
171
  >
85
- <AppShellNav items={navigationItems} />
86
- </AppShellSidebar>
87
- }
88
- >
89
- <AppShellContent>
90
- <Stack g={1}>
91
- <Text as='h1' fs='22px' fw={760}>Queue</Text>
92
- <Text tone='muted'>Daily workspace operations and status movement.</Text>
93
- </Stack>
94
- {children}
95
- </AppShellContent>
96
- </AppShell>
97
- </OrcestrUiProvider>`,
172
+ <AppShellContent scroll={false}>
173
+ <PageTitleBlock
174
+ title='Requests'
175
+ caption='Module workspace with responsive header and AppSidebar navigation.'
176
+ action={<IconButton size={2} v='pad' icon={<LuEllipsis />} aria-label='More actions' />}
177
+ />
178
+ {children}
179
+ </AppShellContent>
180
+ </AppShell>
181
+ </SpecialModal.Body>
182
+ </SpecialModal>
183
+ </>`,
98
184
  layoutFlex: `import {Badge, Button, Flex, Text} from '@orcestr/ui';
99
185
 
100
186
  <Flex col g={3}>
101
187
  <Flex row g={2} a='c' j='sb' wrap>
102
188
  <Flex row g={2} a='c' wrap>
103
- <Badge tone='brand'>status</Badge>
189
+ <Badge tone='primary'>status</Badge>
104
190
  <Text fw={700}>Task TASK-2048</Text>
105
191
  </Flex>
106
192
  <Flex row g={1} a='c'>
@@ -110,23 +196,50 @@ export const codeSamples = {
110
196
  </Flex>
111
197
  <Flex row g={2} wrap>
112
198
  {['Intake', 'Review', 'Complete'].map((item, index) => (
113
- <Flex key={item} col g={1} p={2} r={3} flex='1 1 150px'>
199
+ <Flex
200
+ key={item}
201
+ col
202
+ g={1}
203
+ p={2}
204
+ r={3}
205
+ flex='1 1 150px'
206
+ style={{background: 'var(--oui-gray-a3)'}}
207
+ >
114
208
  <Text fs='12px' tone='muted'>Step {index + 1}</Text>
115
209
  <Text fw={700}>{item}</Text>
116
210
  </Flex>
117
211
  ))}
118
212
  </Flex>
119
213
  </Flex>`,
120
- layoutStack: `import {Box, Flex, Stack, Text} from '@orcestr/ui';
214
+ layoutStack: `import {Flex, Stack, Text} from '@orcestr/ui';
121
215
 
122
216
  <Stack g={2}>
123
217
  {[
124
- ['Created', 'Draft created from intake'],
125
- ['Reserved', 'Capacity is reserved for review'],
126
- ['Scheduled', 'Review window is confirmed'],
127
- ].map(([title, description]) => (
128
- <Flex key={title} row g={2} p={2} r={3} a='s'>
129
- <Box size={8} r={7} mt={1} />
218
+ ['/gallery/cyberpunk-rain.webp', 'Created', 'Draft created from intake'],
219
+ ['/gallery/hollywood-star.webp', 'Reserved', 'Capacity is reserved for review'],
220
+ ['/gallery/ice-cave.webp', 'Scheduled', 'Review window is confirmed'],
221
+ ].map(([image, title, description]) => (
222
+ <Flex
223
+ key={title}
224
+ row
225
+ g={2}
226
+ a='c'
227
+ w='min(100%, 360px)'
228
+ p='8px 10px'
229
+ r={2}
230
+ style={{background: 'var(--oui-gray-a3)'}}
231
+ >
232
+ <img
233
+ src={image}
234
+ alt=''
235
+ style={{
236
+ width: 34,
237
+ height: 34,
238
+ flex: '0 0 34px',
239
+ borderRadius: 999,
240
+ objectFit: 'cover',
241
+ }}
242
+ />
130
243
  <Stack g={0}>
131
244
  <Text fs='13px' fw={700}>{title}</Text>
132
245
  <Text fs='12px' tone='muted' lh={1.45}>{description}</Text>
@@ -147,7 +260,7 @@ const [detailsOpen, setDetailsOpen] = useState(true);
147
260
  </Button>
148
261
  </Flex>
149
262
  <Collapse open={detailsOpen}>
150
- <Stack g={2} p={2} r={3}>
263
+ <Stack g={2} p={2} r={3} style={{background: 'var(--oui-gray-a3)'}}>
151
264
  <Flex row g={2} j='sb'>
152
265
  <Text tone='muted'>Owner</Text>
153
266
  <Text fw={700}>Core team</Text>
@@ -167,7 +280,7 @@ const [detailsOpen, setDetailsOpen] = useState(true);
167
280
 
168
281
  <Grid columns='repeat(3, minmax(0, 1fr))' g={2}>
169
282
  {['A', 'B', 'C', 'D', 'E', 'F'].map((item) => (
170
- <Box key={item} p={2} r={3} ta='center'>
283
+ <Box key={item} p={2} r={3} ta='center' style={{background: 'var(--oui-gray-a3)'}}>
171
284
  <Text fs='13px' fw={700}>{item}</Text>
172
285
  </Box>
173
286
  ))}
@@ -193,11 +306,29 @@ const [detailsOpen, setDetailsOpen] = useState(true);
193
306
  position='absolute'
194
307
  />
195
308
  </div>`,
196
- scrollArea: `import {Badge, Flex, ScrollArea, Stack, Text} from '@orcestr/ui';
309
+ scrollArea: `import {Badge, Box, Flex, ScrollArea, Stack, Text} from '@orcestr/ui';
310
+
311
+ const scrollRows = Array.from({length: 10}, (_, index) => index + 1);
312
+ const richRows = [
313
+ ['Queued', 'No top shade at the initial position.'],
314
+ ['Reserved', 'The top shade starts after 50px.'],
315
+ ['Packed', 'Opacity reaches maximum over 160px.'],
316
+ ['Labeled', 'Bottom shade fades near the end.'],
317
+ ['Reviewed', 'Each edge has its own configuration.'],
318
+ ['Delivered', 'The gradient uses the solid surface color.'],
319
+ ['Checked', 'Content remains readable under the fade.'],
320
+ ['Archived', 'The bottom edge disappears at the end.'],
321
+ ];
197
322
 
198
323
  <Stack g={2}>
199
324
  <ScrollArea h={116} pr={1}>
200
- <Stack g={1}>{rows}</Stack>
325
+ <Stack g={1}>
326
+ {scrollRows.map((row) => (
327
+ <Box key={row} p={2} r={3} style={{background: 'var(--oui-gray-a3)'}}>
328
+ <Text fs='13px'>Scroll row {row}</Text>
329
+ </Box>
330
+ ))}
331
+ </Stack>
201
332
  </ScrollArea>
202
333
 
203
334
  <ScrollArea
@@ -208,7 +339,13 @@ const [detailsOpen, setDetailsOpen] = useState(true);
208
339
  highlightTop={{h: 28, mode: 'static', maxOpacity: 0.96}}
209
340
  highlightBottom={{h: 28, mode: 'static', maxOpacity: 0.96}}
210
341
  >
211
- <Stack g={1}>{rows}</Stack>
342
+ <Stack g={1}>
343
+ {scrollRows.slice(0, 8).map((row) => (
344
+ <Box key={row} p={2} r={3} style={{background: 'var(--oui-gray-a3)'}}>
345
+ <Text fs='13px'>Both edges row {row}</Text>
346
+ </Box>
347
+ ))}
348
+ </Stack>
212
349
  </ScrollArea>
213
350
 
214
351
  <ScrollArea
@@ -232,14 +369,22 @@ const [detailsOpen, setDetailsOpen] = useState(true);
232
369
  }}
233
370
  >
234
371
  <Stack g={1}>
235
- {rows.map((row, index) => (
236
- <Flex key={row.id} row g={2} p={2} r={3} a='c'>
237
- <Badge tone={index < 3 ? 'brand' : 'info'}>
372
+ {richRows.map(([title, description], index) => (
373
+ <Flex
374
+ key={title}
375
+ row
376
+ g={2}
377
+ p={2}
378
+ r={3}
379
+ a='c'
380
+ style={{background: 'var(--oui-gray-a3)'}}
381
+ >
382
+ <Badge tone={index < 3 ? 'primary' : 'info'}>
238
383
  {index + 1}
239
384
  </Badge>
240
385
  <Stack g={0}>
241
- <Text fs='13px' fw={700}>{row.title}</Text>
242
- <Text fs='12px' tone='muted'>{row.description}</Text>
386
+ <Text fs='13px' fw={700}>{title}</Text>
387
+ <Text fs='12px' tone='muted'>{description}</Text>
243
388
  </Stack>
244
389
  </Flex>
245
390
  ))}
@@ -250,15 +395,51 @@ const [detailsOpen, setDetailsOpen] = useState(true);
250
395
 
251
396
  <Flex g={2} a='c' wrap>
252
397
  {[0, 2, 4, 6, 7].map((radius) => (
253
- <Box key={radius} size={32} r={radius} display='flex' a='c' j='c'>
254
- <Text fs='12px'>{radius}</Text>
398
+ <Box
399
+ key={radius}
400
+ size={32}
401
+ r={radius}
402
+ display='flex'
403
+ a='c'
404
+ j='c'
405
+ style={{background: 'var(--oui-gray-a3)'}}
406
+ >
407
+ <Text fs='12px' fw={700}>{radius}</Text>
255
408
  </Box>
256
409
  ))}
257
410
  </Flex>
258
411
  <Button mt={2} v='pad' r={7}>
259
412
  Button r=7
260
413
  </Button>`,
261
- buttons: `import {Button, Spinner} from '@orcestr/ui';
414
+ surfaces: `import {Alert, Button, Card, Grid, Section, Separator, Stack, Text} from '@orcestr/ui';
415
+
416
+ <Section g={3}>
417
+ <Grid columns='repeat(auto-fit, minmax(min(100%, 180px), 1fr))' g={2}>
418
+ <Card v='surface' interactive>
419
+ <Stack g={1}>
420
+ <Text fw={760}>Surface card</Text>
421
+ <Text fs='12px' tone='muted'>Default operational surface.</Text>
422
+ </Stack>
423
+ </Card>
424
+ <Card v='soft'>
425
+ <Stack g={1}>
426
+ <Text fw={760}>Soft card</Text>
427
+ <Text fs='12px' tone='muted'>Quiet grouped content.</Text>
428
+ </Stack>
429
+ </Card>
430
+ <Card v='classic'>
431
+ <Stack g={1}>
432
+ <Text fw={760}>Classic card</Text>
433
+ <Text fs='12px' tone='muted'>More explicit border and background.</Text>
434
+ </Stack>
435
+ </Card>
436
+ </Grid>
437
+ <Separator />
438
+ <Alert title='Inventory sync delayed' action={<Button size={1} v='surface'>Retry</Button>}>
439
+ Check this status before creating the next shipment.
440
+ </Alert>
441
+ </Section>`,
442
+ buttons: `import {Button, CopyButton, CopyIconButton, Spinner} from '@orcestr/ui';
262
443
  import {LuCheck, LuInfo, LuTrash2, LuTriangleAlert} from 'react-icons/lu';
263
444
 
264
445
  <Button size={3}>Solid</Button>
@@ -290,27 +471,58 @@ import {LuCheck, LuInfo, LuTrash2, LuTriangleAlert} from 'react-icons/lu';
290
471
  <Button v='surface' pressAnimation='soft'>Press soft</Button>
291
472
  <Button v='surface' pressAnimation='none'>Press none</Button>
292
473
 
474
+ <CopyButton
475
+ text='https://orcestr.dev/requests/PR-2026-0900'
476
+ label='Copy link'
477
+ successMessage='Link copied'
478
+ v='surface'
479
+ />
480
+ <CopyIconButton
481
+ text='PR-2026-0900'
482
+ label='Copy request number'
483
+ successMessage='Request number copied'
484
+ v='surface'
485
+ />
486
+
293
487
  <Button size={3} loading>Loading</Button>
294
488
  <Button size={3} v='surface' loading leftIcon={<LuCheck size={16} />}>Save</Button>
295
489
  <Button size={3} tone='success' loading leftIcon={<LuCheck size={16} />}>Success</Button>
296
490
  <Spinner />`,
297
491
  iconButtons: `import {Button, IconButton, Menu, Tooltip} from '@orcestr/ui';
298
- import {LuBell, LuCheck, LuCommand, LuEllipsis, LuInfo} from 'react-icons/lu';
492
+ import {
493
+ LuBell,
494
+ LuCheck,
495
+ LuCommand,
496
+ LuDownload,
497
+ LuEllipsis,
498
+ LuInfo,
499
+ LuMessageSquare,
500
+ LuRefreshCw,
501
+ LuSearch,
502
+ LuSettings,
503
+ LuShield,
504
+ LuUpload,
505
+ } from 'react-icons/lu';
299
506
 
300
507
  <IconButton v='solid' icon={<LuCheck size={17} />} aria-label='Solid icon' />
301
- <IconButton v='soft' icon={<LuBell size={17} />} aria-label='Soft icon' />
302
- <IconButton v='surface' icon={<LuBell size={17} />} aria-label='Surface icon' />
303
- <IconButton v='pad' icon={<LuBell size={17} />} aria-label='Pad icon' />
508
+ <IconButton v='soft' icon={<LuSearch size={17} />} aria-label='Search icon' />
509
+ <IconButton v='surface' icon={<LuUpload size={17} />} aria-label='Upload icon' />
510
+ <IconButton v='pad' icon={<LuShield size={17} />} aria-label='Security icon' />
304
511
  <IconButton v='outline' icon={<LuInfo size={17} />} aria-label='Outline icon' />
305
512
  <IconButton v='ghost' icon={<LuEllipsis size={17} />} aria-label='Ghost icon' />
306
513
 
307
- <IconButton size={1} v='surface' icon={<LuBell size={13} />} aria-label='Size 1 icon' />
308
- <IconButton size={2} v='surface' icon={<LuBell size={15} />} aria-label='Size 2 icon' />
309
- <IconButton size={3} v='surface' icon={<LuBell size={17} />} aria-label='Size 3 icon' />
310
- <IconButton size={4} v='surface' icon={<LuBell size={19} />} aria-label='Size 4 icon' />
514
+ <IconButton size={1} v='surface' icon={<LuSearch size={13} />} aria-label='Size 1 search' />
515
+ <IconButton size={2} v='surface' icon={<LuDownload size={15} />} aria-label='Size 2 download' />
516
+ <IconButton size={3} v='surface' icon={<LuRefreshCw size={17} />} aria-label='Size 3 refresh' />
517
+ <IconButton size={4} v='surface' icon={<LuSettings size={19} />} aria-label='Size 4 settings' />
311
518
 
312
519
  <IconButton size={3} v='pad' round={false} r={3} icon={<LuCommand size={17} />} aria-label='Square pad icon' />
313
- <IconButton size={3} v='outline' loading icon={<LuBell size={17} />} aria-label='Loading icon' />
520
+ <IconButton size={3} v='outline' loading icon={<LuRefreshCw size={17} />} aria-label='Loading icon' />
521
+
522
+ <IconButton v='surface' icon={<LuBell size={17} />} badge={64} aria-label='Notifications' />
523
+ <IconButton v='surface' icon={<LuMessageSquare size={17} />} badge={99} aria-label='Unread chats' />
524
+ <IconButton v='pad' icon={<LuShield size={17} />} badge={3} badgeTone='warning' aria-label='Security warnings' />
525
+ <IconButton v='ghost' icon={<LuDownload size={17} />} badge='new' badgeTone='info' aria-label='New export' />
314
526
 
315
527
  <IconButton size={1} v='ghost' icon={<LuEllipsis size={13} />} aria-label='Ghost size 1' />
316
528
  <IconButton size={2} v='ghost' icon={<LuEllipsis size={15} />} aria-label='Ghost size 2' />
@@ -318,10 +530,10 @@ import {LuBell, LuCheck, LuCommand, LuEllipsis, LuInfo} from 'react-icons/lu';
318
530
  <IconButton size={4} v='ghost' icon={<LuEllipsis size={19} />} aria-label='Ghost size 4' />
319
531
 
320
532
  <Tooltip content='Notifications'>
321
- <IconButton v='surface' icon={<LuBell size={17} />} aria-label='Notifications' />
533
+ <IconButton v='surface' icon={<LuBell size={17} />} badge={8} aria-label='Notifications' />
322
534
  </Tooltip>
323
- <IconButton v='surface' loading icon={<LuBell size={17} />} aria-label='Loading action' />
324
- <IconButton v='pad' icon={<LuBell size={17} />} aria-label='Pad action' />
535
+ <IconButton v='surface' loading icon={<LuRefreshCw size={17} />} aria-label='Loading action' />
536
+ <IconButton v='pad' icon={<LuSettings size={17} />} aria-label='Pad action' />
325
537
  <Menu
326
538
  trigger={<IconButton v='surface' icon={<LuEllipsis size={17} />} aria-label='Actions' />}
327
539
  items={menuItems}
@@ -329,6 +541,35 @@ import {LuBell, LuCheck, LuCommand, LuEllipsis, LuInfo} from 'react-icons/lu';
329
541
  <Button v='surface' leftIcon={<LuCommand size={16} />} onClick={openPalette}>
330
542
  Commands
331
543
  </Button>`,
544
+ iconTextButton: `import {IconTextButton} from '@orcestr/ui';
545
+ import {LuCopy, LuExternalLink, LuPackagePlus} from 'react-icons/lu';
546
+
547
+ <IconTextButton icon={<LuPackagePlus size={16} />}>
548
+ Create PO
549
+ </IconTextButton>
550
+ <IconTextButton v='soft' tone='info' icon={<LuCopy size={16} />}>
551
+ Duplicate
552
+ </IconTextButton>
553
+ <IconTextButton href='/requests' v='surface' icon={<LuExternalLink size={16} />}>
554
+ Link action
555
+ </IconTextButton>
556
+ <IconTextButton v='outline' iconSide='end' icon={<LuExternalLink size={16} />}>
557
+ Open details
558
+ </IconTextButton>`,
559
+ contextMenu: `import {ContextMenu, Text, type MenuItem} from '@orcestr/ui';
560
+
561
+ const items: MenuItem[] = [
562
+ {key: 'open', label: 'Open'},
563
+ {key: 'copy', label: 'Copy link'},
564
+ {key: 'delete', label: 'Delete', tone: 'danger', separatorBefore: true},
565
+ ];
566
+
567
+ <ContextMenu items={items}>
568
+ <div className='row'>
569
+ <Text fs='13px' fw={760}>Right-click this row</Text>
570
+ <Text fs='12px' tone='muted'>Context menu reuses Menu item styling.</Text>
571
+ </div>
572
+ </ContextMenu>`,
332
573
  textFields: `import {Button, Flex, Field, TextArea, TextField} from '@orcestr/ui';
333
574
  import {LuSearch} from 'react-icons/lu';
334
575
 
@@ -346,6 +587,120 @@ import {LuSearch} from 'react-icons/lu';
346
587
  <Field label='Comment'>
347
588
  <TextArea rows={4} placeholder='Internal note' />
348
589
  </Field>`,
590
+ inlineEdit: `import {useState} from 'react';
591
+ import {Badge, Field, IconButton, InlineEditField, InlineEditMultiField, Listbox, Popover, Stack} from '@orcestr/ui';
592
+ import {LuCheck, LuPencil} from 'react-icons/lu';
593
+
594
+ const [supplierOpen, setSupplierOpen] = useState(false);
595
+ const [paymentOpen, setPaymentOpen] = useState(false);
596
+ const [supplierKey, setSupplierKey] = useState('northwind');
597
+ const [paymentTermKey, setPaymentTermKey] = useState('net30');
598
+ const [ownerOpen, setOwnerOpen] = useState(false);
599
+ const [ownerKeys, setOwnerKeys] = useState(['michael', 'team']);
600
+ const supplier = suppliers.find((item) => item.key === supplierKey);
601
+ const paymentTerm = paymentTerms.find((item) => item.key === paymentTermKey);
602
+ const selectedOwners = owners.filter((item) => ownerKeys.includes(item.key));
603
+ const toggleOwner = (key) => {
604
+ setOwnerKeys((current) =>
605
+ current.includes(key)
606
+ ? current.filter((item) => item !== key)
607
+ : [...current, key],
608
+ );
609
+ };
610
+
611
+ <Stack g={3}>
612
+ <Field label='Single value'>
613
+ <InlineEditField
614
+ label={supplier?.label ?? 'Choose supplier'}
615
+ meta='Supplier'
616
+ onOpen={() => setSupplierOpen(true)}
617
+ action={
618
+ <Popover
619
+ open={supplierOpen}
620
+ onOpenChange={setSupplierOpen}
621
+ trigger={<IconButton size={1} v='ghost' icon={<LuPencil size={13} />} />}
622
+ className='oui-combobox-content'
623
+ >
624
+ <Listbox
625
+ className='oui-combobox-options'
626
+ items={suppliers.map((item) => ({value: item.key, label: item.label}))}
627
+ value={supplierKey}
628
+ onValueChange={(next) => {
629
+ setSupplierKey(next);
630
+ setSupplierOpen(false);
631
+ }}
632
+ />
633
+ </Popover>
634
+ }
635
+ />
636
+ </Field>
637
+ <Field label='Single value without meta'>
638
+ <InlineEditField
639
+ label={paymentTerm?.label ?? 'Choose payment terms'}
640
+ onOpen={() => setPaymentOpen(true)}
641
+ action={
642
+ <Popover
643
+ open={paymentOpen}
644
+ onOpenChange={setPaymentOpen}
645
+ trigger={<IconButton size={1} v='ghost' icon={<LuPencil size={13} />} />}
646
+ className='oui-combobox-content'
647
+ >
648
+ <Listbox
649
+ className='oui-combobox-options'
650
+ items={paymentTerms.map((item) => ({value: item.key, label: item.label}))}
651
+ value={paymentTermKey}
652
+ onValueChange={(next) => {
653
+ setPaymentTermKey(next);
654
+ setPaymentOpen(false);
655
+ }}
656
+ />
657
+ </Popover>
658
+ }
659
+ />
660
+ </Field>
661
+ <Field label='Multiple values'>
662
+ <InlineEditMultiField
663
+ onOpen={() => setOwnerOpen(true)}
664
+ action={(
665
+ <span onClick={(event) => event.stopPropagation()}>
666
+ <Popover
667
+ open={ownerOpen}
668
+ onOpenChange={setOwnerOpen}
669
+ trigger={<IconButton size={1} v='ghost' icon={<LuPencil size={13} />} />}
670
+ className='oui-combobox-content'
671
+ >
672
+ <Stack g={1} p={1}>
673
+ {owners.map((item) => {
674
+ const selected = ownerKeys.includes(item.key);
675
+ return (
676
+ <button
677
+ key={item.key}
678
+ type='button'
679
+ className='oui-combobox-option'
680
+ data-selected={selected ? 'true' : 'false'}
681
+ onClick={() => toggleOwner(item.key)}
682
+ >
683
+ <span className='oui-multi-select-check'>
684
+ {selected ? <LuCheck size={13} /> : null}
685
+ </span>
686
+ <span className='oui-combobox-option-main'>
687
+ {item.label}
688
+ </span>
689
+ </button>
690
+ );
691
+ })}
692
+ </Stack>
693
+ </Popover>
694
+ </span>
695
+ )}
696
+ col
697
+ >
698
+ {selectedOwners.map((item) => (
699
+ <Badge key={item.key} tone='neutral' v='soft'>{item.label}</Badge>
700
+ ))}
701
+ </InlineEditMultiField>
702
+ </Field>
703
+ </Stack>`,
349
704
  groupedFields: `import {Button, Flex, Field, Grid, Section, Stack, Text, TextArea, TextField} from '@orcestr/ui';
350
705
 
351
706
  <Section g={3}>
@@ -391,7 +746,7 @@ import {LuSearch} from 'react-icons/lu';
391
746
  today='2026-06-26'
392
747
  onValueChange={setDateRange}
393
748
  />`,
394
- selection: `import {Combobox, EntityPicker, MultiSelect, Select, SegmentedControl} from '@orcestr/ui';
749
+ selection: `import {Combobox, EntityPicker, MultiSelect, PaginatedCombobox, Select, SegmentedControl} from '@orcestr/ui';
395
750
  import {LuPlus} from 'react-icons/lu';
396
751
 
397
752
  <Select items={items} value={status} onValueChange={setStatus} clearable />
@@ -454,6 +809,27 @@ import {LuPlus} from 'react-icons/lu';
454
809
  onClick: addEntity,
455
810
  }}
456
811
  />
812
+ <PaginatedCombobox
813
+ value={paginatedValue}
814
+ onChange={setPaginatedValue}
815
+ loadPage={(page, search) => loadEntityPage(locale, page, search)}
816
+ getItemId={(item) => item.id}
817
+ renderSelectedLabel={(item) => item.article}
818
+ renderOption={(item) => (
819
+ <span className='oui-entity-option-main'>
820
+ <span className='oui-entity-option-code'>{item.article}</span>
821
+ <span className='oui-entity-option-meta'>{item.name}</span>
822
+ </span>
823
+ )}
824
+ placeholder='Paginated combobox'
825
+ clearable
826
+ searchAction={{label: 'Create entity from search', onClick: createEntity}}
827
+ optionAction={{
828
+ icon: <LuPlus size={14} />,
829
+ label: (item) => 'Add ' + item.article,
830
+ onClick: addEntity,
831
+ }}
832
+ />
457
833
  <SegmentedControl
458
834
  items={[
459
835
  {value: 'active', label: 'Active'},
@@ -566,7 +942,7 @@ import {LuChevronDown} from 'react-icons/lu';
566
942
  overlayColor='transparent'
567
943
  overlayOpacity={0}
568
944
  overlayBlur={10}
569
- borderColor='color-mix(in srgb, var(--oui-brand) 34%, var(--oui-border))'
945
+ borderColor='color-mix(in srgb, var(--oui-primary-base) 34%, var(--oui-border))'
570
946
  radius={10}
571
947
  shadow='0 24px 90px rgb(0 0 0 / 44%)'
572
948
  footer={
@@ -595,7 +971,7 @@ import {LuChevronDown} from 'react-icons/lu';
595
971
  overlayColor='transparent'
596
972
  overlayOpacity={0}
597
973
  overlayBlur={8}
598
- borderColor='color-mix(in srgb, var(--oui-brand) 38%, var(--oui-border))'
974
+ borderColor='color-mix(in srgb, var(--oui-primary-base) 38%, var(--oui-border))'
599
975
  radius={10}
600
976
  footer={
601
977
  <Flex g={2} j='e' w='100%'>
@@ -619,7 +995,7 @@ import {LuChevronDown} from 'react-icons/lu';
619
995
  overlayColor='transparent'
620
996
  overlayOpacity={0}
621
997
  overlayBlur={6}
622
- borderColor='color-mix(in srgb, var(--oui-brand) 42%, var(--oui-border))'
998
+ borderColor='color-mix(in srgb, var(--oui-primary-base) 42%, var(--oui-border))'
623
999
  radius={10}
624
1000
  >
625
1001
  <Stack g={3}>
@@ -657,7 +1033,7 @@ import {LuChevronDown} from 'react-icons/lu';
657
1033
  overlayOpacity={0}
658
1034
  overlayBlur={14}
659
1035
  animationDuration='1200ms'
660
- borderColor='color-mix(in srgb, var(--oui-brand) 42%, var(--oui-border))'
1036
+ borderColor='color-mix(in srgb, var(--oui-primary-base) 42%, var(--oui-border))'
661
1037
  radius={10}
662
1038
  >
663
1039
  <Stack g={3}>
@@ -692,7 +1068,7 @@ import {LuChevronDown} from 'react-icons/lu';
692
1068
  overlayColor='#3b0712'
693
1069
  overlayOpacity={0.48}
694
1070
  overlayBlur={3}
695
- borderColor='color-mix(in srgb, var(--oui-danger) 46%, var(--oui-border))'
1071
+ borderColor='color-mix(in srgb, var(--oui-danger-base) 46%, var(--oui-border))'
696
1072
  radius={8}
697
1073
  footer={
698
1074
  <Flex g={2} j='e' w='100%'>
@@ -714,10 +1090,10 @@ import {LuChevronDown} from 'react-icons/lu';
714
1090
  {
715
1091
  key: 'create-record',
716
1092
  label: 'Create record',
717
- description: 'Start a workflow.',
1093
+ description: 'Start a new record.',
718
1094
  shortcut: 'C',
719
1095
  group: 'Create',
720
- keywords: ['new', 'workflow'],
1096
+ keywords: ['new', 'record'],
721
1097
  onSelect: () => toast.info('Create record action'),
722
1098
  },
723
1099
  ]}
@@ -740,6 +1116,19 @@ const toast = useToast();
740
1116
  >
741
1117
  Success
742
1118
  </Button>
1119
+ <Button
1120
+ onClick={() =>
1121
+ toast.success({
1122
+ title: 'Endless',
1123
+ message: 'This success toast stays until you click it.',
1124
+ position: 'bottom-right',
1125
+ duration: null,
1126
+ dedupeKey: 'endless-success-toast',
1127
+ })
1128
+ }
1129
+ >
1130
+ Endless
1131
+ </Button>
743
1132
  <Button
744
1133
  onClick={() =>
745
1134
  toast.warning({
@@ -784,31 +1173,14 @@ const toast = useToast();
784
1173
  onClick={() =>
785
1174
  toast.info({
786
1175
  title: 'Glass background',
787
- message: 'Custom blur and translucent background.',
1176
+ message: 'Theme blur and translucent background.',
788
1177
  position: 'bottom-right',
789
- background: 'rgb(18 24 34 / 72%)',
790
- blur: 18,
791
- borderColor: 'rgb(255 255 255 / 18%)',
792
1178
  duration: 5200,
793
1179
  })
794
1180
  }
795
1181
  >
796
1182
  Glass
797
1183
  </Button>
798
- <Button
799
- onClick={() =>
800
- toast.info({
801
- title: 'Static background',
802
- message: 'Blur can be disabled per toast.',
803
- position: 'bottom-left',
804
- background: 'var(--oui-floating-bg)',
805
- blur: false,
806
- duration: 5200,
807
- })
808
- }
809
- >
810
- Static
811
- </Button>
812
1184
 
813
1185
  const toastPositions: Array<{position: ToastPosition; label: string}> = [
814
1186
  {position: 'top-left', label: 'Top left'},
@@ -824,51 +1196,42 @@ const toastPositionVariants: Array<{
824
1196
  label: string;
825
1197
  tone: ToastTone;
826
1198
  message: string;
827
- background?: string;
828
- blur?: number | string | false;
829
1199
  }> = [
830
1200
  {
831
1201
  position: 'top-left',
832
1202
  label: 'Status synced',
833
1203
  tone: 'success',
834
- message: 'Glass toast from the left edge.',
835
- blur: 14,
1204
+ message: 'Default glass toast from the left edge.',
836
1205
  },
837
1206
  {
838
1207
  position: 'top-center',
839
1208
  label: 'Command ready',
840
1209
  tone: 'info',
841
- message: 'Centered toast drops from the top.',
842
- background: 'rgb(18 28 42 / 88%)',
843
- blur: 10,
1210
+ message: 'Centered toast uses the same glass surface.',
844
1211
  },
845
1212
  {
846
1213
  position: 'top-right',
847
1214
  label: 'Needs attention',
848
1215
  tone: 'warning',
849
- message: 'Right edge bubble animation.',
850
- blur: 12,
1216
+ message: 'Right edge toast keeps the same translucent surface.',
851
1217
  },
852
1218
  {
853
1219
  position: 'bottom-left',
854
1220
  label: 'Import queued',
855
1221
  tone: 'info',
856
- message: 'Static background, no blur.',
857
- blur: false,
1222
+ message: 'Bottom left toast keeps the same theme blur.',
858
1223
  },
859
1224
  {
860
1225
  position: 'bottom-center',
861
1226
  label: 'Batch completed',
862
1227
  tone: 'success',
863
- message: 'Bottom center rises into place.',
864
- blur: 16,
1228
+ message: 'Bottom center toast uses the theme defaults.',
865
1229
  },
866
1230
  {
867
1231
  position: 'bottom-right',
868
1232
  label: 'Export failed',
869
1233
  tone: 'danger',
870
1234
  message: 'Actionable toast from the right edge.',
871
- blur: 12,
872
1235
  },
873
1236
  ];
874
1237
 
@@ -880,7 +1243,7 @@ const toastPositionVariants: Array<{
880
1243
  onClick={() =>
881
1244
  toast.info({
882
1245
  title: item.label,
883
- message: 'Positioned toast with directional bubble animation.',
1246
+ message: 'Positioned toast with the default glass surface.',
884
1247
  position: item.position,
885
1248
  duration: 3600,
886
1249
  })
@@ -902,8 +1265,6 @@ const toastPositionVariants: Array<{
902
1265
  message: item.message,
903
1266
  position: item.position,
904
1267
  tone: item.tone,
905
- background: item.background,
906
- blur: item.blur,
907
1268
  duration: 4200 + index * 220,
908
1269
  });
909
1270
  }, index * 120);
@@ -929,6 +1290,116 @@ const toastPositionVariants: Array<{
929
1290
  </Modal>
930
1291
 
931
1292
  <Button onClick={() => setOpen(true)}>Open modal</Button>`,
1293
+ tablePagination: `import {Badge, Flex, Pagination, Stack, Table, Text} from '@orcestr/ui';
1294
+
1295
+ <Stack g={3}>
1296
+ <Table v='surface' w='100%'>
1297
+ <Table.Header>
1298
+ <Table.Row>
1299
+ <Table.ColumnHeaderCell>Document</Table.ColumnHeaderCell>
1300
+ <Table.ColumnHeaderCell>Status</Table.ColumnHeaderCell>
1301
+ <Table.ColumnHeaderCell align='right'>Qty</Table.ColumnHeaderCell>
1302
+ </Table.Row>
1303
+ </Table.Header>
1304
+ <Table.Body>
1305
+ {rows.map((row) => (
1306
+ <Table.Row key={row.name}>
1307
+ <Table.RowHeaderCell>{row.name}</Table.RowHeaderCell>
1308
+ <Table.Cell><Badge>{row.status}</Badge></Table.Cell>
1309
+ <Table.Cell align='right'>{row.quantity}</Table.Cell>
1310
+ </Table.Row>
1311
+ ))}
1312
+ </Table.Body>
1313
+ </Table>
1314
+ <Flex j='sb' a='c' wrap g={2}>
1315
+ <Text fs='13px' tone='muted'>Showing 25 items per page</Text>
1316
+ <Pagination page={page} pageCount={4} onPageChange={setPage} />
1317
+ </Flex>
1318
+ </Stack>`,
1319
+ appSidebar: `import {useState} from 'react';
1320
+ import {AppSidebar, Flex, IconButton, Text} from '@orcestr/ui';
1321
+ import {LuBell, LuBox, LuLayoutDashboard, LuSettings, LuTruck} from 'react-icons/lu';
1322
+
1323
+ const [activeKey, setActiveKey] = useState('requests');
1324
+
1325
+ <AppSidebar
1326
+ header={(
1327
+ <>
1328
+ <div className='oui-app-sidebar-brand'>
1329
+ <span className='oui-app-sidebar-logo'>O</span>
1330
+ <span className='oui-app-sidebar-title'>Deliveries</span>
1331
+ </div>
1332
+ <div className='oui-app-sidebar-actions'>
1333
+ <IconButton size={2} v='ghost' icon={<LuSettings />} />
1334
+ </div>
1335
+ </>
1336
+ )}
1337
+ itemH={38}
1338
+ onNavigate={(item) => setActiveKey(item.key)}
1339
+ groups={[
1340
+ {
1341
+ key: 'main',
1342
+ items: [
1343
+ {
1344
+ key: 'overview',
1345
+ label: 'Overview',
1346
+ icon: <LuLayoutDashboard />,
1347
+ active: activeKey === 'overview',
1348
+ },
1349
+ {
1350
+ key: 'requests',
1351
+ label: 'Requests',
1352
+ icon: <LuTruck />,
1353
+ active: activeKey === 'requests',
1354
+ },
1355
+ {
1356
+ key: 'products',
1357
+ label: 'Products',
1358
+ icon: <LuBox />,
1359
+ active: activeKey === 'products',
1360
+ },
1361
+ ],
1362
+ },
1363
+ ]}
1364
+ footer={(
1365
+ <Flex col g={2}>
1366
+ <Flex g={1}>
1367
+ <IconButton size={2} v='ghost' icon={<LuBell />} badge={64} />
1368
+ <IconButton size={2} v='ghost' icon={<LuSettings />} />
1369
+ </Flex>
1370
+ <Text fs='12px' tone='muted'>Admin workspace</Text>
1371
+ </Flex>
1372
+ )}
1373
+ />`,
1374
+ specialModal: `import {Badge, Button, Flex, SpecialModal, Stack, Text} from '@orcestr/ui';
1375
+
1376
+ <SpecialModal open={open} onOpenChange={setOpen} size='lg' scroll='body'>
1377
+ <SpecialModal.Header
1378
+ title='Request PR-2026-0900'
1379
+ meta={<Badge tone='success'>Closed</Badge>}
1380
+ actions={<SpecialModal.Close />}
1381
+ />
1382
+ <SpecialModal.Body>
1383
+ <Stack g={3}>
1384
+ <Flex g={4} wrap>
1385
+ <Stack g={0} w='min(100%, 220px)'>
1386
+ <Text fs='12px' tone='muted'>Supplier</Text>
1387
+ <Text fw={760}>Northwind Trading LLC</Text>
1388
+ </Stack>
1389
+ <Stack g={0} w='min(100%, 180px)'>
1390
+ <Text fs='12px' tone='muted'>Plan arrival</Text>
1391
+ <Text fw={760}>25.06.2026</Text>
1392
+ </Stack>
1393
+ </Flex>
1394
+ </Stack>
1395
+ </SpecialModal.Body>
1396
+ <SpecialModal.Footer>
1397
+ <Flex g={2} j='e' w='100%'>
1398
+ <Button v='surface' onClick={() => setOpen(false)}>Close</Button>
1399
+ <Button>Save</Button>
1400
+ </Flex>
1401
+ </SpecialModal.Footer>
1402
+ </SpecialModal>`,
932
1403
  data: `import {Button, DataTable, TextField, type DataTableSort} from '@orcestr/ui';
933
1404
 
934
1405
  const [sort, setSort] = useState<DataTableSort | null>({key: 'name', direction: 'asc'});