@foi/design-system 0.0.17 → 0.0.19

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