@fragments-sdk/ui 0.17.1 → 0.18.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 (69) hide show
  1. package/fragments.json +1 -1
  2. package/package.json +3 -3
  3. package/src/components/Accordion/Accordion.contract.json +169 -0
  4. package/src/components/Alert/Alert.contract.json +157 -0
  5. package/src/components/AppShell/AppShell.contract.json +155 -0
  6. package/src/components/Avatar/Avatar.contract.json +189 -0
  7. package/src/components/Badge/Badge.contract.json +187 -0
  8. package/src/components/BentoGrid/BentoGrid.contract.json +135 -0
  9. package/src/components/Box/Box.contract.json +423 -0
  10. package/src/components/Breadcrumbs/Breadcrumbs.contract.json +143 -0
  11. package/src/components/Button/Button.contract.json +205 -0
  12. package/src/components/ButtonGroup/ButtonGroup.contract.json +140 -0
  13. package/src/components/Card/Card.contract.json +185 -0
  14. package/src/components/Chart/Chart.contract.json +129 -0
  15. package/src/components/Checkbox/Checkbox.contract.json +246 -0
  16. package/src/components/Chip/Chip.contract.json +212 -0
  17. package/src/components/CodeBlock/CodeBlock.contract.json +388 -0
  18. package/src/components/Collapsible/Collapsible.contract.json +154 -0
  19. package/src/components/ColorPicker/ColorPicker.contract.json +212 -0
  20. package/src/components/Combobox/Combobox.contract.json +297 -0
  21. package/src/components/Command/Command.contract.json +165 -0
  22. package/src/components/ConversationList/ConversationList.contract.json +151 -0
  23. package/src/components/DataTable/DataTable.contract.json +302 -0
  24. package/src/components/DatePicker/DatePicker.contract.json +288 -0
  25. package/src/components/Dialog/Dialog.contract.json +159 -0
  26. package/src/components/Drawer/Drawer.contract.json +160 -0
  27. package/src/components/Editor/Editor.contract.json +263 -0
  28. package/src/components/EmptyState/EmptyState.contract.json +133 -0
  29. package/src/components/Field/Field.contract.json +157 -0
  30. package/src/components/Fieldset/Fieldset.contract.json +117 -0
  31. package/src/components/Form/Form.contract.json +145 -0
  32. package/src/components/Grid/Grid.contract.json +195 -0
  33. package/src/components/Header/Header.contract.json +194 -0
  34. package/src/components/Icon/Icon.contract.json +194 -0
  35. package/src/components/Image/Image.contract.json +209 -0
  36. package/src/components/Input/Input.contract.json +344 -0
  37. package/src/components/Link/Link.contract.json +180 -0
  38. package/src/components/List/List.contract.json +154 -0
  39. package/src/components/Listbox/Listbox.contract.json +158 -0
  40. package/src/components/Loading/Loading.contract.json +167 -0
  41. package/src/components/Markdown/Markdown.contract.json +127 -0
  42. package/src/components/Menu/Menu.contract.json +177 -0
  43. package/src/components/Message/Message.contract.json +183 -0
  44. package/src/components/NavigationMenu/NavigationMenu.contract.json +203 -0
  45. package/src/components/Pagination/Pagination.contract.json +163 -0
  46. package/src/components/Popover/Popover.contract.json +163 -0
  47. package/src/components/Progress/Progress.contract.json +176 -0
  48. package/src/components/Prompt/Prompt.contract.json +211 -0
  49. package/src/components/RadioGroup/RadioGroup.contract.json +226 -0
  50. package/src/components/ScrollArea/ScrollArea.contract.json +131 -0
  51. package/src/components/Select/Select.contract.json +269 -0
  52. package/src/components/Separator/Separator.contract.json +143 -0
  53. package/src/components/Sidebar/Sidebar.contract.json +258 -0
  54. package/src/components/Skeleton/Skeleton.contract.json +166 -0
  55. package/src/components/Slider/Slider.contract.json +248 -0
  56. package/src/components/Stack/Stack.contract.json +220 -0
  57. package/src/components/Table/Table.contract.json +171 -0
  58. package/src/components/TableOfContents/TableOfContents.contract.json +145 -0
  59. package/src/components/Tabs/Tabs.contract.json +159 -0
  60. package/src/components/Text/Text.contract.json +239 -0
  61. package/src/components/Textarea/Textarea.contract.json +308 -0
  62. package/src/components/Theme/Theme.contract.json +152 -0
  63. package/src/components/ThinkingIndicator/ThinkingIndicator.contract.json +165 -0
  64. package/src/components/Toast/Toast.contract.json +181 -0
  65. package/src/components/Toggle/Toggle.contract.json +231 -0
  66. package/src/components/ToggleGroup/ToggleGroup.contract.json +206 -0
  67. package/src/components/Tooltip/Tooltip.contract.json +214 -0
  68. package/src/components/VisuallyHidden/VisuallyHidden.contract.json +116 -0
  69. package/src/tokens/_derive.scss +4 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fragments-sdk/ui",
3
- "version": "0.17.1",
3
+ "version": "0.18.0",
4
4
  "license": "MIT",
5
5
  "description": "Customizable UI components built on Base UI headless primitives",
6
6
  "author": "Conan McNicholl",
@@ -230,7 +230,7 @@
230
230
  "vite": "^6.0.0",
231
231
  "vitest": "^2.1.8",
232
232
  "vitest-axe": "^0.1.0",
233
- "@fragments-sdk/core": "1.0.1"
233
+ "@fragments-sdk/core": "2.0.0"
234
234
  },
235
235
  "files": [
236
236
  "src",
@@ -246,7 +246,7 @@
246
246
  ],
247
247
  "scripts": {
248
248
  "cli:ensure": "test -f ../../packages/cli/dist/bin.js || pnpm --filter @fragments-sdk/cli build",
249
- "dev": "pnpm run cli:ensure && node ../../packages/cli/dist/bin.js dev",
249
+ "dev": "pnpm run cli:ensure && node ../../packages/cli/dist/bin.js build",
250
250
  "build": "pnpm run cli:ensure && node ../../packages/cli/dist/bin.js build && vite build && tsc -p tsconfig.build.json",
251
251
  "lint": "eslint src",
252
252
  "validate": "pnpm run cli:ensure && node ../../packages/cli/dist/bin.js validate",
@@ -0,0 +1,169 @@
1
+ {
2
+ "$schema": "https://usefragments.com/schemas/contract.v1.json",
3
+ "name": "Accordion",
4
+ "description": "Vertically stacked, collapsible content sections. Use for organizing related content that can be progressively disclosed.",
5
+ "category": "layout",
6
+ "tags": [
7
+ "accordion",
8
+ "collapse",
9
+ "expand",
10
+ "disclosure",
11
+ "faq"
12
+ ],
13
+ "status": "stable",
14
+ "sourcePath": "src/components/Accordion/index.tsx",
15
+ "exportName": "Accordion",
16
+ "propsSummary": [
17
+ "type: single|multiple (default: single)",
18
+ "value: union",
19
+ "defaultValue: union",
20
+ "onValueChange: union",
21
+ "children: node (required)",
22
+ "collapsible: boolean (default: false)",
23
+ "headingLevel: union (default: 3)"
24
+ ],
25
+ "props": {
26
+ "type": {
27
+ "type": "enum",
28
+ "description": "Whether one or multiple items can be open",
29
+ "default": "single",
30
+ "required": false,
31
+ "values": [
32
+ "single",
33
+ "multiple"
34
+ ]
35
+ },
36
+ "value": {
37
+ "type": "union",
38
+ "description": "Controlled open item(s): string in single mode, string[] in multiple mode",
39
+ "required": false
40
+ },
41
+ "defaultValue": {
42
+ "type": "union",
43
+ "description": "Initially open item(s): string in single mode, string[] in multiple mode",
44
+ "required": false
45
+ },
46
+ "onValueChange": {
47
+ "type": "union",
48
+ "description": "Called when open items change (single: string | undefined, multiple: string[])",
49
+ "required": false
50
+ },
51
+ "children": {
52
+ "type": "node",
53
+ "description": "Accordion items (use Accordion.Item with Accordion.Trigger and Accordion.Content)",
54
+ "required": true
55
+ },
56
+ "collapsible": {
57
+ "type": "boolean",
58
+ "description": "Whether all items can be closed (single mode only)",
59
+ "default": "false",
60
+ "required": false
61
+ },
62
+ "headingLevel": {
63
+ "type": "union",
64
+ "description": "Semantic heading level for accordion triggers",
65
+ "default": "3",
66
+ "required": false,
67
+ "values": [
68
+ "2",
69
+ "3",
70
+ "4",
71
+ "5",
72
+ "6"
73
+ ]
74
+ }
75
+ },
76
+ "usage": {
77
+ "when": [
78
+ "FAQ pages with multiple questions and answers",
79
+ "Settings panels with grouped options",
80
+ "Long forms that benefit from progressive disclosure",
81
+ "Navigation menus with nested items"
82
+ ],
83
+ "whenNot": [
84
+ "Primary content that all users need to see",
85
+ "Very short content (just display inline)",
86
+ "Sequential steps (use Stepper or wizard)",
87
+ "Tab-like navigation (use Tabs instead)"
88
+ ],
89
+ "guidelines": [
90
+ "Keep section headers concise and descriptive",
91
+ "Use single mode when only one section should be open at a time",
92
+ "Use multiple mode when users may need to compare sections",
93
+ "Consider defaulting important sections to open",
94
+ "Avoid nesting accordions more than one level deep"
95
+ ],
96
+ "accessibility": [
97
+ "Keyboard navigation with Enter/Space to toggle",
98
+ "Uses proper ARIA expanded/controls attributes",
99
+ "Focus is visible on accordion triggers"
100
+ ]
101
+ },
102
+ "examples": [
103
+ {
104
+ "name": "Basic",
105
+ "description": "Single accordion with collapsible sections",
106
+ "code": "import { Accordion } from '@/components/Accordion';\n\n<Accordion type=\"single\" collapsible defaultValue=\"item-1\">\n <Accordion.Item value=\"item-1\">\n <Accordion.Trigger>What is Fragments UI?</Accordion.Trigger>\n <Accordion.Content>\n Fragments UI is a modern React component library built on Base UI primitives, providing accessible and customizable components.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"item-2\">\n <Accordion.Trigger>How do I install it?</Accordion.Trigger>\n <Accordion.Content>\n Install via npm or pnpm: pnpm add @fragments-sdk/ui\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"item-3\">\n <Accordion.Trigger>Is it accessible?</Accordion.Trigger>\n <Accordion.Content>\n Yes! All components follow WAI-ARIA guidelines and support keyboard navigation.\n </Accordion.Content>\n </Accordion.Item>\n</Accordion>"
107
+ },
108
+ {
109
+ "name": "Multiple Open",
110
+ "description": "Allows multiple sections to be open simultaneously",
111
+ "code": "import { Accordion } from '@/components/Accordion';\n\n<Accordion type=\"multiple\" defaultValue={['features', 'pricing']}>\n <Accordion.Item value=\"features\">\n <Accordion.Trigger>Features</Accordion.Trigger>\n <Accordion.Content>\n Comprehensive component library with theming support, accessibility built-in, and TypeScript-first development.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"pricing\">\n <Accordion.Trigger>Pricing</Accordion.Trigger>\n <Accordion.Content>\n Free and open source. MIT licensed for both personal and commercial use.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"support\">\n <Accordion.Trigger>Support</Accordion.Trigger>\n <Accordion.Content>\n Community support via GitHub issues and discussions.\n </Accordion.Content>\n </Accordion.Item>\n</Accordion>"
112
+ },
113
+ {
114
+ "name": "With Disabled",
115
+ "description": "Accordion with a disabled item",
116
+ "code": "import { Accordion } from '@/components/Accordion';\n\n<Accordion type=\"single\" collapsible>\n <Accordion.Item value=\"available\">\n <Accordion.Trigger>Available Section</Accordion.Trigger>\n <Accordion.Content>\n This section can be expanded and collapsed.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"disabled\" disabled>\n <Accordion.Trigger>Disabled Section</Accordion.Trigger>\n <Accordion.Content>\n This content is not accessible because the item is disabled.\n </Accordion.Content>\n </Accordion.Item>\n <Accordion.Item value=\"another\">\n <Accordion.Trigger>Another Section</Accordion.Trigger>\n <Accordion.Content>\n This section is also available for interaction.\n </Accordion.Content>\n </Accordion.Item>\n</Accordion>"
117
+ }
118
+ ],
119
+ "relations": [
120
+ {
121
+ "component": "Tabs",
122
+ "relationship": "alternative",
123
+ "note": "Use Tabs for horizontal switching between related views"
124
+ },
125
+ {
126
+ "component": "Dialog",
127
+ "relationship": "alternative",
128
+ "note": "Use Dialog for focused content that interrupts the flow"
129
+ },
130
+ {
131
+ "component": "Card",
132
+ "relationship": "complementary",
133
+ "note": "Accordion items can contain Card-like content"
134
+ }
135
+ ],
136
+ "contract": {
137
+ "propsSummary": [
138
+ "type: single|multiple - controls how many items can be open",
139
+ "value/defaultValue are type-discriminated (single -> string, multiple -> string[])",
140
+ "onValueChange is type-discriminated by mode (single -> string|undefined, multiple -> string[])",
141
+ "collapsible: boolean - allow all closed in single mode",
142
+ "Accordion.Trigger forwards button props and defaults type=\"button\""
143
+ ],
144
+ "a11yRules": [
145
+ "A11Y_DISCLOSURE_KEYBOARD",
146
+ "A11Y_FOCUS_VISIBLE"
147
+ ]
148
+ },
149
+ "ai": {
150
+ "compositionPattern": "compound",
151
+ "subComponents": [
152
+ "Item",
153
+ "Trigger",
154
+ "Content"
155
+ ],
156
+ "requiredChildren": [
157
+ "Item"
158
+ ],
159
+ "commonPatterns": [
160
+ "<Accordion type=\"single\" collapsible><Accordion.Item value=\"item-1\"><Accordion.Trigger>{title}</Accordion.Trigger><Accordion.Content>{content}</Accordion.Content></Accordion.Item></Accordion>"
161
+ ]
162
+ },
163
+ "provenance": {
164
+ "source": "migrated",
165
+ "verified": false,
166
+ "frameworkSupport": "native",
167
+ "extractedAt": "2026-03-13T23:18:49.840Z"
168
+ }
169
+ }
@@ -0,0 +1,157 @@
1
+ {
2
+ "$schema": "https://usefragments.com/schemas/contract.v1.json",
3
+ "name": "Alert",
4
+ "description": "Contextual feedback messages for user actions or system status. Supports multiple severity levels with optional actions and dismissibility.",
5
+ "category": "feedback",
6
+ "tags": [
7
+ "notification",
8
+ "message",
9
+ "feedback",
10
+ "banner",
11
+ "toast"
12
+ ],
13
+ "status": "stable",
14
+ "sourcePath": "src/components/Alert/index.tsx",
15
+ "exportName": "Alert",
16
+ "propsSummary": [
17
+ "children: node (required)",
18
+ "severity: info|success|warning|error (default: info)"
19
+ ],
20
+ "props": {
21
+ "children": {
22
+ "type": "node",
23
+ "description": "Alert content - use Alert.Icon, Alert.Body, Alert.Title, Alert.Content, Alert.Actions, Alert.Close sub-components",
24
+ "required": true
25
+ },
26
+ "severity": {
27
+ "type": "enum",
28
+ "description": "Visual severity level",
29
+ "default": "info",
30
+ "required": false,
31
+ "values": [
32
+ "info",
33
+ "success",
34
+ "warning",
35
+ "error"
36
+ ]
37
+ }
38
+ },
39
+ "usage": {
40
+ "when": [
41
+ "Communicating the result of a user action (success, error)",
42
+ "Warning about potential issues before they occur",
43
+ "Providing important contextual information inline",
44
+ "System status notifications that require attention"
45
+ ],
46
+ "whenNot": [
47
+ "Brief status labels (use Badge instead)",
48
+ "Transient notifications (use Toast/Snackbar)",
49
+ "Form-field-level errors (use Input error prop)",
50
+ "Confirmation before destructive actions (use Dialog)"
51
+ ],
52
+ "guidelines": [
53
+ "Match severity to the actual importance: info for context, warning for potential issues, error for failures",
54
+ "Always provide actionable guidance in error alerts",
55
+ "Use Alert.Title for complex messages; skip titles for brief one-liners",
56
+ "Limit to one action per alert to avoid decision paralysis",
57
+ "Use Alert.Close only for non-critical information",
58
+ "Alert.Action and Alert.Close render buttons with type=\"button\" by default (safe inside forms)",
59
+ "Alert.Close composes your onClick handler with built-in dismiss behavior and respects preventDefault()",
60
+ "Alert sub-components forward DOM props (aria-*, data-*, id, handlers) to their rendered elements"
61
+ ],
62
+ "accessibility": [
63
+ "Uses role=\"alert\" for screen reader announcement",
64
+ "Error and warning alerts are announced immediately by assistive technology",
65
+ "Alert.Close must have an accessible label",
66
+ "Color alone must not convey meaning - icons and text reinforce severity"
67
+ ]
68
+ },
69
+ "examples": [
70
+ {
71
+ "name": "Info",
72
+ "description": "Informational context for the user",
73
+ "code": "import { Alert } from '@/components/Alert';\n\n<Alert severity=\"info\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Content>\n Your session will expire in 15 minutes. Save your work to avoid losing changes.\n </Alert.Content>\n </Alert.Body>\n</Alert>"
74
+ },
75
+ {
76
+ "name": "Success",
77
+ "description": "Positive confirmation of completed action",
78
+ "code": "import { Alert } from '@/components/Alert';\n\n<Alert severity=\"success\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Title>Payment processed</Alert.Title>\n <Alert.Content>\n Your order #12345 has been confirmed. You will receive a confirmation email shortly.\n </Alert.Content>\n </Alert.Body>\n</Alert>"
79
+ },
80
+ {
81
+ "name": "Warning",
82
+ "description": "Caution about potential issues",
83
+ "code": "import { Alert } from '@/components/Alert';\n\n<Alert severity=\"warning\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Title>Storage almost full</Alert.Title>\n <Alert.Content>\n You have used 90% of your storage quota. Consider deleting unused files.\n </Alert.Content>\n </Alert.Body>\n</Alert>"
84
+ },
85
+ {
86
+ "name": "Error",
87
+ "description": "Error state requiring user attention",
88
+ "code": "import { Alert } from '@/components/Alert';\n\n<Alert severity=\"error\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Title>Upload failed</Alert.Title>\n <Alert.Content>\n The file could not be uploaded. Check your connection and try again.\n </Alert.Content>\n </Alert.Body>\n</Alert>"
89
+ },
90
+ {
91
+ "name": "With Action",
92
+ "description": "Alert with an actionable button",
93
+ "code": "import { Alert } from '@/components/Alert';\n\n<Alert severity=\"warning\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Title>Update available</Alert.Title>\n <Alert.Content>\n A new version is available with important security fixes.\n </Alert.Content>\n <Alert.Actions>\n <Alert.Action onClick={() => {}}>Update now</Alert.Action>\n </Alert.Actions>\n </Alert.Body>\n</Alert>"
94
+ },
95
+ {
96
+ "name": "Dismissible",
97
+ "description": "Alert that can be closed by the user",
98
+ "code": "import { Alert } from '@/components/Alert';\n\n<Alert severity=\"info\">\n <Alert.Icon />\n <Alert.Body>\n <Alert.Content>\n You can customize your notification preferences in Settings.\n </Alert.Content>\n </Alert.Body>\n <Alert.Close />\n</Alert>"
99
+ }
100
+ ],
101
+ "relations": [
102
+ {
103
+ "component": "Badge",
104
+ "relationship": "alternative",
105
+ "note": "Use Badge for compact, inline status labels"
106
+ },
107
+ {
108
+ "component": "Toast",
109
+ "relationship": "alternative",
110
+ "note": "Use Toast for transient notifications that auto-dismiss"
111
+ },
112
+ {
113
+ "component": "Dialog",
114
+ "relationship": "sibling",
115
+ "note": "Use Dialog for blocking confirmations"
116
+ }
117
+ ],
118
+ "contract": {
119
+ "propsSummary": [
120
+ "severity: info|success|warning|error - visual severity",
121
+ "Sub-components: Alert.Icon, Alert.Body, Alert.Title, Alert.Content, Alert.Actions, Alert.Action, Alert.Close",
122
+ "Alert.Action / Alert.Close accept button props and default type=\"button\""
123
+ ],
124
+ "a11yRules": [
125
+ "A11Y_ALERT_ROLE",
126
+ "A11Y_ALERT_DISMISS",
127
+ "A11Y_ALERT_CONTRAST",
128
+ "A11Y_TARGET_SIZE_MIN"
129
+ ]
130
+ },
131
+ "ai": {
132
+ "compositionPattern": "compound",
133
+ "subComponents": [
134
+ "Icon",
135
+ "Body",
136
+ "Title",
137
+ "Content",
138
+ "Actions",
139
+ "Action",
140
+ "Close"
141
+ ],
142
+ "requiredChildren": [
143
+ "Body"
144
+ ],
145
+ "commonPatterns": [
146
+ "<Alert severity=\"info\"><Alert.Icon /><Alert.Body><Alert.Content>{message}</Alert.Content></Alert.Body></Alert>",
147
+ "<Alert severity=\"warning\"><Alert.Icon /><Alert.Body><Alert.Title>{title}</Alert.Title><Alert.Content>{message}</Alert.Content></Alert.Body></Alert>",
148
+ "<Alert severity=\"error\"><Alert.Icon /><Alert.Body><Alert.Title>{title}</Alert.Title><Alert.Content>{message}</Alert.Content></Alert.Body><Alert.Close /></Alert>"
149
+ ]
150
+ },
151
+ "provenance": {
152
+ "source": "migrated",
153
+ "verified": false,
154
+ "frameworkSupport": "native",
155
+ "extractedAt": "2026-03-13T23:18:50.066Z"
156
+ }
157
+ }
@@ -0,0 +1,155 @@
1
+ {
2
+ "$schema": "https://usefragments.com/schemas/contract.v1.json",
3
+ "name": "AppShell",
4
+ "description": "Full layout wrapper integrating sidebar, header, main content, and optional aside panel. Two structural layouts (default, sidebar) combine with per-slot variant=\"floating\" for full flexibility.",
5
+ "category": "layout",
6
+ "tags": [
7
+ "layout",
8
+ "shell",
9
+ "scaffold",
10
+ "dashboard",
11
+ "app-layout"
12
+ ],
13
+ "status": "stable",
14
+ "sourcePath": "src/components/AppShell/index.tsx",
15
+ "exportName": "AppShell",
16
+ "propsSummary": [
17
+ "children: node (required)",
18
+ "layout: default|sidebar|sidebar-floating|floating (default: default)",
19
+ "bg: string",
20
+ "style: object"
21
+ ],
22
+ "props": {
23
+ "children": {
24
+ "type": "node",
25
+ "description": "Layout content (use AppShell.Header, AppShell.Sidebar, AppShell.Main, AppShell.Aside)",
26
+ "required": true
27
+ },
28
+ "layout": {
29
+ "type": "enum",
30
+ "description": "Structural layout for CSS grid areas",
31
+ "default": "default",
32
+ "required": false,
33
+ "values": [
34
+ "default",
35
+ "sidebar",
36
+ "sidebar-floating",
37
+ "floating"
38
+ ]
39
+ },
40
+ "bg": {
41
+ "type": "string",
42
+ "description": "Background color override for the shell container (accepts any CSS color or token reference like \"var(--fui-bg-secondary)\")",
43
+ "required": false
44
+ },
45
+ "style": {
46
+ "type": "object",
47
+ "description": "",
48
+ "required": false
49
+ }
50
+ },
51
+ "usage": {
52
+ "when": [
53
+ "Building dashboard-style applications",
54
+ "Apps with persistent sidebar navigation",
55
+ "Layouts requiring header, sidebar, and main content areas",
56
+ "Responsive layouts that need mobile drawer behavior"
57
+ ],
58
+ "whenNot": [
59
+ "Simple marketing pages (use standard layout)",
60
+ "Content-first sites without navigation (use simpler layout)",
61
+ "Single-page apps with minimal UI (use minimal layout)"
62
+ ],
63
+ "guidelines": [
64
+ "Use layout=\"default\" when header should span full width (logo in header)",
65
+ "Use layout=\"sidebar\" when sidebar should be full height (logo in sidebar)",
66
+ "Add variant=\"floating\" to individual slots for rounded, elevated appearance",
67
+ "Use bg prop on any slot to override its background color",
68
+ "Combine layout with per-slot variants freely — no enum explosion",
69
+ "AppShell automatically wraps with SidebarProvider",
70
+ "Use AppShell.Sidebar to configure sidebar width and collapse behavior",
71
+ "Main content responds to sidebar collapsed state",
72
+ "Aside panel is hidden on mobile automatically"
73
+ ],
74
+ "accessibility": [
75
+ "Main content area has id=\"main-content\" for skip links",
76
+ "Use Header.SkipLink for keyboard navigation",
77
+ "Sidebar drawer has proper focus trap on mobile",
78
+ "Keyboard navigation supported throughout"
79
+ ]
80
+ },
81
+ "examples": [
82
+ {
83
+ "name": "Default Layout",
84
+ "description": "Header spans full width above sidebar (default). Best when brand/logo should be prominent in header.",
85
+ "code": "import { ChartBar, Gear, House } from '@phosphor-icons/react';\nimport { AppShell } from '@/components/AppShell';\nimport { Box } from '@/components/Box';\nimport { Header } from '@/components/Header';\nimport { Icon } from '@/components/Icon';\nimport { Sidebar } from '@/components/Sidebar';\nimport { Stack } from '@/components/Stack';\nimport { Text } from '@/components/Text';\nimport { ThemeToggle } from '@/components/Theme';\n\n<Box minHeight=\"100vh\" overflow=\"hidden\" border rounded=\"md\">\n <AppShell layout=\"default\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Brand>MyApp</Header.Brand>\n <Header.Nav>\n <Header.NavItem active>Dashboard</Header.NavItem>\n <Header.NavItem>Settings</Header.NavItem>\n </Header.Nav>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"200px\" collapsible=\"offcanvas\">\n <Sidebar.Nav>\n <Sidebar.Section label=\"Menu\">\n <Sidebar.Item icon={<Icon icon={House} size=\"md\" />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<Icon icon={ChartBar} size=\"md\" />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<Icon icon={Gear} size=\"md\" />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\">\n <Stack gap=\"xs\">\n <Text as=\"h2\" size=\"xl\" weight=\"semibold\">Default Layout</Text>\n <Text as=\"p\" color=\"secondary\">\n Header spans full width. Logo is in the header.\n </Text>\n </Stack>\n </AppShell.Main>\n </AppShell>\n</Box>"
86
+ },
87
+ {
88
+ "name": "Sidebar Layout",
89
+ "description": "Sidebar is full height, header sits next to it. Best for documentation sites or when sidebar branding is preferred.",
90
+ "code": "import { ChartBar, Gear, House, MagnifyingGlass } from '@phosphor-icons/react';\nimport { AppShell } from '@/components/AppShell';\nimport { Box } from '@/components/Box';\nimport { Header } from '@/components/Header';\nimport { Icon } from '@/components/Icon';\nimport { Sidebar } from '@/components/Sidebar';\nimport { Stack } from '@/components/Stack';\nimport { Text } from '@/components/Text';\nimport { ThemeToggle } from '@/components/Theme';\n\n<Box minHeight=\"100vh\" overflow=\"hidden\" border rounded=\"md\">\n <AppShell layout=\"sidebar\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Search>\n <Box background=\"secondary\" rounded=\"sm\" paddingX=\"sm\" paddingY=\"xs\">\n <Stack direction=\"row\" align=\"center\" gap=\"sm\">\n <Icon icon={MagnifyingGlass} size=\"sm\" variant=\"tertiary\" />\n <Text size=\"sm\" color=\"tertiary\">Search...</Text>\n </Stack>\n </Box>\n </Header.Search>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"200px\" collapsible=\"offcanvas\">\n <Sidebar.Header>\n <Text weight=\"semibold\">MyApp</Text>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section label=\"Menu\">\n <Sidebar.Item icon={<Icon icon={House} size=\"md\" />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<Icon icon={ChartBar} size=\"md\" />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<Icon icon={Gear} size=\"md\" />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>v1.0.0</Sidebar.Footer>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\">\n <Stack gap=\"xs\">\n <Text as=\"h2\" size=\"xl\" weight=\"semibold\">Sidebar Layout</Text>\n <Text as=\"p\" color=\"secondary\">\n Sidebar is full height. Logo is in the sidebar header.\n </Text>\n </Stack>\n </AppShell.Main>\n </AppShell>\n</Box>"
91
+ },
92
+ {
93
+ "name": "With Aside Panel",
94
+ "description": "App shell with optional right panel for additional context or actions.",
95
+ "code": "import { ChartBar, House } from '@phosphor-icons/react';\nimport { AppShell } from '@/components/AppShell';\nimport { Box } from '@/components/Box';\nimport { Header } from '@/components/Header';\nimport { Icon } from '@/components/Icon';\nimport { Sidebar } from '@/components/Sidebar';\nimport { Stack } from '@/components/Stack';\nimport { Text } from '@/components/Text';\nimport { ThemeToggle } from '@/components/Theme';\n\n<Box minHeight=\"100vh\" overflow=\"hidden\" border rounded=\"md\">\n <AppShell layout=\"default\">\n <AppShell.Header>\n <Header>\n <Header.Brand>App</Header.Brand>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"180px\" collapsible=\"offcanvas\">\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<Icon icon={House} size=\"md\" />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<Icon icon={ChartBar} size=\"md\" />}>Stats</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\">\n <Stack gap=\"xs\">\n <Text as=\"h2\" size=\"xl\" weight=\"semibold\">Main Content</Text>\n <Text as=\"p\">Content with aside panel on the right.</Text>\n </Stack>\n </AppShell.Main>\n\n <AppShell.Aside width=\"180px\">\n <Box padding=\"md\">\n <Stack gap=\"xs\">\n <Text as=\"h3\" size=\"sm\" weight=\"semibold\">Aside Panel</Text>\n <Text as=\"p\" size=\"sm\" color=\"secondary\">\n Additional context, filters, or quick actions.\n </Text>\n </Stack>\n </Box>\n </AppShell.Aside>\n </AppShell>\n</Box>"
96
+ },
97
+ {
98
+ "name": "Collapsible Icon Sidebar",
99
+ "description": "Sidebar that collapses to icons only on desktop.",
100
+ "code": "import { ChartBar, Gear, House } from '@phosphor-icons/react';\nimport { AppShell } from '@/components/AppShell';\nimport { Box } from '@/components/Box';\nimport { Header } from '@/components/Header';\nimport { Icon } from '@/components/Icon';\nimport { Sidebar } from '@/components/Sidebar';\nimport { Text } from '@/components/Text';\nimport { ThemeToggle } from '@/components/Theme';\n\n<Box minHeight=\"100vh\" overflow=\"hidden\" border rounded=\"md\">\n <AppShell layout=\"sidebar\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar collapsible=\"icon\" width=\"200px\" collapsedWidth=\"56px\">\n <Sidebar.Header>\n <Text weight=\"semibold\">App</Text>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<Icon icon={House} size=\"md\" />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<Icon icon={ChartBar} size=\"md\" />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<Icon icon={Gear} size=\"md\" />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\">\n <Text as=\"p\">\n Click the collapse button in the sidebar footer to toggle between expanded and icon-only modes.\n </Text>\n </AppShell.Main>\n </AppShell>\n</Box>"
101
+ },
102
+ {
103
+ "name": "Floating Main",
104
+ "description": "Sidebar layout with floating main content. Per-slot variant=\"floating\" gives the main area rounded corners and a distinct background, while the sidebar blends with the shell.",
105
+ "code": "import { ChartBar, Gear, House, MagnifyingGlass } from '@phosphor-icons/react';\nimport { AppShell } from '@/components/AppShell';\nimport { Box } from '@/components/Box';\nimport { Header } from '@/components/Header';\nimport { Icon } from '@/components/Icon';\nimport { Sidebar } from '@/components/Sidebar';\nimport { Stack } from '@/components/Stack';\nimport { Text } from '@/components/Text';\nimport { ThemeToggle } from '@/components/Theme';\n\n<Box minHeight=\"100vh\" overflow=\"hidden\" border rounded=\"md\">\n <AppShell layout=\"sidebar\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Search>\n <Box background=\"primary\" border rounded=\"sm\" paddingX=\"sm\" paddingY=\"xs\">\n <Stack direction=\"row\" align=\"center\" gap=\"sm\">\n <Icon icon={MagnifyingGlass} size=\"sm\" variant=\"tertiary\" />\n <Text size=\"sm\" color=\"tertiary\">Search...</Text>\n </Stack>\n </Box>\n </Header.Search>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"200px\" collapsible=\"offcanvas\" variant=\"floating\">\n <Sidebar.Header>\n <Text weight=\"semibold\">MyApp</Text>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section label=\"Menu\">\n <Sidebar.Item icon={<Icon icon={House} size=\"md\" />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<Icon icon={ChartBar} size=\"md\" />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<Icon icon={Gear} size=\"md\" />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>v1.0.0</Sidebar.Footer>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\" variant=\"floating\">\n <Stack gap=\"xs\">\n <Text as=\"h2\" size=\"xl\" weight=\"semibold\">Floating Main</Text>\n <Text as=\"p\" color=\"secondary\">\n Main content has rounded corners and visual separation from the sidebar.\n </Text>\n </Stack>\n </AppShell.Main>\n </AppShell>\n</Box>"
106
+ },
107
+ {
108
+ "name": "Floating Main & Aside",
109
+ "description": "Both main content and aside panel float with rounded corners. Each slot independently opts into the floating visual treatment via variant=\"floating\".",
110
+ "code": "import { ChartBar, Gear, House, MagnifyingGlass } from '@phosphor-icons/react';\nimport { AppShell } from '@/components/AppShell';\nimport { Box } from '@/components/Box';\nimport { Header } from '@/components/Header';\nimport { Icon } from '@/components/Icon';\nimport { Sidebar } from '@/components/Sidebar';\nimport { Stack } from '@/components/Stack';\nimport { Text } from '@/components/Text';\nimport { ThemeToggle } from '@/components/Theme';\n\n<Box minHeight=\"100vh\" overflow=\"hidden\" border rounded=\"md\">\n <AppShell layout=\"sidebar\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Search>\n <Box background=\"primary\" border rounded=\"sm\" paddingX=\"sm\" paddingY=\"xs\">\n <Stack direction=\"row\" align=\"center\" gap=\"sm\">\n <Icon icon={MagnifyingGlass} size=\"sm\" variant=\"tertiary\" />\n <Text size=\"sm\" color=\"tertiary\">Search...</Text>\n </Stack>\n </Box>\n </Header.Search>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"200px\" collapsible=\"offcanvas\" variant=\"floating\">\n <Sidebar.Header>\n <Text weight=\"semibold\">MyApp</Text>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section label=\"Menu\">\n <Sidebar.Item icon={<Icon icon={House} size=\"md\" />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<Icon icon={ChartBar} size=\"md\" />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<Icon icon={Gear} size=\"md\" />}>Settings</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>v1.0.0</Sidebar.Footer>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\" variant=\"floating\">\n <Stack gap=\"xs\">\n <Text as=\"h2\" size=\"xl\" weight=\"semibold\">Floating Main & Aside</Text>\n <Text as=\"p\" color=\"secondary\">\n Both main content and aside panel float with rounded corners.\n </Text>\n </Stack>\n </AppShell.Main>\n\n <AppShell.Aside width=\"200px\" variant=\"floating\">\n <Box padding=\"md\">\n <Stack gap=\"xs\">\n <Text as=\"h3\" size=\"sm\" weight=\"semibold\">Aside Panel</Text>\n <Text as=\"p\" size=\"sm\" color=\"secondary\">\n This aside also floats, matching the main content area.\n </Text>\n </Stack>\n </Box>\n </AppShell.Aside>\n </AppShell>\n</Box>"
111
+ },
112
+ {
113
+ "name": "Floating Default Layout",
114
+ "description": "Default header-on-top structure with a floating main content area. Demonstrates that floating is independent of structure — any slot can float in any layout.",
115
+ "code": "import { ChartBar, House } from '@phosphor-icons/react';\nimport { AppShell } from '@/components/AppShell';\nimport { Box } from '@/components/Box';\nimport { Header } from '@/components/Header';\nimport { Icon } from '@/components/Icon';\nimport { Sidebar } from '@/components/Sidebar';\nimport { Stack } from '@/components/Stack';\nimport { Text } from '@/components/Text';\nimport { ThemeToggle } from '@/components/Theme';\n\n<Box minHeight=\"100vh\" overflow=\"hidden\" border rounded=\"md\">\n <AppShell layout=\"default\">\n <AppShell.Header>\n <Header>\n <Header.Brand>MyApp</Header.Brand>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"180px\" collapsible=\"offcanvas\" variant=\"floating\">\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<Icon icon={House} size=\"md\" />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<Icon icon={ChartBar} size=\"md\" />}>Stats</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\" variant=\"floating\">\n <Stack gap=\"xs\">\n <Text as=\"h2\" size=\"xl\" weight=\"semibold\">Floating Default Layout</Text>\n <Text as=\"p\" color=\"secondary\">\n Default structure (header on top) with floating main content. Any slot can float in any layout.\n </Text>\n </Stack>\n </AppShell.Main>\n </AppShell>\n</Box>"
116
+ },
117
+ {
118
+ "name": "Custom Backgrounds",
119
+ "description": "Each slot accepts a bg prop to override its background color independently. Here the sidebar and aside use bg-elevated (lighter) while main uses bg-primary (darker).",
120
+ "code": "import { ChartBar, House } from '@phosphor-icons/react';\nimport { AppShell } from '@/components/AppShell';\nimport { Box } from '@/components/Box';\nimport { Header } from '@/components/Header';\nimport { Icon } from '@/components/Icon';\nimport { Sidebar } from '@/components/Sidebar';\nimport { Stack } from '@/components/Stack';\nimport { Text } from '@/components/Text';\nimport { ThemeToggle } from '@/components/Theme';\n\n<Box minHeight=\"100vh\" overflow=\"hidden\" border rounded=\"md\">\n <AppShell layout=\"sidebar\">\n <AppShell.Header>\n <Header>\n <Header.Trigger />\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"sm\" />\n </Header.Actions>\n </Header>\n </AppShell.Header>\n\n <AppShell.Sidebar width=\"200px\" collapsible=\"offcanvas\" bg=\"var(--fui-bg-elevated)\">\n <Sidebar.Header>\n <Text weight=\"semibold\">MyApp</Text>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section label=\"Menu\">\n <Sidebar.Item icon={<Icon icon={House} size=\"md\" />} active>Home</Sidebar.Item>\n <Sidebar.Item icon={<Icon icon={ChartBar} size=\"md\" />}>Analytics</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n </AppShell.Sidebar>\n\n <AppShell.Main padding=\"md\" bg=\"var(--fui-bg-primary)\">\n <Stack gap=\"xs\">\n <Text as=\"h2\" size=\"xl\" weight=\"semibold\">Custom Backgrounds</Text>\n <Text as=\"p\" color=\"secondary\">\n Sidebar uses bg-elevated (lighter), main uses bg-primary (darker). Any CSS color or token works.\n </Text>\n </Stack>\n </AppShell.Main>\n\n <AppShell.Aside width=\"200px\" bg=\"var(--fui-bg-elevated)\">\n <Box padding=\"md\">\n <Stack gap=\"xs\">\n <Text as=\"h3\" size=\"sm\" weight=\"semibold\">Aside Panel</Text>\n <Text as=\"p\" size=\"sm\" color=\"secondary\">\n Aside with bg-elevated background matching the sidebar.\n </Text>\n </Stack>\n </Box>\n </AppShell.Aside>\n </AppShell>\n</Box>"
121
+ }
122
+ ],
123
+ "relations": [
124
+ {
125
+ "component": "Theme",
126
+ "relationship": "parent",
127
+ "note": "AppShell should be wrapped in ThemeProvider"
128
+ },
129
+ {
130
+ "component": "Header",
131
+ "relationship": "child",
132
+ "note": "Header is placed inside AppShell.Header"
133
+ },
134
+ {
135
+ "component": "Sidebar",
136
+ "relationship": "child",
137
+ "note": "Sidebar content goes inside AppShell.Sidebar"
138
+ }
139
+ ],
140
+ "ai": {
141
+ "compositionPattern": "compound",
142
+ "subComponents": [
143
+ "Header",
144
+ "Sidebar",
145
+ "Main",
146
+ "Aside"
147
+ ]
148
+ },
149
+ "provenance": {
150
+ "source": "migrated",
151
+ "verified": false,
152
+ "frameworkSupport": "native",
153
+ "extractedAt": "2026-03-13T23:18:50.550Z"
154
+ }
155
+ }