@axzydev/axzy_ui_system 1.2.16 → 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.
- package/dist/index.cjs +3058 -1407
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.cts +620 -54
- package/dist/index.d.ts +620 -54
- package/dist/index.js +2974 -1318
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/App.tsx +28 -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/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/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 +24 -4
- package/src/showcases/DataShowcases.tsx +76 -0
- package/src/showcases/FormShowcases.tsx +396 -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,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
|
-
//
|
|
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
|
+
};
|