@fragments-sdk/ui 0.8.8 → 0.9.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 (48) hide show
  1. package/fragments.json +1 -1
  2. package/package.json +2 -2
  3. package/src/components/Accordion/Accordion.module.scss +1 -1
  4. package/src/components/Accordion/Accordion.test.tsx +1 -2
  5. package/src/components/Avatar/Avatar.fragment.tsx +18 -0
  6. package/src/components/Avatar/Avatar.test.tsx +18 -0
  7. package/src/components/Avatar/index.tsx +16 -0
  8. package/src/components/Badge/index.tsx +2 -0
  9. package/src/components/BentoGrid/BentoGrid.fragment.tsx +147 -0
  10. package/src/components/BentoGrid/BentoGrid.module.scss +123 -0
  11. package/src/components/BentoGrid/BentoGrid.test.tsx +140 -0
  12. package/src/components/BentoGrid/index.tsx +150 -0
  13. package/src/components/Button/index.tsx +2 -0
  14. package/src/components/Card/index.tsx +2 -0
  15. package/src/components/Chart/Chart.test.tsx +2 -2
  16. package/src/components/Checkbox/index.tsx +2 -0
  17. package/src/components/CodeBlock/index.tsx +1 -1
  18. package/src/components/Command/Command.test.tsx +1 -1
  19. package/src/components/Command/index.tsx +1 -1
  20. package/src/components/DatePicker/index.tsx +1 -1
  21. package/src/components/Dialog/index.tsx +2 -0
  22. package/src/components/Drawer/index.tsx +2 -0
  23. package/src/components/EmptyState/index.tsx +2 -0
  24. package/src/components/Field/index.tsx +2 -0
  25. package/src/components/Fieldset/index.tsx +2 -0
  26. package/src/components/Form/index.tsx +2 -0
  27. package/src/components/Header/Header.module.scss +4 -0
  28. package/src/components/Icon/index.tsx +2 -0
  29. package/src/components/List/index.tsx +2 -0
  30. package/src/components/Menu/index.tsx +2 -0
  31. package/src/components/NavigationMenu/NavigationMenu.module.scss +1 -2
  32. package/src/components/NavigationMenu/NavigationMenuContext.ts +2 -0
  33. package/src/components/NavigationMenu/index.tsx +51 -24
  34. package/src/components/NavigationMenu/useNavigationMenu.ts +3 -0
  35. package/src/components/Pagination/index.tsx +2 -0
  36. package/src/components/Popover/index.tsx +2 -0
  37. package/src/components/Progress/index.tsx +2 -0
  38. package/src/components/RadioGroup/index.tsx +2 -0
  39. package/src/components/Separator/index.tsx +2 -0
  40. package/src/components/Switch/index.ts +2 -0
  41. package/src/components/Theme/index.tsx +4 -3
  42. package/src/components/Toggle/index.tsx +2 -0
  43. package/src/components/ToggleGroup/ToggleGroup.fragment.tsx +96 -79
  44. package/src/components/ToggleGroup/index.tsx +2 -0
  45. package/src/components/Tooltip/index.tsx +2 -0
  46. package/src/index.ts +3 -2
  47. package/src/styles/globals.scss +5 -0
  48. package/src/tokens/_variables.scss +1 -1
@@ -1,9 +1,9 @@
1
- import React from 'react';
2
- import { defineFragment } from '@fragments-sdk/cli/core';
3
- import { ToggleGroup } from '.';
1
+ import React from "react";
2
+ import { defineFragment } from "@fragments-sdk/cli/core";
3
+ import { ToggleGroup } from ".";
4
4
 
5
5
  function DefaultExample() {
6
- const [value, setValue] = React.useState('left');
6
+ const [value, setValue] = React.useState("left");
7
7
 
8
8
  return (
9
9
  <ToggleGroup value={value} onChange={setValue}>
@@ -15,7 +15,7 @@ function DefaultExample() {
15
15
  }
16
16
 
17
17
  function PillsExample() {
18
- const [value, setValue] = React.useState('all');
18
+ const [value, setValue] = React.useState("all");
19
19
 
20
20
  return (
21
21
  <ToggleGroup value={value} onChange={setValue} variant="pills">
@@ -27,7 +27,7 @@ function PillsExample() {
27
27
  }
28
28
 
29
29
  function OutlineExample() {
30
- const [value, setValue] = React.useState('day');
30
+ const [value, setValue] = React.useState("day");
31
31
 
32
32
  return (
33
33
  <ToggleGroup value={value} onChange={setValue} variant="outline">
@@ -39,11 +39,11 @@ function OutlineExample() {
39
39
  }
40
40
 
41
41
  function SizesExample() {
42
- const [value1, setValue1] = React.useState('a');
43
- const [value2, setValue2] = React.useState('a');
42
+ const [value1, setValue1] = React.useState("a");
43
+ const [value2, setValue2] = React.useState("a");
44
44
 
45
45
  return (
46
- <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
46
+ <div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
47
47
  <ToggleGroup value={value1} onChange={setValue1} size="sm">
48
48
  <ToggleGroup.Item value="a">Small</ToggleGroup.Item>
49
49
  <ToggleGroup.Item value="b">Size</ToggleGroup.Item>
@@ -57,12 +57,19 @@ function SizesExample() {
57
57
  }
58
58
 
59
59
  function ViewSwitcherExample() {
60
- const [view, setView] = React.useState('grid');
60
+ const [view, setView] = React.useState("grid");
61
61
 
62
62
  return (
63
63
  <ToggleGroup value={view} onChange={setView} size="sm">
64
64
  <ToggleGroup.Item value="grid">
65
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
65
+ <svg
66
+ width="16"
67
+ height="16"
68
+ viewBox="0 0 24 24"
69
+ fill="none"
70
+ stroke="currentColor"
71
+ strokeWidth="2"
72
+ >
66
73
  <rect x="3" y="3" width="7" height="7" />
67
74
  <rect x="14" y="3" width="7" height="7" />
68
75
  <rect x="3" y="14" width="7" height="7" />
@@ -70,7 +77,14 @@ function ViewSwitcherExample() {
70
77
  </svg>
71
78
  </ToggleGroup.Item>
72
79
  <ToggleGroup.Item value="list">
73
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
80
+ <svg
81
+ width="16"
82
+ height="16"
83
+ viewBox="0 0 24 24"
84
+ fill="none"
85
+ stroke="currentColor"
86
+ strokeWidth="2"
87
+ >
74
88
  <line x1="3" y1="6" x2="21" y2="6" />
75
89
  <line x1="3" y1="12" x2="21" y2="12" />
76
90
  <line x1="3" y1="18" x2="21" y2="18" />
@@ -81,13 +95,15 @@ function ViewSwitcherExample() {
81
95
  }
82
96
 
83
97
  function DisabledItemExample() {
84
- const [value, setValue] = React.useState('basic');
98
+ const [value, setValue] = React.useState("basic");
85
99
 
86
100
  return (
87
101
  <ToggleGroup value={value} onChange={setValue}>
88
102
  <ToggleGroup.Item value="basic">Basic</ToggleGroup.Item>
89
103
  <ToggleGroup.Item value="pro">Pro</ToggleGroup.Item>
90
- <ToggleGroup.Item value="enterprise" disabled>Enterprise</ToggleGroup.Item>
104
+ <ToggleGroup.Item value="enterprise" disabled>
105
+ Enterprise
106
+ </ToggleGroup.Item>
91
107
  </ToggleGroup>
92
108
  );
93
109
  }
@@ -96,104 +112,105 @@ export default defineFragment({
96
112
  component: ToggleGroup,
97
113
 
98
114
  meta: {
99
- name: 'ToggleGroup',
100
- description: 'A group of toggle buttons where only one can be selected at a time. Useful for switching between views, modes, or options.',
101
- category: 'forms',
102
- status: 'stable',
103
- tags: ['toggle', 'group', 'fragmented', 'control', 'tabs', 'switch'],
104
- since: '0.2.0',
115
+ name: "ToggleGroup",
116
+ description:
117
+ "A group of toggle buttons where only one can be selected at a time. Useful for switching between views, modes, or options.",
118
+ category: "forms",
119
+ status: "stable",
120
+ tags: ["toggle", "group", "fragmented", "control", "tabs", "switch"],
121
+ since: "0.2.0",
105
122
  },
106
123
 
107
124
  usage: {
108
125
  when: [
109
- 'Switching between mutually exclusive views or modes',
110
- 'Selecting one option from a small set (2-5 options)',
111
- 'Fragmented controls like view switchers',
112
- 'Filter or sort options',
126
+ "Switching between mutually exclusive views or modes",
127
+ "Selecting one option from a small set (2-5 options)",
128
+ "Fragmented controls like view switchers",
129
+ "Filter or sort options",
113
130
  ],
114
131
  whenNot: [
115
- 'Multiple selections allowed (use Checkbox group)',
116
- 'Many options (use Select or RadioGroup)',
117
- 'Navigation between pages (use Tabs)',
118
- 'On/off toggle (use Switch component)',
132
+ "Multiple selections allowed (use Checkbox group)",
133
+ "Many options (use Select or RadioGroup)",
134
+ "Navigation between pages (use Tabs)",
135
+ "On/off toggle (use Switch component)",
119
136
  ],
120
137
  guidelines: [
121
- 'Keep options to 2-5 items for clarity',
122
- 'Use clear, concise labels',
123
- 'Consider icons for common actions (grid/list view)',
124
- 'Ensure adequate touch targets on mobile',
138
+ "Keep options to 2-5 items for clarity",
139
+ "Use clear, concise labels",
140
+ "Consider icons for common actions (grid/list view)",
141
+ "Ensure adequate touch targets on mobile",
125
142
  ],
126
143
  accessibility: [
127
144
  'Uses role="group" for semantic grouping',
128
145
  'Each item has role="radio" with aria-checked',
129
- 'Keyboard navigable with Tab and arrow keys',
130
- 'Focus visible on active item',
146
+ "Keyboard navigable with Tab and arrow keys",
147
+ "Focus visible on active item",
131
148
  ],
132
149
  },
133
150
 
134
151
  props: {
135
152
  value: {
136
- type: 'string',
137
- description: 'Currently selected value',
153
+ type: "string",
154
+ description: "Currently selected value",
138
155
  required: true,
139
156
  },
140
157
  onChange: {
141
- type: 'function',
142
- description: 'Called with new value when selection changes',
158
+ type: "function",
159
+ description: "Called with new value when selection changes",
143
160
  required: true,
144
161
  },
145
162
  children: {
146
- type: 'node',
147
- description: 'ToggleGroup.Item components',
163
+ type: "node",
164
+ description: "ToggleGroup.Item components",
148
165
  required: true,
149
166
  },
150
167
  variant: {
151
- type: 'enum',
152
- description: 'Visual style',
153
- values: ['default', 'pills', 'outline'],
154
- default: 'default',
168
+ type: "enum",
169
+ description: "Visual style",
170
+ values: ["default", "pills", "outline"],
171
+ default: "default",
155
172
  },
156
173
  size: {
157
- type: 'enum',
158
- description: 'Size variant',
159
- values: ['sm', 'md'],
160
- default: 'md',
174
+ type: "enum",
175
+ description: "Size variant",
176
+ values: ["sm", "md"],
177
+ default: "md",
161
178
  },
162
179
  gap: {
163
- type: 'enum',
164
- description: 'Gap between items (pills/outline variants)',
165
- values: ['none', 'xs', 'sm'],
166
- default: 'xs',
180
+ type: "enum",
181
+ description: "Gap between items (pills/outline variants)",
182
+ values: ["none", "xs", "sm"],
183
+ default: "xs",
167
184
  },
168
185
  },
169
186
 
170
187
  relations: [
171
- { component: 'RadioGroup', relationship: 'alternative', note: 'RadioGroup for form-style single selection' },
172
- { component: 'Tabs', relationship: 'alternative', note: 'Tabs for content panel switching' },
173
- { component: 'Switch', relationship: 'sibling', note: 'Switch for single on/off control' },
188
+ {
189
+ component: "RadioGroup",
190
+ relationship: "alternative",
191
+ note: "RadioGroup for form-style single selection",
192
+ },
193
+ { component: "Tabs", relationship: "alternative", note: "Tabs for content panel switching" },
194
+ { component: "Switch", relationship: "sibling", note: "Switch for single on/off control" },
174
195
  ],
175
196
 
176
197
  contract: {
177
198
  propsSummary: [
178
- 'value: string - selected value (required)',
179
- 'onChange: (value: string) => void - change handler (required)',
180
- 'children: ToggleGroup.Item[] - toggle items',
181
- 'variant: default|pills|outline - visual style',
182
- 'size: sm|md - size variant',
183
- 'gap: none|xs|sm - spacing',
184
- ],
185
- scenarioTags: [
186
- 'forms.selection',
187
- 'input.toggle',
188
- 'control.fragmented',
199
+ "value: string - selected value (required)",
200
+ "onChange: (value: string) => void - change handler (required)",
201
+ "children: ToggleGroup.Item[] - toggle items",
202
+ "variant: default|pills|outline - visual style",
203
+ "size: sm|md - size variant",
204
+ "gap: none|xs|sm - spacing",
189
205
  ],
190
- a11yRules: ['A11Y_GROUP_ROLE', 'A11Y_KEYBOARD_ACCESSIBLE'],
206
+ scenarioTags: ["forms.selection", "input.toggle", "control.fragmented"],
207
+ a11yRules: ["A11Y_GROUP_ROLE", "A11Y_KEYBOARD_ACCESSIBLE"],
191
208
  },
192
209
 
193
210
  variants: [
194
211
  {
195
- name: 'Default',
196
- description: 'Basic toggle group',
212
+ name: "Default",
213
+ description: "Basic toggle group",
197
214
  code: `<ToggleGroup value={value} onChange={setValue}>
198
215
  <ToggleGroup.Item value="left">Left</ToggleGroup.Item>
199
216
  <ToggleGroup.Item value="center">Center</ToggleGroup.Item>
@@ -202,8 +219,8 @@ export default defineFragment({
202
219
  render: () => <DefaultExample />,
203
220
  },
204
221
  {
205
- name: 'Pills Variant',
206
- description: 'Pill-shaped toggle buttons',
222
+ name: "Pills Variant",
223
+ description: "Pill-shaped toggle buttons",
207
224
  code: `<ToggleGroup value={value} onChange={setValue} variant="pills">
208
225
  <ToggleGroup.Item value="all">All</ToggleGroup.Item>
209
226
  <ToggleGroup.Item value="active">Active</ToggleGroup.Item>
@@ -212,8 +229,8 @@ export default defineFragment({
212
229
  render: () => <PillsExample />,
213
230
  },
214
231
  {
215
- name: 'Outline Variant',
216
- description: 'Outlined toggle buttons',
232
+ name: "Outline Variant",
233
+ description: "Outlined toggle buttons",
217
234
  code: `<ToggleGroup value={value} onChange={setValue} variant="outline">
218
235
  <ToggleGroup.Item value="day">Day</ToggleGroup.Item>
219
236
  <ToggleGroup.Item value="week">Week</ToggleGroup.Item>
@@ -222,8 +239,8 @@ export default defineFragment({
222
239
  render: () => <OutlineExample />,
223
240
  },
224
241
  {
225
- name: 'Sizes',
226
- description: 'Different size variants',
242
+ name: "Sizes",
243
+ description: "Different size variants",
227
244
  code: `<ToggleGroup value={value} onChange={setValue} size="sm">
228
245
  <ToggleGroup.Item value="a">Small</ToggleGroup.Item>
229
246
  <ToggleGroup.Item value="b">Size</ToggleGroup.Item>
@@ -235,8 +252,8 @@ export default defineFragment({
235
252
  render: () => <SizesExample />,
236
253
  },
237
254
  {
238
- name: 'View Switcher',
239
- description: 'Common pattern for switching between views',
255
+ name: "View Switcher",
256
+ description: "Common pattern for switching between views",
240
257
  code: `<ToggleGroup value={view} onChange={setView} size="sm">
241
258
  <ToggleGroup.Item value="grid"><GridIcon /></ToggleGroup.Item>
242
259
  <ToggleGroup.Item value="list"><ListIcon /></ToggleGroup.Item>
@@ -244,8 +261,8 @@ export default defineFragment({
244
261
  render: () => <ViewSwitcherExample />,
245
262
  },
246
263
  {
247
- name: 'With Disabled Item',
248
- description: 'Toggle group with a disabled option',
264
+ name: "With Disabled Item",
265
+ description: "Toggle group with a disabled option",
249
266
  code: `<ToggleGroup value={value} onChange={setValue}>
250
267
  <ToggleGroup.Item value="basic">Basic</ToggleGroup.Item>
251
268
  <ToggleGroup.Item value="pro">Pro</ToggleGroup.Item>
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  import * as React from 'react';
2
4
  import styles from './ToggleGroup.module.scss';
3
5
  import '../../styles/globals.scss';
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  import * as React from 'react';
2
4
  import { Tooltip as BaseTooltip } from '@base-ui/react/tooltip';
3
5
  import styles from './Tooltip.module.scss';
package/src/index.ts CHANGED
@@ -1,5 +1,3 @@
1
- 'use client';
2
-
3
1
  // Import CSS variables and base styles
4
2
  // This ensures --fui-* variables are available when using any component
5
3
  import './styles/globals.scss';
@@ -184,6 +182,9 @@ export {
184
182
  // Grid
185
183
  export { Grid, type GridProps, type GridItemProps, type ResponsiveColumns } from './components/Grid';
186
184
 
185
+ // BentoGrid
186
+ export { BentoGrid, type BentoGridProps, type BentoGridItemProps, type ResponsiveSpan } from './components/BentoGrid';
187
+
187
188
  // Separator
188
189
  export { Separator, type SeparatorProps } from './components/Separator';
189
190
 
@@ -44,6 +44,11 @@ body {
44
44
  font-feature-settings: "rlig" 1, "calt" 1;
45
45
  }
46
46
 
47
+ // Global link reset
48
+ a {
49
+ text-decoration: none;
50
+ }
51
+
47
52
  *::selection {
48
53
  background-color: var(--fui-color-success-bg, rgba(16, 163, 127, 0.1));
49
54
  color: var(--fui-text-primary, #171717);
@@ -350,7 +350,7 @@ $fui-theme-toggle-lg-height: 34px !default;
350
350
  $fui-theme-toggle-lg-icon: 18px !default;
351
351
 
352
352
  // CodeBlock (light mode)
353
- $fui-code-bg: var(--fui-bg-elevated) !default;
353
+ $fui-code-bg: #1e1e1e !default;
354
354
  $fui-code-header-bg: var(--fui-bg-elevated) !default;
355
355
  $fui-code-text: #d4d4d4 !default;
356
356
  $fui-code-text-muted: #6b7280 !default;