@axzydev/axzy_ui_system 1.2.15 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/index.cjs +3067 -1409
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.css +1 -1
  4. package/dist/index.d.cts +620 -54
  5. package/dist/index.d.ts +620 -54
  6. package/dist/index.js +2983 -1320
  7. package/dist/index.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/App.tsx +28 -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/chip-input/chip-input.doc.mdx +44 -0
  21. package/src/components/molecules/chip-input/chip-input.props.ts +42 -0
  22. package/src/components/molecules/chip-input/chip-input.stories.tsx +52 -0
  23. package/src/components/molecules/chip-input/chip-input.tsx +205 -0
  24. package/src/components/molecules/date-picker/datePicker.tsx +45 -56
  25. package/src/components/molecules/dropdown-menu/dropdown-menu.doc.mdx +46 -0
  26. package/src/components/molecules/dropdown-menu/dropdown-menu.props.ts +41 -0
  27. package/src/components/molecules/dropdown-menu/dropdown-menu.stories.tsx +41 -0
  28. package/src/components/molecules/dropdown-menu/dropdown-menu.tsx +219 -0
  29. package/src/components/molecules/field/field.doc.mdx +43 -0
  30. package/src/components/molecules/field/field.props.ts +23 -0
  31. package/src/components/molecules/field/field.stories.tsx +42 -0
  32. package/src/components/molecules/field/field.tsx +54 -0
  33. package/src/components/molecules/multi-select/multi-select.doc.mdx +55 -0
  34. package/src/components/molecules/multi-select/multi-select.props.ts +65 -0
  35. package/src/components/molecules/multi-select/multi-select.stories.tsx +59 -0
  36. package/src/components/molecules/multi-select/multi-select.tsx +386 -0
  37. package/src/components/molecules/search-select/search-select.doc.mdx +5 -0
  38. package/src/components/molecules/search-select/search-select.props.ts +10 -1
  39. package/src/components/molecules/search-select/search-select.stories.tsx +18 -0
  40. package/src/components/molecules/search-select/search-select.tsx +102 -28
  41. package/src/components/molecules/time-picker/timePicker.tsx +14 -26
  42. package/src/components/molecules/wysiwyg/wysiwyg.props.ts +51 -0
  43. package/src/components/molecules/wysiwyg/wysiwyg.stories.tsx +95 -0
  44. package/src/components/molecules/wysiwyg/wysiwyg.tsx +609 -0
  45. package/src/components/organisms/data-table/dataTable.tsx +16 -5
  46. package/src/components/organisms/form-builder/fieldRenderer.tsx +144 -27
  47. package/src/components/organisms/form-builder/formBuilder.context.tsx +77 -15
  48. package/src/components/organisms/form-builder/formBuilder.doc.mdx +213 -86
  49. package/src/components/organisms/form-builder/formBuilder.props.ts +118 -36
  50. package/src/components/organisms/form-builder/formBuilder.stories.tsx +694 -96
  51. package/src/components/organisms/form-builder/formBuilder.tsx +152 -69
  52. package/src/components/organisms/form-builder/useFormBuilder.ts +59 -21
  53. package/src/hooks/useFloatingPanel.ts +100 -0
  54. package/src/index.ts +24 -4
  55. package/src/showcases/DataShowcases.tsx +76 -0
  56. package/src/showcases/FormShowcases.tsx +396 -10
  57. package/src/showcases/HomeShowcase.tsx +6 -6
  58. package/src/showcases/NavigationShowcases.tsx +72 -2
  59. package/src/showcases/StructureShowcases.tsx +64 -0
  60. 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.15",
7
+ "version": "1.3.0",
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,24 @@ import {
41
42
  SlideToggleShowcase,
42
43
  DropfileShowcase,
43
44
  FormBuilderShowcase,
45
+ WysiwygShowcase,
46
+ FieldShowcase,
47
+ MultiSelectShowcase,
48
+ ChipInputShowcase,
44
49
  } from "./showcases/FormShowcases";
45
50
  import {
46
51
  TableShowcase,
47
52
  DataTableShowcase,
48
53
  BadgetShowcase,
49
54
  ImageShowcase,
55
+ ChipShowcase,
50
56
  } from "./showcases/DataShowcases";
51
57
  import {
52
58
  TabsShowcase,
53
59
  StepperShowcase,
54
60
  PaginationShowcase,
55
61
  TripleFilterShowcase,
62
+ DropdownMenuShowcase,
56
63
  } from "./showcases/NavigationShowcases";
57
64
  import {
58
65
  DialogShowcase,
@@ -86,6 +93,7 @@ const categories = [
86
93
  { id: "grid", label: "ITGrid" },
87
94
  { id: "card", label: "ITCard" },
88
95
  { id: "text", label: "ITText" },
96
+ { id: "accordion", label: "ITAccordion" },
89
97
  { id: "pageheader", label: "ITPageHeader" },
90
98
  { id: "page", label: "ITPage" },
91
99
  { id: "screen-dashboard", label: "Dashboard Ejemplo" },
@@ -101,11 +109,15 @@ const categories = [
101
109
  { id: "input", label: "ITInput" },
102
110
  { id: "select", label: "ITSelect" },
103
111
  { id: "searchselect", label: "ITSearchSelect" },
112
+ { id: "multiselect", label: "ITMultiSelect" },
113
+ { id: "chipinput", label: "ITChipInput" },
114
+ { id: "field", label: "ITField" },
104
115
  { id: "datepicker", label: "ITDatePicker" },
105
116
  { id: "timepicker", label: "ITTimePicker" },
106
117
  { id: "calendar", label: "ITCalendar" },
107
118
  { id: "slidetoggle", label: "ITSlideToggle" },
108
119
  { id: "dropfile", label: "ITDropfile" },
120
+ { id: "wysiwyg", label: "ITWysiwyg" },
109
121
  { id: "formbuilder", label: "ITFormBuilder" },
110
122
  ],
111
123
  },
@@ -117,6 +129,7 @@ const categories = [
117
129
  { id: "table", label: "ITTable" },
118
130
  { id: "datatable", label: "ITDataTable" },
119
131
  { id: "badget", label: "ITBadget" },
132
+ { id: "chip", label: "ITChip" },
120
133
  { id: "image", label: "ITImage" },
121
134
  ],
122
135
  },
@@ -129,6 +142,7 @@ const categories = [
129
142
  { id: "stepper", label: "ITStepper" },
130
143
  { id: "pagination", label: "ITPagination" },
131
144
  { id: "triplefilter", label: "ITTripleFilter" },
145
+ { id: "dropdownmenu", label: "ITDropdownMenu" },
132
146
  ],
133
147
  },
134
148
  {
@@ -249,6 +263,8 @@ function App() {
249
263
  return <CardShowcase />;
250
264
  case "text":
251
265
  return <TextShowcase />;
266
+ case "accordion":
267
+ return <AccordionShowcase />;
252
268
  case "pageheader":
253
269
  return <PageHeaderShowcase />;
254
270
  case "page":
@@ -268,6 +284,12 @@ function App() {
268
284
  return <SelectShowcase />;
269
285
  case "searchselect":
270
286
  return <SearchSelectShowcase />;
287
+ case "multiselect":
288
+ return <MultiSelectShowcase />;
289
+ case "chipinput":
290
+ return <ChipInputShowcase />;
291
+ case "field":
292
+ return <FieldShowcase />;
271
293
  case "datepicker":
272
294
  return <DatePickerShowcase />;
273
295
  case "timepicker":
@@ -278,6 +300,8 @@ function App() {
278
300
  return <SlideToggleShowcase />;
279
301
  case "dropfile":
280
302
  return <DropfileShowcase />;
303
+ case "wysiwyg":
304
+ return <WysiwygShowcase />;
281
305
  case "formbuilder":
282
306
  return <FormBuilderShowcase />;
283
307
  // Data
@@ -287,6 +311,8 @@ function App() {
287
311
  return <DataTableShowcase />;
288
312
  case "badget":
289
313
  return <BadgetShowcase />;
314
+ case "chip":
315
+ return <ChipShowcase />;
290
316
  case "image":
291
317
  return <ImageShowcase />;
292
318
  // Navigation
@@ -298,6 +324,8 @@ function App() {
298
324
  return <PaginationShowcase />;
299
325
  case "triplefilter":
300
326
  return <TripleFilterShowcase />;
327
+ case "dropdownmenu":
328
+ return <DropdownMenuShowcase />;
301
329
  // Feedback
302
330
  case "dialog":
303
331
  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
+ };