@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.
- package/dist/index.cjs +3349 -1457
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.cts +719 -54
- package/dist/index.d.ts +719 -54
- package/dist/index.js +3283 -1387
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/App.tsx +32 -0
- package/src/components/atoms/badget/badget.tsx +2 -4
- package/src/components/atoms/chip/chip.doc.mdx +47 -0
- package/src/components/atoms/chip/chip.props.ts +32 -0
- package/src/components/atoms/chip/chip.stories.tsx +64 -0
- package/src/components/atoms/chip/chip.tsx +112 -0
- package/src/components/atoms/grid/grid.tsx +1 -2
- package/src/components/molecules/accordion/accordion.doc.mdx +47 -0
- package/src/components/molecules/accordion/accordion.props.ts +35 -0
- package/src/components/molecules/accordion/accordion.stories.tsx +68 -0
- package/src/components/molecules/accordion/accordion.tsx +123 -0
- package/src/components/molecules/calendar/calendar.doc.mdx +2 -1
- package/src/components/molecules/calendar/calendar.tsx +102 -24
- package/src/components/molecules/chip-input/chip-input.doc.mdx +44 -0
- package/src/components/molecules/chip-input/chip-input.props.ts +42 -0
- package/src/components/molecules/chip-input/chip-input.stories.tsx +52 -0
- package/src/components/molecules/chip-input/chip-input.tsx +205 -0
- package/src/components/molecules/date-picker/datePicker.tsx +45 -56
- package/src/components/molecules/dropdown-menu/dropdown-menu.doc.mdx +46 -0
- package/src/components/molecules/dropdown-menu/dropdown-menu.props.ts +41 -0
- package/src/components/molecules/dropdown-menu/dropdown-menu.stories.tsx +41 -0
- package/src/components/molecules/dropdown-menu/dropdown-menu.tsx +219 -0
- package/src/components/molecules/field/field.doc.mdx +43 -0
- package/src/components/molecules/field/field.props.ts +23 -0
- package/src/components/molecules/field/field.stories.tsx +42 -0
- package/src/components/molecules/field/field.tsx +54 -0
- package/src/components/molecules/masked-input/masked-input.doc.mdx +78 -0
- package/src/components/molecules/masked-input/masked-input.props.ts +58 -0
- package/src/components/molecules/masked-input/masked-input.stories.tsx +126 -0
- package/src/components/molecules/masked-input/masked-input.tsx +244 -0
- package/src/components/molecules/multi-select/multi-select.doc.mdx +55 -0
- package/src/components/molecules/multi-select/multi-select.props.ts +65 -0
- package/src/components/molecules/multi-select/multi-select.stories.tsx +59 -0
- package/src/components/molecules/multi-select/multi-select.tsx +386 -0
- package/src/components/molecules/search-select/search-select.doc.mdx +5 -0
- package/src/components/molecules/search-select/search-select.props.ts +10 -1
- package/src/components/molecules/search-select/search-select.stories.tsx +18 -0
- package/src/components/molecules/search-select/search-select.tsx +102 -28
- package/src/components/molecules/time-picker/timePicker.tsx +14 -26
- package/src/components/molecules/wysiwyg/wysiwyg.props.ts +51 -0
- package/src/components/molecules/wysiwyg/wysiwyg.stories.tsx +95 -0
- package/src/components/molecules/wysiwyg/wysiwyg.tsx +609 -0
- package/src/components/organisms/form-builder/fieldRenderer.tsx +144 -27
- package/src/components/organisms/form-builder/formBuilder.context.tsx +77 -15
- package/src/components/organisms/form-builder/formBuilder.doc.mdx +213 -86
- package/src/components/organisms/form-builder/formBuilder.props.ts +118 -36
- package/src/components/organisms/form-builder/formBuilder.stories.tsx +694 -96
- package/src/components/organisms/form-builder/formBuilder.tsx +152 -69
- package/src/components/organisms/form-builder/useFormBuilder.ts +59 -21
- package/src/hooks/useFloatingPanel.ts +100 -0
- package/src/index.ts +26 -4
- package/src/showcases/DataShowcases.tsx +76 -0
- package/src/showcases/FormShowcases.tsx +574 -10
- package/src/showcases/HomeShowcase.tsx +6 -6
- package/src/showcases/NavigationShowcases.tsx +72 -2
- package/src/showcases/StructureShowcases.tsx +64 -0
- package/src/types/chip.types.ts +13 -0
package/package.json
CHANGED
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
|
-
//
|
|
64
|
-
|
|
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
|
+
};
|