@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.
- package/dist/assets/ui.css +320 -183
- package/dist/components/Header/Header.module.scss.cjs +42 -21
- package/dist/components/Header/Header.module.scss.js +42 -21
- package/dist/components/Header/index.cjs +121 -3
- package/dist/components/Header/index.d.ts +26 -3
- package/dist/components/Header/index.d.ts.map +1 -1
- package/dist/components/Header/index.js +122 -4
- package/dist/components/Sidebar/Sidebar.module.scss.cjs +42 -42
- package/dist/components/Sidebar/Sidebar.module.scss.js +42 -42
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/fragments.json +1 -1
- package/package.json +3 -3
- package/src/components/Accordion/Accordion.contract.json +169 -0
- package/src/components/Alert/Alert.contract.json +157 -0
- package/src/components/AppShell/AppShell.contract.json +155 -0
- package/src/components/Avatar/Avatar.contract.json +189 -0
- package/src/components/Badge/Badge.contract.json +187 -0
- package/src/components/BentoGrid/BentoGrid.contract.json +135 -0
- package/src/components/Box/Box.contract.json +423 -0
- package/src/components/Breadcrumbs/Breadcrumbs.contract.json +143 -0
- package/src/components/Button/Button.contract.json +205 -0
- package/src/components/ButtonGroup/ButtonGroup.contract.json +140 -0
- package/src/components/Card/Card.contract.json +185 -0
- package/src/components/Chart/Chart.contract.json +129 -0
- package/src/components/Checkbox/Checkbox.contract.json +246 -0
- package/src/components/Chip/Chip.contract.json +212 -0
- package/src/components/CodeBlock/CodeBlock.contract.json +388 -0
- package/src/components/Collapsible/Collapsible.contract.json +154 -0
- package/src/components/ColorPicker/ColorPicker.contract.json +212 -0
- package/src/components/Combobox/Combobox.contract.json +297 -0
- package/src/components/Command/Command.contract.json +165 -0
- package/src/components/ConversationList/ConversationList.contract.json +151 -0
- package/src/components/DataTable/DataTable.contract.json +302 -0
- package/src/components/DatePicker/DatePicker.contract.json +288 -0
- package/src/components/Dialog/Dialog.contract.json +159 -0
- package/src/components/Drawer/Drawer.contract.json +160 -0
- package/src/components/Editor/Editor.contract.json +263 -0
- package/src/components/EmptyState/EmptyState.contract.json +133 -0
- package/src/components/Field/Field.contract.json +157 -0
- package/src/components/Fieldset/Fieldset.contract.json +117 -0
- package/src/components/Form/Form.contract.json +145 -0
- package/src/components/Grid/Grid.contract.json +195 -0
- package/src/components/Header/Header.contract.json +194 -0
- package/src/components/Header/Header.module.scss +99 -0
- package/src/components/Header/index.tsx +191 -10
- package/src/components/Icon/Icon.contract.json +194 -0
- package/src/components/Image/Image.contract.json +209 -0
- package/src/components/Input/Input.contract.json +344 -0
- package/src/components/Link/Link.contract.json +180 -0
- package/src/components/List/List.contract.json +154 -0
- package/src/components/Listbox/Listbox.contract.json +158 -0
- package/src/components/Loading/Loading.contract.json +167 -0
- package/src/components/Markdown/Markdown.contract.json +127 -0
- package/src/components/Menu/Menu.contract.json +177 -0
- package/src/components/Message/Message.contract.json +183 -0
- package/src/components/NavigationMenu/NavigationMenu.contract.json +203 -0
- package/src/components/Pagination/Pagination.contract.json +163 -0
- package/src/components/Popover/Popover.contract.json +163 -0
- package/src/components/Progress/Progress.contract.json +176 -0
- package/src/components/Prompt/Prompt.contract.json +211 -0
- package/src/components/RadioGroup/RadioGroup.contract.json +226 -0
- package/src/components/ScrollArea/ScrollArea.contract.json +131 -0
- package/src/components/Select/Select.contract.json +269 -0
- package/src/components/Separator/Separator.contract.json +143 -0
- package/src/components/Sidebar/Sidebar.contract.json +258 -0
- package/src/components/Sidebar/Sidebar.module.scss +6 -4
- package/src/components/Skeleton/Skeleton.contract.json +166 -0
- package/src/components/Slider/Slider.contract.json +248 -0
- package/src/components/Stack/Stack.contract.json +220 -0
- package/src/components/Table/Table.contract.json +171 -0
- package/src/components/TableOfContents/TableOfContents.contract.json +145 -0
- package/src/components/Tabs/Tabs.contract.json +159 -0
- package/src/components/Text/Text.contract.json +239 -0
- package/src/components/Textarea/Textarea.contract.json +308 -0
- package/src/components/Theme/Theme.contract.json +152 -0
- package/src/components/ThinkingIndicator/ThinkingIndicator.contract.json +165 -0
- package/src/components/Toast/Toast.contract.json +181 -0
- package/src/components/Toggle/Toggle.contract.json +231 -0
- package/src/components/ToggleGroup/ToggleGroup.contract.json +206 -0
- package/src/components/Tooltip/Tooltip.contract.json +214 -0
- package/src/components/VisuallyHidden/VisuallyHidden.contract.json +116 -0
- package/src/index.ts +1 -0
- package/src/tokens/_derive.scss +4 -1
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://usefragments.com/schemas/contract.v1.json",
|
|
3
|
+
"name": "Button",
|
|
4
|
+
"description": "Interactive element for user actions and form submissions",
|
|
5
|
+
"category": "forms",
|
|
6
|
+
"tags": [
|
|
7
|
+
"action",
|
|
8
|
+
"button",
|
|
9
|
+
"form",
|
|
10
|
+
"interactive"
|
|
11
|
+
],
|
|
12
|
+
"status": "stable",
|
|
13
|
+
"sourcePath": "src/components/Button/index.tsx",
|
|
14
|
+
"exportName": "Button",
|
|
15
|
+
"propsSummary": [
|
|
16
|
+
"as: button|a",
|
|
17
|
+
"children: node (required)",
|
|
18
|
+
"variant: primary|secondary|ghost|danger|outlined|outline|icon (default: \"primary\")",
|
|
19
|
+
"size: sm|md|lg (default: \"md\")",
|
|
20
|
+
"icon: boolean",
|
|
21
|
+
"fullWidth: boolean",
|
|
22
|
+
"asChild: boolean"
|
|
23
|
+
],
|
|
24
|
+
"props": {
|
|
25
|
+
"as": {
|
|
26
|
+
"type": "enum",
|
|
27
|
+
"description": "Render as a native button or anchor element",
|
|
28
|
+
"default": "button",
|
|
29
|
+
"required": false,
|
|
30
|
+
"values": [
|
|
31
|
+
"button",
|
|
32
|
+
"a"
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"children": {
|
|
36
|
+
"type": "node",
|
|
37
|
+
"description": "Button label content",
|
|
38
|
+
"required": true
|
|
39
|
+
},
|
|
40
|
+
"variant": {
|
|
41
|
+
"type": "enum",
|
|
42
|
+
"description": "Visual style variant (\"icon\" is a convenience alias for outlined + icon-only layout)",
|
|
43
|
+
"default": "\"primary\"",
|
|
44
|
+
"required": false,
|
|
45
|
+
"values": [
|
|
46
|
+
"primary",
|
|
47
|
+
"secondary",
|
|
48
|
+
"ghost",
|
|
49
|
+
"danger",
|
|
50
|
+
"outlined",
|
|
51
|
+
"outline",
|
|
52
|
+
"icon"
|
|
53
|
+
],
|
|
54
|
+
"constraints": [
|
|
55
|
+
"Only one primary button per context"
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
"size": {
|
|
59
|
+
"type": "enum",
|
|
60
|
+
"description": "Button size",
|
|
61
|
+
"default": "\"md\"",
|
|
62
|
+
"required": false,
|
|
63
|
+
"values": [
|
|
64
|
+
"sm",
|
|
65
|
+
"md",
|
|
66
|
+
"lg"
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
"icon": {
|
|
70
|
+
"type": "boolean",
|
|
71
|
+
"description": "Render as icon-only button (square aspect ratio). Useful with any visual variant; variant=\"icon\" is the default outlined icon-only shortcut.",
|
|
72
|
+
"default": "false",
|
|
73
|
+
"required": false
|
|
74
|
+
},
|
|
75
|
+
"fullWidth": {
|
|
76
|
+
"type": "boolean",
|
|
77
|
+
"description": "Make button full width of container",
|
|
78
|
+
"default": "false",
|
|
79
|
+
"required": false
|
|
80
|
+
},
|
|
81
|
+
"asChild": {
|
|
82
|
+
"type": "boolean",
|
|
83
|
+
"description": "Merge button styling onto child element (e.g. Next.js Link)",
|
|
84
|
+
"default": "false",
|
|
85
|
+
"required": false
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"usage": {
|
|
89
|
+
"when": [
|
|
90
|
+
"Triggering an action (save, submit, delete, etc.)",
|
|
91
|
+
"Form submission",
|
|
92
|
+
"Opening dialogs or menus",
|
|
93
|
+
"Navigation when action context is needed"
|
|
94
|
+
],
|
|
95
|
+
"whenNot": [
|
|
96
|
+
"Simple navigation (use Link)",
|
|
97
|
+
"Toggling state (use Switch or Checkbox)",
|
|
98
|
+
"Selecting from options (use Select or RadioGroup)"
|
|
99
|
+
],
|
|
100
|
+
"guidelines": [
|
|
101
|
+
"Use Primary for the main action in a context",
|
|
102
|
+
"Only one Primary button per section/form",
|
|
103
|
+
"Use Danger variant for destructive actions",
|
|
104
|
+
"Loading state should disable the button",
|
|
105
|
+
"When using asChild, pass interaction and accessibility props directly on Button (they are forwarded to the child element)",
|
|
106
|
+
"Use variant=\"icon\" for the default icon-only action button, or combine icon={true} with another visual variant when needed"
|
|
107
|
+
],
|
|
108
|
+
"accessibility": [
|
|
109
|
+
"Button text should describe the action",
|
|
110
|
+
"Avoid generic labels like \"Click here\"",
|
|
111
|
+
"Icon-only buttons need aria-label"
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
"examples": [
|
|
115
|
+
{
|
|
116
|
+
"name": "Primary",
|
|
117
|
+
"description": "Default action button for primary actions",
|
|
118
|
+
"code": "<Button variant=\"primary\">Save Changes</Button>"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"name": "Secondary",
|
|
122
|
+
"description": "Less prominent action button",
|
|
123
|
+
"code": "<Button variant=\"secondary\">Cancel</Button>"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"name": "Ghost",
|
|
127
|
+
"description": "Minimal visual weight for subtle actions",
|
|
128
|
+
"code": "<Button variant=\"ghost\">Learn More</Button>"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"name": "Danger",
|
|
132
|
+
"description": "Destructive action requiring attention",
|
|
133
|
+
"code": "<Button variant=\"danger\">Delete Item</Button>"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"name": "Outline",
|
|
137
|
+
"description": "Bordered button with transparent background",
|
|
138
|
+
"code": "<Button variant=\"outline\">View Details</Button>"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"name": "Icon",
|
|
142
|
+
"description": "Convenience icon-only button alias (ghost + square icon sizing)",
|
|
143
|
+
"code": "<Button variant=\"icon\" aria-label=\"Add item\">\n <span aria-hidden>+</span>\n</Button>"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"name": "Sizes",
|
|
147
|
+
"description": "Available size options",
|
|
148
|
+
"code": "<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>\n <Button size=\"sm\">Small</Button>\n <Button size=\"md\">Medium</Button>\n <Button size=\"lg\">Large</Button>\n</div>"
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"name": "Disabled",
|
|
152
|
+
"description": "Non-interactive state",
|
|
153
|
+
"code": "<Button disabled>Cannot Click</Button>"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"name": "As Child",
|
|
157
|
+
"description": "Compose button styles onto another interactive element while preserving forwarded props",
|
|
158
|
+
"code": "<Button asChild variant=\"outlined\" aria-label=\"Open billing settings\">\n <a href=\"#billing-settings\">Billing Settings</a>\n</Button>"
|
|
159
|
+
}
|
|
160
|
+
],
|
|
161
|
+
"relations": [
|
|
162
|
+
{
|
|
163
|
+
"component": "Link",
|
|
164
|
+
"relationship": "alternative",
|
|
165
|
+
"note": "Use Link for navigation without action context"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"component": "Icon",
|
|
169
|
+
"relationship": "complementary",
|
|
170
|
+
"note": "Use Icon inside Button for icon-leading/trailing or icon-only actions"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"component": "ButtonGroup",
|
|
174
|
+
"relationship": "parent",
|
|
175
|
+
"note": "Use ButtonGroup for related action sets"
|
|
176
|
+
}
|
|
177
|
+
],
|
|
178
|
+
"contract": {
|
|
179
|
+
"propsSummary": [
|
|
180
|
+
"variant: primary|secondary|ghost|danger|outlined|outline|icon (default: primary, icon = outlined + icon-only)",
|
|
181
|
+
"size: sm|md|lg (default: md)",
|
|
182
|
+
"disabled: boolean - disables interaction",
|
|
183
|
+
"type: button|submit|reset (default: button)",
|
|
184
|
+
"onClick: (event) => void - action handler",
|
|
185
|
+
"asChild: boolean - composes styles/props onto a child element (links/router links)",
|
|
186
|
+
"icon: boolean - icon-only square layout (can be combined with visual variants)"
|
|
187
|
+
],
|
|
188
|
+
"a11yRules": [
|
|
189
|
+
"A11Y_BTN_LABEL",
|
|
190
|
+
"A11Y_BTN_FOCUS"
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
"ai": {
|
|
194
|
+
"compositionPattern": "compound",
|
|
195
|
+
"subComponents": [
|
|
196
|
+
"Root"
|
|
197
|
+
]
|
|
198
|
+
},
|
|
199
|
+
"provenance": {
|
|
200
|
+
"source": "migrated",
|
|
201
|
+
"verified": false,
|
|
202
|
+
"frameworkSupport": "native",
|
|
203
|
+
"extractedAt": "2026-03-13T23:18:51.517Z"
|
|
204
|
+
}
|
|
205
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://usefragments.com/schemas/contract.v1.json",
|
|
3
|
+
"name": "ButtonGroup",
|
|
4
|
+
"description": "Groups related buttons together with consistent spacing and alignment. Useful for action bars, toolbars, and related button sets.",
|
|
5
|
+
"category": "forms",
|
|
6
|
+
"tags": [
|
|
7
|
+
"button",
|
|
8
|
+
"group",
|
|
9
|
+
"toolbar",
|
|
10
|
+
"actions",
|
|
11
|
+
"layout"
|
|
12
|
+
],
|
|
13
|
+
"status": "stable",
|
|
14
|
+
"sourcePath": "src/components/ButtonGroup/index.tsx",
|
|
15
|
+
"exportName": "ButtonGroup",
|
|
16
|
+
"propsSummary": [
|
|
17
|
+
"children: node (required)",
|
|
18
|
+
"gap: none|xs|sm|md (default: sm)",
|
|
19
|
+
"wrap: boolean (default: false)",
|
|
20
|
+
"align: start|center|end"
|
|
21
|
+
],
|
|
22
|
+
"props": {
|
|
23
|
+
"children": {
|
|
24
|
+
"type": "node",
|
|
25
|
+
"description": "Button elements to group together",
|
|
26
|
+
"required": true
|
|
27
|
+
},
|
|
28
|
+
"gap": {
|
|
29
|
+
"type": "enum",
|
|
30
|
+
"description": "Spacing between buttons",
|
|
31
|
+
"default": "sm",
|
|
32
|
+
"required": false,
|
|
33
|
+
"values": [
|
|
34
|
+
"none",
|
|
35
|
+
"xs",
|
|
36
|
+
"sm",
|
|
37
|
+
"md"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"wrap": {
|
|
41
|
+
"type": "boolean",
|
|
42
|
+
"description": "Allow buttons to wrap to next line",
|
|
43
|
+
"default": "false",
|
|
44
|
+
"required": false
|
|
45
|
+
},
|
|
46
|
+
"align": {
|
|
47
|
+
"type": "enum",
|
|
48
|
+
"description": "Alignment of buttons",
|
|
49
|
+
"required": false,
|
|
50
|
+
"values": [
|
|
51
|
+
"start",
|
|
52
|
+
"center",
|
|
53
|
+
"end"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"usage": {
|
|
58
|
+
"when": [
|
|
59
|
+
"Grouping related actions together",
|
|
60
|
+
"Creating toolbars or action bars",
|
|
61
|
+
"Form submit/cancel button pairs",
|
|
62
|
+
"Pagination controls"
|
|
63
|
+
],
|
|
64
|
+
"whenNot": [
|
|
65
|
+
"Unrelated buttons (use Stack instead)",
|
|
66
|
+
"Navigation links (use nav element)",
|
|
67
|
+
"Single button (no grouping needed)"
|
|
68
|
+
],
|
|
69
|
+
"guidelines": [
|
|
70
|
+
"Keep button groups focused on related actions",
|
|
71
|
+
"Use consistent button variants within a group",
|
|
72
|
+
"Consider visual hierarchy - primary action should stand out",
|
|
73
|
+
"Limit to 2-4 buttons per group for clarity",
|
|
74
|
+
"Pass role/aria-label/id/data-* directly to ButtonGroup when you need semantic grouping hooks"
|
|
75
|
+
],
|
|
76
|
+
"accessibility": [
|
|
77
|
+
"Group provides semantic relationship between buttons",
|
|
78
|
+
"Each button remains individually focusable",
|
|
79
|
+
"Consider using role=\"group\" with aria-label for screen readers"
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
"examples": [
|
|
83
|
+
{
|
|
84
|
+
"name": "Default",
|
|
85
|
+
"description": "Basic button group with default spacing",
|
|
86
|
+
"code": "<ButtonGroup>\n <Button variant=\"secondary\">Cancel</Button>\n <Button variant=\"primary\">Save</Button>\n</ButtonGroup>"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "Gap Variants",
|
|
90
|
+
"description": "Different spacing options",
|
|
91
|
+
"code": "<div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>\n <ButtonGroup gap=\"none\">\n <Button variant=\"secondary\" size=\"sm\">None</Button>\n <Button variant=\"secondary\" size=\"sm\">Gap</Button>\n </ButtonGroup>\n <ButtonGroup gap=\"xs\">\n <Button variant=\"secondary\" size=\"sm\">XS</Button>\n <Button variant=\"secondary\" size=\"sm\">Gap</Button>\n </ButtonGroup>\n <ButtonGroup gap=\"sm\">\n <Button variant=\"secondary\" size=\"sm\">SM</Button>\n <Button variant=\"secondary\" size=\"sm\">Gap</Button>\n </ButtonGroup>\n <ButtonGroup gap=\"md\">\n <Button variant=\"secondary\" size=\"sm\">MD</Button>\n <Button variant=\"secondary\" size=\"sm\">Gap</Button>\n </ButtonGroup>\n</div>"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "Alignment",
|
|
95
|
+
"description": "Different alignment options",
|
|
96
|
+
"code": "<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', width: '300px' }}>\n <ButtonGroup align=\"start\">\n <Button variant=\"secondary\" size=\"sm\">Start</Button>\n <Button variant=\"secondary\" size=\"sm\">Aligned</Button>\n </ButtonGroup>\n <ButtonGroup align=\"center\">\n <Button variant=\"secondary\" size=\"sm\">Center</Button>\n <Button variant=\"secondary\" size=\"sm\">Aligned</Button>\n </ButtonGroup>\n <ButtonGroup align=\"end\">\n <Button variant=\"secondary\" size=\"sm\">End</Button>\n <Button variant=\"secondary\" size=\"sm\">Aligned</Button>\n </ButtonGroup>\n</div>"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"name": "Form Actions",
|
|
100
|
+
"description": "Common pattern for form submit/cancel",
|
|
101
|
+
"code": "<ButtonGroup align=\"end\" role=\"group\" aria-label=\"Form actions\">\n <Button variant=\"ghost\">Cancel</Button>\n <Button variant=\"primary\">Submit</Button>\n</ButtonGroup>"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"relations": [
|
|
105
|
+
{
|
|
106
|
+
"component": "Button",
|
|
107
|
+
"relationship": "child",
|
|
108
|
+
"note": "ButtonGroup contains Button components"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"component": "Stack",
|
|
112
|
+
"relationship": "alternative",
|
|
113
|
+
"note": "Use Stack for more general layout needs"
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
"contract": {
|
|
117
|
+
"propsSummary": [
|
|
118
|
+
"children: ReactNode - buttons to group",
|
|
119
|
+
"gap: none|xs|sm|md - spacing between buttons",
|
|
120
|
+
"wrap: boolean - allow wrapping",
|
|
121
|
+
"align: start|center|end - alignment",
|
|
122
|
+
"Pass-through DOM props supported on root (id, role, aria-*, data-*, handlers)"
|
|
123
|
+
],
|
|
124
|
+
"a11yRules": [
|
|
125
|
+
"A11Y_GROUP_LABEL"
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
"ai": {
|
|
129
|
+
"compositionPattern": "compound",
|
|
130
|
+
"subComponents": [
|
|
131
|
+
"Root"
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
"provenance": {
|
|
135
|
+
"source": "migrated",
|
|
136
|
+
"verified": false,
|
|
137
|
+
"frameworkSupport": "native",
|
|
138
|
+
"extractedAt": "2026-03-13T23:18:51.693Z"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://usefragments.com/schemas/contract.v1.json",
|
|
3
|
+
"name": "Card",
|
|
4
|
+
"description": "Container for grouping related content",
|
|
5
|
+
"category": "layout",
|
|
6
|
+
"tags": [
|
|
7
|
+
"container",
|
|
8
|
+
"layout",
|
|
9
|
+
"surface"
|
|
10
|
+
],
|
|
11
|
+
"status": "stable",
|
|
12
|
+
"sourcePath": "src/components/Card/index.tsx",
|
|
13
|
+
"exportName": "Card",
|
|
14
|
+
"propsSummary": [
|
|
15
|
+
"children: node (required)",
|
|
16
|
+
"variant: default|outlined|outline|elevated (default: default)",
|
|
17
|
+
"padding: none|sm|md|lg (default: md)",
|
|
18
|
+
"as: article|div|section (default: article)",
|
|
19
|
+
"style: object"
|
|
20
|
+
],
|
|
21
|
+
"props": {
|
|
22
|
+
"children": {
|
|
23
|
+
"type": "node",
|
|
24
|
+
"description": "Card content - use Card.Header, Card.Body, Card.Footer sub-components",
|
|
25
|
+
"required": true
|
|
26
|
+
},
|
|
27
|
+
"variant": {
|
|
28
|
+
"type": "enum",
|
|
29
|
+
"description": "Visual style of the card surface",
|
|
30
|
+
"default": "default",
|
|
31
|
+
"required": false,
|
|
32
|
+
"values": [
|
|
33
|
+
"default",
|
|
34
|
+
"outlined",
|
|
35
|
+
"outline",
|
|
36
|
+
"elevated"
|
|
37
|
+
],
|
|
38
|
+
"constraints": [
|
|
39
|
+
"Use \"elevated\" sparingly to maintain visual hierarchy"
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
"padding": {
|
|
43
|
+
"type": "enum",
|
|
44
|
+
"description": "Internal padding size",
|
|
45
|
+
"default": "md",
|
|
46
|
+
"required": false,
|
|
47
|
+
"values": [
|
|
48
|
+
"none",
|
|
49
|
+
"sm",
|
|
50
|
+
"md",
|
|
51
|
+
"lg"
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
"as": {
|
|
55
|
+
"type": "enum",
|
|
56
|
+
"description": "Semantic HTML element for the card root",
|
|
57
|
+
"default": "article",
|
|
58
|
+
"required": false,
|
|
59
|
+
"values": [
|
|
60
|
+
"article",
|
|
61
|
+
"div",
|
|
62
|
+
"section"
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
"style": {
|
|
66
|
+
"type": "object",
|
|
67
|
+
"description": "",
|
|
68
|
+
"required": false
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"usage": {
|
|
72
|
+
"when": [
|
|
73
|
+
"Grouping related pieces of content together",
|
|
74
|
+
"Creating visual separation between content sections",
|
|
75
|
+
"Displaying a preview or summary of an item",
|
|
76
|
+
"Building dashboard widgets or tiles"
|
|
77
|
+
],
|
|
78
|
+
"whenNot": [
|
|
79
|
+
"Simple text content that does not need grouping",
|
|
80
|
+
"Modal or dialog content (use Dialog component)",
|
|
81
|
+
"Navigation items (use List or Sidebar patterns)"
|
|
82
|
+
],
|
|
83
|
+
"guidelines": [
|
|
84
|
+
"Use consistent card variants within the same context",
|
|
85
|
+
"Cards in a grid should have uniform sizing",
|
|
86
|
+
"Use elevated variant sparingly for emphasis",
|
|
87
|
+
"If a card is clickable, provide clear hover/focus affordances and prefer explicit buttons/links inside the card"
|
|
88
|
+
],
|
|
89
|
+
"accessibility": [
|
|
90
|
+
"Card is a semantic container (article/div/section); onClick does not automatically add button semantics",
|
|
91
|
+
"Card titles should be appropriate heading levels"
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
"examples": [
|
|
95
|
+
{
|
|
96
|
+
"name": "Default",
|
|
97
|
+
"description": "Standard card with subtle shadow",
|
|
98
|
+
"code": "<Card>\n <Card.Header>\n <Card.Title>Card Title</Card.Title>\n <Card.Description>A brief description</Card.Description>\n </Card.Header>\n <Card.Body>Card content goes here.</Card.Body>\n</Card>"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"name": "Outlined",
|
|
102
|
+
"description": "Card with border instead of shadow",
|
|
103
|
+
"code": "<Card variant=\"outlined\">\n <Card.Header>\n <Card.Title>Outlined Card</Card.Title>\n </Card.Header>\n <Card.Body>Content with border.</Card.Body>\n</Card>"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "Outline",
|
|
107
|
+
"description": "Card with border, using the \"outline\" alias for \"outlined\"",
|
|
108
|
+
"code": "<Card variant=\"outline\">\n <Card.Header>\n <Card.Title>Outline Card</Card.Title>\n </Card.Header>\n <Card.Body>Uses the Radix/Shadcn-style alias.</Card.Body>\n</Card>"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"name": "Elevated",
|
|
112
|
+
"description": "Card with prominent shadow for emphasis",
|
|
113
|
+
"code": "<Card variant=\"elevated\">\n <Card.Header>\n <Card.Title>Featured Item</Card.Title>\n </Card.Header>\n <Card.Body>Important content.</Card.Body>\n</Card>"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"name": "Interactive",
|
|
117
|
+
"description": "Clickable card surface (root stays a semantic container)",
|
|
118
|
+
"code": "<Card as=\"section\" onClick={() => alert('Card clicked!')}>\n <Card.Header>\n <Card.Title>Click Me</Card.Title>\n <Card.Description>This card is interactive</Card.Description>\n </Card.Header>\n <Card.Body>Click anywhere on this card.</Card.Body>\n</Card>"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"name": "Section Root",
|
|
122
|
+
"description": "Use the as prop to match the surrounding document semantics",
|
|
123
|
+
"code": "<Card as=\"section\" aria-labelledby=\"billing-card-title\">\n <Card.Header>\n <Card.Title id=\"billing-card-title\">Billing Summary</Card.Title>\n </Card.Header>\n <Card.Body>Section semantics can improve document structure for grouped content.</Card.Body>\n</Card>"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"name": "With Footer",
|
|
127
|
+
"description": "Card with header, body, and footer",
|
|
128
|
+
"code": "<Card>\n <Card.Header>\n <Card.Title>Card with Footer</Card.Title>\n <Card.Description>Complete card layout</Card.Description>\n </Card.Header>\n <Card.Body>Main content area.</Card.Body>\n <Card.Footer>Footer actions go here</Card.Footer>\n</Card>"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"name": "Content Only",
|
|
132
|
+
"description": "Card with just body content",
|
|
133
|
+
"code": "<Card>\n <Card.Body>Just content, no header or footer.</Card.Body>\n</Card>"
|
|
134
|
+
}
|
|
135
|
+
],
|
|
136
|
+
"relations": [
|
|
137
|
+
{
|
|
138
|
+
"component": "Grid",
|
|
139
|
+
"relationship": "parent",
|
|
140
|
+
"note": "Use Grid + Card for responsive card layouts"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"component": "List",
|
|
144
|
+
"relationship": "alternative",
|
|
145
|
+
"note": "Use List for linear, text-first layouts"
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
"contract": {
|
|
149
|
+
"propsSummary": [
|
|
150
|
+
"variant: default|outlined|outline|elevated (default: default)",
|
|
151
|
+
"padding: none|sm|md|lg (default: md)",
|
|
152
|
+
"as: article|div|section (default: article) - card root element",
|
|
153
|
+
"onClick: (event) => void - click handler on root (semantics unchanged)",
|
|
154
|
+
"Sub-components: Card.Header, Card.Title, Card.Description, Card.Body, Card.Footer"
|
|
155
|
+
],
|
|
156
|
+
"a11yRules": [
|
|
157
|
+
"A11Y_CARD_HEADING",
|
|
158
|
+
"A11Y_CARD_INTERACTIVE"
|
|
159
|
+
]
|
|
160
|
+
},
|
|
161
|
+
"ai": {
|
|
162
|
+
"compositionPattern": "compound",
|
|
163
|
+
"subComponents": [
|
|
164
|
+
"Header",
|
|
165
|
+
"Title",
|
|
166
|
+
"Description",
|
|
167
|
+
"Body",
|
|
168
|
+
"Footer"
|
|
169
|
+
],
|
|
170
|
+
"requiredChildren": [
|
|
171
|
+
"Body"
|
|
172
|
+
],
|
|
173
|
+
"commonPatterns": [
|
|
174
|
+
"<Card><Card.Body>{content}</Card.Body></Card>",
|
|
175
|
+
"<Card><Card.Header><Card.Title>{title}</Card.Title></Card.Header><Card.Body>{content}</Card.Body></Card>",
|
|
176
|
+
"<Card><Card.Header><Card.Title>{title}</Card.Title><Card.Description>{desc}</Card.Description></Card.Header><Card.Body>{content}</Card.Body><Card.Footer>{actions}</Card.Footer></Card>"
|
|
177
|
+
]
|
|
178
|
+
},
|
|
179
|
+
"provenance": {
|
|
180
|
+
"source": "migrated",
|
|
181
|
+
"verified": false,
|
|
182
|
+
"frameworkSupport": "native",
|
|
183
|
+
"extractedAt": "2026-03-13T23:18:51.869Z"
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://usefragments.com/schemas/contract.v1.json",
|
|
3
|
+
"name": "Chart",
|
|
4
|
+
"description": "Composable chart wrapper for recharts with theme-aware tooltips, legends, and color integration.",
|
|
5
|
+
"category": "display",
|
|
6
|
+
"tags": [
|
|
7
|
+
"chart",
|
|
8
|
+
"graph",
|
|
9
|
+
"data-visualization",
|
|
10
|
+
"recharts"
|
|
11
|
+
],
|
|
12
|
+
"status": "stable",
|
|
13
|
+
"sourcePath": "src/components/Chart/index.tsx",
|
|
14
|
+
"exportName": "ChartContainer",
|
|
15
|
+
"propsSummary": [
|
|
16
|
+
"config: object (required)",
|
|
17
|
+
"children: element (required)",
|
|
18
|
+
"summary: string",
|
|
19
|
+
"dataTable: node",
|
|
20
|
+
"style: object"
|
|
21
|
+
],
|
|
22
|
+
"props": {
|
|
23
|
+
"config": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"description": "ChartConfig mapping data keys to labels/colors (optional icon per series)",
|
|
26
|
+
"required": true
|
|
27
|
+
},
|
|
28
|
+
"children": {
|
|
29
|
+
"type": "element",
|
|
30
|
+
"description": "A recharts chart component (LineChart, BarChart, etc.)",
|
|
31
|
+
"required": true
|
|
32
|
+
},
|
|
33
|
+
"summary": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"description": "Non-visual summary announced to assistive technology users",
|
|
36
|
+
"required": false
|
|
37
|
+
},
|
|
38
|
+
"dataTable": {
|
|
39
|
+
"type": "node",
|
|
40
|
+
"description": "Optional accessible data table or textual fallback",
|
|
41
|
+
"required": false
|
|
42
|
+
},
|
|
43
|
+
"style": {
|
|
44
|
+
"type": "object",
|
|
45
|
+
"description": "",
|
|
46
|
+
"required": false
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"usage": {
|
|
50
|
+
"when": [
|
|
51
|
+
"Displaying data trends over time",
|
|
52
|
+
"Comparing categorical data",
|
|
53
|
+
"Showing distribution or composition",
|
|
54
|
+
"Dashboard data visualizations"
|
|
55
|
+
],
|
|
56
|
+
"whenNot": [
|
|
57
|
+
"Simple numeric values (use Text or Badge)",
|
|
58
|
+
"Progress toward a goal (use Progress)",
|
|
59
|
+
"Tabular data without visualization (use Table)"
|
|
60
|
+
],
|
|
61
|
+
"guidelines": [
|
|
62
|
+
"Use ChartContainer to wrap recharts chart components",
|
|
63
|
+
"Define a ChartConfig to map data keys to labels and colors (and optionally icons for custom legend/tooltip UIs)",
|
|
64
|
+
"Use FUI CSS variables for colors so charts adapt to theme changes",
|
|
65
|
+
"Use ChartTooltip and ChartLegend for consistent themed overlays",
|
|
66
|
+
"ChartTooltip and ChartLegend accept custom content renderers for advanced formatting"
|
|
67
|
+
],
|
|
68
|
+
"accessibility": [
|
|
69
|
+
"Charts include recharts accessibilityLayer by default",
|
|
70
|
+
"Provide meaningful labels in ChartConfig for screen readers",
|
|
71
|
+
"Consider providing a data table alternative for complex charts"
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
"examples": [
|
|
75
|
+
{
|
|
76
|
+
"name": "Line Chart",
|
|
77
|
+
"description": "Multi-series line chart showing trends over time",
|
|
78
|
+
"code": "<div style={{ width: '100%', height: 300 }}>\n <ChartContainer\n config={{\n revenue: { label: 'Revenue', color: 'var(--fui-color-accent)' },\n users: { label: 'Users', color: 'var(--fui-color-info)' },\n }}\n >\n <LineChart data={monthlyData} margin={{ top: 5, right: 20, bottom: 5, left: 0 }}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"month\" />\n <YAxis />\n <ChartTooltip />\n <ChartLegend />\n <Line type=\"monotone\" dataKey=\"revenue\" stroke=\"var(--fui-color-accent)\" strokeWidth={2} dot={false} />\n <Line type=\"monotone\" dataKey=\"users\" stroke=\"var(--fui-color-info)\" strokeWidth={2} dot={false} />\n </LineChart>\n </ChartContainer>\n</div>"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"name": "Bar Chart",
|
|
82
|
+
"description": "Categorical bar chart comparing device sessions",
|
|
83
|
+
"code": "<div style={{ width: '100%', height: 300 }}>\n <ChartContainer\n config={{\n sessions: { label: 'Sessions', color: 'var(--fui-color-accent)' },\n }}\n >\n <BarChart data={deviceData} margin={{ top: 5, right: 20, bottom: 5, left: 0 }}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"device\" />\n <YAxis />\n <ChartTooltip />\n <Bar dataKey=\"sessions\" fill=\"var(--fui-color-accent)\" radius={[4, 4, 0, 0]} />\n </BarChart>\n </ChartContainer>\n</div>"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"name": "Area Chart",
|
|
87
|
+
"description": "Filled area chart showing revenue trend",
|
|
88
|
+
"code": "<div style={{ width: '100%', height: 300 }}>\n <ChartContainer\n config={{\n revenue: { label: 'Revenue', color: 'var(--fui-color-accent)' },\n }}\n >\n <AreaChart data={monthlyData} margin={{ top: 5, right: 20, bottom: 5, left: 0 }}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"month\" />\n <YAxis />\n <ChartTooltip />\n <Area type=\"monotone\" dataKey=\"revenue\" stroke=\"var(--fui-color-accent)\" fill=\"var(--fui-color-accent)\" fillOpacity={0.15} strokeWidth={2} />\n </AreaChart>\n </ChartContainer>\n</div>"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"name": "Pie Chart",
|
|
92
|
+
"description": "Donut chart showing browser share distribution",
|
|
93
|
+
"code": "<div style={{ width: '100%', height: 300 }}>\n <ChartContainer\n config={{\n Chrome: { label: 'Chrome', color: 'var(--fui-color-accent)' },\n Firefox: { label: 'Firefox', color: 'var(--fui-color-info)' },\n Safari: { label: 'Safari', color: 'var(--fui-color-success)' },\n Edge: { label: 'Edge', color: 'var(--fui-color-warning)' },\n }}\n >\n <PieChart>\n <ChartTooltip />\n <ChartLegend />\n <Pie\n data={browserData}\n dataKey=\"value\"\n nameKey=\"name\"\n cx=\"50%\"\n cy=\"50%\"\n innerRadius={60}\n outerRadius={90}\n strokeWidth={2}\n >\n {browserData.map((entry) => (\n <Cell key={entry.name} fill={entry.color} />\n ))}\n </Pie>\n </PieChart>\n </ChartContainer>\n</div>"
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
"relations": [
|
|
97
|
+
{
|
|
98
|
+
"component": "Card",
|
|
99
|
+
"relationship": "parent",
|
|
100
|
+
"note": "Charts are typically placed inside Cards"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"component": "Progress",
|
|
104
|
+
"relationship": "alternative",
|
|
105
|
+
"note": "Use Progress for single-value completion"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"component": "Table",
|
|
109
|
+
"relationship": "sibling",
|
|
110
|
+
"note": "Combine with Table for full data views"
|
|
111
|
+
}
|
|
112
|
+
],
|
|
113
|
+
"contract": {
|
|
114
|
+
"propsSummary": [
|
|
115
|
+
"config: ChartConfig - maps data keys to labels and theme colors",
|
|
116
|
+
"children: ReactElement - recharts chart component",
|
|
117
|
+
"Chart.Tooltip / Chart.Legend support custom content renderers for advanced overlays"
|
|
118
|
+
],
|
|
119
|
+
"a11yRules": [
|
|
120
|
+
"A11Y_CHART_LABEL"
|
|
121
|
+
]
|
|
122
|
+
},
|
|
123
|
+
"provenance": {
|
|
124
|
+
"source": "migrated",
|
|
125
|
+
"verified": false,
|
|
126
|
+
"frameworkSupport": "native",
|
|
127
|
+
"extractedAt": "2026-03-13T23:18:52.043Z"
|
|
128
|
+
}
|
|
129
|
+
}
|