@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.
- 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/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/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/tokens/_derive.scss +4 -1
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://usefragments.com/schemas/contract.v1.json",
|
|
3
|
+
"name": "Tooltip",
|
|
4
|
+
"description": "Contextual help text that appears on hover or focus. Perfect for explaining icons, truncated text, or providing additional context.",
|
|
5
|
+
"category": "feedback",
|
|
6
|
+
"tags": [
|
|
7
|
+
"tooltip",
|
|
8
|
+
"hint",
|
|
9
|
+
"help",
|
|
10
|
+
"hover",
|
|
11
|
+
"contextual"
|
|
12
|
+
],
|
|
13
|
+
"status": "stable",
|
|
14
|
+
"sourcePath": "src/components/Tooltip/index.tsx",
|
|
15
|
+
"exportName": "Tooltip",
|
|
16
|
+
"propsSummary": [
|
|
17
|
+
"children: element (required)",
|
|
18
|
+
"content: node (required)",
|
|
19
|
+
"side: top|bottom|left|right (default: top)",
|
|
20
|
+
"align: start|center|end (default: center)",
|
|
21
|
+
"sideOffset: number (default: 6)",
|
|
22
|
+
"delay: number",
|
|
23
|
+
"closeDelay: number",
|
|
24
|
+
"disabled: boolean (default: false)",
|
|
25
|
+
"arrow: boolean (default: true)",
|
|
26
|
+
"open: boolean",
|
|
27
|
+
"defaultOpen: boolean",
|
|
28
|
+
"onOpenChange: function",
|
|
29
|
+
"contentProps: object",
|
|
30
|
+
"style: object"
|
|
31
|
+
],
|
|
32
|
+
"props": {
|
|
33
|
+
"children": {
|
|
34
|
+
"type": "element",
|
|
35
|
+
"description": "The element that triggers the tooltip",
|
|
36
|
+
"required": true
|
|
37
|
+
},
|
|
38
|
+
"content": {
|
|
39
|
+
"type": "node",
|
|
40
|
+
"description": "Content to display in the tooltip",
|
|
41
|
+
"required": true
|
|
42
|
+
},
|
|
43
|
+
"side": {
|
|
44
|
+
"type": "enum",
|
|
45
|
+
"description": "Which side to show the tooltip",
|
|
46
|
+
"default": "top",
|
|
47
|
+
"required": false,
|
|
48
|
+
"values": [
|
|
49
|
+
"top",
|
|
50
|
+
"bottom",
|
|
51
|
+
"left",
|
|
52
|
+
"right"
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
"align": {
|
|
56
|
+
"type": "enum",
|
|
57
|
+
"description": "Alignment along the side",
|
|
58
|
+
"default": "center",
|
|
59
|
+
"required": false,
|
|
60
|
+
"values": [
|
|
61
|
+
"start",
|
|
62
|
+
"center",
|
|
63
|
+
"end"
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
"sideOffset": {
|
|
67
|
+
"type": "number",
|
|
68
|
+
"description": "Distance from trigger in pixels",
|
|
69
|
+
"default": "6",
|
|
70
|
+
"required": false
|
|
71
|
+
},
|
|
72
|
+
"delay": {
|
|
73
|
+
"type": "number",
|
|
74
|
+
"description": "Delay before showing (ms)",
|
|
75
|
+
"default": "400",
|
|
76
|
+
"required": false
|
|
77
|
+
},
|
|
78
|
+
"closeDelay": {
|
|
79
|
+
"type": "number",
|
|
80
|
+
"description": "Delay before hiding (ms)",
|
|
81
|
+
"default": "0",
|
|
82
|
+
"required": false
|
|
83
|
+
},
|
|
84
|
+
"disabled": {
|
|
85
|
+
"type": "boolean",
|
|
86
|
+
"description": "Disable the tooltip",
|
|
87
|
+
"default": "false",
|
|
88
|
+
"required": false
|
|
89
|
+
},
|
|
90
|
+
"arrow": {
|
|
91
|
+
"type": "boolean",
|
|
92
|
+
"description": "Show arrow pointing to trigger",
|
|
93
|
+
"default": "true",
|
|
94
|
+
"required": false
|
|
95
|
+
},
|
|
96
|
+
"open": {
|
|
97
|
+
"type": "boolean",
|
|
98
|
+
"description": "Controlled open state",
|
|
99
|
+
"required": false
|
|
100
|
+
},
|
|
101
|
+
"defaultOpen": {
|
|
102
|
+
"type": "boolean",
|
|
103
|
+
"description": "Default open state",
|
|
104
|
+
"default": "false",
|
|
105
|
+
"required": false
|
|
106
|
+
},
|
|
107
|
+
"onOpenChange": {
|
|
108
|
+
"type": "function",
|
|
109
|
+
"description": "Callback when open state changes",
|
|
110
|
+
"required": false
|
|
111
|
+
},
|
|
112
|
+
"contentProps": {
|
|
113
|
+
"type": "object",
|
|
114
|
+
"description": "Props forwarded to the tooltip popup element (preferred way to pass popup attrs/className/style)",
|
|
115
|
+
"required": false
|
|
116
|
+
},
|
|
117
|
+
"style": {
|
|
118
|
+
"type": "object",
|
|
119
|
+
"description": "",
|
|
120
|
+
"required": false
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
"usage": {
|
|
124
|
+
"when": [
|
|
125
|
+
"Explaining icon-only buttons",
|
|
126
|
+
"Showing full text for truncated content",
|
|
127
|
+
"Providing keyboard shortcuts",
|
|
128
|
+
"Brief contextual help that fits in one line"
|
|
129
|
+
],
|
|
130
|
+
"whenNot": [
|
|
131
|
+
"Long-form help content (use Popover)",
|
|
132
|
+
"Critical information users must see (use Alert)",
|
|
133
|
+
"Interactive content (use Popover or Menu)",
|
|
134
|
+
"Mobile-primary interfaces (tooltips require hover)"
|
|
135
|
+
],
|
|
136
|
+
"guidelines": [
|
|
137
|
+
"Keep tooltip text concise (under 80 characters)",
|
|
138
|
+
"Use sentence case, no period for single sentences",
|
|
139
|
+
"Avoid duplicating visible label text",
|
|
140
|
+
"Consider mobile users who cannot hover",
|
|
141
|
+
"Use contentProps for tooltip popup attributes/styling; top-level HTML attrs are applied to the popup for backward compatibility"
|
|
142
|
+
],
|
|
143
|
+
"accessibility": [
|
|
144
|
+
"Accessible via focus as well as hover",
|
|
145
|
+
"Uses role=\"tooltip\" with proper aria association",
|
|
146
|
+
"Delay prevents tooltips from appearing during navigation"
|
|
147
|
+
]
|
|
148
|
+
},
|
|
149
|
+
"examples": [
|
|
150
|
+
{
|
|
151
|
+
"name": "Default",
|
|
152
|
+
"description": "Basic tooltip on hover",
|
|
153
|
+
"code": "<Tooltip content=\"Save your changes\">\n <Button>Save</Button>\n</Tooltip>"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"name": "Positions",
|
|
157
|
+
"description": "Tooltips on different sides",
|
|
158
|
+
"code": "<div style={{ display: 'flex', gap: '16px', padding: '40px' }}>\n <Tooltip content=\"Top tooltip\" side=\"top\">\n <Button variant=\"secondary\">Top</Button>\n </Tooltip>\n <Tooltip content=\"Bottom tooltip\" side=\"bottom\">\n <Button variant=\"secondary\">Bottom</Button>\n </Tooltip>\n <Tooltip content=\"Left tooltip\" side=\"left\">\n <Button variant=\"secondary\">Left</Button>\n </Tooltip>\n <Tooltip content=\"Right tooltip\" side=\"right\">\n <Button variant=\"secondary\">Right</Button>\n </Tooltip>\n</div>"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"name": "With Shortcut",
|
|
162
|
+
"description": "Tooltip showing keyboard shortcut",
|
|
163
|
+
"code": "<Tooltip content=\"Undo (Ctrl+Z)\">\n <Button variant=\"ghost\">Undo</Button>\n</Tooltip>"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"name": "No Arrow",
|
|
167
|
+
"description": "Tooltip without arrow",
|
|
168
|
+
"code": "<Tooltip content=\"Clean tooltip\" arrow={false}>\n <Button variant=\"secondary\">Hover me</Button>\n</Tooltip>"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"name": "With Content Props",
|
|
172
|
+
"description": "Pass popup attributes/styling using contentProps",
|
|
173
|
+
"code": "<Tooltip content=\"Custom popup attrs\" contentProps={{ id: 'custom-tooltip-popup' }}>\n <Button variant=\"secondary\">Hover me</Button>\n</Tooltip>"
|
|
174
|
+
}
|
|
175
|
+
],
|
|
176
|
+
"relations": [
|
|
177
|
+
{
|
|
178
|
+
"component": "Popover",
|
|
179
|
+
"relationship": "alternative",
|
|
180
|
+
"note": "Use Popover for interactive or longer content"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"component": "Alert",
|
|
184
|
+
"relationship": "alternative",
|
|
185
|
+
"note": "Use Alert for critical information that must be visible"
|
|
186
|
+
}
|
|
187
|
+
],
|
|
188
|
+
"contract": {
|
|
189
|
+
"propsSummary": [
|
|
190
|
+
"content: ReactNode - tooltip content",
|
|
191
|
+
"side: top|bottom|left|right - position",
|
|
192
|
+
"delay: number - show delay in ms (default: 400)",
|
|
193
|
+
"arrow: boolean - show arrow (default: true)",
|
|
194
|
+
"contentProps: HTMLAttributes<HTMLDivElement> - popup element props"
|
|
195
|
+
],
|
|
196
|
+
"a11yRules": [
|
|
197
|
+
"A11Y_TOOLTIP_FOCUS",
|
|
198
|
+
"A11Y_TOOLTIP_ROLE"
|
|
199
|
+
]
|
|
200
|
+
},
|
|
201
|
+
"ai": {
|
|
202
|
+
"compositionPattern": "compound",
|
|
203
|
+
"subComponents": [
|
|
204
|
+
"Root",
|
|
205
|
+
"Provider"
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
"provenance": {
|
|
209
|
+
"source": "migrated",
|
|
210
|
+
"verified": false,
|
|
211
|
+
"frameworkSupport": "native",
|
|
212
|
+
"extractedAt": "2026-03-13T23:19:07.058Z"
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://usefragments.com/schemas/contract.v1.json",
|
|
3
|
+
"name": "VisuallyHidden",
|
|
4
|
+
"description": "Hides content visually while keeping it accessible to screen readers. Essential for accessible icon-only buttons and supplementary text.",
|
|
5
|
+
"category": "navigation",
|
|
6
|
+
"tags": [
|
|
7
|
+
"accessibility",
|
|
8
|
+
"a11y",
|
|
9
|
+
"screen-reader",
|
|
10
|
+
"hidden",
|
|
11
|
+
"sr-only"
|
|
12
|
+
],
|
|
13
|
+
"status": "stable",
|
|
14
|
+
"sourcePath": "src/components/VisuallyHidden/index.tsx",
|
|
15
|
+
"exportName": "VisuallyHidden",
|
|
16
|
+
"propsSummary": [
|
|
17
|
+
"children: node (required)",
|
|
18
|
+
"as: span|div (default: span)"
|
|
19
|
+
],
|
|
20
|
+
"props": {
|
|
21
|
+
"children": {
|
|
22
|
+
"type": "node",
|
|
23
|
+
"description": "Content to hide visually",
|
|
24
|
+
"required": true
|
|
25
|
+
},
|
|
26
|
+
"as": {
|
|
27
|
+
"type": "enum",
|
|
28
|
+
"description": "HTML element to render",
|
|
29
|
+
"default": "span",
|
|
30
|
+
"required": false,
|
|
31
|
+
"values": [
|
|
32
|
+
"span",
|
|
33
|
+
"div"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"usage": {
|
|
38
|
+
"when": [
|
|
39
|
+
"Providing accessible labels for icon-only buttons",
|
|
40
|
+
"Adding context that screen readers need but sighted users don't",
|
|
41
|
+
"Hiding decorative content while providing text alternatives",
|
|
42
|
+
"Skip links for keyboard navigation"
|
|
43
|
+
],
|
|
44
|
+
"whenNot": [
|
|
45
|
+
"Hiding content from everyone (use display: none or conditional render)",
|
|
46
|
+
"Content that should be visible on focus (use focus-visible styles)",
|
|
47
|
+
"Temporarily hidden content (use proper ARIA attributes)",
|
|
48
|
+
"Lazy-loaded content (use suspense or loading states)"
|
|
49
|
+
],
|
|
50
|
+
"guidelines": [
|
|
51
|
+
"Always use with icon-only interactive elements",
|
|
52
|
+
"Keep hidden text concise but descriptive",
|
|
53
|
+
"Test with screen readers to verify announcements",
|
|
54
|
+
"Don't overuse; visible text is often better",
|
|
55
|
+
"VisuallyHidden forwards DOM props and className to the rendered element"
|
|
56
|
+
],
|
|
57
|
+
"accessibility": [
|
|
58
|
+
"Content is announced by screen readers",
|
|
59
|
+
"Content is focusable if interactive elements are inside",
|
|
60
|
+
"Essential for WCAG 2.1 compliance with icon-only controls",
|
|
61
|
+
"Must convey equivalent information to visual content"
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
"examples": [
|
|
65
|
+
{
|
|
66
|
+
"name": "Icon Button Label",
|
|
67
|
+
"description": "Accessible label for icon-only button",
|
|
68
|
+
"code": "<button style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '40px',\n height: '40px',\n border: '1px solid var(--fui-border-default)',\n borderRadius: '8px',\n background: 'var(--fui-color-surface-primary)',\n cursor: 'pointer'\n}}>\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n <VisuallyHidden>Search</VisuallyHidden>\n</button>"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "Supplementary Text",
|
|
72
|
+
"description": "Additional context for screen readers",
|
|
73
|
+
"code": "<a href=\"#\" style={{ color: 'var(--fui-color-accent)' }}>\n Read more\n <VisuallyHidden> about our accessibility features</VisuallyHidden>\n</a>"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"name": "Skip Link",
|
|
77
|
+
"description": "Navigation aid that becomes visible on focus",
|
|
78
|
+
"code": "<div>\n <VisuallyHidden as=\"div\">\n <a\n href=\"#main-content\"\n style={{\n position: 'absolute',\n padding: '8px 16px',\n background: 'var(--fui-color-accent)',\n color: 'white'\n }}\n >\n Skip to main content\n </a>\n </VisuallyHidden>\n <p style={{ color: 'var(--fui-color-text-tertiary)', fontSize: '14px' }}>\n (Screen reader only: \"Skip to main content\" link)\n </p>\n</div>"
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
"relations": [
|
|
82
|
+
{
|
|
83
|
+
"component": "Button",
|
|
84
|
+
"relationship": "child",
|
|
85
|
+
"note": "Use inside icon-only buttons for accessible labels"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"component": "Icon",
|
|
89
|
+
"relationship": "sibling",
|
|
90
|
+
"note": "Pair with icons to provide text alternatives"
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"contract": {
|
|
94
|
+
"propsSummary": [
|
|
95
|
+
"children: ReactNode - hidden text (required)",
|
|
96
|
+
"as: span|div - HTML element",
|
|
97
|
+
"Forwards standard DOM props (id, aria-*, data-*, className, handlers)"
|
|
98
|
+
],
|
|
99
|
+
"a11yRules": [
|
|
100
|
+
"A11Y_SR_ONLY",
|
|
101
|
+
"A11Y_ICON_LABEL"
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
"ai": {
|
|
105
|
+
"compositionPattern": "compound",
|
|
106
|
+
"subComponents": [
|
|
107
|
+
"Root"
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
"provenance": {
|
|
111
|
+
"source": "migrated",
|
|
112
|
+
"verified": false,
|
|
113
|
+
"frameworkSupport": "native",
|
|
114
|
+
"extractedAt": "2026-03-13T23:19:06.625Z"
|
|
115
|
+
}
|
|
116
|
+
}
|
package/src/tokens/_derive.scss
CHANGED
|
@@ -214,7 +214,10 @@
|
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
// Light mode background — stone uses white, colorful palettes use palette[50]
|
|
217
|
-
$bg:
|
|
217
|
+
$bg: #ffffff;
|
|
218
|
+
@if $palette-name != 'stone' {
|
|
219
|
+
$bg: get-shade($palette, 50);
|
|
220
|
+
}
|
|
218
221
|
|
|
219
222
|
@return (
|
|
220
223
|
primary: get-shade($palette, 900), // Main text (high contrast)
|