astryx-dracula 0.1.3 → 0.2.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.
Files changed (94) hide show
  1. package/BRAND.md +1 -1
  2. package/README.md +2 -0
  3. package/USAGE.md +13 -0
  4. package/astryx-dracula.js +4 -4
  5. package/astryx.integration.mjs +3 -0
  6. package/package.json +4 -2
  7. package/templates/ai-chat-landing.template.mjs +6 -0
  8. package/templates/ai-chat-landing.tsx +476 -0
  9. package/templates/ai-chat.template.mjs +6 -0
  10. package/templates/ai-chat.tsx +762 -0
  11. package/templates/blank.template.mjs +6 -0
  12. package/templates/blank.tsx +16 -0
  13. package/templates/centered-hero.template.mjs +6 -0
  14. package/templates/centered-hero.tsx +188 -0
  15. package/templates/classic-gallery.template.mjs +6 -0
  16. package/templates/classic-gallery.tsx +181 -0
  17. package/templates/contact-form.template.mjs +6 -0
  18. package/templates/contact-form.tsx +292 -0
  19. package/templates/dashboard-portfolio.template.mjs +6 -0
  20. package/templates/dashboard-portfolio.tsx +800 -0
  21. package/templates/dashboard.template.mjs +6 -0
  22. package/templates/dashboard.tsx +774 -0
  23. package/templates/detail-page.template.mjs +6 -0
  24. package/templates/detail-page.tsx +695 -0
  25. package/templates/documentation-design.template.mjs +6 -0
  26. package/templates/documentation-design.tsx +751 -0
  27. package/templates/documentation-technical.template.mjs +6 -0
  28. package/templates/documentation-technical.tsx +292 -0
  29. package/templates/documentation.template.mjs +6 -0
  30. package/templates/documentation.tsx +347 -0
  31. package/templates/editor.template.mjs +6 -0
  32. package/templates/editor.tsx +959 -0
  33. package/templates/file-explorer.template.mjs +6 -0
  34. package/templates/file-explorer.tsx +577 -0
  35. package/templates/form-two-column.template.mjs +6 -0
  36. package/templates/form-two-column.tsx +314 -0
  37. package/templates/gallery-hero.template.mjs +6 -0
  38. package/templates/gallery-hero.tsx +287 -0
  39. package/templates/ide.template.mjs +6 -0
  40. package/templates/ide.tsx +533 -0
  41. package/templates/incident-console.template.mjs +6 -0
  42. package/templates/incident-console.tsx +584 -0
  43. package/templates/kanban-board.template.mjs +6 -0
  44. package/templates/kanban-board.tsx +746 -0
  45. package/templates/library.template.mjs +6 -0
  46. package/templates/library.tsx +489 -0
  47. package/templates/login-card.template.mjs +6 -0
  48. package/templates/login-card.tsx +200 -0
  49. package/templates/login-split.template.mjs +6 -0
  50. package/templates/login-split.tsx +318 -0
  51. package/templates/login-sso.template.mjs +6 -0
  52. package/templates/login-sso.tsx +277 -0
  53. package/templates/login.template.mjs +6 -0
  54. package/templates/login.tsx +98 -0
  55. package/templates/messaging-shell.template.mjs +6 -0
  56. package/templates/messaging-shell.tsx +675 -0
  57. package/templates/mixed-gallery.template.mjs +6 -0
  58. package/templates/mixed-gallery.tsx +190 -0
  59. package/templates/payment-form.template.mjs +6 -0
  60. package/templates/payment-form.tsx +990 -0
  61. package/templates/product-detail.template.mjs +6 -0
  62. package/templates/product-detail.tsx +366 -0
  63. package/templates/product-gallery.template.mjs +6 -0
  64. package/templates/product-gallery.tsx +173 -0
  65. package/templates/settings-dialog.template.mjs +6 -0
  66. package/templates/settings-dialog.tsx +920 -0
  67. package/templates/settings-sidebar.template.mjs +6 -0
  68. package/templates/settings-sidebar.tsx +952 -0
  69. package/templates/settings.template.mjs +6 -0
  70. package/templates/settings.tsx +235 -0
  71. package/templates/shell-nav.template.mjs +6 -0
  72. package/templates/shell-nav.tsx +306 -0
  73. package/templates/shell-side-nav.template.mjs +6 -0
  74. package/templates/shell-side-nav.tsx +238 -0
  75. package/templates/shell-top-nav.template.mjs +6 -0
  76. package/templates/shell-top-nav.tsx +243 -0
  77. package/templates/side-gallery.template.mjs +6 -0
  78. package/templates/side-gallery.tsx +179 -0
  79. package/templates/table-grouped.template.mjs +6 -0
  80. package/templates/table-grouped.tsx +1174 -0
  81. package/templates/table-page-chart.template.mjs +6 -0
  82. package/templates/table-page-chart.tsx +693 -0
  83. package/templates/table-page-heatmap-status.template.mjs +6 -0
  84. package/templates/table-page-heatmap-status.tsx +547 -0
  85. package/templates/table-page-shoe-store-heatmap.template.mjs +6 -0
  86. package/templates/table-page-shoe-store-heatmap.tsx +1038 -0
  87. package/templates/table-page.template.mjs +6 -0
  88. package/templates/table-page.tsx +445 -0
  89. package/templates/table.template.mjs +6 -0
  90. package/templates/table.tsx +84 -0
  91. package/templates/theme-showcase.template.mjs +6 -0
  92. package/templates/theme-showcase.tsx +1282 -0
  93. package/theme.css +4 -4
  94. package/tokens.css +4 -4
@@ -0,0 +1,6 @@
1
+ export default {
2
+ type: 'page',
3
+ name: 'Settings Form',
4
+ description: 'Single scrolling form with profile sections',
5
+ category: 'forms',
6
+ };
@@ -0,0 +1,235 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ import {useState} from 'react';
4
+ import {useMediaQuery} from '@astryxdesign/core/hooks';
5
+ import {
6
+ VStack,
7
+ HStack,
8
+ StackItem,
9
+ Layout,
10
+ LayoutContent,
11
+ LayoutHeader,
12
+ LayoutPanel,
13
+ } from '@astryxdesign/core/Layout';
14
+ import {Grid} from '@astryxdesign/core/Grid';
15
+ import {List, ListItem} from '@astryxdesign/core/List';
16
+ import {TabList, Tab, TabMenu} from '@astryxdesign/core/TabList';
17
+ import {Text, Heading} from '@astryxdesign/core/Text';
18
+ import {TextInput} from '@astryxdesign/core/TextInput';
19
+ import {Button} from '@astryxdesign/core/Button';
20
+ import {Divider} from '@astryxdesign/core/Divider';
21
+ import {CheckboxInput} from '@astryxdesign/core/CheckboxInput';
22
+ import {Typeahead} from '@astryxdesign/core/Typeahead';
23
+ import {Search} from 'lucide-react';
24
+ import type {SearchableItem, SearchSource} from '@astryxdesign/core/Typeahead';
25
+
26
+ const NAV_ITEMS = [
27
+ 'Profile',
28
+ 'Account',
29
+ 'Members',
30
+ 'Billing',
31
+ 'Invoices',
32
+ 'API',
33
+ ];
34
+
35
+ const SETTINGS_ITEMS: SearchableItem[] = [
36
+ {id: '1', label: 'Username'},
37
+ {id: '2', label: 'First name'},
38
+ {id: '3', label: 'Last name'},
39
+ {id: '4', label: 'Email address'},
40
+ {id: '5', label: 'Change password'},
41
+ {id: '6', label: 'Data Export Access'},
42
+ {id: '7', label: 'Allow Admin to Add Members'},
43
+ {id: '8', label: 'Two-Factor Authentication'},
44
+ ];
45
+
46
+ const settingsSearchSource: SearchSource<SearchableItem> = {
47
+ search: (query: string) =>
48
+ SETTINGS_ITEMS.filter(item =>
49
+ item.label.toLowerCase().includes(query.toLowerCase()),
50
+ ),
51
+ bootstrap: () => SETTINGS_ITEMS,
52
+ };
53
+
54
+ export default function SettingsTemplate() {
55
+ const isNarrow = useMediaQuery('(max-width: 768px)');
56
+ const [activeNav, setActiveNav] = useState('Profile');
57
+ const [username, setUsername] = useState('vlad_tepes');
58
+ const [firstName, setFirstName] = useState('Vlad');
59
+ const [lastName, setLastName] = useState('Tepes');
60
+ const [email, setEmail] = useState('vlad_tepes@castle-dracula.ro');
61
+ const [currentPw, setCurrentPw] = useState('password123');
62
+ const [newPw, setNewPw] = useState('password123');
63
+ const [confirmPw, setConfirmPw] = useState('password123');
64
+ const [dataExport, setDataExport] = useState(false);
65
+ const [adminMembers, setAdminMembers] = useState(false);
66
+ const [twoFactor, setTwoFactor] = useState(false);
67
+ const [searchValue, setSearchValue] = useState<SearchableItem | null>(null);
68
+
69
+ return (
70
+ <Layout
71
+ height="fill"
72
+ contentWidth={1440}
73
+ header={
74
+ <LayoutHeader hasDivider>
75
+ <HStack vAlign="center">
76
+ <StackItem size="fill">
77
+ <Heading level={1}>Settings</Heading>
78
+ </StackItem>
79
+ <Typeahead
80
+ label="Search"
81
+ isLabelHidden
82
+ placeholder="Search coven settings..."
83
+ searchSource={settingsSearchSource}
84
+ value={searchValue}
85
+ onChange={setSearchValue}
86
+ hasEntriesOnFocus
87
+ startIcon={Search}
88
+ />
89
+ </HStack>
90
+ </LayoutHeader>
91
+ }
92
+ start={
93
+ isNarrow ? undefined : (
94
+ <LayoutPanel hasDivider={false} width={260} padding={2}>
95
+ <List density="balanced">
96
+ {NAV_ITEMS.map(item => (
97
+ <ListItem
98
+ key={item}
99
+ label={item}
100
+ isSelected={activeNav === item}
101
+ onClick={() => setActiveNav(item)}
102
+ />
103
+ ))}
104
+ </List>
105
+ </LayoutPanel>
106
+ )
107
+ }
108
+ content={
109
+ <LayoutContent padding={4}>
110
+ <VStack gap={4}>
111
+ {/* Mobile: the sidebar nav collapses to a horizontal, centered
112
+ tab bar above the content. */}
113
+ {isNarrow && (
114
+ <VStack hAlign="center">
115
+ <TabList value={activeNav} onChange={setActiveNav}>
116
+ {NAV_ITEMS.slice(0, 3).map(item => (
117
+ <Tab key={item} value={item} label={item} />
118
+ ))}
119
+ <TabMenu
120
+ label="More"
121
+ options={NAV_ITEMS.slice(3).map(item => ({
122
+ value: item,
123
+ label: item,
124
+ }))}
125
+ />
126
+ </TabList>
127
+ </VStack>
128
+ )}
129
+ <Grid columns={{minWidth: 320}} gap={10}>
130
+ <VStack gap={1}>
131
+ <Heading level={3}>Basic information</Heading>
132
+ <Text type="body" color="secondary">
133
+ View and update your crypt details and coven account information.
134
+ </Text>
135
+ </VStack>
136
+ <VStack gap={4}>
137
+ <TextInput
138
+ label="Username"
139
+ value={username}
140
+ onChange={setUsername}
141
+ />
142
+ <TextInput
143
+ label="First name"
144
+ value={firstName}
145
+ onChange={setFirstName}
146
+ />
147
+ <TextInput
148
+ label="Last name"
149
+ value={lastName}
150
+ onChange={setLastName}
151
+ />
152
+ <TextInput
153
+ label="Email address"
154
+ value={email}
155
+ onChange={setEmail}
156
+ />
157
+ <HStack>
158
+ <Button label="Save" variant="primary" />
159
+ </HStack>
160
+ </VStack>
161
+ </Grid>
162
+
163
+ <Divider />
164
+
165
+ <Grid columns={{minWidth: 320}} gap={10}>
166
+ <VStack gap={1}>
167
+ <Heading level={3}>Change password</Heading>
168
+ <Text type="body" color="secondary">
169
+ Update your password to keep your coffin sealed.
170
+ </Text>
171
+ </VStack>
172
+ <VStack gap={4}>
173
+ <TextInput
174
+ label="Verify current password"
175
+ type="password"
176
+ value={currentPw}
177
+ onChange={setCurrentPw}
178
+ />
179
+ <TextInput
180
+ label="New password"
181
+ type="password"
182
+ value={newPw}
183
+ onChange={setNewPw}
184
+ />
185
+ <TextInput
186
+ label="Confirm password"
187
+ type="password"
188
+ value={confirmPw}
189
+ onChange={setConfirmPw}
190
+ />
191
+ <HStack>
192
+ <Button label="Save" variant="primary" />
193
+ </HStack>
194
+ </VStack>
195
+ </Grid>
196
+
197
+ <Divider />
198
+
199
+ <Grid columns={{minWidth: 320}} gap={10}>
200
+ <VStack gap={1}>
201
+ <Heading level={3}>Advanced settings</Heading>
202
+ <Text type="body" color="secondary">
203
+ Configure detailed coven preferences and warding options.
204
+ </Text>
205
+ </VStack>
206
+ <VStack gap={5}>
207
+ <CheckboxInput
208
+ label="Data Export Access"
209
+ description="Allow export of personal data and backups."
210
+ value={dataExport}
211
+ onChange={setDataExport}
212
+ />
213
+ <CheckboxInput
214
+ label="Allow Admin to Add Members"
215
+ description="Admins can invite and manage members."
216
+ value={adminMembers}
217
+ onChange={setAdminMembers}
218
+ />
219
+ <CheckboxInput
220
+ label="Enable Two-Factor Authentication"
221
+ description="Require 2FA for added account security."
222
+ value={twoFactor}
223
+ onChange={setTwoFactor}
224
+ />
225
+ <HStack>
226
+ <Button label="Save" variant="primary" />
227
+ </HStack>
228
+ </VStack>
229
+ </Grid>
230
+ </VStack>
231
+ </LayoutContent>
232
+ }
233
+ />
234
+ );
235
+ }
@@ -0,0 +1,6 @@
1
+ export default {
2
+ type: 'page',
3
+ name: 'Shell Nav',
4
+ description: 'Top and side nav app shell with code editor',
5
+ category: 'tooling',
6
+ };
@@ -0,0 +1,306 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ import {Fragment, useState, useMemo, useEffect} from 'react';
4
+ import {AppShell} from '@astryxdesign/core/AppShell';
5
+ import {Layout, LayoutHeader, LayoutContent} from '@astryxdesign/core/Layout';
6
+ import {TopNav} from '@astryxdesign/core/TopNav';
7
+ import {DropdownMenu, DropdownMenuItem} from '@astryxdesign/core/DropdownMenu';
8
+ import {CommandPalette} from '@astryxdesign/core/CommandPalette';
9
+ import {createStaticSource} from '@astryxdesign/core/Typeahead';
10
+ import {Divider} from '@astryxdesign/core/Divider';
11
+ import {Kbd} from '@astryxdesign/core/Kbd';
12
+ import {SideNav} from '@astryxdesign/core/SideNav';
13
+ import {TreeList} from '@astryxdesign/core/TreeList';
14
+ import type {TreeListItemData} from '@astryxdesign/core/TreeList';
15
+ import {Icon} from '@astryxdesign/core/Icon';
16
+ import {Text} from '@astryxdesign/core/Text';
17
+ import {Button} from '@astryxdesign/core/Button';
18
+ import {Card} from '@astryxdesign/core/Card';
19
+ import {VStack, HStack} from '@astryxdesign/core/Stack';
20
+ import {Search, Folder, FileText} from 'lucide-react';
21
+
22
+ const noop = () => {};
23
+
24
+ const folder = (
25
+ id: string,
26
+ children: TreeListItemData[],
27
+ isExpanded = true,
28
+ ): TreeListItemData => ({
29
+ id,
30
+ label: <Text maxLines={1}>{id}</Text>,
31
+ startContent: <Icon icon={Folder} size="xsm" />,
32
+ isExpanded,
33
+ children,
34
+ });
35
+
36
+ const file = (id: string, isSelected = false): TreeListItemData => ({
37
+ id,
38
+ label: <Text maxLines={1}>{id}</Text>,
39
+ startContent: <Icon icon={FileText} size="xsm" />,
40
+ isSelected,
41
+ });
42
+
43
+ const FILE_TREE: TreeListItemData[] = [
44
+ folder('src', [
45
+ folder('components', [
46
+ file('AppShell.tsx', true),
47
+ file('TopNav.tsx'),
48
+ file('SideNav.tsx'),
49
+ ]),
50
+ folder('hooks', [file('useTheme.ts'), file('useResizable.ts')]),
51
+ file('index.tsx'),
52
+ file('App.tsx'),
53
+ ]),
54
+ folder('public', [file('favicon.ico'), file('robots.txt')], false),
55
+ file('package.json'),
56
+ file('tsconfig.json'),
57
+ file('README.md'),
58
+ ];
59
+
60
+ // Each menu is split into groups; groups are separated by a divider.
61
+ // `[label, shortcut]` — the shortcut renders as a single combined Kbd
62
+ // (e.g. ⌘N); an empty shortcut renders no Kbd.
63
+ type MenuEntry = [label: string, shortcut: string];
64
+
65
+ // Wide enough that label + Kbd shortcut never clip at the menu edge —
66
+ // "Previous Tab ⌃⇧⇥" is the widest row and touched the border at 280.
67
+ const MENU_WIDTH = 300;
68
+
69
+ const MENUS: {label: string; groups: MenuEntry[][]}[] = [
70
+ {
71
+ label: 'File',
72
+ groups: [
73
+ [
74
+ ['New File', '⌘N'],
75
+ ['New Window', '⇧⌘N'],
76
+ ],
77
+ [
78
+ ['Open...', '⌘O'],
79
+ ['Save', '⌘S'],
80
+ ['Save As...', '⇧⌘S'],
81
+ ],
82
+ [['Close Editor', '⌘W']],
83
+ ],
84
+ },
85
+ {
86
+ label: 'Edit',
87
+ groups: [
88
+ [
89
+ ['Undo', '⌘Z'],
90
+ ['Redo', '⇧⌘Z'],
91
+ ],
92
+ [
93
+ ['Cut', '⌘X'],
94
+ ['Copy', '⌘C'],
95
+ ['Paste', '⌘V'],
96
+ ],
97
+ [['Find', '⌘F']],
98
+ ],
99
+ },
100
+ {
101
+ label: 'View',
102
+ groups: [
103
+ [['Command Palette', '⇧⌘P']],
104
+ [
105
+ ['Explorer', '⇧⌘E'],
106
+ ['Search', '⇧⌘F'],
107
+ ],
108
+ [
109
+ ['Toggle Terminal', '⌃`'],
110
+ ['Zen Mode', '⌘K'],
111
+ ],
112
+ ],
113
+ },
114
+ {
115
+ label: 'Window',
116
+ groups: [
117
+ [
118
+ ['Minimize', '⌘M'],
119
+ ['Zoom', ''],
120
+ ],
121
+ [
122
+ ['Next Tab', '⌃⇥'],
123
+ ['Previous Tab', '⌃⇧⇥'],
124
+ ],
125
+ [['Bring All to Front', '']],
126
+ ],
127
+ },
128
+ {
129
+ label: 'Help',
130
+ groups: [
131
+ [
132
+ ['Documentation', ''],
133
+ ['Release Notes', ''],
134
+ ['Report Issue', ''],
135
+ ['About', ''],
136
+ ],
137
+ ],
138
+ },
139
+ ];
140
+
141
+ const CODE_LINES = [
142
+ '38%',
143
+ '62%',
144
+ '54%',
145
+ '0%',
146
+ '46%',
147
+ '70%',
148
+ '58%',
149
+ '34%',
150
+ '0%',
151
+ '50%',
152
+ '66%',
153
+ '42%',
154
+ '60%',
155
+ '28%',
156
+ ];
157
+
158
+ const EDITOR_TABS = ['AppShell.tsx', 'TopNav.tsx', 'theme.ts'];
159
+
160
+ const COMMANDS = [
161
+ {id: 'new-file', label: 'New File'},
162
+ {id: 'open-file', label: 'Open File…'},
163
+ {id: 'save-all', label: 'Save All'},
164
+ {id: 'find-in-files', label: 'Find in Files'},
165
+ {id: 'toggle-terminal', label: 'Toggle Terminal'},
166
+ {id: 'go-to-symbol', label: 'Go to Symbol…'},
167
+ {id: 'appshell', label: 'AppShell.tsx'},
168
+ {id: 'topnav', label: 'TopNav.tsx'},
169
+ {id: 'sidenav', label: 'SideNav.tsx'},
170
+ {id: 'use-theme', label: 'useTheme.ts'},
171
+ {id: 'theme', label: 'theme.ts'},
172
+ ];
173
+
174
+ export default function ShellNav() {
175
+ const [isPaletteOpen, setIsPaletteOpen] = useState(false);
176
+ const searchSource = useMemo(() => createStaticSource(COMMANDS), []);
177
+
178
+ useEffect(() => {
179
+ const handleKeyDown = (e: KeyboardEvent) => {
180
+ if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
181
+ e.preventDefault();
182
+ setIsPaletteOpen(true);
183
+ }
184
+ };
185
+ window.addEventListener('keydown', handleKeyDown);
186
+ return () => window.removeEventListener('keydown', handleKeyDown);
187
+ }, []);
188
+
189
+ return (
190
+ <>
191
+ <AppShell
192
+ contentPadding={0}
193
+ topNav={
194
+ <TopNav
195
+ label="Dracula Studio menu bar"
196
+ startContent={
197
+ <>
198
+ {MENUS.map(menu => (
199
+ <DropdownMenu
200
+ key={menu.label}
201
+ button={{label: menu.label, variant: 'ghost', size: 'sm'}}
202
+ hasChevron={false}
203
+ menuWidth={MENU_WIDTH}>
204
+ {menu.groups.map((group, gi) => (
205
+ <Fragment key={gi}>
206
+ {gi > 0 && <Divider />}
207
+ {group.map(([label, shortcut]) => (
208
+ <DropdownMenuItem
209
+ key={label}
210
+ label={label}
211
+ onClick={noop}
212
+ endContent={
213
+ shortcut ? <Kbd keys={shortcut} /> : undefined
214
+ }
215
+ />
216
+ ))}
217
+ </Fragment>
218
+ ))}
219
+ </DropdownMenu>
220
+ ))}
221
+ </>
222
+ }
223
+ endContent={
224
+ // A real palette trigger, not a lookalike field: the previous
225
+ // TextInput swallowed keystrokes (fixed value, noop onChange)
226
+ // while a wrapper div opened the palette on click. The dead Run
227
+ // and Share buttons go with it — demo chrome must not ship
228
+ // controls that do nothing.
229
+ <Button
230
+ label="Search files and commands"
231
+ variant="secondary"
232
+ size="sm"
233
+ tooltip="Search files and commands (⌘K)"
234
+ icon={<Icon icon={Search} size="sm" />}
235
+ onClick={() => setIsPaletteOpen(true)}
236
+ />
237
+ }
238
+ />
239
+ }
240
+ sideNav={
241
+ <SideNav
242
+ resizable={{defaultWidth: 240, minWidth: 180, maxWidth: 400}}>
243
+ <TreeList items={FILE_TREE} density="compact" />
244
+ </SideNav>
245
+ }>
246
+ <Layout
247
+ height="fill"
248
+ header={
249
+ <LayoutHeader hasDivider padding={6}>
250
+ <HStack gap={2}>
251
+ {EDITOR_TABS.map(tab => (
252
+ <Card
253
+ key={tab}
254
+ variant="muted"
255
+ padding={0}
256
+ width={132}
257
+ height={36}
258
+ />
259
+ ))}
260
+ </HStack>
261
+ </LayoutHeader>
262
+ }
263
+ content={
264
+ <LayoutContent padding={6}>
265
+ <VStack gap={2}>
266
+ {CODE_LINES.map((width, i) =>
267
+ width === '0%' ? (
268
+ <Card
269
+ key={i}
270
+ variant="muted"
271
+ padding={0}
272
+ width={1}
273
+ height={14}
274
+ />
275
+ ) : (
276
+ <HStack key={i} gap={3} vAlign="center">
277
+ <Card
278
+ variant="muted"
279
+ padding={0}
280
+ width={20}
281
+ height={14}
282
+ />
283
+ <Card
284
+ variant="muted"
285
+ padding={0}
286
+ width={width}
287
+ height={14}
288
+ />
289
+ </HStack>
290
+ ),
291
+ )}
292
+ </VStack>
293
+ </LayoutContent>
294
+ }
295
+ />
296
+ </AppShell>
297
+ <CommandPalette
298
+ isOpen={isPaletteOpen}
299
+ onOpenChange={setIsPaletteOpen}
300
+ searchSource={searchSource}
301
+ label="Search files and commands"
302
+ onValueChange={() => setIsPaletteOpen(false)}
303
+ />
304
+ </>
305
+ );
306
+ }
@@ -0,0 +1,6 @@
1
+ export default {
2
+ type: 'page',
3
+ name: 'Sidebar Shell',
4
+ description: 'Workspace sidebar with conversation list',
5
+ category: 'tooling',
6
+ };