@foi/design-system 0.0.18 → 0.0.20
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/README.md +665 -77
- package/dist/{DatePicker.utils-ytCEcs6T.js → DatePicker.utils-D6aKFBuv.js} +2 -2
- package/dist/{DatePicker.utils-ytCEcs6T.js.map → DatePicker.utils-D6aKFBuv.js.map} +1 -1
- package/dist/Toast-k4dxCveh.js +1366 -0
- package/dist/Toast-k4dxCveh.js.map +1 -0
- package/dist/components/atoms/Button/Button.interface.d.ts +1 -1
- package/dist/components/atoms/Checkbox/Checkbox.interface.d.ts +3 -3
- package/dist/components/atoms/Chip/Chip.d.ts +4 -0
- package/dist/components/atoms/Chip/Chip.emotion.d.ts +2 -0
- package/dist/components/atoms/Chip/Chip.interface.d.ts +14 -0
- package/dist/components/atoms/Chip/index.d.ts +5 -0
- package/dist/components/atoms/DatePicker/DatePicker.interface.d.ts +2 -2
- package/dist/components/atoms/DatePicker/DatePickerMenu/DatePickerMenu.interface.d.ts +3 -3
- package/dist/components/atoms/IconButton/IconButton.interface.d.ts +2 -2
- package/dist/components/atoms/NumberField/NumberField.interface.d.ts +2 -2
- package/dist/components/atoms/Radio/Radio.interface.d.ts +2 -2
- package/dist/components/atoms/Select/Select.interface.d.ts +2 -2
- package/dist/components/atoms/Select/SelectMenu/SelectMenu.interface.d.ts +1 -1
- package/dist/components/atoms/Slider/Slider.interface.d.ts +4 -4
- package/dist/components/atoms/Switch/Switch.interface.d.ts +1 -1
- package/dist/components/atoms/TextField/TextField.interface.d.ts +2 -2
- package/dist/components/molecules/CheckboxGroup/CheckboxGroup.interface.d.ts +2 -2
- package/dist/components/molecules/CheckboxTree/CheckboxTree.interface.d.ts +2 -2
- package/dist/components/molecules/Modal/Modal.interface.d.ts +4 -4
- package/dist/components/molecules/RadioGroup/RadioGroup.interface.d.ts +2 -2
- package/dist/components/molecules/Toast/Toast.context.d.ts +2 -0
- package/dist/components/molecules/Toast/Toast.d.ts +4 -0
- package/dist/components/molecules/Toast/Toast.emotion.d.ts +4 -0
- package/dist/components/molecules/Toast/Toast.hook.d.ts +1 -0
- package/dist/components/molecules/Toast/Toast.interface.d.ts +33 -0
- package/dist/components/molecules/Toast/Toast.provider.d.ts +3 -0
- package/dist/components/molecules/Toast/index.d.ts +3 -0
- package/dist/components/organisms/DataGrid/DataGrid.interface.d.ts +3 -3
- package/dist/components/organisms/DataGrid/DataGridMenu/DataGridMenu.interface.d.ts +1 -1
- package/dist/hocs/ThemeProvider/ThemeProvider.interface.d.ts +6 -0
- package/dist/hocs/ThemeProvider/components/{Button.d.ts → atoms/Button.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{Checkbox.d.ts → atoms/Checkbox.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/atoms/Chip.d.ts +13 -0
- package/dist/hocs/ThemeProvider/components/{DatePicker.d.ts → atoms/DatePicker.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{DatePickerMenu.d.ts → atoms/DatePickerMenu.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{IconButton.d.ts → atoms/IconButton.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{NumberField.d.ts → atoms/NumberField.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{Pagination.d.ts → atoms/Pagination.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{PaginationMenu.d.ts → atoms/PaginationMenu.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{Radio.d.ts → atoms/Radio.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{Select.d.ts → atoms/Select.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{SelectMenu.d.ts → atoms/SelectMenu.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{Slider.d.ts → atoms/Slider.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{Switch.d.ts → atoms/Switch.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{TextField.d.ts → atoms/TextField.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/index.d.ts +23 -17
- package/dist/hocs/ThemeProvider/components/{CheckboxGroup.d.ts → molecules/CheckboxGroup.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{CheckboxTree.d.ts → molecules/CheckboxTree.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{Modal.d.ts → molecules/Modal.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{RadioGroup.d.ts → molecules/RadioGroup.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/molecules/Toast.d.ts +16 -0
- package/dist/hocs/ThemeProvider/components/{DataGrid.d.ts → organisms/DataGrid.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/components/{DataGridMenu.d.ts → organisms/DataGridMenu.d.ts} +1 -1
- package/dist/hocs/ThemeProvider/interfaces/Components.interface.d.ts +2 -0
- package/dist/hooks.d.ts +2 -0
- package/dist/hooks.mjs +2 -2
- package/dist/index.d.ts +14 -11
- package/dist/index.mjs +5596 -509
- package/dist/index.mjs.map +1 -1
- package/dist/theme/dark/components/atoms/Chip.d.ts +13 -0
- package/dist/theme/dark/components/index.d.ts +287 -263
- package/dist/theme/dark/components/molecules/Toast.d.ts +17 -0
- package/dist/theme/dark/index.d.ts +287 -263
- package/dist/theme/index.d.ts +287 -263
- package/dist/{theme-CLkxVsoE.js → theme-BjrtNRDQ.js} +230 -218
- package/dist/theme-BjrtNRDQ.js.map +1 -0
- package/dist/theme.d.ts +22 -0
- package/dist/theme.mjs +1 -1
- package/dist/utilities.mjs +1 -1
- package/package.json +1 -13
- package/dist/RadioGroup-D_R-nwCD.js +0 -456
- package/dist/RadioGroup-D_R-nwCD.js.map +0 -1
- package/dist/RadioGroup.context-CdFGi5z1.js +0 -601
- package/dist/RadioGroup.context-CdFGi5z1.js.map +0 -1
- package/dist/Switch-DK5hEXUS.js +0 -4196
- package/dist/Switch-DK5hEXUS.js.map +0 -1
- package/dist/ThemeProvider-BlqXHfU_.js +0 -39
- package/dist/ThemeProvider-BlqXHfU_.js.map +0 -1
- package/dist/atoms.d.ts +0 -21
- package/dist/atoms.mjs +0 -3
- package/dist/emotion-react-jsx-runtime.browser.esm-Ct_bZ5JG.js +0 -995
- package/dist/emotion-react-jsx-runtime.browser.esm-Ct_bZ5JG.js.map +0 -1
- package/dist/hocs.d.ts +0 -2
- package/dist/hocs.mjs +0 -2
- package/dist/molecules.d.ts +0 -8
- package/dist/molecules.mjs +0 -2
- package/dist/theme-CLkxVsoE.js.map +0 -1
- package/dist/useStateCallback-B4O93zzK.js +0 -32
- package/dist/useStateCallback-B4O93zzK.js.map +0 -1
- /package/dist/theme/dark/components/{Button.d.ts → atoms/Button.d.ts} +0 -0
- /package/dist/theme/dark/components/{Checkbox.d.ts → atoms/Checkbox.d.ts} +0 -0
- /package/dist/theme/dark/components/{DatePicker.d.ts → atoms/DatePicker.d.ts} +0 -0
- /package/dist/theme/dark/components/{DatePickerMenu.d.ts → atoms/DatePickerMenu.d.ts} +0 -0
- /package/dist/theme/dark/components/{IconButton.d.ts → atoms/IconButton.d.ts} +0 -0
- /package/dist/theme/dark/components/{NumberField.d.ts → atoms/NumberField.d.ts} +0 -0
- /package/dist/theme/dark/components/{Pagination.d.ts → atoms/Pagination.d.ts} +0 -0
- /package/dist/theme/dark/components/{PaginationMenu.d.ts → atoms/PaginationMenu.d.ts} +0 -0
- /package/dist/theme/dark/components/{Radio.d.ts → atoms/Radio.d.ts} +0 -0
- /package/dist/theme/dark/components/{Select.d.ts → atoms/Select.d.ts} +0 -0
- /package/dist/theme/dark/components/{SelectMenu.d.ts → atoms/SelectMenu.d.ts} +0 -0
- /package/dist/theme/dark/components/{Slider.d.ts → atoms/Slider.d.ts} +0 -0
- /package/dist/theme/dark/components/{Switch.d.ts → atoms/Switch.d.ts} +0 -0
- /package/dist/theme/dark/components/{TextField.d.ts → atoms/TextField.d.ts} +0 -0
- /package/dist/theme/dark/components/{CheckboxGroup.d.ts → molecules/CheckboxGroup.d.ts} +0 -0
- /package/dist/theme/dark/components/{CheckboxTree.d.ts → molecules/CheckboxTree.d.ts} +0 -0
- /package/dist/theme/dark/components/{Modal.d.ts → molecules/Modal.d.ts} +0 -0
- /package/dist/theme/dark/components/{RadioGroup.d.ts → molecules/RadioGroup.d.ts} +0 -0
- /package/dist/theme/dark/components/{DataGrid.d.ts → organisms/DataGrid.d.ts} +0 -0
- /package/dist/theme/dark/components/{DataGridMenu.d.ts → organisms/DataGridMenu.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -46,12 +46,13 @@ npm publish --access public
|
|
|
46
46
|
| ------------- | ------------------------------------------------------------------------------------------ |
|
|
47
47
|
| `Button` | Primary action button with variant/size/color support |
|
|
48
48
|
| `Checkbox` | Single checkbox — standalone, RHF, or inside a group |
|
|
49
|
+
| `Chip` | Compact inline label for statuses and tags — themed variants, accepts text or ReactNode |
|
|
49
50
|
| `DatePicker` | Date input with calendar menu, integrates with RHF |
|
|
50
51
|
| `Icon` | Font-based icon using Material Symbols Rounded — pass a `name` prop |
|
|
51
|
-
| `IconButton` | Clickable icon with button semantics
|
|
52
|
+
| `IconButton` | Clickable icon with button semantics |
|
|
52
53
|
| `NumberField` | Numeric input with increment/decrement buttons, min/max/step support, and two layout modes |
|
|
53
54
|
| `Pagination` | Page navigation bar with first/prev/next/last buttons and optional rows-per-page selector |
|
|
54
|
-
| `Radio` | Single radio button — used inside `RadioGroup`
|
|
55
|
+
| `Radio` | Single radio button — used inside `RadioGroup` |
|
|
55
56
|
| `Select` | Dropdown select with RHF integration |
|
|
56
57
|
| `Skeleton` | Animated placeholder shown while content is loading — rectangular or circular |
|
|
57
58
|
| `Slider` | Range slider with RHF integration |
|
|
@@ -60,17 +61,18 @@ npm publish --access public
|
|
|
60
61
|
|
|
61
62
|
### Molecules
|
|
62
63
|
|
|
63
|
-
| Component | Description
|
|
64
|
-
| --------------- |
|
|
65
|
-
| `CheckboxGroup` | Manages a set of `Checkbox` children as a `string[]` RHF field
|
|
66
|
-
| `CheckboxTree` | Hierarchical checkbox group with parent/child selection logic
|
|
64
|
+
| Component | Description |
|
|
65
|
+
| --------------- | --------------------------------------------------------------------------------- |
|
|
66
|
+
| `CheckboxGroup` | Manages a set of `Checkbox` children as a `string[]` RHF field |
|
|
67
|
+
| `CheckboxTree` | Hierarchical checkbox group with parent/child selection logic |
|
|
67
68
|
| `Modal` | Overlay dialog rendered via React portal — closes on ×, backdrop click, or Escape |
|
|
68
|
-
| `RadioGroup` | Manages a set of `Radio` children as a single RHF field
|
|
69
|
+
| `RadioGroup` | Manages a set of `Radio` children as a single RHF field |
|
|
70
|
+
| `Toast` | Notification system — push transient messages from anywhere via `useToast` |
|
|
69
71
|
|
|
70
72
|
### Organisms
|
|
71
73
|
|
|
72
|
-
| Component | Description
|
|
73
|
-
| ---------- |
|
|
74
|
+
| Component | Description |
|
|
75
|
+
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
74
76
|
| `DataGrid` | Async data table with server-side sorting, filtering (search / multiselect), pagination or infinite scroll, skeleton loading state, and custom action columns via `render` |
|
|
75
77
|
|
|
76
78
|
## Usage with React Hook Form
|
|
@@ -81,9 +83,7 @@ All field components share the same integration pattern. Define a Zod schema, pa
|
|
|
81
83
|
import { useForm } from 'react-hook-form';
|
|
82
84
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
83
85
|
import { z } from 'zod';
|
|
84
|
-
import TextField from '@
|
|
85
|
-
import NumberField from '@components/atoms/NumberField';
|
|
86
|
-
import Button from '@components/atoms/Button';
|
|
86
|
+
import { TextField, NumberField, Button } from '@foi/design-system';
|
|
87
87
|
|
|
88
88
|
const schema = z.object({
|
|
89
89
|
email: z.string().email('Invalid email'),
|
|
@@ -139,31 +139,30 @@ A text input field with a floating label, helper text, and full error state inte
|
|
|
139
139
|
|
|
140
140
|
### Props
|
|
141
141
|
|
|
142
|
-
| Prop
|
|
143
|
-
|
|
|
144
|
-
| `name`
|
|
145
|
-
| `label`
|
|
146
|
-
| `control`
|
|
147
|
-
| `value`
|
|
148
|
-
| `onValueChange`
|
|
149
|
-
| `type`
|
|
150
|
-
| `width`
|
|
151
|
-
| `helperText`
|
|
152
|
-
| `showErrorText`
|
|
153
|
-
| `hasPadding`
|
|
154
|
-
| `startAdornment
|
|
155
|
-
| `endAdornment`
|
|
156
|
-
| `regex`
|
|
157
|
-
| `format`
|
|
158
|
-
| `disabled`
|
|
159
|
-
| `theme`
|
|
160
|
-
| `variant`
|
|
142
|
+
| Prop | Type | Default | Description |
|
|
143
|
+
| ---------------- | ------------------------------------------ | ----------- | --------------------------------------------------------- |
|
|
144
|
+
| `name` | `string` | — | Field name, used by RHF |
|
|
145
|
+
| `label` | `string` | — | Floating label text |
|
|
146
|
+
| `control` | `Control` | — | RHF control object; omit for uncontrolled mode |
|
|
147
|
+
| `value` | `string` | — | Value in uncontrolled mode |
|
|
148
|
+
| `onValueChange` | `(value: string) => void` | — | Change handler in uncontrolled mode |
|
|
149
|
+
| `type` | `'text' \| 'password' \| 'email'` | `'text'` | HTML input type |
|
|
150
|
+
| `width` | `'small' \| 'medium' \| 'large' \| 'full'` | — | Preset width |
|
|
151
|
+
| `helperText` | `string` | — | Hint text shown below the field when there is no error |
|
|
152
|
+
| `showErrorText` | `boolean` | `true` | Show the validation error message below the field |
|
|
153
|
+
| `hasPadding` | `boolean` | `false` | Add bottom padding to reserve space for helper/error text |
|
|
154
|
+
| `startAdornment` | `JSX.Element` | — | Element rendered to the left of the input |
|
|
155
|
+
| `endAdornment` | `JSX.Element` | — | Element rendered to the right of the input |
|
|
156
|
+
| `regex` | `RegExp` | — | Block keystrokes that don't match the pattern |
|
|
157
|
+
| `format` | `(value: string) => string` | — | Transform the value before it is stored |
|
|
158
|
+
| `disabled` | `boolean` | `false` | Disable the field |
|
|
159
|
+
| `theme` | `EVENTS` | — | One-off token override for this instance |
|
|
160
|
+
| `variant` | `string` | `'default'` | Theme variant name |
|
|
161
161
|
|
|
162
162
|
### Example
|
|
163
163
|
|
|
164
164
|
```tsx
|
|
165
|
-
import TextField from '@
|
|
166
|
-
import Icon from '@components/atoms/Icon';
|
|
165
|
+
import { TextField, Icon } from '@foi/design-system';
|
|
167
166
|
|
|
168
167
|
<TextField
|
|
169
168
|
name='email'
|
|
@@ -172,7 +171,7 @@ import Icon from '@components/atoms/Icon';
|
|
|
172
171
|
type='email'
|
|
173
172
|
startAdornment={<Icon name='mail' />}
|
|
174
173
|
helperText='We will never share your email'
|
|
175
|
-
|
|
174
|
+
/>;
|
|
176
175
|
```
|
|
177
176
|
|
|
178
177
|
## NumberField
|
|
@@ -183,12 +182,12 @@ A numeric input that stores a `number` in RHF (or `undefined` when empty). The f
|
|
|
183
182
|
|
|
184
183
|
All `TextField` props apply except `type`, `endAdornment`, and `startAdornment` (in `spinner` mode). The following props are specific to `NumberField`:
|
|
185
184
|
|
|
186
|
-
| Prop | Type
|
|
187
|
-
| --------- |
|
|
188
|
-
| `min` | `number`
|
|
189
|
-
| `max` | `number`
|
|
190
|
-
| `step` | `number`
|
|
191
|
-
| `display` | `'standard' \| 'spinner'`
|
|
185
|
+
| Prop | Type | Default | Description |
|
|
186
|
+
| --------- | ------------------------- | ------------ | -------------------------------------------------------------------------------------- |
|
|
187
|
+
| `min` | `number` | — | Minimum allowed value; decrement button disables at this bound |
|
|
188
|
+
| `max` | `number` | — | Maximum allowed value; increment button disables at this bound |
|
|
189
|
+
| `step` | `number` | `1` | Amount added or subtracted on each button click |
|
|
190
|
+
| `display` | `'standard' \| 'spinner'` | `'standard'` | `standard`: both buttons on the right; `spinner`: remove left, input centre, add right |
|
|
192
191
|
|
|
193
192
|
### Display modes
|
|
194
193
|
|
|
@@ -207,7 +206,7 @@ All `TextField` props apply except `type`, `endAdornment`, and `startAdornment`
|
|
|
207
206
|
### Example
|
|
208
207
|
|
|
209
208
|
```tsx
|
|
210
|
-
import NumberField from '@
|
|
209
|
+
import { NumberField } from '@foi/design-system';
|
|
211
210
|
|
|
212
211
|
// Standard — quantity picker with bounds
|
|
213
212
|
<NumberField
|
|
@@ -235,8 +234,8 @@ import NumberField from '@components/atoms/NumberField';
|
|
|
235
234
|
Wrap your app in `ThemeProvider` and pass one or more named themes. The active theme is selected by the `theme` prop and its tokens are injected as CSS custom properties that every component consumes.
|
|
236
235
|
|
|
237
236
|
```tsx
|
|
238
|
-
import ThemeProvider from '@
|
|
239
|
-
import darkTheme from '
|
|
237
|
+
import { ThemeProvider } from '@foi/design-system';
|
|
238
|
+
import { darkTheme } from '@foi/design-system/theme';
|
|
240
239
|
|
|
241
240
|
<ThemeProvider themes={[darkTheme]} theme='dark'>
|
|
242
241
|
<App />
|
|
@@ -249,11 +248,35 @@ A theme is a plain object with a `name`, an optional `fonts` map, and a `compone
|
|
|
249
248
|
|
|
250
249
|
Each variant contains:
|
|
251
250
|
|
|
252
|
-
- `ROOT` — static styles applied unconditionally (e.g. `border-radius`)
|
|
253
|
-
- `EVENTS` — styles scoped to interaction states
|
|
251
|
+
- `ROOT` — static styles applied unconditionally (e.g. `border-radius`, `background-color`)
|
|
252
|
+
- `EVENTS` — styles scoped to interaction states. The complete set of possible states is:
|
|
253
|
+
|
|
254
|
+
| State | Description |
|
|
255
|
+
| ---------------- | ------------------------------------------------------------------------------- |
|
|
256
|
+
| `ENABLED` | Default resting state — element is interactive and fully visible |
|
|
257
|
+
| `VALUE` | The filled or selected part of the element (e.g. track fill, typed text colour) |
|
|
258
|
+
| `HOVER` | While the pointer is over the element |
|
|
259
|
+
| `ACTIVE` | While the element is being pressed |
|
|
260
|
+
| `FOCUS` | When the element has keyboard focus |
|
|
261
|
+
| `ERROR` | Container styles when validation fails |
|
|
262
|
+
| `ERROR_VALUE` | Value part when in error state |
|
|
263
|
+
| `ERROR_HOVER` | Hover while in error state |
|
|
264
|
+
| `ERROR_ACTIVE` | Press while in error state |
|
|
265
|
+
| `ERROR_FOCUS` | Focus while in error state |
|
|
266
|
+
| `DISABLED` | When the element is not interactive |
|
|
267
|
+
| `DISABLED_VALUE` | Value part when disabled |
|
|
268
|
+
| `LOADING` | During a pending async operation |
|
|
269
|
+
| `LOADING_VALUE` | Value part during loading |
|
|
270
|
+
|
|
271
|
+
Not every component uses all states — each component defines only the states relevant to its interaction model. The TypeScript type exported from the component's theme file tells you exactly which states are available:
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
import type { BUTTON } from '@foi/design-system/theme';
|
|
275
|
+
// BUTTON includes the EVENTS type — autocomplete shows only the states Button supports
|
|
276
|
+
```
|
|
254
277
|
|
|
255
278
|
```ts
|
|
256
|
-
import type { BUTTON } from '@
|
|
279
|
+
import type { BUTTON } from '@foi/design-system/theme';
|
|
257
280
|
|
|
258
281
|
const component = {
|
|
259
282
|
BUTTON: {
|
|
@@ -321,15 +344,19 @@ An async data table that delegates all data operations to the server via `onFetc
|
|
|
321
344
|
### Defining columns
|
|
322
345
|
|
|
323
346
|
```tsx
|
|
324
|
-
import DataGrid from '@
|
|
325
|
-
import type { DataGridColumn } from '@
|
|
347
|
+
import { DataGrid } from '@foi/design-system';
|
|
348
|
+
import type { DataGridColumn } from '@foi/design-system';
|
|
326
349
|
|
|
327
|
-
interface Product {
|
|
350
|
+
interface Product {
|
|
351
|
+
id: number;
|
|
352
|
+
name: string;
|
|
353
|
+
price: number;
|
|
354
|
+
}
|
|
328
355
|
|
|
329
356
|
const columns: DataGridColumn<Product>[] = [
|
|
330
357
|
{
|
|
331
358
|
key: 'name',
|
|
332
|
-
label: 'Product',
|
|
359
|
+
label: 'Product', // string → wrapped in the themed --DATAGRID-thLabel span
|
|
333
360
|
type: 'text',
|
|
334
361
|
filter: { type: 'search' },
|
|
335
362
|
},
|
|
@@ -345,7 +372,7 @@ const columns: DataGridColumn<Product>[] = [
|
|
|
345
372
|
`label` accepts any `ReactNode`. A plain string is automatically wrapped in the themed `--DATAGRID-thLabel` span so it inherits the header typography. Pass a custom node to render icons, badges, or anything else without that wrapper:
|
|
346
373
|
|
|
347
374
|
```tsx
|
|
348
|
-
import Icon from '@
|
|
375
|
+
import { Icon } from '@foi/design-system';
|
|
349
376
|
|
|
350
377
|
{
|
|
351
378
|
key: 'price',
|
|
@@ -369,7 +396,7 @@ const onFetch = async ({ page, pageSize, sort, filters }) => {
|
|
|
369
396
|
return { data: response.items, total: response.total };
|
|
370
397
|
};
|
|
371
398
|
|
|
372
|
-
<DataGrid<Product> columns={columns} onFetch={onFetch}
|
|
399
|
+
<DataGrid<Product> columns={columns} onFetch={onFetch} />;
|
|
373
400
|
```
|
|
374
401
|
|
|
375
402
|
### Action columns
|
|
@@ -398,11 +425,11 @@ const columnsWithActions: DataGridColumn<Product>[] = [
|
|
|
398
425
|
|
|
399
426
|
### Pagination modes
|
|
400
427
|
|
|
401
|
-
| Prop | Value | Behaviour
|
|
402
|
-
| ----------------- | -------------- |
|
|
428
|
+
| Prop | Value | Behaviour |
|
|
429
|
+
| ----------------- | -------------- | ------------------------------------------------------ |
|
|
403
430
|
| `paginationType` | `'pagination'` | Renders a `<Pagination>` bar below the table (default) |
|
|
404
|
-
| `paginationType` | `'scroll'` | Appends rows as the user scrolls down
|
|
405
|
-
| `pageSizeOptions` | `number[]` | Shows a rows-per-page selector in the bar
|
|
431
|
+
| `paginationType` | `'scroll'` | Appends rows as the user scrolls down |
|
|
432
|
+
| `pageSizeOptions` | `number[]` | Shows a rows-per-page selector in the bar |
|
|
406
433
|
|
|
407
434
|
## Modal
|
|
408
435
|
|
|
@@ -411,9 +438,7 @@ A portal-based overlay dialog. Renders into `document.body` so it sits above all
|
|
|
411
438
|
### Basic usage
|
|
412
439
|
|
|
413
440
|
```tsx
|
|
414
|
-
import Modal from '@
|
|
415
|
-
import Button from '@components/atoms/Button';
|
|
416
|
-
import Icon from '@components/atoms/Icon';
|
|
441
|
+
import { Modal, Button, Icon } from '@foi/design-system';
|
|
417
442
|
|
|
418
443
|
const [open, setOpen] = useState(false);
|
|
419
444
|
|
|
@@ -428,38 +453,601 @@ const [open, setOpen] = useState(false);
|
|
|
428
453
|
}
|
|
429
454
|
footer={
|
|
430
455
|
<>
|
|
431
|
-
<Button onClick={() => setOpen(false)} variant='ghost'>
|
|
456
|
+
<Button onClick={() => setOpen(false)} variant='ghost'>
|
|
457
|
+
Cancelar
|
|
458
|
+
</Button>
|
|
432
459
|
<Button onClick={() => setOpen(false)}>Aceptar</Button>
|
|
433
460
|
</>
|
|
434
461
|
}
|
|
435
462
|
>
|
|
436
463
|
Contenido del modal.
|
|
437
|
-
</Modal
|
|
464
|
+
</Modal>;
|
|
438
465
|
```
|
|
439
466
|
|
|
440
467
|
Apply `--MODAL-title` to the title element inside `header` to receive the themed font and colour styles.
|
|
441
468
|
|
|
442
469
|
### Props
|
|
443
470
|
|
|
444
|
-
| Prop
|
|
445
|
-
|
|
|
446
|
-
| `open`
|
|
447
|
-
| `onClose`
|
|
448
|
-
| `header`
|
|
449
|
-
| `showCloseButton
|
|
450
|
-
| `size`
|
|
451
|
-
| `children`
|
|
452
|
-
| `footer`
|
|
453
|
-
| `staticBackdrop`
|
|
454
|
-
| `className`
|
|
471
|
+
| Prop | Type | Default | Description |
|
|
472
|
+
| ----------------- | -------------- | ------- | ------------------------------------------------- |
|
|
473
|
+
| `open` | `boolean` | — | Controls visibility |
|
|
474
|
+
| `onClose` | `() => void` | — | Called when the modal requests to close |
|
|
475
|
+
| `header` | `ReactNode` | — | Full header bar content (rendered before ×) |
|
|
476
|
+
| `showCloseButton` | `boolean` | `true` | Whether to render the × icon button |
|
|
477
|
+
| `size` | `'md' \| 'lg'` | `'md'` | `'md'` = 480 px, `'lg'` = 720 px |
|
|
478
|
+
| `children` | `ReactNode` | — | Main body content |
|
|
479
|
+
| `footer` | `ReactNode` | — | Footer row content (typically action buttons) |
|
|
480
|
+
| `staticBackdrop` | `boolean` | `false` | When `true`, backdrop click and Escape do nothing |
|
|
481
|
+
| `className` | `string` | — | Extra CSS class on the modal panel |
|
|
455
482
|
|
|
456
483
|
### Close triggers
|
|
457
484
|
|
|
458
|
-
| Trigger
|
|
459
|
-
|
|
|
460
|
-
| × button
|
|
461
|
-
| Backdrop click
|
|
462
|
-
| Escape key
|
|
485
|
+
| Trigger | `staticBackdrop=false` | `staticBackdrop=true` |
|
|
486
|
+
| -------------- | ---------------------- | --------------------- |
|
|
487
|
+
| × button | ✓ | ✓ |
|
|
488
|
+
| Backdrop click | ✓ | — |
|
|
489
|
+
| Escape key | ✓ | — |
|
|
490
|
+
|
|
491
|
+
## Button
|
|
492
|
+
|
|
493
|
+
The primary interactive element. Accepts any `ReactNode` as children and natively supports all standard `<button>` HTML attributes.
|
|
494
|
+
|
|
495
|
+
### Props
|
|
496
|
+
|
|
497
|
+
| Prop | Type | Default | Description |
|
|
498
|
+
| ----------- | ---------------------- | ----------- | ----------------------------------------------- |
|
|
499
|
+
| `children` | `ReactNode` | — | Button label or content |
|
|
500
|
+
| `type` | `'button' \| 'submit'` | `'button'` | HTML button type |
|
|
501
|
+
| `iconStart` | `JSX.Element` | — | Icon rendered before the label |
|
|
502
|
+
| `iconEnd` | `JSX.Element` | — | Icon rendered after the label |
|
|
503
|
+
| `loading` | `boolean` | `false` | Shows a loading indicator; button stays mounted |
|
|
504
|
+
| `disabled` | `boolean` | `false` | Prevents interaction |
|
|
505
|
+
| `className` | `string` | — | Extra CSS class |
|
|
506
|
+
| `variant` | `string` | `'default'` | Theme variant |
|
|
507
|
+
| `theme` | `EVENTS` | — | One-off token override |
|
|
508
|
+
|
|
509
|
+
### Example
|
|
510
|
+
|
|
511
|
+
```tsx
|
|
512
|
+
import { Button, Icon } from '@foi/design-system';
|
|
513
|
+
|
|
514
|
+
<Button onClick={handleSave}>Guardar</Button>
|
|
515
|
+
<Button type='submit' iconStart={<Icon name='send' />}>Enviar</Button>
|
|
516
|
+
<Button loading={isSaving} disabled={isSaving}>Guardando…</Button>
|
|
517
|
+
<Button variant='danger' onClick={handleDelete}>Eliminar</Button>
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
## Icon
|
|
521
|
+
|
|
522
|
+
Renders a single icon from the [Material Symbols Rounded](https://fonts.google.com/icons) font. The font is loaded automatically by `ThemeProvider`.
|
|
523
|
+
|
|
524
|
+
### Props
|
|
525
|
+
|
|
526
|
+
| Prop | Type | Default | Description |
|
|
527
|
+
| ----------- | ------------------------------ | ------- | ---------------------------------- |
|
|
528
|
+
| `name` | `string` | — | Material Symbols ligature name |
|
|
529
|
+
| `fill` | `boolean` | `false` | Use the filled variant of the icon |
|
|
530
|
+
| `size` | `'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Icon size |
|
|
531
|
+
| `className` | `string` | — | Extra CSS class |
|
|
532
|
+
| `style` | `CSSProperties` | — | Inline styles |
|
|
533
|
+
|
|
534
|
+
### Example
|
|
535
|
+
|
|
536
|
+
```tsx
|
|
537
|
+
import { Icon } from '@foi/design-system';
|
|
538
|
+
|
|
539
|
+
<Icon name='home' />
|
|
540
|
+
<Icon name='search' size='lg' />
|
|
541
|
+
<Icon name='favorite' fill />
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
## IconButton
|
|
545
|
+
|
|
546
|
+
A button that renders a single icon with no visible text. Accepts all standard `<button>` HTML attributes.
|
|
547
|
+
|
|
548
|
+
### Props
|
|
549
|
+
|
|
550
|
+
| Prop | Type | Default | Description |
|
|
551
|
+
| ----------- | ------------- | ----------- | ------------------------------------------------- |
|
|
552
|
+
| `icon` | `JSX.Element` | — | Icon element to render (use `<Icon />`) |
|
|
553
|
+
| `onClick` | `function` | — | Click handler |
|
|
554
|
+
| `isFlipped` | `boolean` | `false` | Mirrors the icon horizontally (useful for arrows) |
|
|
555
|
+
| `disabled` | `boolean` | `false` | Prevents interaction |
|
|
556
|
+
| `className` | `string` | — | Extra CSS class |
|
|
557
|
+
| `variant` | `string` | `'default'` | Theme variant |
|
|
558
|
+
| `theme` | `EVENTS` | — | One-off token override |
|
|
559
|
+
|
|
560
|
+
### Example
|
|
561
|
+
|
|
562
|
+
```tsx
|
|
563
|
+
import { IconButton, Icon } from '@foi/design-system';
|
|
564
|
+
|
|
565
|
+
<IconButton icon={<Icon name='close' />} onClick={() => setOpen(false)} />
|
|
566
|
+
<IconButton icon={<Icon name='arrow_forward' />} isFlipped onClick={goBack} />
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
## Checkbox
|
|
570
|
+
|
|
571
|
+
A single checkbox. Can be used standalone (controlled or RHF), or as a child of `CheckboxGroup` / `CheckboxTree`.
|
|
572
|
+
|
|
573
|
+
### Props
|
|
574
|
+
|
|
575
|
+
| Prop | Type | Default | Description |
|
|
576
|
+
| --------------- | ---------------------------- | ----------- | ------------------------------------------------ |
|
|
577
|
+
| `name` | `string` | — | RHF field name (required in standalone RHF mode) |
|
|
578
|
+
| `control` | `Control` | — | RHF control object |
|
|
579
|
+
| `checked` | `boolean` | — | Controlled mode value (use with `onChecked`) |
|
|
580
|
+
| `onChecked` | `(checked: boolean) => void` | — | Controlled mode change handler |
|
|
581
|
+
| `label` | `string` | — | Text label next to the checkbox |
|
|
582
|
+
| `icon` | `JSX.Element` | checkmark | Custom icon shown when checked |
|
|
583
|
+
| `disabled` | `boolean` | `false` | Prevents interaction |
|
|
584
|
+
| `helperText` | `string` | — | Hint text below the checkbox |
|
|
585
|
+
| `showErrorText` | `boolean` | `true` | Show validation error message |
|
|
586
|
+
| `variant` | `string` | `'default'` | Theme variant |
|
|
587
|
+
| `theme` | `EVENTS` | — | One-off token override |
|
|
588
|
+
|
|
589
|
+
### Example
|
|
590
|
+
|
|
591
|
+
```tsx
|
|
592
|
+
import { Checkbox } from '@foi/design-system';
|
|
593
|
+
|
|
594
|
+
// RHF
|
|
595
|
+
<Checkbox name='agree' control={control} label='Acepto los términos' />;
|
|
596
|
+
|
|
597
|
+
// Controlled
|
|
598
|
+
const [checked, setChecked] = useState(false);
|
|
599
|
+
<Checkbox checked={checked} onChecked={setChecked} label='Recordarme' />;
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
## Radio
|
|
603
|
+
|
|
604
|
+
A single radio button. Always used inside `RadioGroup` — it receives its state from the group context automatically.
|
|
605
|
+
|
|
606
|
+
### Props
|
|
607
|
+
|
|
608
|
+
| Prop | Type | Default | Description |
|
|
609
|
+
| ---------- | ------------- | ----------- | -------------------------------------------- |
|
|
610
|
+
| `value` | `string` | — | The value this option represents |
|
|
611
|
+
| `label` | `string` | — | Text label next to the radio |
|
|
612
|
+
| `icon` | `JSX.Element` | filled dot | Custom icon shown when selected |
|
|
613
|
+
| `disabled` | `boolean` | `false` | Overrides the group `disabled` for this item |
|
|
614
|
+
| `variant` | `string` | `'default'` | Theme variant |
|
|
615
|
+
| `theme` | `EVENTS` | — | One-off token override |
|
|
616
|
+
|
|
617
|
+
## Select
|
|
618
|
+
|
|
619
|
+
A dropdown select field backed by a virtual-scroll list. Integrates with RHF and stores the selected `value` string.
|
|
620
|
+
|
|
621
|
+
### Props
|
|
622
|
+
|
|
623
|
+
| Prop | Type | Default | Description |
|
|
624
|
+
| ------------------ | -------------- | ----------- | --------------------------------------------------- |
|
|
625
|
+
| `name` | `string` | — | RHF field name |
|
|
626
|
+
| `label` | `string` | — | Floating label |
|
|
627
|
+
| `control` | `Control` | — | RHF control object |
|
|
628
|
+
| `options` | `OptionProp[]` | — | List of `{ value, label, description? }` items |
|
|
629
|
+
| `disabled` | `boolean` | `false` | Prevents interaction |
|
|
630
|
+
| `range` | `number` | `100` | Options per page (virtual scroll activates above 3) |
|
|
631
|
+
| `hasSearch` | `boolean` | `false` | Shows a search input — filters after 3 characters |
|
|
632
|
+
| `hasDescription` | `boolean` | `false` | Renders a secondary description line per option |
|
|
633
|
+
| `hasStaticOptions` | `boolean` | `false` | Renders dropdown inline (no absolute positioning) |
|
|
634
|
+
| `helperText` | `string` | — | Hint text below the field |
|
|
635
|
+
| `showErrorText` | `boolean` | `true` | Show validation error message |
|
|
636
|
+
| `hasPadding` | `boolean` | `false` | Add bottom padding for helper/error text |
|
|
637
|
+
| `variant` | `string` | `'default'` | Theme variant |
|
|
638
|
+
| `theme` | `EVENTS` | — | One-off token override |
|
|
639
|
+
|
|
640
|
+
### Example
|
|
641
|
+
|
|
642
|
+
```tsx
|
|
643
|
+
import { Select } from '@foi/design-system';
|
|
644
|
+
|
|
645
|
+
const options = [
|
|
646
|
+
{ value: 'cl', label: 'Chile' },
|
|
647
|
+
{ value: 'ar', label: 'Argentina', description: 'Buenos Aires' },
|
|
648
|
+
];
|
|
649
|
+
|
|
650
|
+
<Select name='country' control={control} label='País' options={options} hasSearch />;
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
## DatePicker
|
|
654
|
+
|
|
655
|
+
A date input field with an inline or floating calendar. Stores a `Date` value in RHF.
|
|
656
|
+
|
|
657
|
+
### Props
|
|
658
|
+
|
|
659
|
+
| Prop | Type | Default | Description |
|
|
660
|
+
| ------------------ | -------------- | ----------- | ----------------------------------------------------- |
|
|
661
|
+
| `name` | `string` | — | RHF field name |
|
|
662
|
+
| `label` | `string` | — | Floating label |
|
|
663
|
+
| `control` | `Control` | — | RHF control object |
|
|
664
|
+
| `language` | `'es' \| 'en'` | browser | Date format and labels (`DD/MM/YYYY` vs `MM/DD/YYYY`) |
|
|
665
|
+
| `minDate` | `Date` | — | Earliest selectable date |
|
|
666
|
+
| `maxDate` | `Date` | — | Latest selectable date |
|
|
667
|
+
| `disablePast` | `boolean` | `false` | Disables all dates before today |
|
|
668
|
+
| `disableFuture` | `boolean` | `false` | Disables all dates after today |
|
|
669
|
+
| `hasStaticOptions` | `boolean` | `false` | Renders calendar inline instead of floating |
|
|
670
|
+
| `disabled` | `boolean` | `false` | Prevents interaction |
|
|
671
|
+
| `helperText` | `string` | — | Hint text below the field |
|
|
672
|
+
| `showErrorText` | `boolean` | `true` | Show validation error message |
|
|
673
|
+
| `hasPadding` | `boolean` | `false` | Add bottom padding for helper/error text |
|
|
674
|
+
| `variant` | `string` | `'default'` | Theme variant |
|
|
675
|
+
| `theme` | `EVENTS` | — | One-off token override |
|
|
676
|
+
|
|
677
|
+
### Example
|
|
678
|
+
|
|
679
|
+
```tsx
|
|
680
|
+
import { DatePicker } from '@foi/design-system';
|
|
681
|
+
|
|
682
|
+
<DatePicker
|
|
683
|
+
name='birthDate'
|
|
684
|
+
control={control}
|
|
685
|
+
label='Fecha de nacimiento'
|
|
686
|
+
language='es'
|
|
687
|
+
disableFuture
|
|
688
|
+
maxDate={new Date('2005-01-01')}
|
|
689
|
+
/>;
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
## Switch
|
|
693
|
+
|
|
694
|
+
A toggle switch that stores a `boolean` value in RHF.
|
|
695
|
+
|
|
696
|
+
### Props
|
|
697
|
+
|
|
698
|
+
| Prop | Type | Default | Description |
|
|
699
|
+
| ------------ | ------------- | ----------- | ----------------------------- |
|
|
700
|
+
| `name` | `string` | — | RHF field name |
|
|
701
|
+
| `control` | `Control` | — | RHF control object |
|
|
702
|
+
| `label` | `string` | — | Text label next to the switch |
|
|
703
|
+
| `iconOn` | `JSX.Element` | — | Icon on the thumb when on |
|
|
704
|
+
| `iconOff` | `JSX.Element` | — | Icon on the thumb when off |
|
|
705
|
+
| `disabled` | `boolean` | `false` | Prevents interaction |
|
|
706
|
+
| `helperText` | `string` | — | Hint text below the switch |
|
|
707
|
+
| `variant` | `string` | `'default'` | Theme variant |
|
|
708
|
+
| `theme` | `EVENTS` | — | One-off token override |
|
|
709
|
+
|
|
710
|
+
### Example
|
|
711
|
+
|
|
712
|
+
```tsx
|
|
713
|
+
import { Switch, Icon } from '@foi/design-system';
|
|
714
|
+
|
|
715
|
+
<Switch
|
|
716
|
+
name='notifications'
|
|
717
|
+
control={control}
|
|
718
|
+
label='Activar notificaciones'
|
|
719
|
+
iconOn={<Icon name='notifications' />}
|
|
720
|
+
iconOff={<Icon name='notifications_off' />}
|
|
721
|
+
/>;
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
## Slider
|
|
725
|
+
|
|
726
|
+
A range slider that stores a `number[]` value in RHF. Single-thumb mode uses a 1-element array; range mode uses a 2-element array.
|
|
727
|
+
|
|
728
|
+
### Props
|
|
729
|
+
|
|
730
|
+
| Prop | Type | Default | Description |
|
|
731
|
+
| ------------ | ---------------------------- | -------------- | ------------------------------------------------- |
|
|
732
|
+
| `name` | `string` | — | RHF field name |
|
|
733
|
+
| `control` | `Control` | — | RHF control object |
|
|
734
|
+
| `min` | `number` | — | Minimum value |
|
|
735
|
+
| `max` | `number` | — | Maximum value (`Infinity` disables click-to-seek) |
|
|
736
|
+
| `step` | `number` | `1` | Snap granularity |
|
|
737
|
+
| `distance` | `number` | `0` | Minimum gap between thumbs (range mode only) |
|
|
738
|
+
| `direction` | `'horizontal' \| 'vertical'` | `'horizontal'` | Slider orientation |
|
|
739
|
+
| `track` | `'normal' \| 'inverted'` | `'normal'` | Fill direction of the track |
|
|
740
|
+
| `showMarks` | `boolean` | `false` | Show a dot at every `step` position |
|
|
741
|
+
| `iconMin` | `JSX.Element` | — | Icon inside the min/single thumb |
|
|
742
|
+
| `iconMax` | `JSX.Element` | — | Icon inside the max thumb (range mode only) |
|
|
743
|
+
| `helperText` | `string` | — | Hint text below the slider |
|
|
744
|
+
| `disabled` | `boolean` | `false` | Prevents interaction |
|
|
745
|
+
| `variant` | `string` | `'default'` | Theme variant |
|
|
746
|
+
| `theme` | `EVENTS` | — | One-off token override |
|
|
747
|
+
|
|
748
|
+
### Example
|
|
749
|
+
|
|
750
|
+
```tsx
|
|
751
|
+
import { Slider } from '@foi/design-system';
|
|
752
|
+
|
|
753
|
+
// Single thumb — value is [number]
|
|
754
|
+
<Slider name='volume' control={control} min={0} max={100} />
|
|
755
|
+
|
|
756
|
+
// Range — value is [number, number]
|
|
757
|
+
<Slider name='priceRange' control={control} min={0} max={10000} step={100} distance={500} showMarks />
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
## Skeleton
|
|
761
|
+
|
|
762
|
+
An animated placeholder rendered while content is loading. Has no logic — simply swap it out once your data arrives.
|
|
763
|
+
|
|
764
|
+
### Props
|
|
765
|
+
|
|
766
|
+
| Prop | Type | Default | Description |
|
|
767
|
+
| ----------- | ----------------------------- | --------------- | -------------------------- |
|
|
768
|
+
| `variant` | `'rectangular' \| 'circular'` | `'rectangular'` | Shape of the placeholder |
|
|
769
|
+
| `width` | `string \| number` | — | CSS width or pixel number |
|
|
770
|
+
| `height` | `string \| number` | — | CSS height or pixel number |
|
|
771
|
+
| `className` | `string` | — | Extra CSS class |
|
|
772
|
+
|
|
773
|
+
### Example
|
|
774
|
+
|
|
775
|
+
```tsx
|
|
776
|
+
import { Skeleton } from '@foi/design-system';
|
|
777
|
+
|
|
778
|
+
// While loading a user avatar
|
|
779
|
+
{
|
|
780
|
+
isLoading ? <Skeleton variant='circular' width={40} height={40} /> : <Avatar src={user.photo} />;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
// While loading a text block
|
|
784
|
+
{
|
|
785
|
+
isLoading ? <Skeleton width='100%' height={20} /> : <p>{content}</p>;
|
|
786
|
+
}
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
## Pagination
|
|
790
|
+
|
|
791
|
+
A standalone page-navigation bar. `DataGrid` uses this internally, but it can also be used independently.
|
|
792
|
+
|
|
793
|
+
### Props
|
|
794
|
+
|
|
795
|
+
| Prop | Type | Default | Description |
|
|
796
|
+
| ------------------ | ------------------------ | ------- | ------------------------------------------------- |
|
|
797
|
+
| `page` | `number` | — | Zero-based current page index |
|
|
798
|
+
| `total` | `number` | — | Total row count (used to compute page count) |
|
|
799
|
+
| `pageSize` | `number` | — | Rows per page |
|
|
800
|
+
| `onPageChange` | `(page: number) => void` | — | Fired when the user navigates to a different page |
|
|
801
|
+
| `pageSizeOptions` | `number[]` | — | Shows a rows-per-page selector with these options |
|
|
802
|
+
| `onPageSizeChange` | `(size: number) => void` | — | Fired when the user changes the page size |
|
|
803
|
+
| `loading` | `boolean` | `false` | Disables all controls while data is fetching |
|
|
804
|
+
|
|
805
|
+
### Example
|
|
806
|
+
|
|
807
|
+
```tsx
|
|
808
|
+
import { Pagination } from '@foi/design-system';
|
|
809
|
+
|
|
810
|
+
<Pagination
|
|
811
|
+
page={page}
|
|
812
|
+
total={total}
|
|
813
|
+
pageSize={pageSize}
|
|
814
|
+
onPageChange={setPage}
|
|
815
|
+
pageSizeOptions={[10, 25, 50]}
|
|
816
|
+
onPageSizeChange={setPageSize}
|
|
817
|
+
/>;
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
## CheckboxGroup
|
|
821
|
+
|
|
822
|
+
Manages a set of `Checkbox` children as a `string[]` RHF field. The group value is the array of `value` props of all checked children.
|
|
823
|
+
|
|
824
|
+
### Props
|
|
825
|
+
|
|
826
|
+
| Prop | Type | Default | Description |
|
|
827
|
+
| --------------- | ---------------------------- | ------------ | ---------------------------------------------- |
|
|
828
|
+
| `name` | `string` | — | RHF field name |
|
|
829
|
+
| `control` | `Control` | — | RHF control object |
|
|
830
|
+
| `children` | `ReactNode` | — | `<Checkbox>` elements (each must have `value`) |
|
|
831
|
+
| `label` | `string` | — | Group label above the checkboxes |
|
|
832
|
+
| `direction` | `'vertical' \| 'horizontal'` | `'vertical'` | Layout direction of the items |
|
|
833
|
+
| `disabled` | `boolean` | `false` | Disables all children |
|
|
834
|
+
| `helperText` | `string` | — | Hint text below the group |
|
|
835
|
+
| `showErrorText` | `boolean` | `true` | Show validation error message |
|
|
836
|
+
| `variant` | `string` | `'default'` | Theme variant |
|
|
837
|
+
| `theme` | `EVENTS` | — | One-off token override |
|
|
838
|
+
|
|
839
|
+
### Example
|
|
840
|
+
|
|
841
|
+
```tsx
|
|
842
|
+
import { CheckboxGroup, Checkbox } from '@foi/design-system';
|
|
843
|
+
|
|
844
|
+
const schema = z.object({
|
|
845
|
+
skills: z.array(z.string()).min(1, 'Selecciona al menos una'),
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
<CheckboxGroup name='skills' control={control} label='Habilidades' direction='horizontal'>
|
|
849
|
+
<Checkbox value='react' label='React' />
|
|
850
|
+
<Checkbox value='vue' label='Vue' />
|
|
851
|
+
<Checkbox value='svelte' label='Svelte' />
|
|
852
|
+
</CheckboxGroup>;
|
|
853
|
+
```
|
|
854
|
+
|
|
855
|
+
## CheckboxTree
|
|
856
|
+
|
|
857
|
+
A hierarchical checkbox group. The parent checkbox controls all children simultaneously and shows an indeterminate state when some (but not all) children are checked.
|
|
858
|
+
|
|
859
|
+
### Props
|
|
860
|
+
|
|
861
|
+
| Prop | Type | Default | Description |
|
|
862
|
+
| ------------------- | ------------- | ----------- | ------------------------------------------------- |
|
|
863
|
+
| `name` | `string` | — | RHF field name |
|
|
864
|
+
| `control` | `Control` | — | RHF control object |
|
|
865
|
+
| `children` | `ReactNode` | — | `<Checkbox>` elements (each must have `value`) |
|
|
866
|
+
| `label` | `string` | — | Label on the parent (select-all) checkbox |
|
|
867
|
+
| `iconChecked` | `JSX.Element` | checkmark | Icon on the parent when all children are checked |
|
|
868
|
+
| `iconIndeterminate` | `JSX.Element` | dash | Icon on the parent when some children are checked |
|
|
869
|
+
| `disabled` | `boolean` | `false` | Disables the parent and all children |
|
|
870
|
+
| `helperText` | `string` | — | Hint text below the tree |
|
|
871
|
+
| `showErrorText` | `boolean` | `true` | Show validation error message |
|
|
872
|
+
| `variant` | `string` | `'default'` | Theme variant |
|
|
873
|
+
| `theme` | `EVENTS` | — | One-off token override |
|
|
874
|
+
|
|
875
|
+
### Example
|
|
876
|
+
|
|
877
|
+
```tsx
|
|
878
|
+
import { CheckboxTree, Checkbox } from '@foi/design-system';
|
|
879
|
+
|
|
880
|
+
<CheckboxTree name='permissions' control={control} label='Seleccionar todo'>
|
|
881
|
+
<Checkbox value='read' label='Leer' />
|
|
882
|
+
<Checkbox value='write' label='Escribir' />
|
|
883
|
+
<Checkbox value='delete' label='Eliminar' />
|
|
884
|
+
</CheckboxTree>;
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
## RadioGroup
|
|
888
|
+
|
|
889
|
+
Manages a set of `Radio` children as a single `string` RHF field. The value is the `value` prop of the selected child.
|
|
890
|
+
|
|
891
|
+
### Props
|
|
892
|
+
|
|
893
|
+
| Prop | Type | Default | Description |
|
|
894
|
+
| --------------- | ---------------------------- | ------------ | ------------------------------------------- |
|
|
895
|
+
| `name` | `string` | — | RHF field name |
|
|
896
|
+
| `control` | `Control` | — | RHF control object |
|
|
897
|
+
| `children` | `ReactNode` | — | `<Radio>` elements (each must have `value`) |
|
|
898
|
+
| `label` | `string` | — | Group label above the radios |
|
|
899
|
+
| `direction` | `'vertical' \| 'horizontal'` | `'vertical'` | Layout direction of the items |
|
|
900
|
+
| `disabled` | `boolean` | `false` | Disables all children |
|
|
901
|
+
| `helperText` | `string` | — | Hint text below the group |
|
|
902
|
+
| `showErrorText` | `boolean` | `true` | Show validation error message |
|
|
903
|
+
| `variant` | `string` | `'default'` | Theme variant |
|
|
904
|
+
| `theme` | `EVENTS` | — | One-off token override |
|
|
905
|
+
|
|
906
|
+
### Example
|
|
907
|
+
|
|
908
|
+
```tsx
|
|
909
|
+
import { RadioGroup, Radio } from '@foi/design-system';
|
|
910
|
+
|
|
911
|
+
const schema = z.object({
|
|
912
|
+
plan: z.string().min(1, 'Selecciona un plan'),
|
|
913
|
+
});
|
|
914
|
+
|
|
915
|
+
<RadioGroup name='plan' control={control} label='Plan' direction='horizontal'>
|
|
916
|
+
<Radio value='free' label='Gratis' />
|
|
917
|
+
<Radio value='pro' label='Pro' />
|
|
918
|
+
<Radio value='enterprise' label='Enterprise' />
|
|
919
|
+
</RadioGroup>;
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
## Chip
|
|
923
|
+
|
|
924
|
+
A compact inline label for displaying statuses, tags, or categories. Height is fixed at 24px and width adapts to its content.
|
|
925
|
+
|
|
926
|
+
### Props
|
|
927
|
+
|
|
928
|
+
| Prop | Type | Default | Description |
|
|
929
|
+
| ----------- | ----------- | ----------- | ---------------------------------------------------------- |
|
|
930
|
+
| `children` | `ReactNode` | — | Label text or custom content |
|
|
931
|
+
| `variant` | `string` | `'default'` | Theme variant — any key defined under `CHIP` in your theme |
|
|
932
|
+
| `className` | `string` | — | Extra CSS class |
|
|
933
|
+
| `theme` | `EVENTS` | — | One-off token override |
|
|
934
|
+
|
|
935
|
+
When `children` is a plain string it is wrapped in a `span.--CHIP-label` that applies horizontal padding. Pass a `ReactNode` to render custom content (e.g. icon + text) directly inside the chip.
|
|
936
|
+
|
|
937
|
+
### Example
|
|
938
|
+
|
|
939
|
+
```tsx
|
|
940
|
+
import { Chip } from '@foi/design-system';
|
|
941
|
+
|
|
942
|
+
// Plain string — wrapped in a padded span automatically
|
|
943
|
+
<Chip>Activo</Chip>
|
|
944
|
+
<Chip variant='myVariant'>Pendiente</Chip>
|
|
945
|
+
|
|
946
|
+
// Custom content — ReactNode renders directly inside the chip
|
|
947
|
+
<Chip variant='myVariant'>
|
|
948
|
+
<Icon name='star' />
|
|
949
|
+
<span>Destacado</span>
|
|
950
|
+
</Chip>
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
## Toast
|
|
954
|
+
|
|
955
|
+
A notification system built around a React context. `ThemeProvider` automatically includes the provider — no additional setup required. Call `useToast` from anywhere inside the tree to push transient messages.
|
|
956
|
+
|
|
957
|
+
### Setup
|
|
958
|
+
|
|
959
|
+
`ThemeProvider` includes `ToastProvider` internally. Optionally configure position and default duration via the `toast` prop:
|
|
960
|
+
|
|
961
|
+
```tsx
|
|
962
|
+
<ThemeProvider themes={[darkTheme]} theme='dark' toast={{ position: 'top-right', duration: 4000 }}>
|
|
963
|
+
<App />
|
|
964
|
+
</ThemeProvider>
|
|
965
|
+
```
|
|
966
|
+
|
|
967
|
+
### `useToast`
|
|
968
|
+
|
|
969
|
+
```tsx
|
|
970
|
+
import { useToast } from '@foi/design-system/hooks';
|
|
971
|
+
|
|
972
|
+
const { push } = useToast();
|
|
973
|
+
|
|
974
|
+
push('Archivo guardado', { variant: 'success', icon: 'check_circle' });
|
|
975
|
+
```
|
|
976
|
+
|
|
977
|
+
### `push` options
|
|
978
|
+
|
|
979
|
+
| Option | Type | Default | Description |
|
|
980
|
+
| ---------- | --------- | ----------- | -------------------------------------------------- |
|
|
981
|
+
| `variant` | `string` | `'default'` | Theme variant (maps to a key defined in the theme) |
|
|
982
|
+
| `icon` | `string` | — | Material Symbols icon name rendered on the left |
|
|
983
|
+
| `duration` | `number` | `3000` | Milliseconds before the toast auto-dismisses |
|
|
984
|
+
| `closable` | `boolean` | `false` | Render a × button so the user can dismiss manually |
|
|
985
|
+
|
|
986
|
+
### `ToastPosition`
|
|
987
|
+
|
|
988
|
+
| Value | Description |
|
|
989
|
+
| ----------------- | ------------- |
|
|
990
|
+
| `'bottom-right'` | Default |
|
|
991
|
+
| `'bottom-center'` | Bottom center |
|
|
992
|
+
| `'bottom-left'` | Bottom left |
|
|
993
|
+
| `'top-right'` | Top right |
|
|
994
|
+
| `'top-center'` | Top center |
|
|
995
|
+
| `'top-left'` | Top left |
|
|
996
|
+
|
|
997
|
+
### Example
|
|
998
|
+
|
|
999
|
+
```tsx
|
|
1000
|
+
import { useToast } from '@foi/design-system/hooks';
|
|
1001
|
+
|
|
1002
|
+
const Notifier = () => {
|
|
1003
|
+
const { push } = useToast();
|
|
1004
|
+
|
|
1005
|
+
const save = async () => {
|
|
1006
|
+
try {
|
|
1007
|
+
await api.save();
|
|
1008
|
+
push('Guardado correctamente', { icon: 'check_circle' });
|
|
1009
|
+
} catch {
|
|
1010
|
+
push('No se pudo guardar', { icon: 'error', closable: true, duration: 8000 });
|
|
1011
|
+
}
|
|
1012
|
+
};
|
|
1013
|
+
|
|
1014
|
+
return <Button onClick={save}>Guardar</Button>;
|
|
1015
|
+
};
|
|
1016
|
+
```
|
|
1017
|
+
|
|
1018
|
+
### Defining toast variants in the theme
|
|
1019
|
+
|
|
1020
|
+
Toast variants are defined in the theme under the `TOAST` key. Each variant must be self-contained (all tokens, not just overrides) because `useCreateComponentStyles` loads only the requested variant:
|
|
1021
|
+
|
|
1022
|
+
```ts
|
|
1023
|
+
import type { TOAST } from '@foi/design-system/theme';
|
|
1024
|
+
|
|
1025
|
+
const toast = {
|
|
1026
|
+
TOAST: {
|
|
1027
|
+
DEFAULT: {
|
|
1028
|
+
ROOT: { 'background-color': '#1e293b', 'border-radius': '6px' },
|
|
1029
|
+
EVENTS: {
|
|
1030
|
+
ENABLED: {
|
|
1031
|
+
'color-primary': '#f8fafc',
|
|
1032
|
+
'border-color': '#334155',
|
|
1033
|
+
'icon-color': '#94a3b8',
|
|
1034
|
+
},
|
|
1035
|
+
},
|
|
1036
|
+
},
|
|
1037
|
+
// Add as many named variants as your design requires
|
|
1038
|
+
MY_VARIANT: {
|
|
1039
|
+
ROOT: { 'background-color': '#1e293b', 'border-radius': '6px' },
|
|
1040
|
+
EVENTS: {
|
|
1041
|
+
ENABLED: {
|
|
1042
|
+
'color-primary': '#f8fafc',
|
|
1043
|
+
'border-color': '#10b981',
|
|
1044
|
+
'icon-color': '#10b981',
|
|
1045
|
+
},
|
|
1046
|
+
},
|
|
1047
|
+
},
|
|
1048
|
+
},
|
|
1049
|
+
} as const satisfies TOAST;
|
|
1050
|
+
```
|
|
463
1051
|
|
|
464
1052
|
## Project structure
|
|
465
1053
|
|