@axzydev/axzy_ui_system 1.2.16 → 1.3.1

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 (65) hide show
  1. package/dist/index.cjs +3349 -1457
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.css +1 -1
  4. package/dist/index.d.cts +719 -54
  5. package/dist/index.d.ts +719 -54
  6. package/dist/index.js +3283 -1387
  7. package/dist/index.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/App.tsx +32 -0
  10. package/src/components/atoms/badget/badget.tsx +2 -4
  11. package/src/components/atoms/chip/chip.doc.mdx +47 -0
  12. package/src/components/atoms/chip/chip.props.ts +32 -0
  13. package/src/components/atoms/chip/chip.stories.tsx +64 -0
  14. package/src/components/atoms/chip/chip.tsx +112 -0
  15. package/src/components/atoms/grid/grid.tsx +1 -2
  16. package/src/components/molecules/accordion/accordion.doc.mdx +47 -0
  17. package/src/components/molecules/accordion/accordion.props.ts +35 -0
  18. package/src/components/molecules/accordion/accordion.stories.tsx +68 -0
  19. package/src/components/molecules/accordion/accordion.tsx +123 -0
  20. package/src/components/molecules/calendar/calendar.doc.mdx +2 -1
  21. package/src/components/molecules/calendar/calendar.tsx +102 -24
  22. package/src/components/molecules/chip-input/chip-input.doc.mdx +44 -0
  23. package/src/components/molecules/chip-input/chip-input.props.ts +42 -0
  24. package/src/components/molecules/chip-input/chip-input.stories.tsx +52 -0
  25. package/src/components/molecules/chip-input/chip-input.tsx +205 -0
  26. package/src/components/molecules/date-picker/datePicker.tsx +45 -56
  27. package/src/components/molecules/dropdown-menu/dropdown-menu.doc.mdx +46 -0
  28. package/src/components/molecules/dropdown-menu/dropdown-menu.props.ts +41 -0
  29. package/src/components/molecules/dropdown-menu/dropdown-menu.stories.tsx +41 -0
  30. package/src/components/molecules/dropdown-menu/dropdown-menu.tsx +219 -0
  31. package/src/components/molecules/field/field.doc.mdx +43 -0
  32. package/src/components/molecules/field/field.props.ts +23 -0
  33. package/src/components/molecules/field/field.stories.tsx +42 -0
  34. package/src/components/molecules/field/field.tsx +54 -0
  35. package/src/components/molecules/masked-input/masked-input.doc.mdx +78 -0
  36. package/src/components/molecules/masked-input/masked-input.props.ts +58 -0
  37. package/src/components/molecules/masked-input/masked-input.stories.tsx +126 -0
  38. package/src/components/molecules/masked-input/masked-input.tsx +244 -0
  39. package/src/components/molecules/multi-select/multi-select.doc.mdx +55 -0
  40. package/src/components/molecules/multi-select/multi-select.props.ts +65 -0
  41. package/src/components/molecules/multi-select/multi-select.stories.tsx +59 -0
  42. package/src/components/molecules/multi-select/multi-select.tsx +386 -0
  43. package/src/components/molecules/search-select/search-select.doc.mdx +5 -0
  44. package/src/components/molecules/search-select/search-select.props.ts +10 -1
  45. package/src/components/molecules/search-select/search-select.stories.tsx +18 -0
  46. package/src/components/molecules/search-select/search-select.tsx +102 -28
  47. package/src/components/molecules/time-picker/timePicker.tsx +14 -26
  48. package/src/components/molecules/wysiwyg/wysiwyg.props.ts +51 -0
  49. package/src/components/molecules/wysiwyg/wysiwyg.stories.tsx +95 -0
  50. package/src/components/molecules/wysiwyg/wysiwyg.tsx +609 -0
  51. package/src/components/organisms/form-builder/fieldRenderer.tsx +144 -27
  52. package/src/components/organisms/form-builder/formBuilder.context.tsx +77 -15
  53. package/src/components/organisms/form-builder/formBuilder.doc.mdx +213 -86
  54. package/src/components/organisms/form-builder/formBuilder.props.ts +118 -36
  55. package/src/components/organisms/form-builder/formBuilder.stories.tsx +694 -96
  56. package/src/components/organisms/form-builder/formBuilder.tsx +152 -69
  57. package/src/components/organisms/form-builder/useFormBuilder.ts +59 -21
  58. package/src/hooks/useFloatingPanel.ts +100 -0
  59. package/src/index.ts +26 -4
  60. package/src/showcases/DataShowcases.tsx +76 -0
  61. package/src/showcases/FormShowcases.tsx +574 -10
  62. package/src/showcases/HomeShowcase.tsx +6 -6
  63. package/src/showcases/NavigationShowcases.tsx +72 -2
  64. package/src/showcases/StructureShowcases.tsx +64 -0
  65. package/src/types/chip.types.ts +13 -0
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "packageManager": "pnpm@10.34.0",
5
5
  "private": false,
6
6
  "license": "MIT",
7
- "version": "1.2.16",
7
+ "version": "1.3.1",
8
8
  "type": "module",
9
9
  "sideEffects": [
10
10
  "*.css"
package/src/App.tsx CHANGED
@@ -18,6 +18,7 @@ import {
18
18
  CardShowcase,
19
19
  LayoutShowcase,
20
20
  TextShowcase,
21
+ AccordionShowcase,
21
22
  } from "./showcases/StructureShowcases";
22
23
  import {
23
24
  StackShowcase,
@@ -41,18 +42,25 @@ import {
41
42
  SlideToggleShowcase,
42
43
  DropfileShowcase,
43
44
  FormBuilderShowcase,
45
+ WysiwygShowcase,
46
+ FieldShowcase,
47
+ MaskedInputShowcase,
48
+ MultiSelectShowcase,
49
+ ChipInputShowcase,
44
50
  } from "./showcases/FormShowcases";
45
51
  import {
46
52
  TableShowcase,
47
53
  DataTableShowcase,
48
54
  BadgetShowcase,
49
55
  ImageShowcase,
56
+ ChipShowcase,
50
57
  } from "./showcases/DataShowcases";
51
58
  import {
52
59
  TabsShowcase,
53
60
  StepperShowcase,
54
61
  PaginationShowcase,
55
62
  TripleFilterShowcase,
63
+ DropdownMenuShowcase,
56
64
  } from "./showcases/NavigationShowcases";
57
65
  import {
58
66
  DialogShowcase,
@@ -86,6 +94,7 @@ const categories = [
86
94
  { id: "grid", label: "ITGrid" },
87
95
  { id: "card", label: "ITCard" },
88
96
  { id: "text", label: "ITText" },
97
+ { id: "accordion", label: "ITAccordion" },
89
98
  { id: "pageheader", label: "ITPageHeader" },
90
99
  { id: "page", label: "ITPage" },
91
100
  { id: "screen-dashboard", label: "Dashboard Ejemplo" },
@@ -101,11 +110,16 @@ const categories = [
101
110
  { id: "input", label: "ITInput" },
102
111
  { id: "select", label: "ITSelect" },
103
112
  { id: "searchselect", label: "ITSearchSelect" },
113
+ { id: "multiselect", label: "ITMultiSelect" },
114
+ { id: "chipinput", label: "ITChipInput" },
115
+ { id: "field", label: "ITField" },
104
116
  { id: "datepicker", label: "ITDatePicker" },
105
117
  { id: "timepicker", label: "ITTimePicker" },
118
+ { id: "maskedinput", label: "ITMaskedInput" },
106
119
  { id: "calendar", label: "ITCalendar" },
107
120
  { id: "slidetoggle", label: "ITSlideToggle" },
108
121
  { id: "dropfile", label: "ITDropfile" },
122
+ { id: "wysiwyg", label: "ITWysiwyg" },
109
123
  { id: "formbuilder", label: "ITFormBuilder" },
110
124
  ],
111
125
  },
@@ -117,6 +131,7 @@ const categories = [
117
131
  { id: "table", label: "ITTable" },
118
132
  { id: "datatable", label: "ITDataTable" },
119
133
  { id: "badget", label: "ITBadget" },
134
+ { id: "chip", label: "ITChip" },
120
135
  { id: "image", label: "ITImage" },
121
136
  ],
122
137
  },
@@ -129,6 +144,7 @@ const categories = [
129
144
  { id: "stepper", label: "ITStepper" },
130
145
  { id: "pagination", label: "ITPagination" },
131
146
  { id: "triplefilter", label: "ITTripleFilter" },
147
+ { id: "dropdownmenu", label: "ITDropdownMenu" },
132
148
  ],
133
149
  },
134
150
  {
@@ -249,6 +265,8 @@ function App() {
249
265
  return <CardShowcase />;
250
266
  case "text":
251
267
  return <TextShowcase />;
268
+ case "accordion":
269
+ return <AccordionShowcase />;
252
270
  case "pageheader":
253
271
  return <PageHeaderShowcase />;
254
272
  case "page":
@@ -268,16 +286,26 @@ function App() {
268
286
  return <SelectShowcase />;
269
287
  case "searchselect":
270
288
  return <SearchSelectShowcase />;
289
+ case "multiselect":
290
+ return <MultiSelectShowcase />;
291
+ case "chipinput":
292
+ return <ChipInputShowcase />;
293
+ case "field":
294
+ return <FieldShowcase />;
271
295
  case "datepicker":
272
296
  return <DatePickerShowcase />;
273
297
  case "timepicker":
274
298
  return <TimePickerShowcase />;
299
+ case "maskedinput":
300
+ return <MaskedInputShowcase />;
275
301
  case "calendar":
276
302
  return <CalendarShowcase />;
277
303
  case "slidetoggle":
278
304
  return <SlideToggleShowcase />;
279
305
  case "dropfile":
280
306
  return <DropfileShowcase />;
307
+ case "wysiwyg":
308
+ return <WysiwygShowcase />;
281
309
  case "formbuilder":
282
310
  return <FormBuilderShowcase />;
283
311
  // Data
@@ -287,6 +315,8 @@ function App() {
287
315
  return <DataTableShowcase />;
288
316
  case "badget":
289
317
  return <BadgetShowcase />;
318
+ case "chip":
319
+ return <ChipShowcase />;
290
320
  case "image":
291
321
  return <ImageShowcase />;
292
322
  // Navigation
@@ -298,6 +328,8 @@ function App() {
298
328
  return <PaginationShowcase />;
299
329
  case "triplefilter":
300
330
  return <TripleFilterShowcase />;
331
+ case "dropdownmenu":
332
+ return <DropdownMenuShowcase />;
301
333
  // Feedback
302
334
  case "dialog":
303
335
  return <DialogShowcase />;
@@ -32,9 +32,7 @@ export default function ITBadget({
32
32
 
33
33
  const getStyle = () => {
34
34
  const style: React.CSSProperties = {
35
- fontSize: config.fontSize,
36
35
  fontWeight: config.fontWeight,
37
- padding: config.padding,
38
36
  borderRadius: config.borderRadius, // '9999px' in theme
39
37
  borderWidth: '1px', // Default border width for consistency
40
38
  borderStyle: 'solid',
@@ -60,8 +58,8 @@ export default function ITBadget({
60
58
  <span
61
59
  className={clsx(
62
60
  "inline-flex items-center justify-center",
63
- // Fallback size if theme doesn't have it (though theme does have it for primary)
64
- !config.padding ? badgeSizes[size] : "",
61
+ // Apply size classes (padding/font-size)
62
+ badgeSizes[size],
65
63
  className
66
64
  )}
67
65
  style={getStyle()}
@@ -0,0 +1,47 @@
1
+ import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks';
2
+ import * as StoriesData from './chip.stories';
3
+
4
+ <Meta of={StoriesData} />
5
+
6
+ # ITChip
7
+
8
+ Compact tag / pill for labels, active filters, and multi-value selections.
9
+
10
+ ## Props
11
+
12
+ | Prop | Type | Default | Description |
13
+ |------|------|---------|-------------|
14
+ | `label` | `string` | — | Text label. Overridden by `children`. |
15
+ | `children` | `ReactNode` | — | Custom content inside the chip. |
16
+ | `color` | semantic color key | `"secondary"` | Palette color. |
17
+ | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Chip size. |
18
+ | `variant` | `"soft" \| "filled" \| "outlined"` | `"soft"` | Visual style. |
19
+ | `icon` | `ReactNode` | — | Icon before the label. |
20
+ | `removable` | `boolean` | `false` | Shows an (X) button. |
21
+ | `onRemove` | `() => void` | — | Fired when the remove button is pressed. |
22
+ | `onClick` | `() => void` | — | Makes the chip clickable (filter/toggle). |
23
+ | `selected` | `boolean` | `false` | Highlights the chip as selected. |
24
+ | `disabled` | `boolean` | `false` | Disables interactions. |
25
+ | `className` | `string` | — | Extra CSS classes. |
26
+
27
+ ## Usage
28
+
29
+ ```tsx
30
+ import { ITChip } from '@axzydev/axzy_ui_system';
31
+
32
+ <ITChip label="React" color="primary" />
33
+ <ITChip label="México" color="success" variant="outlined" removable onRemove={remove} />
34
+ <ITChip label="Activos" selected onClick={toggle} />
35
+ ```
36
+
37
+ ## Notes
38
+
39
+ - Colors come from `theme.colors`, so they follow the active theme/dark mode.
40
+ - Interactive chips (`onClick`) expose `role="button"` and keyboard support (Enter/Space).
41
+ - The remove button is a nested `<button>`; keep `onClick` on the chip for selection toggles.
42
+
43
+ ## Stories
44
+
45
+ <Primary />
46
+ <Controls />
47
+ <Stories />
@@ -0,0 +1,32 @@
1
+ import { chipVariants } from "@/types/chip.types";
2
+ import { ColorsTypes } from "@/types/colors.types";
3
+ import { SizesTypes } from "@/types/sizes.types";
4
+ import { ReactNode } from "react";
5
+
6
+ /** Props for the ITChip tag/pill component. */
7
+ export interface ITChipProps {
8
+ /** Text label displayed inside the chip. Overridden if `children` is provided. */
9
+ label?: string;
10
+ /** Custom content rendered inside the chip. Takes precedence over `label`. */
11
+ children?: ReactNode;
12
+ /** Color theme key from the semantic palette (e.g. `"primary"`, `"success"`, `"danger"`). @default "secondary" */
13
+ color?: ColorsTypes;
14
+ /** Chip size. Valid values: `"sm"`, `"md"`, `"lg"`. @default "md" */
15
+ size?: SizesTypes;
16
+ /** Visual style. Valid values: `"soft"`, `"filled"`, `"outlined"`. @default "soft" */
17
+ variant?: keyof typeof chipVariants;
18
+ /** Icon rendered before the label. */
19
+ icon?: ReactNode;
20
+ /** Shows a remove (X) button at the end of the chip. @default false */
21
+ removable?: boolean;
22
+ /** Callback fired when the remove button is pressed. */
23
+ onRemove?: () => void;
24
+ /** Makes the chip clickable (filter/toggle usage). */
25
+ onClick?: () => void;
26
+ /** Highlights the chip as selected, using the `color` palette. @default false */
27
+ selected?: boolean;
28
+ /** Disables all chip interactions and reduces opacity. @default false */
29
+ disabled?: boolean;
30
+ /** Additional CSS classes for the chip element. */
31
+ className?: string;
32
+ }
@@ -0,0 +1,64 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import ITChip from "@/components/atoms/chip/chip";
3
+
4
+ const meta: Meta<typeof ITChip> = {
5
+ title: "Components/Data Display/ITChip",
6
+ component: ITChip,
7
+ parameters: { layout: "centered" },
8
+ argTypes: {
9
+ color: {
10
+ control: "select",
11
+ options: ["primary", "secondary", "success", "danger", "warning", "info", "purple"],
12
+ },
13
+ size: { control: "select", options: ["sm", "md", "lg"] },
14
+ variant: { control: "select", options: ["soft", "filled", "outlined"] },
15
+ selected: { control: "boolean" },
16
+ disabled: { control: "boolean" },
17
+ removable: { control: "boolean" },
18
+ },
19
+ };
20
+
21
+ export default meta;
22
+ type Story = StoryObj<typeof ITChip>;
23
+
24
+ export const Default: Story = {
25
+ args: { label: "React", color: "primary" },
26
+ };
27
+
28
+ export const Variants: Story = {
29
+ render: () => (
30
+ <div className="flex flex-wrap items-center gap-3">
31
+ <ITChip label="Soft" variant="soft" color="primary" />
32
+ <ITChip label="Filled" variant="filled" color="primary" />
33
+ <ITChip label="Outlined" variant="outlined" color="primary" />
34
+ </div>
35
+ ),
36
+ };
37
+
38
+ export const Colors: Story = {
39
+ render: () => (
40
+ <div className="flex flex-wrap items-center gap-3">
41
+ {["primary", "secondary", "success", "danger", "warning", "info", "purple"].map((c) => (
42
+ <ITChip key={c} label={c} color={c as never} />
43
+ ))}
44
+ </div>
45
+ ),
46
+ };
47
+
48
+ export const Sizes: Story = {
49
+ render: () => (
50
+ <div className="flex flex-wrap items-center gap-3">
51
+ <ITChip label="Small" size="sm" />
52
+ <ITChip label="Medium" size="md" />
53
+ <ITChip label="Large" size="lg" />
54
+ </div>
55
+ ),
56
+ };
57
+
58
+ export const Removable: Story = {
59
+ args: { label: "México", color: "success", removable: true },
60
+ };
61
+
62
+ export const Selected: Story = {
63
+ args: { label: "Activos", color: "primary", selected: true, onClick: () => {} },
64
+ };
@@ -0,0 +1,112 @@
1
+ import clsx from "clsx";
2
+ import { ITChipProps } from "./chip.props";
3
+ import { chipSizes } from "@/types/chip.types";
4
+ import { theme } from "@/theme/theme";
5
+ import { FaTimes } from "react-icons/fa";
6
+ import ITText from "@/components/atoms/text/text";
7
+
8
+ /**
9
+ * Compact tag / pill used for labels, active filters, and multi-value selections.
10
+ *
11
+ * Supports soft, filled, and outlined variants, an optional leading icon,
12
+ * a removable (X) affordance, and a selected state for filter toggles.
13
+ *
14
+ * @example
15
+ * <ITChip label="React" color="primary" />
16
+ *
17
+ * @example
18
+ * <ITChip label="México" color="success" variant="outlined" removable onRemove={() => remove("MX")} />
19
+ *
20
+ * @example
21
+ * <ITChip label="Activos" selected onClick={() => toggle()} />
22
+ */
23
+ export default function ITChip({
24
+ label,
25
+ children,
26
+ color = "secondary",
27
+ size = "md",
28
+ variant = "soft",
29
+ icon,
30
+ removable = false,
31
+ onRemove,
32
+ onClick,
33
+ selected = false,
34
+ disabled = false,
35
+ className,
36
+ }: ITChipProps) {
37
+ const palette = (theme.colors as Record<string, Record<number, string>>)[color]
38
+ || theme.colors.secondary;
39
+
40
+ const style: React.CSSProperties = {
41
+ borderWidth: "1px",
42
+ borderStyle: "solid",
43
+ transition: "all 0.15s",
44
+ };
45
+
46
+ if (variant === "filled") {
47
+ style.backgroundColor = palette[500];
48
+ style.color = "#ffffff";
49
+ style.borderColor = palette[500];
50
+ } else if (variant === "outlined") {
51
+ style.backgroundColor = "transparent";
52
+ style.color = palette[700];
53
+ style.borderColor = palette[400];
54
+ } else {
55
+ style.backgroundColor = palette[100];
56
+ style.color = palette[700];
57
+ style.borderColor = palette[200];
58
+ }
59
+
60
+ if (selected) {
61
+ style.backgroundColor = palette[500];
62
+ style.color = "#ffffff";
63
+ style.borderColor = palette[500];
64
+ }
65
+
66
+ const interactive = Boolean(onClick) && !disabled;
67
+
68
+ return (
69
+ <span
70
+ role={interactive ? "button" : undefined}
71
+ tabIndex={interactive ? 0 : undefined}
72
+ aria-pressed={interactive ? selected : undefined}
73
+ aria-disabled={disabled || undefined}
74
+ onClick={interactive ? onClick : undefined}
75
+ onKeyDown={
76
+ interactive
77
+ ? (e) => {
78
+ if (e.key === "Enter" || e.key === " ") {
79
+ e.preventDefault();
80
+ onClick?.();
81
+ }
82
+ }
83
+ : undefined
84
+ }
85
+ className={clsx(
86
+ "inline-flex items-center justify-center rounded-full font-medium whitespace-nowrap align-middle",
87
+ chipSizes[size],
88
+ interactive && "cursor-pointer hover:brightness-95 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-300",
89
+ disabled && "opacity-50 cursor-not-allowed",
90
+ className
91
+ )}
92
+ style={style}
93
+ >
94
+ {icon && <span className="inline-flex items-center shrink-0">{icon}</span>}
95
+ {children ?? <ITText as="span" className="truncate">{label}</ITText>}
96
+ {removable && (
97
+ <button
98
+ type="button"
99
+ aria-label={label ? `Quitar ${label}` : "Quitar"}
100
+ disabled={disabled}
101
+ onClick={(e) => {
102
+ e.stopPropagation();
103
+ onRemove?.();
104
+ }}
105
+ className="inline-flex items-center justify-center rounded-full opacity-70 hover:opacity-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-current -mr-0.5 shrink-0"
106
+ >
107
+ <FaTimes size={10} />
108
+ </button>
109
+ )}
110
+ </span>
111
+ );
112
+ }
@@ -70,8 +70,7 @@ export default function ITGrid({
70
70
  return (
71
71
  <Component
72
72
  className={clsx(
73
- "col-span-full",
74
- colSpanClass(xs ?? sm, columns),
73
+ colSpanClass(xs ?? sm, columns) ?? "col-span-full",
75
74
  sm !== undefined && breakpointSpan(sm, "sm", columns),
76
75
  md !== undefined && breakpointSpan(md, "md", columns),
77
76
  lg !== undefined && breakpointSpan(lg, "lg", columns),
@@ -0,0 +1,47 @@
1
+ import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks';
2
+ import * as StoriesData from './accordion.stories';
3
+
4
+ <Meta of={StoriesData} />
5
+
6
+ # ITAccordion
7
+
8
+ Collapsible sections for FAQs, settings panels, and long content.
9
+
10
+ ## Props
11
+
12
+ | Prop | Type | Default | Description |
13
+ |------|------|---------|-------------|
14
+ | `items` | `ITAccordionItem[]` | — | Sections to render: `{ id, title, content, icon?, disabled? }`. |
15
+ | `allowMultiple` | `boolean` | `false` | Allows several sections open at once. |
16
+ | `defaultOpenIds` | `string[]` | `[]` | Open ids on first render (uncontrolled). |
17
+ | `openIds` | `string[]` | — | Controlled open ids. |
18
+ | `onChange` | `(openIds: string[]) => void` | — | Fired with the next open ids. |
19
+ | `variant` | `"default" \| "separated" \| "bordered"` | `"separated"` | Visual style. |
20
+ | `className` | `string` | — | Extra CSS classes for the wrapper. |
21
+ | `itemClassName` | `string` | — | Extra CSS classes per item. |
22
+
23
+ ## Usage
24
+
25
+ ```tsx
26
+ import { ITAccordion } from '@axzydev/axzy_ui_system';
27
+
28
+ <ITAccordion
29
+ items={[
30
+ { id: "a", title: "¿Qué es AXZY?", content: "Un sistema de componentes." },
31
+ { id: "b", title: "¿Cómo instalo?", content: "pnpm add @axzydev/axzy_ui_system" },
32
+ ]}
33
+ defaultOpenIds={["a"]}
34
+ />
35
+ ```
36
+
37
+ ## Notes
38
+
39
+ - Controlled via `openIds` + `onChange`; uncontrolled via `defaultOpenIds`.
40
+ - Single-open by default; pass `allowMultiple` to open several.
41
+ - Header buttons expose `aria-expanded` / `aria-controls`; the body is a labelled `region`.
42
+
43
+ ## Stories
44
+
45
+ <Primary />
46
+ <Controls />
47
+ <Stories />
@@ -0,0 +1,35 @@
1
+ import { ReactNode } from "react";
2
+
3
+ /** A single collapsible section inside {@link ITAccordionProps}. */
4
+ export interface ITAccordionItem {
5
+ /** Unique identifier for the item. */
6
+ id: string;
7
+ /** Header content (usually text). */
8
+ title: ReactNode;
9
+ /** Body content revealed when the item is open. */
10
+ content: ReactNode;
11
+ /** Optional icon rendered before the title. */
12
+ icon?: ReactNode;
13
+ /** Disables toggling for this item. @default false */
14
+ disabled?: boolean;
15
+ }
16
+
17
+ /** Props for the ITAccordion component. */
18
+ export interface ITAccordionProps {
19
+ /** Sections to render. */
20
+ items: ITAccordionItem[];
21
+ /** Allows more than one section open at the same time. @default false */
22
+ allowMultiple?: boolean;
23
+ /** Ids open on first render (uncontrolled mode). */
24
+ defaultOpenIds?: string[];
25
+ /** Controlled list of open ids. When provided, the component is controlled. */
26
+ openIds?: string[];
27
+ /** Fired with the next list of open ids whenever a section toggles. */
28
+ onChange?: (openIds: string[]) => void;
29
+ /** Visual style. Valid values: `"default"`, `"separated"`, `"bordered"`. @default "separated" */
30
+ variant?: "default" | "separated" | "bordered";
31
+ /** Additional CSS classes for the wrapper. */
32
+ className?: string;
33
+ /** Additional CSS classes applied to every item. */
34
+ itemClassName?: string;
35
+ }
@@ -0,0 +1,68 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import ITAccordion from "@/components/molecules/accordion/accordion";
3
+ import ITBadget from "@/components/atoms/badget/badget";
4
+
5
+ const meta: Meta<typeof ITAccordion> = {
6
+ title: "Components/Structure/ITAccordion",
7
+ component: ITAccordion,
8
+ parameters: { layout: "centered" },
9
+ };
10
+
11
+ export default meta;
12
+ type Story = StoryObj<typeof ITAccordion>;
13
+
14
+ const items = [
15
+ {
16
+ id: "what",
17
+ title: "¿Qué es AXZY UI System?",
18
+ content: "Una librería de componentes React + TypeScript con Tailwind CSS v4.",
19
+ },
20
+ {
21
+ id: "install",
22
+ title: "¿Cómo lo instalo?",
23
+ content: "pnpm add @axzydev/axzy_ui_system",
24
+ },
25
+ {
26
+ id: "theme",
27
+ title: "¿Puedo personalizar el tema?",
28
+ content: "Sí, usa ITThemeProvider para definir la paleta y tokens.",
29
+ },
30
+ ];
31
+
32
+ export const Default: Story = {
33
+ render: () => (
34
+ <div className="w-[520px]">
35
+ <ITAccordion items={items} defaultOpenIds={["what"]} />
36
+ </div>
37
+ ),
38
+ };
39
+
40
+ export const AllowMultiple: Story = {
41
+ render: () => (
42
+ <div className="w-[520px]">
43
+ <ITAccordion items={items} allowMultiple defaultOpenIds={["what", "install"]} />
44
+ </div>
45
+ ),
46
+ };
47
+
48
+ export const Bordered: Story = {
49
+ render: () => (
50
+ <div className="w-[520px]">
51
+ <ITAccordion items={items} variant="bordered" defaultOpenIds={["install"]} />
52
+ </div>
53
+ ),
54
+ };
55
+
56
+ export const WithIconAndBadge: Story = {
57
+ render: () => (
58
+ <div className="w-[520px]">
59
+ <ITAccordion
60
+ items={[
61
+ { id: "1", title: "Novedades", icon: <span>✨</span>, content: "3 componentes nuevos." },
62
+ { id: "2", title: "Pendientes", content: <ITBadget label="2" color="warning" size="sm" /> },
63
+ ]}
64
+ defaultOpenIds={["1"]}
65
+ />
66
+ </div>
67
+ ),
68
+ };