@astryxdesign/cli 0.1.2 → 0.1.3

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 (238) hide show
  1. package/CHANGELOG.md +64 -1
  2. package/README.md +49 -55
  3. package/docs/layout.doc.dense.mjs +90 -0
  4. package/docs/layout.doc.mjs +160 -0
  5. package/docs/principles.doc.dense.mjs +2 -2
  6. package/docs/principles.doc.mjs +4 -0
  7. package/docs/principles.doc.zh.mjs +2 -2
  8. package/docs/theme.doc.mjs +2 -2
  9. package/package.json +13 -1
  10. package/src/api/blog.mjs +192 -0
  11. package/src/api/blog.test.mjs +144 -0
  12. package/src/api/component.mjs +253 -12
  13. package/src/api/discover.mjs +14 -7
  14. package/src/api/doctor.mjs +10 -25
  15. package/src/api/index.mjs +1 -0
  16. package/src/api/layout.mjs +11 -10
  17. package/src/api/layout.test.mjs +4 -1
  18. package/src/api/template-integration.test.mjs +225 -0
  19. package/src/api/template.mjs +242 -84
  20. package/src/api/validate-integration.mjs +370 -0
  21. package/src/api/validate-integration.test.mjs +222 -0
  22. package/src/codemod.mjs +93 -0
  23. package/src/codemod.test.mjs +134 -0
  24. package/src/codemods/__tests__/registry.test.mjs +1 -0
  25. package/src/codemods/__tests__/runner.test.mjs +103 -0
  26. package/src/codemods/integration-discovery.mjs +168 -0
  27. package/src/codemods/integration-discovery.test.mjs +234 -0
  28. package/src/codemods/integration-runner.mjs +109 -0
  29. package/src/codemods/registry.mjs +1 -0
  30. package/src/codemods/run-codemod.mjs +207 -0
  31. package/src/codemods/runner.mjs +73 -96
  32. package/src/codemods/transforms/v0.0.15/index.mjs +0 -13
  33. package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-css-surfaces.test.mjs +67 -0
  34. package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-declare-module.test.mjs +61 -0
  35. package/src/codemods/transforms/v0.1.0/__tests__/v0.1.0-ordering.test.mjs +104 -0
  36. package/src/codemods/transforms/{v0.0.15 → v0.1.0}/drop-xds-prefix-imports.mjs +15 -4
  37. package/src/codemods/transforms/v0.1.0/index.mjs +43 -6
  38. package/src/codemods/transforms/v0.1.0/migrate-xds-css-surfaces.mjs +77 -0
  39. package/src/codemods/transforms/v0.1.0/migrate-xds-declare-module.mjs +78 -0
  40. package/src/codemods/transforms/v0.1.3/__tests__/migrate-layout-components-to-experimental.test.mjs +360 -0
  41. package/src/codemods/transforms/v0.1.3/index.mjs +19 -0
  42. package/src/codemods/transforms/v0.1.3/migrate-layout-components-to-experimental.mjs +260 -0
  43. package/src/commands/agent-docs.mjs +4 -1
  44. package/src/commands/blog.mjs +60 -0
  45. package/src/commands/build-theme.import-path.test.mjs +2 -12
  46. package/src/commands/build-theme.mjs +117 -0
  47. package/src/commands/build-theme.prose.test.mjs +5 -15
  48. package/src/commands/build-theme.watch.test.mjs +149 -0
  49. package/src/commands/component/index.mjs +44 -10
  50. package/src/commands/component-ownership.test.mjs +227 -0
  51. package/src/commands/discover.mjs +5 -16
  52. package/src/commands/doctor.test.mjs +3 -3
  53. package/src/commands/ensure-core-built.mjs +120 -0
  54. package/src/commands/json-contract.test.mjs +0 -32
  55. package/src/commands/swizzle.mjs +224 -235
  56. package/src/commands/swizzle.path-safety.test.mjs +3 -3
  57. package/src/commands/swizzle.routing.test.mjs +279 -0
  58. package/src/commands/template.mjs +33 -37
  59. package/src/commands/upgrade.config-ordering.test.mjs +273 -0
  60. package/src/commands/upgrade.integration-policy.test.mjs +204 -0
  61. package/src/commands/upgrade.mjs +349 -170
  62. package/src/commands/validate-integration.mjs +110 -0
  63. package/src/commands/validate-integration.test.mjs +124 -0
  64. package/src/config.mjs +7 -20
  65. package/src/config.test.mjs +89 -13
  66. package/src/index.mjs +8 -3
  67. package/src/integration.mjs +19 -0
  68. package/src/lib/component-discovery.mjs +177 -0
  69. package/src/lib/config-cache.mjs +91 -0
  70. package/src/lib/config-cache.test.mjs +83 -0
  71. package/src/lib/config-schema.mjs +41 -55
  72. package/src/lib/error-codes.mjs +15 -12
  73. package/src/lib/integration-warnings.mjs +62 -0
  74. package/src/lib/integration-warnings.test.mjs +102 -0
  75. package/src/lib/integrations.mjs +92 -115
  76. package/src/lib/integrations.test.mjs +88 -107
  77. package/src/lib/manifest.mjs +5 -2
  78. package/src/lib/module-loader.mjs +80 -0
  79. package/src/lib/module-loader.test.mjs +106 -0
  80. package/src/lib/project.mjs +502 -0
  81. package/src/lib/project.test.mjs +308 -0
  82. package/src/lib/site.mjs +20 -0
  83. package/src/template.mjs +73 -0
  84. package/src/template.test.mjs +127 -0
  85. package/src/types/api.d.ts +2 -6
  86. package/src/types/base.d.ts +3 -9
  87. package/src/types/codemod.d.ts +81 -0
  88. package/src/types/component.d.ts +27 -2
  89. package/src/types/config.d.ts +56 -85
  90. package/src/types/error-codes.d.ts +5 -3
  91. package/src/types/index.d.ts +0 -1
  92. package/src/types/integration.d.ts +29 -0
  93. package/src/types/swizzle.d.ts +9 -2
  94. package/src/types/template-api.d.ts +54 -0
  95. package/src/types/template.d.ts +10 -7
  96. package/src/types/upgrade.d.ts +29 -0
  97. package/src/types/validate-integration.d.ts +24 -0
  98. package/src/utils/github.mjs +0 -237
  99. package/src/utils/interactive.mjs +2 -2
  100. package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotVariants.doc.mjs +14 -0
  101. package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotVariants.tsx +28 -0
  102. package/templates/blocks/components/Blockquote/BlockquoteTestimonials.doc.mjs +14 -0
  103. package/templates/blocks/components/Blockquote/BlockquoteTestimonials.tsx +34 -0
  104. package/templates/blocks/components/Blockquote/BlockquoteWithCite.doc.mjs +14 -0
  105. package/templates/blocks/components/Blockquote/BlockquoteWithCite.tsx +21 -0
  106. package/templates/blocks/components/BreadcrumbItem/BreadcrumbItemBasic.doc.mjs +14 -0
  107. package/templates/blocks/components/BreadcrumbItem/BreadcrumbItemBasic.tsx +15 -0
  108. package/templates/blocks/components/ButtonGroup/ButtonGroupBasic.doc.mjs +14 -0
  109. package/templates/blocks/components/ButtonGroup/ButtonGroupBasic.tsx +16 -0
  110. package/templates/blocks/components/ChatDictationButton/ChatDictationButtonBasic.doc.mjs +19 -0
  111. package/templates/blocks/components/ChatDictationButton/ChatDictationButtonBasic.tsx +34 -0
  112. package/templates/blocks/components/CheckboxListItem/CheckboxListItemBasic.doc.mjs +14 -0
  113. package/templates/blocks/components/CheckboxListItem/CheckboxListItemBasic.tsx +30 -0
  114. package/templates/blocks/components/CollapsibleGroup/CollapsibleGroupAccordion.doc.mjs +14 -0
  115. package/templates/blocks/components/CollapsibleGroup/CollapsibleGroupAccordion.tsx +31 -0
  116. package/templates/blocks/components/CommandPaletteEmpty/CommandPaletteEmptyBasic.doc.mjs +14 -0
  117. package/templates/blocks/components/CommandPaletteEmpty/CommandPaletteEmptyBasic.tsx +26 -0
  118. package/templates/blocks/components/CommandPaletteFooter/CommandPaletteFooterBasic.doc.mjs +14 -0
  119. package/templates/blocks/components/CommandPaletteFooter/CommandPaletteFooterBasic.tsx +32 -0
  120. package/templates/blocks/components/CommandPaletteGroup/CommandPaletteGroupBasic.doc.mjs +18 -0
  121. package/templates/blocks/components/CommandPaletteGroup/CommandPaletteGroupBasic.tsx +32 -0
  122. package/templates/blocks/components/CommandPaletteItem/CommandPaletteItemBasic.doc.mjs +14 -0
  123. package/templates/blocks/components/CommandPaletteItem/CommandPaletteItemBasic.tsx +27 -0
  124. package/templates/blocks/components/ContextMenu/ContextMenuBasic.doc.mjs +14 -0
  125. package/templates/blocks/components/ContextMenu/ContextMenuBasic.tsx +32 -0
  126. package/templates/blocks/components/DateRangeInput/DateRangeInputWithPresets.doc.mjs +14 -0
  127. package/templates/blocks/components/DateRangeInput/DateRangeInputWithPresets.tsx +46 -0
  128. package/templates/blocks/components/DateRangeInput/DateRangeInputWithValidation.doc.mjs +14 -0
  129. package/templates/blocks/components/DateRangeInput/DateRangeInputWithValidation.tsx +52 -0
  130. package/templates/blocks/components/DateTimeInput/DateTimeInputWithValidation.doc.mjs +14 -0
  131. package/templates/blocks/components/DateTimeInput/DateTimeInputWithValidation.tsx +43 -0
  132. package/templates/blocks/components/DialogHeader/DialogHeaderBasic.doc.mjs +14 -0
  133. package/templates/blocks/components/DialogHeader/DialogHeaderBasic.tsx +30 -0
  134. package/templates/blocks/components/DropdownMenu/DropdownMenuShowcase.tsx +0 -6
  135. package/templates/blocks/components/DropdownMenuItem/DropdownMenuItemBasic.doc.mjs +14 -0
  136. package/templates/blocks/components/DropdownMenuItem/DropdownMenuItemBasic.tsx +27 -0
  137. package/templates/blocks/components/DropdownMenuItem/DropdownMenuItemShowcase.tsx +1 -5
  138. package/templates/blocks/components/FieldLabel/FieldLabelBasic.doc.mjs +14 -0
  139. package/templates/blocks/components/FieldLabel/FieldLabelBasic.tsx +20 -0
  140. package/templates/blocks/components/FieldStatus/FieldStatusBasic.doc.mjs +14 -0
  141. package/templates/blocks/components/FieldStatus/FieldStatusBasic.tsx +23 -0
  142. package/templates/blocks/components/FileInput/FileInputBasic.doc.mjs +14 -0
  143. package/templates/blocks/components/FileInput/FileInputBasic.tsx +22 -0
  144. package/templates/blocks/components/GridSpan/GridSpanColumns.doc.mjs +14 -0
  145. package/templates/blocks/components/GridSpan/GridSpanColumns.tsx +38 -0
  146. package/templates/blocks/components/HStack/HStackBasic.doc.mjs +14 -0
  147. package/templates/blocks/components/HStack/HStackBasic.tsx +16 -0
  148. package/templates/blocks/components/Hooks/useKeyboardHintHookUsage.doc.mjs +14 -0
  149. package/templates/blocks/components/Hooks/useKeyboardHintHookUsage.tsx +57 -0
  150. package/templates/blocks/components/HoverCard/HoverCardInteractiveContent.doc.mjs +1 -1
  151. package/templates/blocks/components/HoverCard/HoverCardInteractiveContent.tsx +9 -4
  152. package/templates/blocks/components/InputGroup/InputGroupBasic.doc.mjs +14 -0
  153. package/templates/blocks/components/InputGroup/InputGroupBasic.tsx +27 -0
  154. package/templates/blocks/components/LayoutContent/LayoutContentBasic.doc.mjs +23 -0
  155. package/templates/blocks/components/LayoutContent/LayoutContentBasic.tsx +40 -0
  156. package/templates/blocks/components/LayoutFooter/LayoutFooterActions.doc.mjs +22 -0
  157. package/templates/blocks/components/LayoutFooter/LayoutFooterActions.tsx +41 -0
  158. package/templates/blocks/components/LayoutHeader/LayoutHeaderWithActions.doc.mjs +23 -0
  159. package/templates/blocks/components/LayoutHeader/LayoutHeaderWithActions.tsx +40 -0
  160. package/templates/blocks/components/LayoutPanel/LayoutPanelNavigation.doc.mjs +22 -0
  161. package/templates/blocks/components/LayoutPanel/LayoutPanelNavigation.tsx +37 -0
  162. package/templates/blocks/components/Lightbox/LightboxGallery.doc.mjs +14 -0
  163. package/templates/blocks/components/Lightbox/LightboxGallery.tsx +53 -0
  164. package/templates/blocks/components/Lightbox/LightboxShowcase.tsx +4 -3
  165. package/templates/blocks/components/Lightbox/LightboxVideo.doc.mjs +14 -0
  166. package/templates/blocks/components/Lightbox/LightboxVideo.tsx +27 -0
  167. package/templates/blocks/components/Lightbox/LightboxZoom.doc.mjs +14 -0
  168. package/templates/blocks/components/Lightbox/LightboxZoom.tsx +33 -0
  169. package/templates/blocks/components/LinkProvider/LinkProviderCustomLink.doc.mjs +1 -1
  170. package/templates/blocks/components/MetadataListItem/MetadataListItemBasic.doc.mjs +14 -0
  171. package/templates/blocks/components/MetadataListItem/MetadataListItemBasic.tsx +19 -0
  172. package/templates/blocks/components/MobileNavToggle/MobileNavToggleBasic.doc.mjs +23 -0
  173. package/templates/blocks/components/MobileNavToggle/MobileNavToggleBasic.tsx +42 -0
  174. package/templates/blocks/components/MoreMenu/MoreMenuShowcase.tsx +0 -6
  175. package/templates/blocks/components/NavIcon/NavIconBasic.doc.mjs +14 -0
  176. package/templates/blocks/components/NavIcon/NavIconBasic.tsx +16 -0
  177. package/templates/blocks/components/RadioListItem/RadioListItemBasic.doc.mjs +14 -0
  178. package/templates/blocks/components/RadioListItem/RadioListItemBasic.tsx +30 -0
  179. package/templates/blocks/components/Resizable/ResizableSidebar.doc.mjs +25 -0
  180. package/templates/blocks/components/Resizable/ResizableSidebar.tsx +67 -0
  181. package/templates/blocks/components/SegmentedControlItem/SegmentedControlItemBasic.doc.mjs +14 -0
  182. package/templates/blocks/components/SegmentedControlItem/SegmentedControlItemBasic.tsx +21 -0
  183. package/templates/blocks/components/SelectorOption/SelectorOptionBasic.doc.mjs +14 -0
  184. package/templates/blocks/components/SelectorOption/SelectorOptionBasic.tsx +39 -0
  185. package/templates/blocks/components/SideNavCollapseButton/SideNavCollapseButtonBasic.doc.mjs +14 -0
  186. package/templates/blocks/components/SideNavCollapseButton/SideNavCollapseButtonBasic.tsx +55 -0
  187. package/templates/blocks/components/SideNavHeading/SideNavHeadingBasic.doc.mjs +14 -0
  188. package/templates/blocks/components/SideNavHeading/SideNavHeadingBasic.tsx +38 -0
  189. package/templates/blocks/components/SideNavItem/SideNavItemBasic.doc.mjs +14 -0
  190. package/templates/blocks/components/SideNavItem/SideNavItemBasic.tsx +49 -0
  191. package/templates/blocks/components/SideNavSection/SideNavSectionBasic.doc.mjs +14 -0
  192. package/templates/blocks/components/SideNavSection/SideNavSectionBasic.tsx +71 -0
  193. package/templates/blocks/components/StackItem/StackItemFill.doc.mjs +14 -0
  194. package/templates/blocks/components/StackItem/StackItemFill.tsx +28 -0
  195. package/templates/blocks/components/Tab/TabWithSelectedIcon.doc.mjs +13 -0
  196. package/templates/blocks/components/Tab/TabWithSelectedIcon.tsx +39 -0
  197. package/templates/blocks/components/TabMenu/TabMenuBasic.doc.mjs +14 -0
  198. package/templates/blocks/components/TabMenu/TabMenuBasic.tsx +23 -0
  199. package/templates/blocks/components/Table/StickyColumnsHookUsage.doc.mjs +1 -1
  200. package/templates/blocks/components/ToggleButtonGroup/ToggleButtonGroupVertical.doc.mjs +14 -0
  201. package/templates/blocks/components/ToggleButtonGroup/ToggleButtonGroupVertical.tsx +47 -0
  202. package/templates/blocks/components/TopNavHeading/TopNavHeadingBasic.doc.mjs +14 -0
  203. package/templates/blocks/components/TopNavHeading/TopNavHeadingBasic.tsx +22 -0
  204. package/templates/blocks/components/TopNavItem/TopNavItemBasic.doc.mjs +14 -0
  205. package/templates/blocks/components/TopNavItem/TopNavItemBasic.tsx +21 -0
  206. package/templates/blocks/components/TopNavMegaMenu/TopNavMegaMenuBasic.doc.mjs +20 -0
  207. package/templates/blocks/components/TopNavMegaMenu/TopNavMegaMenuBasic.tsx +46 -0
  208. package/templates/blocks/components/TopNavMegaMenuFeaturedCard/TopNavMegaMenuFeaturedCardBasic.doc.mjs +14 -0
  209. package/templates/blocks/components/TopNavMegaMenuFeaturedCard/TopNavMegaMenuFeaturedCardBasic.tsx +16 -0
  210. package/templates/blocks/components/TopNavMegaMenuItem/TopNavMegaMenuItemBasic.doc.mjs +14 -0
  211. package/templates/blocks/components/TopNavMegaMenuItem/TopNavMegaMenuItemBasic.tsx +26 -0
  212. package/templates/blocks/components/TopNavMenu/TopNavMenuBasic.doc.mjs +14 -0
  213. package/templates/blocks/components/TopNavMenu/TopNavMenuBasic.tsx +43 -0
  214. package/templates/blocks/components/TypeaheadItem/TypeaheadItemBasic.doc.mjs +14 -0
  215. package/templates/blocks/components/TypeaheadItem/TypeaheadItemBasic.tsx +43 -0
  216. package/templates/blocks/components/VStack/VStackBasic.doc.mjs +14 -0
  217. package/templates/blocks/components/VStack/VStackBasic.tsx +20 -0
  218. package/templates/pages/kanban-board/page.tsx +729 -0
  219. package/templates/pages/kanban-board/template.doc.mjs +12 -0
  220. package/templates/pages/shell-nav/page.tsx +321 -0
  221. package/templates/pages/shell-nav/template.doc.mjs +12 -0
  222. package/templates/pages/shell-side-nav/page.tsx +241 -0
  223. package/templates/pages/shell-side-nav/template.doc.mjs +12 -0
  224. package/templates/pages/shell-top-nav/page.tsx +224 -0
  225. package/templates/pages/shell-top-nav/template.doc.mjs +12 -0
  226. package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-config-surfaces.test.mjs +0 -116
  227. package/src/codemods/transforms/v0.1.0/migrate-xds-config-surfaces.mjs +0 -230
  228. package/src/commands/gap-report.mjs +0 -464
  229. package/src/commands/gap-report.test.mjs +0 -168
  230. package/src/commands/swizzle-gap-safety.test.mjs +0 -273
  231. package/src/lib/config.mjs +0 -113
  232. package/src/lib/config.test.mjs +0 -91
  233. package/src/types/gap-report.d.ts +0 -29
  234. package/templates/blocks/components/TreeListBranches/TreeListBranchesShowcase.doc.mjs +0 -14
  235. package/templates/blocks/components/TreeListBranches/TreeListBranchesShowcase.tsx +0 -64
  236. package/templates/blocks/components/TreeListItem/TreeListItemShowcase.doc.mjs +0 -14
  237. package/templates/blocks/components/TreeListItem/TreeListItemShowcase.tsx +0 -60
  238. /package/src/codemods/transforms/{v0.0.15 → v0.1.0}/__tests__/drop-xds-prefix-imports.test.mjs +0 -0
@@ -0,0 +1,12 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'page',
6
+ name: 'Kanban Board',
7
+ displayName: 'Kanban Board',
8
+ description:
9
+ 'Task board with color-coded status columns, draggable task cards, priority tags, and metadata',
10
+ isReady: true,
11
+ category: 'Tools - Kanban Board',
12
+ };
@@ -0,0 +1,321 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {Fragment, useState, useMemo, useEffect} from 'react';
6
+ import {AppShell} from '@astryxdesign/core/AppShell';
7
+ import {Layout, LayoutHeader, LayoutContent} from '@astryxdesign/core/Layout';
8
+ import {TopNav} from '@astryxdesign/core/TopNav';
9
+ import {DropdownMenu, DropdownMenuItem} from '@astryxdesign/core/DropdownMenu';
10
+ import {CommandPalette} from '@astryxdesign/core/CommandPalette';
11
+ import {createStaticSource} from '@astryxdesign/core/Typeahead';
12
+ import {Divider} from '@astryxdesign/core/Divider';
13
+ import {Kbd} from '@astryxdesign/core/Kbd';
14
+ import {SideNav} from '@astryxdesign/core/SideNav';
15
+ import {TreeList} from '@astryxdesign/core/TreeList';
16
+ import type {TreeListItemData} from '@astryxdesign/core/TreeList';
17
+ import {Icon} from '@astryxdesign/core/Icon';
18
+ import {Text} from '@astryxdesign/core/Text';
19
+ import {IconButton} from '@astryxdesign/core/IconButton';
20
+ import {Button} from '@astryxdesign/core/Button';
21
+ import {TextInput} from '@astryxdesign/core/TextInput';
22
+ import {Card} from '@astryxdesign/core/Card';
23
+ import {Stack, VStack, HStack} from '@astryxdesign/core/Stack';
24
+ import {
25
+ PlayIcon,
26
+ MagnifyingGlassIcon,
27
+ FolderIcon,
28
+ DocumentTextIcon,
29
+ } from '@heroicons/react/24/outline';
30
+
31
+ const noop = () => {};
32
+
33
+ const folder = (
34
+ id: string,
35
+ children: TreeListItemData[],
36
+ isExpanded = true,
37
+ ): TreeListItemData => ({
38
+ id,
39
+ label: <Text maxLines={1}>{id}</Text>,
40
+ startContent: <Icon icon={FolderIcon} size="xsm" />,
41
+ isExpanded,
42
+ children,
43
+ });
44
+
45
+ const file = (id: string, isSelected = false): TreeListItemData => ({
46
+ id,
47
+ label: <Text maxLines={1}>{id}</Text>,
48
+ startContent: <Icon icon={DocumentTextIcon} size="xsm" />,
49
+ isSelected,
50
+ });
51
+
52
+ const FILE_TREE: TreeListItemData[] = [
53
+ folder('src', [
54
+ folder('components', [
55
+ file('AppShell.tsx', true),
56
+ file('TopNav.tsx'),
57
+ file('SideNav.tsx'),
58
+ ]),
59
+ folder('hooks', [file('useTheme.ts'), file('useResizable.ts')]),
60
+ file('index.tsx'),
61
+ file('App.tsx'),
62
+ ]),
63
+ folder('public', [file('favicon.ico'), file('robots.txt')], false),
64
+ file('package.json'),
65
+ file('tsconfig.json'),
66
+ file('README.md'),
67
+ ];
68
+
69
+ // Each menu is split into groups; groups are separated by a divider.
70
+ // `[label, shortcut]` — the shortcut renders as a single combined Kbd
71
+ // (e.g. ⌘N); an empty shortcut renders no Kbd.
72
+ type MenuEntry = [label: string, shortcut: string];
73
+
74
+ const MENU_WIDTH = 280;
75
+
76
+ const MENUS: {label: string; groups: MenuEntry[][]}[] = [
77
+ {
78
+ label: 'File',
79
+ groups: [
80
+ [
81
+ ['New File', '⌘N'],
82
+ ['New Window', '⇧⌘N'],
83
+ ],
84
+ [
85
+ ['Open...', '⌘O'],
86
+ ['Save', '⌘S'],
87
+ ['Save As...', '⇧⌘S'],
88
+ ],
89
+ [['Close Editor', '⌘W']],
90
+ ],
91
+ },
92
+ {
93
+ label: 'Edit',
94
+ groups: [
95
+ [
96
+ ['Undo', '⌘Z'],
97
+ ['Redo', '⇧⌘Z'],
98
+ ],
99
+ [
100
+ ['Cut', '⌘X'],
101
+ ['Copy', '⌘C'],
102
+ ['Paste', '⌘V'],
103
+ ],
104
+ [['Find', '⌘F']],
105
+ ],
106
+ },
107
+ {
108
+ label: 'View',
109
+ groups: [
110
+ [['Command Palette', '⇧⌘P']],
111
+ [
112
+ ['Explorer', '⇧⌘E'],
113
+ ['Search', '⇧⌘F'],
114
+ ],
115
+ [
116
+ ['Toggle Terminal', '⌃`'],
117
+ ['Zen Mode', '⌘K'],
118
+ ],
119
+ ],
120
+ },
121
+ {
122
+ label: 'Window',
123
+ groups: [
124
+ [
125
+ ['Minimize', '⌘M'],
126
+ ['Zoom', ''],
127
+ ],
128
+ [
129
+ ['Next Tab', '⌃⇥'],
130
+ ['Previous Tab', '⌃⇧⇥'],
131
+ ],
132
+ [['Bring All to Front', '']],
133
+ ],
134
+ },
135
+ {
136
+ label: 'Help',
137
+ groups: [
138
+ [
139
+ ['Documentation', ''],
140
+ ['Release Notes', ''],
141
+ ['Report Issue', ''],
142
+ ['About', ''],
143
+ ],
144
+ ],
145
+ },
146
+ ];
147
+
148
+ const CODE_LINES = [
149
+ '38%',
150
+ '62%',
151
+ '54%',
152
+ '0%',
153
+ '46%',
154
+ '70%',
155
+ '58%',
156
+ '34%',
157
+ '0%',
158
+ '50%',
159
+ '66%',
160
+ '42%',
161
+ '60%',
162
+ '28%',
163
+ ];
164
+
165
+ const EDITOR_TABS = ['AppShell.tsx', 'TopNav.tsx', 'theme.ts'];
166
+
167
+ const COMMANDS = [
168
+ {id: 'new-file', label: 'New File'},
169
+ {id: 'open-file', label: 'Open File…'},
170
+ {id: 'save-all', label: 'Save All'},
171
+ {id: 'find-in-files', label: 'Find in Files'},
172
+ {id: 'toggle-terminal', label: 'Toggle Terminal'},
173
+ {id: 'go-to-symbol', label: 'Go to Symbol…'},
174
+ {id: 'appshell', label: 'AppShell.tsx'},
175
+ {id: 'topnav', label: 'TopNav.tsx'},
176
+ {id: 'sidenav', label: 'SideNav.tsx'},
177
+ {id: 'use-theme', label: 'useTheme.ts'},
178
+ {id: 'theme', label: 'theme.ts'},
179
+ ];
180
+
181
+ export default function ShellNav() {
182
+ const [isPaletteOpen, setIsPaletteOpen] = useState(false);
183
+ const searchSource = useMemo(() => createStaticSource(COMMANDS), []);
184
+
185
+ useEffect(() => {
186
+ const handleKeyDown = (e: KeyboardEvent) => {
187
+ if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
188
+ e.preventDefault();
189
+ setIsPaletteOpen(true);
190
+ }
191
+ };
192
+ window.addEventListener('keydown', handleKeyDown);
193
+ return () => window.removeEventListener('keydown', handleKeyDown);
194
+ }, []);
195
+
196
+ return (
197
+ <>
198
+ <AppShell
199
+ contentPadding={0}
200
+ topNav={
201
+ <TopNav
202
+ label="Astryx Studio menu bar"
203
+ startContent={
204
+ <>
205
+ {MENUS.map(menu => (
206
+ <DropdownMenu
207
+ key={menu.label}
208
+ button={{label: menu.label, variant: 'ghost', size: 'sm'}}
209
+ hasChevron={false}
210
+ menuWidth={MENU_WIDTH}>
211
+ {menu.groups.map((group, gi) => (
212
+ <Fragment key={gi}>
213
+ {gi > 0 && <Divider />}
214
+ {group.map(([label, shortcut]) => (
215
+ <DropdownMenuItem
216
+ key={label}
217
+ label={label}
218
+ onClick={noop}
219
+ endContent={
220
+ shortcut ? <Kbd keys={shortcut} /> : undefined
221
+ }
222
+ />
223
+ ))}
224
+ </Fragment>
225
+ ))}
226
+ </DropdownMenu>
227
+ ))}
228
+ </>
229
+ }
230
+ endContent={
231
+ <>
232
+ <Stack onClick={() => setIsPaletteOpen(true)}>
233
+ <TextInput
234
+ label="Search files and commands"
235
+ isLabelHidden
236
+ size="sm"
237
+ width={240}
238
+ startIcon={MagnifyingGlassIcon}
239
+ placeholder="Search files and commands…"
240
+ value=""
241
+ onChange={() => {}}
242
+ />
243
+ </Stack>
244
+ <IconButton
245
+ label="Run project"
246
+ tooltip="Run"
247
+ variant="ghost"
248
+ icon={<Icon icon={PlayIcon} size="sm" />}
249
+ />
250
+ <Button label="Share" variant="secondary" />
251
+ </>
252
+ }
253
+ />
254
+ }
255
+ sideNav={
256
+ <SideNav
257
+ resizable={{defaultWidth: 240, minWidth: 180, maxWidth: 400}}>
258
+ <TreeList items={FILE_TREE} density="compact" />
259
+ </SideNav>
260
+ }>
261
+ <Layout
262
+ height="fill"
263
+ header={
264
+ <LayoutHeader hasDivider padding={6}>
265
+ <HStack gap={2}>
266
+ {EDITOR_TABS.map(tab => (
267
+ <Card
268
+ key={tab}
269
+ variant="muted"
270
+ padding={0}
271
+ width={132}
272
+ height={36}
273
+ />
274
+ ))}
275
+ </HStack>
276
+ </LayoutHeader>
277
+ }
278
+ content={
279
+ <LayoutContent padding={6}>
280
+ <VStack gap={2}>
281
+ {CODE_LINES.map((width, i) =>
282
+ width === '0%' ? (
283
+ <Card
284
+ key={i}
285
+ variant="muted"
286
+ padding={0}
287
+ width={1}
288
+ height={14}
289
+ />
290
+ ) : (
291
+ <HStack key={i} gap={3} vAlign="center">
292
+ <Card
293
+ variant="muted"
294
+ padding={0}
295
+ width={20}
296
+ height={14}
297
+ />
298
+ <Card
299
+ variant="muted"
300
+ padding={0}
301
+ width={width}
302
+ height={14}
303
+ />
304
+ </HStack>
305
+ ),
306
+ )}
307
+ </VStack>
308
+ </LayoutContent>
309
+ }
310
+ />
311
+ </AppShell>
312
+ <CommandPalette
313
+ isOpen={isPaletteOpen}
314
+ onOpenChange={setIsPaletteOpen}
315
+ searchSource={searchSource}
316
+ label="Search files and commands"
317
+ onValueChange={() => setIsPaletteOpen(false)}
318
+ />
319
+ </>
320
+ );
321
+ }
@@ -0,0 +1,12 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'page',
6
+ name: 'Shell Nav',
7
+ displayName: 'Shell Nav',
8
+ description:
9
+ 'A top + side nav app shell with a File/Edit/View/Window/Help menu bar plus command-palette search, a resizable file-tree SideNav, and a static grey-card tabbed code editor.',
10
+ isReady: true,
11
+ category: 'Shell - Top Nav + Left Sidebar',
12
+ };
@@ -0,0 +1,241 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {useState} from 'react';
6
+ import {AppShell} from '@astryxdesign/core/AppShell';
7
+ import {Divider} from '@astryxdesign/core/Divider';
8
+ import {Layout, LayoutContent, LayoutFooter} from '@astryxdesign/core/Layout';
9
+ import {
10
+ SideNav,
11
+ SideNavHeading,
12
+ SideNavItem,
13
+ SideNavSection,
14
+ } from '@astryxdesign/core/SideNav';
15
+ import {NavIcon} from '@astryxdesign/core/NavIcon';
16
+ import {Icon} from '@astryxdesign/core/Icon';
17
+ import type {IconType} from '@astryxdesign/core/Icon';
18
+ import {MoreMenu} from '@astryxdesign/core/MoreMenu';
19
+ import {StatusDot} from '@astryxdesign/core/StatusDot';
20
+ import type {StatusDotVariant} from '@astryxdesign/core/StatusDot';
21
+ import {Card} from '@astryxdesign/core/Card';
22
+ import {Stack, VStack, HStack} from '@astryxdesign/core/Stack';
23
+ import {
24
+ SparklesIcon,
25
+ PlusIcon,
26
+ MagnifyingGlassIcon,
27
+ BookOpenIcon,
28
+ Cog6ToothIcon,
29
+ UserCircleIcon,
30
+ UserIcon,
31
+ BuildingOffice2Icon,
32
+ CodeBracketIcon,
33
+ } from '@heroicons/react/24/outline';
34
+
35
+ type Conversation = {
36
+ label: string;
37
+ status: StatusDotVariant;
38
+ statusLabel: string;
39
+ };
40
+
41
+ type Workspace = {
42
+ name: string;
43
+ icon: IconType;
44
+ chats: Conversation[];
45
+ };
46
+
47
+ const WORKSPACES: Workspace[] = [
48
+ {
49
+ name: 'Personal',
50
+ icon: UserIcon,
51
+ chats: [
52
+ {
53
+ label: 'Weekend trip planning',
54
+ status: 'success',
55
+ statusLabel: 'Active',
56
+ },
57
+ {
58
+ label: 'Recipe ideas for the week',
59
+ status: 'neutral',
60
+ statusLabel: 'Idle',
61
+ },
62
+ {
63
+ label: 'Book recommendations',
64
+ status: 'warning',
65
+ statusLabel: 'Needs review',
66
+ },
67
+ {label: 'Home workout plan', status: 'neutral', statusLabel: 'Idle'},
68
+ ],
69
+ },
70
+ {
71
+ name: 'Acme Corp',
72
+ icon: BuildingOffice2Icon,
73
+ chats: [
74
+ {label: 'Q3 roadmap draft', status: 'accent', statusLabel: 'In progress'},
75
+ {
76
+ label: 'Customer onboarding flow',
77
+ status: 'success',
78
+ statusLabel: 'Active',
79
+ },
80
+ {
81
+ label: 'Pricing strategy review',
82
+ status: 'warning',
83
+ statusLabel: 'Needs review',
84
+ },
85
+ {label: 'Standup summary', status: 'neutral', statusLabel: 'Idle'},
86
+ ],
87
+ },
88
+ {
89
+ name: 'Open Source',
90
+ icon: CodeBracketIcon,
91
+ chats: [
92
+ {
93
+ label: 'StyleX migration notes',
94
+ status: 'accent',
95
+ statusLabel: 'In progress',
96
+ },
97
+ {
98
+ label: 'Skeleton loading states',
99
+ status: 'success',
100
+ statusLabel: 'Active',
101
+ },
102
+ {label: 'Accessibility audit', status: 'error', statusLabel: 'Blocked'},
103
+ {label: 'Release notes v4.0', status: 'neutral', statusLabel: 'Idle'},
104
+ ],
105
+ },
106
+ ];
107
+
108
+ const SELECTED_CHAT = 'StyleX migration notes';
109
+
110
+ const MESSAGES = [
111
+ {role: 'assistant', width: '78%', height: 104},
112
+ {role: 'user', width: '48%', height: 48},
113
+ {role: 'assistant', width: '64%', height: 132},
114
+ {role: 'user', width: '38%', height: 40},
115
+ ];
116
+
117
+ function ConversationItem({
118
+ label,
119
+ status,
120
+ statusLabel,
121
+ isSelected,
122
+ }: {
123
+ label: string;
124
+ status: StatusDotVariant;
125
+ statusLabel: string;
126
+ isSelected?: boolean;
127
+ }) {
128
+ const [isHovered, setIsHovered] = useState(false);
129
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
130
+ const showMenu = isHovered || isMenuOpen;
131
+
132
+ return (
133
+ <Stack
134
+ onMouseEnter={() => setIsHovered(true)}
135
+ onMouseLeave={() => setIsHovered(false)}>
136
+ <SideNavItem
137
+ label={label}
138
+ href="#"
139
+ isSelected={isSelected}
140
+ endContent={
141
+ showMenu ? (
142
+ <MoreMenu
143
+ size="sm"
144
+ label="Conversation options"
145
+ onOpenChange={setIsMenuOpen}
146
+ items={[
147
+ {label: 'Pin', onClick: () => {}},
148
+ {label: 'Rename', onClick: () => {}},
149
+ {label: 'Archive', onClick: () => {}},
150
+ {label: 'Delete', onClick: () => {}},
151
+ ]}
152
+ />
153
+ ) : (
154
+ <StatusDot variant={status} label={statusLabel} />
155
+ )
156
+ }
157
+ />
158
+ </Stack>
159
+ );
160
+ }
161
+
162
+ export default function ShellSideNav() {
163
+ return (
164
+ <AppShell
165
+ contentPadding={0}
166
+ sideNav={
167
+ <SideNav
168
+ collapsible
169
+ resizable={{defaultWidth: 300, minWidth: 220, maxWidth: 420}}
170
+ header={
171
+ <SideNavHeading
172
+ heading="AI Assistant"
173
+ icon={<NavIcon icon={<Icon icon={SparklesIcon} size="sm" />} />}
174
+ headingHref="#"
175
+ />
176
+ }
177
+ footer={
178
+ <SideNavSection title="Account" isHeaderHidden>
179
+ <SideNavItem label="Settings" icon={Cog6ToothIcon} href="#" />
180
+ <SideNavItem label="Sarah Chen" icon={UserCircleIcon} href="#" />
181
+ </SideNavSection>
182
+ }>
183
+ <SideNavSection title="Menu" isHeaderHidden>
184
+ <SideNavItem label="New chat" icon={PlusIcon} href="#" />
185
+ <SideNavItem label="Search" icon={MagnifyingGlassIcon} href="#" />
186
+ <SideNavItem label="Library" icon={BookOpenIcon} href="#" />
187
+ </SideNavSection>
188
+ <Divider />
189
+ <SideNavSection title="Workspaces" isHeaderHidden>
190
+ {WORKSPACES.map(workspace => (
191
+ <SideNavItem
192
+ key={workspace.name}
193
+ label={workspace.name}
194
+ icon={workspace.icon}
195
+ collapsible={{defaultIsCollapsed: false}}>
196
+ <VStack gap={0.5}>
197
+ {workspace.chats.map(chat => (
198
+ <ConversationItem
199
+ key={chat.label}
200
+ label={chat.label}
201
+ status={chat.status}
202
+ statusLabel={chat.statusLabel}
203
+ isSelected={chat.label === SELECTED_CHAT}
204
+ />
205
+ ))}
206
+ </VStack>
207
+ </SideNavItem>
208
+ ))}
209
+ </SideNavSection>
210
+ </SideNav>
211
+ }>
212
+ <Layout
213
+ height="fill"
214
+ contentWidth={768}
215
+ content={
216
+ <LayoutContent padding={6}>
217
+ <VStack gap={5}>
218
+ {MESSAGES.map((message, mi) => (
219
+ <HStack
220
+ key={mi}
221
+ hAlign={message.role === 'assistant' ? 'start' : 'end'}>
222
+ <Card
223
+ variant="muted"
224
+ padding={0}
225
+ width={message.width}
226
+ height={message.height}
227
+ />
228
+ </HStack>
229
+ ))}
230
+ </VStack>
231
+ </LayoutContent>
232
+ }
233
+ footer={
234
+ <LayoutFooter>
235
+ <Card variant="muted" padding={0} width="100%" height={56} />
236
+ </LayoutFooter>
237
+ }
238
+ />
239
+ </AppShell>
240
+ );
241
+ }
@@ -0,0 +1,12 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'page',
6
+ name: 'Side Nav',
7
+ displayName: 'Side Nav',
8
+ description:
9
+ 'A side-nav app shell with a collapsible, resizable SideNav (new chat, search, library, and workspace-grouped conversations with status dots) over static grey-card conversation and composer placeholders.',
10
+ isReady: true,
11
+ category: 'Shell - Left Sidebar',
12
+ };