@fragments-sdk/ui 0.17.0 → 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 (84) hide show
  1. package/dist/assets/ui.css +320 -183
  2. package/dist/components/Header/Header.module.scss.cjs +42 -21
  3. package/dist/components/Header/Header.module.scss.js +42 -21
  4. package/dist/components/Header/index.cjs +121 -3
  5. package/dist/components/Header/index.d.ts +26 -3
  6. package/dist/components/Header/index.d.ts.map +1 -1
  7. package/dist/components/Header/index.js +122 -4
  8. package/dist/components/Sidebar/Sidebar.module.scss.cjs +42 -42
  9. package/dist/components/Sidebar/Sidebar.module.scss.js +42 -42
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/fragments.json +1 -1
  13. package/package.json +3 -3
  14. package/src/components/Accordion/Accordion.contract.json +169 -0
  15. package/src/components/Alert/Alert.contract.json +157 -0
  16. package/src/components/AppShell/AppShell.contract.json +155 -0
  17. package/src/components/Avatar/Avatar.contract.json +189 -0
  18. package/src/components/Badge/Badge.contract.json +187 -0
  19. package/src/components/BentoGrid/BentoGrid.contract.json +135 -0
  20. package/src/components/Box/Box.contract.json +423 -0
  21. package/src/components/Breadcrumbs/Breadcrumbs.contract.json +143 -0
  22. package/src/components/Button/Button.contract.json +205 -0
  23. package/src/components/ButtonGroup/ButtonGroup.contract.json +140 -0
  24. package/src/components/Card/Card.contract.json +185 -0
  25. package/src/components/Chart/Chart.contract.json +129 -0
  26. package/src/components/Checkbox/Checkbox.contract.json +246 -0
  27. package/src/components/Chip/Chip.contract.json +212 -0
  28. package/src/components/CodeBlock/CodeBlock.contract.json +388 -0
  29. package/src/components/Collapsible/Collapsible.contract.json +154 -0
  30. package/src/components/ColorPicker/ColorPicker.contract.json +212 -0
  31. package/src/components/Combobox/Combobox.contract.json +297 -0
  32. package/src/components/Command/Command.contract.json +165 -0
  33. package/src/components/ConversationList/ConversationList.contract.json +151 -0
  34. package/src/components/DataTable/DataTable.contract.json +302 -0
  35. package/src/components/DatePicker/DatePicker.contract.json +288 -0
  36. package/src/components/Dialog/Dialog.contract.json +159 -0
  37. package/src/components/Drawer/Drawer.contract.json +160 -0
  38. package/src/components/Editor/Editor.contract.json +263 -0
  39. package/src/components/EmptyState/EmptyState.contract.json +133 -0
  40. package/src/components/Field/Field.contract.json +157 -0
  41. package/src/components/Fieldset/Fieldset.contract.json +117 -0
  42. package/src/components/Form/Form.contract.json +145 -0
  43. package/src/components/Grid/Grid.contract.json +195 -0
  44. package/src/components/Header/Header.contract.json +194 -0
  45. package/src/components/Header/Header.module.scss +99 -0
  46. package/src/components/Header/index.tsx +191 -10
  47. package/src/components/Icon/Icon.contract.json +194 -0
  48. package/src/components/Image/Image.contract.json +209 -0
  49. package/src/components/Input/Input.contract.json +344 -0
  50. package/src/components/Link/Link.contract.json +180 -0
  51. package/src/components/List/List.contract.json +154 -0
  52. package/src/components/Listbox/Listbox.contract.json +158 -0
  53. package/src/components/Loading/Loading.contract.json +167 -0
  54. package/src/components/Markdown/Markdown.contract.json +127 -0
  55. package/src/components/Menu/Menu.contract.json +177 -0
  56. package/src/components/Message/Message.contract.json +183 -0
  57. package/src/components/NavigationMenu/NavigationMenu.contract.json +203 -0
  58. package/src/components/Pagination/Pagination.contract.json +163 -0
  59. package/src/components/Popover/Popover.contract.json +163 -0
  60. package/src/components/Progress/Progress.contract.json +176 -0
  61. package/src/components/Prompt/Prompt.contract.json +211 -0
  62. package/src/components/RadioGroup/RadioGroup.contract.json +226 -0
  63. package/src/components/ScrollArea/ScrollArea.contract.json +131 -0
  64. package/src/components/Select/Select.contract.json +269 -0
  65. package/src/components/Separator/Separator.contract.json +143 -0
  66. package/src/components/Sidebar/Sidebar.contract.json +258 -0
  67. package/src/components/Sidebar/Sidebar.module.scss +6 -4
  68. package/src/components/Skeleton/Skeleton.contract.json +166 -0
  69. package/src/components/Slider/Slider.contract.json +248 -0
  70. package/src/components/Stack/Stack.contract.json +220 -0
  71. package/src/components/Table/Table.contract.json +171 -0
  72. package/src/components/TableOfContents/TableOfContents.contract.json +145 -0
  73. package/src/components/Tabs/Tabs.contract.json +159 -0
  74. package/src/components/Text/Text.contract.json +239 -0
  75. package/src/components/Textarea/Textarea.contract.json +308 -0
  76. package/src/components/Theme/Theme.contract.json +152 -0
  77. package/src/components/ThinkingIndicator/ThinkingIndicator.contract.json +165 -0
  78. package/src/components/Toast/Toast.contract.json +181 -0
  79. package/src/components/Toggle/Toggle.contract.json +231 -0
  80. package/src/components/ToggleGroup/ToggleGroup.contract.json +206 -0
  81. package/src/components/Tooltip/Tooltip.contract.json +214 -0
  82. package/src/components/VisuallyHidden/VisuallyHidden.contract.json +116 -0
  83. package/src/index.ts +1 -0
  84. package/src/tokens/_derive.scss +4 -1
@@ -0,0 +1,143 @@
1
+ {
2
+ "$schema": "https://usefragments.com/schemas/contract.v1.json",
3
+ "name": "Separator",
4
+ "description": "Visual divider between content sections. Use to create clear visual boundaries and improve content organization.",
5
+ "category": "layout",
6
+ "tags": [
7
+ "separator",
8
+ "divider",
9
+ "hr",
10
+ "line",
11
+ "layout"
12
+ ],
13
+ "status": "stable",
14
+ "sourcePath": "src/components/Separator/index.tsx",
15
+ "exportName": "Separator",
16
+ "propsSummary": [
17
+ "orientation: horizontal|vertical (default: horizontal)",
18
+ "spacing: none|sm|md|lg (default: none)",
19
+ "soft: boolean (default: false)",
20
+ "label: string",
21
+ "style: object"
22
+ ],
23
+ "props": {
24
+ "orientation": {
25
+ "type": "enum",
26
+ "description": "Direction of the separator",
27
+ "default": "horizontal",
28
+ "required": false,
29
+ "values": [
30
+ "horizontal",
31
+ "vertical"
32
+ ]
33
+ },
34
+ "spacing": {
35
+ "type": "enum",
36
+ "description": "Margin around the separator",
37
+ "default": "none",
38
+ "required": false,
39
+ "values": [
40
+ "none",
41
+ "sm",
42
+ "md",
43
+ "lg"
44
+ ]
45
+ },
46
+ "soft": {
47
+ "type": "boolean",
48
+ "description": "Softer, lighter appearance",
49
+ "default": "false",
50
+ "required": false
51
+ },
52
+ "label": {
53
+ "type": "string",
54
+ "description": "Optional text label (horizontal only)",
55
+ "required": false
56
+ },
57
+ "style": {
58
+ "type": "object",
59
+ "description": "",
60
+ "required": false
61
+ }
62
+ },
63
+ "usage": {
64
+ "when": [
65
+ "Dividing content sections",
66
+ "Separating groups of related items",
67
+ "Creating visual breathing room",
68
+ "Labeled section breaks"
69
+ ],
70
+ "whenNot": [
71
+ "Creating grid layouts (use CSS Grid)",
72
+ "Decorative borders (use CSS)",
73
+ "Spacing alone is sufficient"
74
+ ],
75
+ "guidelines": [
76
+ "Use sparingly - too many separators create visual noise",
77
+ "Consider if spacing alone would work",
78
+ "Use soft variant for subtle separation",
79
+ "Labeled separators work well for major section breaks"
80
+ ],
81
+ "accessibility": [
82
+ "Uses role=\"separator\" for semantic meaning",
83
+ "Decorative separators should be aria-hidden"
84
+ ]
85
+ },
86
+ "examples": [
87
+ {
88
+ "name": "Default",
89
+ "description": "Basic horizontal separator",
90
+ "code": "<div style={{ width: '300px' }}>\n <p>Content above</p>\n <Separator spacing=\"md\" />\n <p>Content below</p>\n</div>"
91
+ },
92
+ {
93
+ "name": "With Label",
94
+ "description": "Labeled section divider",
95
+ "code": "<div style={{ width: '300px' }}>\n <p>First section</p>\n <Separator label=\"Or\" spacing=\"md\" />\n <p>Second section</p>\n</div>"
96
+ },
97
+ {
98
+ "name": "Soft",
99
+ "description": "Subtle separator",
100
+ "code": "<div style={{ width: '300px' }}>\n <p>Content above</p>\n <Separator soft spacing=\"md\" />\n <p>Content below</p>\n</div>"
101
+ },
102
+ {
103
+ "name": "Vertical",
104
+ "description": "Vertical separator between elements",
105
+ "code": "<div style={{ display: 'flex', alignItems: 'center', gap: '16px', height: '40px' }}>\n <span>Item 1</span>\n <Separator orientation=\"vertical\" />\n <span>Item 2</span>\n <Separator orientation=\"vertical\" />\n <span>Item 3</span>\n</div>"
106
+ },
107
+ {
108
+ "name": "Spacing Options",
109
+ "description": "Different spacing sizes",
110
+ "code": "<div style={{ width: '300px' }}>\n <p>No spacing</p>\n <Separator spacing=\"none\" />\n <p>Small spacing</p>\n <Separator spacing=\"sm\" />\n <p>Medium spacing</p>\n <Separator spacing=\"md\" />\n <p>Large spacing</p>\n <Separator spacing=\"lg\" />\n <p>End</p>\n</div>"
111
+ }
112
+ ],
113
+ "relations": [
114
+ {
115
+ "component": "Card",
116
+ "relationship": "sibling",
117
+ "note": "Cards provide stronger visual grouping"
118
+ }
119
+ ],
120
+ "contract": {
121
+ "propsSummary": [
122
+ "orientation: horizontal|vertical - direction",
123
+ "spacing: none|sm|md|lg - margin",
124
+ "soft: boolean - lighter appearance",
125
+ "label: string - centered label text"
126
+ ],
127
+ "a11yRules": [
128
+ "A11Y_SEPARATOR_ROLE"
129
+ ]
130
+ },
131
+ "ai": {
132
+ "compositionPattern": "compound",
133
+ "subComponents": [
134
+ "Root"
135
+ ]
136
+ },
137
+ "provenance": {
138
+ "source": "migrated",
139
+ "verified": false,
140
+ "frameworkSupport": "native",
141
+ "extractedAt": "2026-03-13T23:19:03.327Z"
142
+ }
143
+ }
@@ -0,0 +1,258 @@
1
+ {
2
+ "$schema": "https://usefragments.com/schemas/contract.v1.json",
3
+ "name": "Sidebar",
4
+ "description": "Responsive navigation sidebar with collapsible desktop mode and mobile drawer behavior.",
5
+ "category": "navigation",
6
+ "tags": [
7
+ "sidebar",
8
+ "navigation",
9
+ "drawer",
10
+ "menu",
11
+ "layout"
12
+ ],
13
+ "status": "stable",
14
+ "sourcePath": "src/components/Sidebar/index.tsx",
15
+ "exportName": "Sidebar",
16
+ "propsSummary": [
17
+ "children: node (required)",
18
+ "collapsed: boolean",
19
+ "defaultCollapsed: boolean (default: false)",
20
+ "onCollapsedChange: function",
21
+ "open: boolean",
22
+ "defaultOpen: boolean (default: false)",
23
+ "onOpenChange: function",
24
+ "width: string (default: 240px)",
25
+ "collapsedWidth: string (default: 56px)",
26
+ "position: left|right (default: left)",
27
+ "collapsible: icon|offcanvas|none (default: icon)",
28
+ "style: object"
29
+ ],
30
+ "props": {
31
+ "children": {
32
+ "type": "node",
33
+ "description": "Sidebar content (use Sidebar.Header, Sidebar.Nav, Sidebar.Section, etc.)",
34
+ "required": true
35
+ },
36
+ "collapsed": {
37
+ "type": "boolean",
38
+ "description": "Icon-only mode for desktop (controlled)",
39
+ "required": false
40
+ },
41
+ "defaultCollapsed": {
42
+ "type": "boolean",
43
+ "description": "Initial collapsed state (uncontrolled)",
44
+ "default": "false",
45
+ "required": false
46
+ },
47
+ "onCollapsedChange": {
48
+ "type": "function",
49
+ "description": "Called when collapsed state changes",
50
+ "required": false
51
+ },
52
+ "open": {
53
+ "type": "boolean",
54
+ "description": "Mobile drawer open state (controlled)",
55
+ "required": false
56
+ },
57
+ "defaultOpen": {
58
+ "type": "boolean",
59
+ "description": "Initial open state (uncontrolled)",
60
+ "default": "false",
61
+ "required": false
62
+ },
63
+ "onOpenChange": {
64
+ "type": "function",
65
+ "description": "Called when open state changes",
66
+ "required": false
67
+ },
68
+ "width": {
69
+ "type": "string",
70
+ "description": "Width of expanded sidebar",
71
+ "default": "240px",
72
+ "required": false
73
+ },
74
+ "collapsedWidth": {
75
+ "type": "string",
76
+ "description": "Width when collapsed",
77
+ "default": "56px",
78
+ "required": false
79
+ },
80
+ "position": {
81
+ "type": "enum",
82
+ "description": "Sidebar position",
83
+ "default": "left",
84
+ "required": false,
85
+ "values": [
86
+ "left",
87
+ "right"
88
+ ]
89
+ },
90
+ "collapsible": {
91
+ "type": "enum",
92
+ "description": "Collapse behavior mode",
93
+ "default": "icon",
94
+ "required": false,
95
+ "values": [
96
+ "icon",
97
+ "offcanvas",
98
+ "none"
99
+ ]
100
+ },
101
+ "style": {
102
+ "type": "object",
103
+ "description": "",
104
+ "required": false
105
+ }
106
+ },
107
+ "usage": {
108
+ "when": [
109
+ "Primary app navigation with multiple sections",
110
+ "Dashboard layouts requiring persistent navigation",
111
+ "Admin interfaces with hierarchical menu structure",
112
+ "Apps that need both mobile drawer and desktop sidebar"
113
+ ],
114
+ "whenNot": [
115
+ "Simple websites with few pages (use header nav)",
116
+ "Content-focused sites where navigation is secondary",
117
+ "Single-page applications with no navigation needs",
118
+ "Mobile-only apps where bottom navigation is preferred"
119
+ ],
120
+ "guidelines": [
121
+ "Group related items into sections with clear labels",
122
+ "Use icons for all items to support collapsed mode",
123
+ "Limit nesting to 2 levels maximum",
124
+ "Place most frequently used items at the top",
125
+ "Use badges sparingly for notifications or counts",
126
+ "The `active` prop on items should be controlled by your app based on current route",
127
+ "Use `collapsedContent` on Header to show just a logo icon when collapsed",
128
+ "Submenus are hidden when collapsed - use tooltips for navigation hints instead",
129
+ "Use SidebarProvider to enable external triggers and keyboard shortcuts",
130
+ "Use asChild with routing libraries (Next.js Link, React Router NavLink)",
131
+ "Sidebar.Item and Sidebar.SubItem onClick handlers receive the click event object",
132
+ "Use Sidebar.MenuSkeleton while loading navigation data"
133
+ ],
134
+ "accessibility": [
135
+ "Uses semantic <nav> element with aria-label",
136
+ "aria-current=\"page\" on active items",
137
+ "aria-expanded on items with submenus",
138
+ "Escape key closes mobile drawer",
139
+ "Cmd/Ctrl+B keyboard shortcut toggles sidebar (when using SidebarProvider)",
140
+ "Focus trap in mobile drawer mode",
141
+ "Minimum 44px touch targets"
142
+ ]
143
+ },
144
+ "examples": [
145
+ {
146
+ "name": "Default",
147
+ "description": "Standard sidebar with navigation sections. The `active` prop highlights the current page.",
148
+ "code": "<Sidebar>\n <Sidebar.Header>\n <Logo />\n <span>Acme App</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Dashboard</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<UsersIcon />}>Team</Sidebar.Item>\n <Sidebar.Item icon={<FolderIcon />}>Projects</Sidebar.Item>\n </Sidebar.Section>\n <Sidebar.Section label=\"Settings\">\n <Sidebar.Item icon={<GearIcon />}>Preferences</Sidebar.Item>\n <Sidebar.Item icon={<HelpIcon />}>Help</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n</Sidebar>"
149
+ },
150
+ {
151
+ "name": "Collapsed",
152
+ "description": "Icon-only collapsed state. Header shows only logo, tooltips appear on hover.",
153
+ "code": "function App() {\n const [collapsed, setCollapsed] = useState(true);\n\n return (\n <Sidebar collapsed={collapsed} onCollapsedChange={setCollapsed}>\n <Sidebar.Header collapsedContent={<Logo />}>\n <Logo />\n <span>Acme App</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Dashboard</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n </Sidebar>\n );\n}"
154
+ },
155
+ {
156
+ "name": "With Badges",
157
+ "description": "Navigation items with notification badges for counts or alerts.",
158
+ "code": "<Sidebar>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Dashboard</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />} badge=\"3\">Analytics</Sidebar.Item>\n <Sidebar.Item icon={<UsersIcon />} badge=\"12\">Team</Sidebar.Item>\n <Sidebar.Item icon={<FolderIcon />}>Projects</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n</Sidebar>"
159
+ },
160
+ {
161
+ "name": "With Submenu",
162
+ "description": "Nested navigation with expandable sections. Use defaultExpanded for initial state without manual state tracking.",
163
+ "code": "<Sidebar>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />}>Dashboard</Sidebar.Item>\n {/* Use defaultExpanded for uncontrolled mode - no state needed! */}\n <Sidebar.Item icon={<FolderIcon />} hasSubmenu defaultExpanded>\n Projects\n </Sidebar.Item>\n <Sidebar.Submenu>\n <Sidebar.SubItem active>Website Redesign</Sidebar.SubItem>\n <Sidebar.SubItem>Mobile App</Sidebar.SubItem>\n <Sidebar.SubItem>API Integration</Sidebar.SubItem>\n </Sidebar.Submenu>\n {/* Multiple submenus work without tracking separate state */}\n <Sidebar.Item icon={<UsersIcon />} hasSubmenu>\n Team\n </Sidebar.Item>\n <Sidebar.Submenu>\n <Sidebar.SubItem>Engineering</Sidebar.SubItem>\n <Sidebar.SubItem>Design</Sidebar.SubItem>\n </Sidebar.Submenu>\n </Sidebar.Section>\n </Sidebar.Nav>\n</Sidebar>"
164
+ },
165
+ {
166
+ "name": "With Disabled Items",
167
+ "description": "Some navigation items are disabled for permissions or feature flags.",
168
+ "code": "<Sidebar>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Dashboard</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n <Sidebar.Item icon={<UsersIcon />} disabled>\n Team (Coming Soon)\n </Sidebar.Item>\n <Sidebar.Item icon={<FolderIcon />} disabled>\n Projects (Upgrade)\n </Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n</Sidebar>"
169
+ },
170
+ {
171
+ "name": "With Provider & External Trigger",
172
+ "description": "SidebarProvider enables external triggers and keyboard shortcuts (Cmd/Ctrl+B).",
173
+ "code": "function App() {\n return (\n <SidebarProvider>\n <Sidebar>\n <Sidebar.Header>\n <Logo />\n <span>Acme App</span>\n <Sidebar.CollapseToggle />\n </Sidebar.Header>\n {/* sidebar nav */}\n </Sidebar>\n <MainContent />\n </SidebarProvider>\n );\n}\n\nfunction MainContent() {\n const { toggleSidebar, state } = useSidebar();\n return (\n <main>\n <p>State: {state}</p>\n <button onClick={toggleSidebar}>Toggle</button>\n </main>\n );\n}"
174
+ },
175
+ {
176
+ "name": "With asChild (Polymorphic)",
177
+ "description": "Use asChild to render items as custom elements like Next.js Link or React Router NavLink.",
178
+ "code": "import { Link } from 'next/link';\n\n<Sidebar>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active asChild>\n <Link href=\"/dashboard\">Dashboard</Link>\n </Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />} asChild>\n <Link href=\"/analytics\">Analytics</Link>\n </Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n</Sidebar>"
179
+ },
180
+ {
181
+ "name": "With Section Action",
182
+ "description": "Section headers can include action buttons for quick actions like \"Add Project\".",
183
+ "code": "<Sidebar>\n <Sidebar.Nav>\n <Sidebar.Section\n label=\"Projects\"\n action={\n <Sidebar.SectionAction aria-label=\"Add project\" onClick={handleAdd}>\n <PlusIcon />\n </Sidebar.SectionAction>\n }\n >\n <Sidebar.Item icon={<FolderIcon />}>Website Redesign</Sidebar.Item>\n <Sidebar.Item icon={<FolderIcon />}>Mobile App</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n</Sidebar>"
184
+ },
185
+ {
186
+ "name": "With Loading Skeleton",
187
+ "description": "Show skeleton placeholders while navigation data is loading.",
188
+ "code": "<Sidebar>\n <Sidebar.Nav>\n {loading ? (\n <Sidebar.MenuSkeleton count={6} />\n ) : (\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />}>Dashboard</Sidebar.Item>\n {/* ... */}\n </Sidebar.Section>\n )}\n </Sidebar.Nav>\n</Sidebar>"
189
+ },
190
+ {
191
+ "name": "With Rail Toggle",
192
+ "description": "Add a Rail component for a subtle drag-handle style toggle at the sidebar edge. Hover to reveal, click to toggle.",
193
+ "code": "<Sidebar collapsed={collapsed} onCollapsedChange={setCollapsed}>\n <Sidebar.Header>{/* ... */}</Sidebar.Header>\n <Sidebar.Nav>{/* ... */}</Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n <Sidebar.Rail />\n</Sidebar>"
194
+ },
195
+ {
196
+ "name": "Offcanvas Collapsed",
197
+ "description": "Offcanvas mode hides the sidebar completely when collapsed, but the toggle button remains visible as a floating button so the user can always re-expand.",
198
+ "code": "function App() {\n const [collapsed, setCollapsed] = useState(true);\n\n return (\n <Sidebar collapsed={collapsed} onCollapsedChange={setCollapsed} collapsible=\"offcanvas\">\n <Sidebar.Header collapsedContent={<Logo />}>\n <Logo />\n <span>Acme App</span>\n </Sidebar.Header>\n <Sidebar.Nav>\n <Sidebar.Section>\n <Sidebar.Item icon={<HomeIcon />} active>Dashboard</Sidebar.Item>\n <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>\n </Sidebar.Section>\n </Sidebar.Nav>\n <Sidebar.Footer>\n <Sidebar.CollapseToggle />\n </Sidebar.Footer>\n </Sidebar>\n );\n}"
199
+ }
200
+ ],
201
+ "relations": [
202
+ {
203
+ "component": "Tabs",
204
+ "relationship": "alternative",
205
+ "note": "Use Tabs for in-page section navigation"
206
+ },
207
+ {
208
+ "component": "Menu",
209
+ "relationship": "composition",
210
+ "note": "Use Menu for contextual actions within sidebar"
211
+ }
212
+ ],
213
+ "contract": {
214
+ "propsSummary": [
215
+ "collapsed: boolean - icon-only desktop mode",
216
+ "open: boolean - mobile drawer state",
217
+ "width: string - expanded width (default: 240px)",
218
+ "position: left|right - sidebar position",
219
+ "active: boolean - set on Sidebar.Item to mark current page (app-controlled)",
220
+ "Sidebar.Item/SubItem onClick: (event) => void - click handler receives mouse event"
221
+ ],
222
+ "a11yRules": [
223
+ "A11Y_NAV_LANDMARK",
224
+ "A11Y_FOCUS_TRAP",
225
+ "A11Y_ESCAPE_CLOSE"
226
+ ]
227
+ },
228
+ "ai": {
229
+ "compositionPattern": "compound",
230
+ "subComponents": [
231
+ "Header",
232
+ "Nav",
233
+ "Section",
234
+ "SectionAction",
235
+ "Item",
236
+ "SubItem",
237
+ "Submenu",
238
+ "Footer",
239
+ "Trigger",
240
+ "Overlay",
241
+ "CollapseToggle",
242
+ "Rail",
243
+ "MenuSkeleton"
244
+ ],
245
+ "requiredChildren": [
246
+ "Nav"
247
+ ],
248
+ "commonPatterns": [
249
+ "<Sidebar><Sidebar.Header>{logo}</Sidebar.Header><Sidebar.Nav><Sidebar.Section><Sidebar.Item icon={icon} active>{label}</Sidebar.Item></Sidebar.Section></Sidebar.Nav><Sidebar.Footer><Sidebar.CollapseToggle /></Sidebar.Footer></Sidebar>"
250
+ ]
251
+ },
252
+ "provenance": {
253
+ "source": "migrated",
254
+ "verified": false,
255
+ "frameworkSupport": "native",
256
+ "extractedAt": "2026-03-13T23:19:03.784Z"
257
+ }
258
+ }
@@ -226,6 +226,7 @@
226
226
 
227
227
  .itemWrapper {
228
228
  list-style: none;
229
+ width: 100%;
229
230
  }
230
231
 
231
232
  .item {
@@ -235,8 +236,9 @@
235
236
 
236
237
  display: flex;
237
238
  align-items: center;
238
- gap: var(--fui-space-3, $fui-space-3);
239
- padding: var(--fui-space-1, $fui-space-1) var(--fui-space-2, $fui-space-2);
239
+ width: 100%;
240
+ gap: var(--fui-sidebar-item-gap, var(--fui-space-2, $fui-space-2));
241
+ padding: var(--fui-sidebar-item-padding-y, var(--fui-space-1, $fui-space-1)) var(--fui-sidebar-item-padding-x, var(--fui-space-2, $fui-space-2));
240
242
  border-radius: var(--fui-radius-md, $fui-radius-md);
241
243
  color: var(--fui-text-secondary, $fui-text-secondary);
242
244
  text-decoration: none;
@@ -635,8 +637,8 @@
635
637
  .skeletonItem {
636
638
  display: flex;
637
639
  align-items: center;
638
- gap: var(--fui-space-3, $fui-space-3);
639
- padding: var(--fui-space-1, $fui-space-1) var(--fui-space-2, $fui-space-2);
640
+ gap: var(--fui-sidebar-item-gap, var(--fui-space-2, $fui-space-2));
641
+ padding: var(--fui-sidebar-item-padding-y, var(--fui-space-1, $fui-space-1)) var(--fui-sidebar-item-padding-x, var(--fui-space-2, $fui-space-2));
640
642
  min-height: var(--fui-sidebar-item-height, $fui-sidebar-item-height);
641
643
  }
642
644
 
@@ -0,0 +1,166 @@
1
+ {
2
+ "$schema": "https://usefragments.com/schemas/contract.v1.json",
3
+ "name": "Skeleton",
4
+ "description": "Placeholder loading state for content",
5
+ "category": "feedback",
6
+ "tags": [
7
+ "loading",
8
+ "placeholder",
9
+ "skeleton",
10
+ "shimmer"
11
+ ],
12
+ "status": "stable",
13
+ "sourcePath": "src/components/Skeleton/index.tsx",
14
+ "exportName": "Skeleton",
15
+ "propsSummary": [
16
+ "variant: text|heading|avatar|button|input|rect (default: rect)",
17
+ "size: sm|md|lg (default: md)",
18
+ "width: union",
19
+ "height: union",
20
+ "fill: boolean (default: false)",
21
+ "radius: sm|md|lg|none|full",
22
+ "static: boolean (default: false)"
23
+ ],
24
+ "props": {
25
+ "variant": {
26
+ "type": "enum",
27
+ "description": "Semantic variant that auto-sizes",
28
+ "default": "rect",
29
+ "required": false,
30
+ "values": [
31
+ "text",
32
+ "heading",
33
+ "avatar",
34
+ "button",
35
+ "input",
36
+ "rect"
37
+ ]
38
+ },
39
+ "size": {
40
+ "type": "enum",
41
+ "description": "Size for avatar/button variants",
42
+ "default": "md",
43
+ "required": false,
44
+ "values": [
45
+ "sm",
46
+ "md",
47
+ "lg"
48
+ ]
49
+ },
50
+ "width": {
51
+ "type": "union",
52
+ "description": "Custom width (string or number)",
53
+ "required": false
54
+ },
55
+ "height": {
56
+ "type": "union",
57
+ "description": "Custom height (string or number)",
58
+ "required": false
59
+ },
60
+ "fill": {
61
+ "type": "boolean",
62
+ "description": "Fill parent container",
63
+ "default": "false",
64
+ "required": false
65
+ },
66
+ "radius": {
67
+ "type": "enum",
68
+ "description": "Border radius override",
69
+ "required": false,
70
+ "values": [
71
+ "sm",
72
+ "md",
73
+ "lg",
74
+ "none",
75
+ "full"
76
+ ]
77
+ },
78
+ "static": {
79
+ "type": "boolean",
80
+ "description": "Disable skeleton animation",
81
+ "default": "false",
82
+ "required": false
83
+ }
84
+ },
85
+ "usage": {
86
+ "when": [
87
+ "Content is loading asynchronously",
88
+ "Preventing layout shift during data fetching",
89
+ "Providing visual feedback that content is coming",
90
+ "Improving perceived performance"
91
+ ],
92
+ "whenNot": [
93
+ "Short loading times (< 300ms)",
94
+ "When spinner is more appropriate",
95
+ "Background operations without visible impact"
96
+ ],
97
+ "guidelines": [
98
+ "Match skeleton shape to expected content",
99
+ "Use semantic variants (text, heading, avatar) for consistency",
100
+ "Maintain similar dimensions to loaded content",
101
+ "Avoid too many skeleton elements - simplify complex layouts",
102
+ "Skeleton and Skeleton.Text forward DOM props (id, aria-*, data-*, handlers)"
103
+ ],
104
+ "accessibility": [
105
+ "Skeletons are decorative - use aria-hidden",
106
+ "Announce loading state separately if needed",
107
+ "Ensure sufficient contrast for the animation"
108
+ ]
109
+ },
110
+ "examples": [
111
+ {
112
+ "name": "Default",
113
+ "description": "Basic rectangle skeleton",
114
+ "code": "<Skeleton width={200} height={20} />"
115
+ },
116
+ {
117
+ "name": "Text Lines",
118
+ "description": "Multi-line text placeholder",
119
+ "code": "<Skeleton.Text lines={3} />"
120
+ },
121
+ {
122
+ "name": "Semantic Variants",
123
+ "description": "Pre-configured shapes for common elements",
124
+ "code": "<div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--fui-space-2)' }}>\n <Skeleton variant=\"heading\" width={200} />\n <Skeleton variant=\"text\" width=\"100%\" />\n <Skeleton variant=\"text\" width=\"80%\" />\n</div>"
125
+ },
126
+ {
127
+ "name": "Avatar Skeleton",
128
+ "description": "Circular placeholder for avatars",
129
+ "code": "<div style={{ display: 'flex', gap: 'var(--fui-space-1)', alignItems: 'center' }}>\n <Skeleton.Circle size=\"sm\" />\n <Skeleton.Circle size=\"md\" />\n <Skeleton.Circle size=\"lg\" />\n</div>"
130
+ },
131
+ {
132
+ "name": "Card Skeleton",
133
+ "description": "Composed skeleton for a card layout",
134
+ "code": "<div style={{ width: 300, padding: 'var(--fui-space-2)', border: '1px solid var(--fui-border)', borderRadius: 'var(--fui-radius-lg)' }}>\n <Skeleton variant=\"rect\" height={120} radius=\"md\" />\n <div style={{ marginTop: 'var(--fui-space-2)' }}>\n <Skeleton variant=\"heading\" width=\"60%\" />\n </div>\n <div style={{ marginTop: 'var(--fui-space-1)' }}>\n <Skeleton.Text lines={2} />\n </div>\n</div>"
135
+ }
136
+ ],
137
+ "relations": [
138
+ {
139
+ "component": "Progress",
140
+ "relationship": "alternative",
141
+ "note": "Use Progress for determinate loading"
142
+ }
143
+ ],
144
+ "contract": {
145
+ "propsSummary": [
146
+ "variant: text|heading|avatar|button|input|rect",
147
+ "size: sm|md|lg (for avatar/button)",
148
+ "width/height: custom dimensions",
149
+ "fill: boolean - fill parent",
150
+ "Skeleton / Skeleton.Text forward div DOM props"
151
+ ]
152
+ },
153
+ "ai": {
154
+ "compositionPattern": "compound",
155
+ "subComponents": [
156
+ "Text",
157
+ "Circle"
158
+ ]
159
+ },
160
+ "provenance": {
161
+ "source": "migrated",
162
+ "verified": false,
163
+ "frameworkSupport": "native",
164
+ "extractedAt": "2026-03-13T23:19:03.952Z"
165
+ }
166
+ }