@axzydev/axzy_ui_system 1.4.8 → 1.5.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/README.md +2 -11
- package/dist/index.cjs +1826 -1351
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +115 -14
- package/dist/index.d.ts +115 -14
- package/dist/index.js +1481 -1010
- package/dist/index.js.map +1 -1
- package/dist/layered.css +1 -1
- package/package.json +3 -16
- package/src/App.tsx +90 -73
- package/src/components/atoms/badget/badget.tsx +23 -5
- package/src/components/atoms/chip/chip.tsx +3 -1
- package/src/components/atoms/image/image.tsx +3 -1
- package/src/components/atoms/input/input.tsx +8 -5
- package/src/components/atoms/loader/loader.tsx +3 -1
- package/src/components/atoms/slide/slide.props.ts +12 -0
- package/src/components/atoms/slide/slide.tsx +3 -0
- package/src/components/molecules/alert/alert.tsx +3 -1
- package/src/components/molecules/breadcrumbs/breadcrumbs.tsx +3 -1
- package/src/components/molecules/calendar/calendar.tsx +9 -6
- package/src/components/molecules/card/card.tsx +5 -2
- package/src/components/molecules/chip-input/chip-input.tsx +9 -7
- package/src/components/molecules/date-picker/datePicker.tsx +9 -9
- package/src/components/molecules/dropdown-menu/dropdown-menu.props.ts +1 -1
- package/src/components/molecules/dropdown-menu/dropdown-menu.tsx +6 -3
- package/src/components/molecules/field/field.tsx +3 -1
- package/src/components/molecules/form-header/form-header.tsx +3 -1
- package/src/components/molecules/line-bar-chart/line-bar-chart.props.ts +2 -2
- package/src/components/molecules/line-bar-chart/line-bar-chart.tsx +20 -15
- package/src/components/molecules/masked-input/masked-input.tsx +3 -1
- package/src/components/molecules/multi-select/multi-select.tsx +12 -9
- package/src/components/molecules/pagination/pagination.tsx +11 -5
- package/src/components/molecules/search-select/search-select.tsx +11 -9
- package/src/components/molecules/select/select.tsx +6 -4
- package/src/components/molecules/stepper/stepper.tsx +6 -4
- package/src/components/molecules/table/table.tsx +30 -28
- package/src/components/molecules/time-picker/timePicker.tsx +8 -6
- package/src/components/molecules/wysiwyg/wysiwyg.tsx +23 -12
- package/src/components/organisms/confirm-dialog/confirm-dialog.props.ts +4 -4
- package/src/components/organisms/confirm-dialog/confirm-dialog.tsx +16 -8
- package/src/components/organisms/data-table/dataTable.tsx +31 -25
- package/src/components/organisms/dialog/dialog.tsx +3 -0
- package/src/components/organisms/drawer/drawer.tsx +3 -0
- package/src/components/organisms/dropfile/dropfile.tsx +19 -17
- package/src/components/organisms/form-builder/fieldRenderer.tsx +4 -2
- package/src/components/organisms/navbar/navbar.tsx +4 -2
- package/src/components/organisms/page-header/page-header.tsx +3 -1
- package/src/components/organisms/searchTable/components/PaginationControls.tsx +8 -6
- package/src/components/organisms/searchTable/components/PaginationInfo.tsx +3 -1
- package/src/components/organisms/searchTable/components/SearchAndSortBar.tsx +7 -5
- package/src/components/organisms/searchTable/components/SearchInput.tsx +4 -2
- package/src/components/organisms/searchTable/components/SortButton.tsx +13 -11
- package/src/components/organisms/searchTable/components/TableEmptyState.tsx +4 -2
- package/src/components/organisms/searchTable/components/TableRow.tsx +6 -4
- package/src/components/organisms/searchTable/searchTable.tsx +4 -2
- package/src/components/organisms/sidebar/sidebar.props.ts +1 -1
- package/src/components/organisms/sidebar/sidebar.tsx +9 -4
- package/src/components/organisms/toast/toast.tsx +3 -1
- package/src/components/organisms/topbar/topbar.tsx +4 -2
- package/src/components/templates/page/page.props.ts +4 -4
- package/src/components/templates/page/page.tsx +6 -4
- package/src/components/theme-provider/themeProvider.tsx +28 -17
- package/src/dev.css +77 -2
- package/src/global.d.ts +10 -0
- package/src/i18n/context.ts +9 -0
- package/src/i18n/index.ts +22 -0
- package/src/i18n/locales/en.ts +163 -0
- package/src/i18n/locales/es.ts +165 -0
- package/src/i18n/provider.tsx +44 -0
- package/src/i18n/translator.ts +82 -0
- package/src/i18n/types.ts +54 -0
- package/src/i18n/useITTranslation.ts +20 -0
- package/src/index.css +0 -1
- package/src/index.ts +7 -1
- package/src/sandbox/LandingShowcase.tsx +224 -580
- package/src/sandbox/NotFoundShowcase.tsx +51 -36
- package/src/sandbox/TopbarSearch.tsx +6 -4
- package/src/sandbox/controls.tsx +180 -0
- package/src/sandbox/i18n.ts +1929 -0
- package/src/sandbox/icons.tsx +25 -0
- package/src/sandbox/locale.tsx +72 -0
- package/src/sandbox/ui.tsx +377 -0
- package/src/sandbox/useHashRoute.ts +46 -10
- package/src/showcases/DataShowcases.tsx +103 -87
- package/src/showcases/FeedbackShowcases.tsx +37 -30
- package/src/showcases/FormShowcases.tsx +302 -214
- package/src/showcases/GettingStartedShowcase.tsx +151 -145
- package/src/showcases/HelpShowcase.tsx +126 -128
- package/src/showcases/HomeShowcase.tsx +678 -482
- package/src/showcases/LayoutPrimitivesShowcases.tsx +129 -114
- package/src/showcases/NavigationShowcases.tsx +45 -37
- package/src/showcases/PageShowcases.tsx +171 -152
- package/src/showcases/ProductoDetalle.tsx +272 -129
- package/src/showcases/ShowcaseLayout.tsx +270 -216
- package/src/showcases/SizesShowcase.tsx +123 -64
- package/src/showcases/StructureShowcases.tsx +157 -131
- package/src/showcases/portfolioUi.tsx +153 -0
- package/src/showcases/techIcons.ts +3 -0
- package/src/utils/table.utils.ts +10 -2
- package/src/components/atoms/avatar/avatar.doc.mdx +0 -48
- package/src/components/atoms/avatar/avatar.stories.tsx +0 -64
- package/src/components/atoms/badget/badget.doc.mdx +0 -46
- package/src/components/atoms/badget/badget.stories.tsx +0 -75
- package/src/components/atoms/button/button.doc.mdx +0 -59
- package/src/components/atoms/button/button.stories.tsx +0 -173
- package/src/components/atoms/checkbox/checkbox.doc.mdx +0 -54
- package/src/components/atoms/checkbox/checkbox.stories.tsx +0 -53
- package/src/components/atoms/chip/chip.doc.mdx +0 -47
- package/src/components/atoms/chip/chip.stories.tsx +0 -64
- package/src/components/atoms/divider/divider.doc.mdx +0 -42
- package/src/components/atoms/divider/divider.stories.tsx +0 -33
- package/src/components/atoms/flex/flex.doc.mdx +0 -59
- package/src/components/atoms/flex/flex.stories.tsx +0 -70
- package/src/components/atoms/grid/grid.doc.mdx +0 -54
- package/src/components/atoms/grid/grid.stories.tsx +0 -71
- package/src/components/atoms/image/image.doc.mdx +0 -44
- package/src/components/atoms/image/image.stories.tsx +0 -48
- package/src/components/atoms/input/input.doc.mdx +0 -70
- package/src/components/atoms/input/input.stories.tsx +0 -113
- package/src/components/atoms/input-number/input-number.doc.mdx +0 -74
- package/src/components/atoms/input-number/input-number.stories.tsx +0 -111
- package/src/components/atoms/loader/loader.doc.mdx +0 -43
- package/src/components/atoms/loader/loader.stories.tsx +0 -104
- package/src/components/atoms/popover/popover.doc.mdx +0 -53
- package/src/components/atoms/popover/popover.stories.tsx +0 -24
- package/src/components/atoms/progress/progress.doc.mdx +0 -48
- package/src/components/atoms/progress/progress.stories.tsx +0 -39
- package/src/components/atoms/radio/radio.doc.mdx +0 -62
- package/src/components/atoms/radio/radio.stories.tsx +0 -48
- package/src/components/atoms/segmented-control/segmented-control.doc.mdx +0 -60
- package/src/components/atoms/segmented-control/segmented-control.stories.tsx +0 -62
- package/src/components/atoms/skeleton/skeleton.doc.mdx +0 -43
- package/src/components/atoms/skeleton/skeleton.stories.tsx +0 -29
- package/src/components/atoms/slide/slide.doc.mdx +0 -46
- package/src/components/atoms/slide/slide.stories.tsx +0 -120
- package/src/components/atoms/slider/slider.doc.mdx +0 -49
- package/src/components/atoms/slider/slider.stories.tsx +0 -29
- package/src/components/atoms/stack/stack.doc.mdx +0 -126
- package/src/components/atoms/stack/stack.stories.tsx +0 -283
- package/src/components/atoms/text/text.doc.mdx +0 -41
- package/src/components/atoms/text/text.stories.tsx +0 -66
- package/src/components/atoms/textarea/textarea.doc.mdx +0 -64
- package/src/components/atoms/textarea/textarea.stories.tsx +0 -26
- package/src/components/atoms/tooltip/tooltip.doc.mdx +0 -47
- package/src/components/atoms/tooltip/tooltip.stories.tsx +0 -19
- package/src/components/isolation/isolation.stories.tsx +0 -202
- package/src/components/molecules/accordion/accordion.doc.mdx +0 -47
- package/src/components/molecules/accordion/accordion.stories.tsx +0 -68
- package/src/components/molecules/alert/alert.doc.mdx +0 -48
- package/src/components/molecules/alert/alert.stories.tsx +0 -40
- package/src/components/molecules/breadcrumbs/breadcrumbs.doc.mdx +0 -57
- package/src/components/molecules/breadcrumbs/breadcrumbs.stories.tsx +0 -20
- package/src/components/molecules/calendar/calendar.doc.mdx +0 -76
- package/src/components/molecules/calendar/calendar.stories.tsx +0 -90
- package/src/components/molecules/card/card.doc.mdx +0 -54
- package/src/components/molecules/card/card.stories.tsx +0 -57
- package/src/components/molecules/chip-input/chip-input.doc.mdx +0 -44
- package/src/components/molecules/chip-input/chip-input.stories.tsx +0 -52
- package/src/components/molecules/date-picker/date-picker.doc.mdx +0 -65
- package/src/components/molecules/date-picker/date-picker.stories.tsx +0 -88
- package/src/components/molecules/dropdown-menu/dropdown-menu.doc.mdx +0 -46
- package/src/components/molecules/dropdown-menu/dropdown-menu.stories.tsx +0 -41
- package/src/components/molecules/empty-state/empty-state.doc.mdx +0 -50
- package/src/components/molecules/empty-state/empty-state.stories.tsx +0 -19
- package/src/components/molecules/field/field.doc.mdx +0 -43
- package/src/components/molecules/field/field.stories.tsx +0 -42
- package/src/components/molecules/form-header/form-header.doc.mdx +0 -38
- package/src/components/molecules/form-header/form-header.stories.tsx +0 -52
- package/src/components/molecules/masked-input/masked-input.doc.mdx +0 -78
- package/src/components/molecules/masked-input/masked-input.stories.tsx +0 -126
- package/src/components/molecules/multi-select/multi-select.doc.mdx +0 -55
- package/src/components/molecules/multi-select/multi-select.stories.tsx +0 -59
- package/src/components/molecules/pagination/pagination.doc.mdx +0 -62
- package/src/components/molecules/pagination/pagination.stories.tsx +0 -110
- package/src/components/molecules/search-select/search-select.doc.mdx +0 -77
- package/src/components/molecules/search-select/search-select.stories.tsx +0 -146
- package/src/components/molecules/select/select.doc.mdx +0 -75
- package/src/components/molecules/select/select.stories.tsx +0 -85
- package/src/components/molecules/stat-card/stat-card.doc.mdx +0 -48
- package/src/components/molecules/stat-card/stat-card.stories.tsx +0 -40
- package/src/components/molecules/stepper/stepper.doc.mdx +0 -54
- package/src/components/molecules/stepper/stepper.stories.tsx +0 -154
- package/src/components/molecules/table/table.doc.mdx +0 -140
- package/src/components/molecules/table/table.stories.tsx +0 -402
- package/src/components/molecules/tabs/tabs.doc.mdx +0 -52
- package/src/components/molecules/tabs/tabs.stories.tsx +0 -31
- package/src/components/molecules/time-picker/timePicker.doc.mdx +0 -68
- package/src/components/molecules/time-picker/timePicker.stories.tsx +0 -130
- package/src/components/molecules/wysiwyg/wysiwyg.stories.tsx +0 -95
- package/src/components/organisms/confirm-dialog/confirm-dialog.doc.mdx +0 -60
- package/src/components/organisms/confirm-dialog/confirm-dialog.stories.tsx +0 -32
- package/src/components/organisms/data-table/ITDataTable.doc.mdx +0 -132
- package/src/components/organisms/data-table/ITDataTable.stories.tsx +0 -353
- package/src/components/organisms/dialog/dialog.doc.mdx +0 -54
- package/src/components/organisms/dialog/dialog.stories.tsx +0 -126
- package/src/components/organisms/drawer/drawer.doc.mdx +0 -59
- package/src/components/organisms/drawer/drawer.stories.tsx +0 -40
- package/src/components/organisms/dropfile/dropfile.doc.mdx +0 -74
- package/src/components/organisms/dropfile/dropfile.stories.tsx +0 -93
- package/src/components/organisms/form-builder/formBuilder.doc.mdx +0 -251
- package/src/components/organisms/form-builder/formBuilder.stories.tsx +0 -914
- package/src/components/organisms/navbar/navbar.doc.mdx +0 -77
- package/src/components/organisms/navbar/navbar.stories.tsx +0 -83
- package/src/components/organisms/page-header/page-header.doc.mdx +0 -54
- package/src/components/organisms/page-header/page-header.stories.tsx +0 -74
- package/src/components/organisms/searchTable/searchTable.doc.mdx +0 -79
- package/src/components/organisms/searchTable/searchTable.stories.tsx +0 -73
- package/src/components/organisms/sidebar/sidebar.doc.mdx +0 -176
- package/src/components/organisms/sidebar/sidebar.stories.tsx +0 -234
- package/src/components/organisms/toast/toast.doc.mdx +0 -50
- package/src/components/organisms/toast/toast.stories.tsx +0 -137
- package/src/components/organisms/topbar/topbar.doc.mdx +0 -72
- package/src/components/organisms/topbar/topbar.stories.tsx +0 -79
- package/src/components/organisms/triple-filter/tripleFilter.doc.mdx +0 -62
- package/src/components/organisms/triple-filter/tripleFilter.stories.tsx +0 -31
- package/src/components/templates/layout/layout.doc.mdx +0 -53
- package/src/components/templates/layout/layout.stories.tsx +0 -113
- package/src/components/templates/page/page.doc.mdx +0 -86
- package/src/components/templates/page/page.stories.tsx +0 -97
- package/src/components/theme-provider/themeProvider.doc.mdx +0 -85
- package/src/components/theme-provider/themeProvider.stories.tsx +0 -58
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import ITSidebar from '@/components/organisms/sidebar/sidebar';
|
|
3
|
-
import { FaHome, FaUsers, FaCog, FaChartBar, FaShieldAlt, FaShoppingCart, FaRegBell } from 'react-icons/fa';
|
|
4
|
-
import { expect, fn, userEvent, waitFor } from 'storybook/test';
|
|
5
|
-
|
|
6
|
-
const meta: Meta<typeof ITSidebar> = {
|
|
7
|
-
title: 'Components/Layout & Navigation/ITSidebar',
|
|
8
|
-
component: ITSidebar,
|
|
9
|
-
parameters: {
|
|
10
|
-
layout: 'fullscreen',
|
|
11
|
-
docs: {
|
|
12
|
-
description: {
|
|
13
|
-
component: 'Un sidebar moderno, verdaderamente minimalista, hermoso y personalizable con estados colapsables y submenús. Soporta theming global con hover states y glassmorphism elegantes.',
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export default meta;
|
|
20
|
-
type Story = StoryObj<typeof ITSidebar>;
|
|
21
|
-
|
|
22
|
-
const baseNavigationItems = [
|
|
23
|
-
{
|
|
24
|
-
id: 'dashboard',
|
|
25
|
-
label: 'Dashboard',
|
|
26
|
-
icon: <FaHome />,
|
|
27
|
-
action: () => console.log('Dashboard clicked'),
|
|
28
|
-
isActive: true,
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
id: 'users',
|
|
32
|
-
label: 'Gestión de Usuarios',
|
|
33
|
-
icon: <FaUsers />,
|
|
34
|
-
badge: '3',
|
|
35
|
-
subitems: [
|
|
36
|
-
{ id: 'users-list', label: 'Lista de Usuarios', action: () => console.log('Users list'), isActive: false },
|
|
37
|
-
{ id: 'users-roles', label: 'Roles y Permisos', action: () => console.log('Roles'), isActive: false },
|
|
38
|
-
],
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
id: 'analytics',
|
|
42
|
-
label: 'Analíticas',
|
|
43
|
-
icon: <FaChartBar />,
|
|
44
|
-
action: () => console.log('Analytics clicked'),
|
|
45
|
-
isActive: false,
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
id: 'security',
|
|
49
|
-
label: 'Seguridad',
|
|
50
|
-
icon: <FaShieldAlt />,
|
|
51
|
-
badge: '!',
|
|
52
|
-
action: () => console.log('Security clicked'),
|
|
53
|
-
isActive: false,
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
id: 'settings',
|
|
57
|
-
label: 'Configuración',
|
|
58
|
-
icon: <FaCog />,
|
|
59
|
-
subitems: [
|
|
60
|
-
{ id: 'settings-general', label: 'General', action: () => console.log('General'), isActive: false },
|
|
61
|
-
{ id: 'settings-theme', label: 'Apariencia', action: () => console.log('Theme'), isActive: false },
|
|
62
|
-
],
|
|
63
|
-
},
|
|
64
|
-
];
|
|
65
|
-
|
|
66
|
-
export const Default: Story = {
|
|
67
|
-
args: {
|
|
68
|
-
navigationItems: baseNavigationItems,
|
|
69
|
-
isCollapsed: false,
|
|
70
|
-
visibleOnMobile: true,
|
|
71
|
-
},
|
|
72
|
-
render: (args) => (
|
|
73
|
-
<div className="h-screen bg-gray-50 flex">
|
|
74
|
-
<ITSidebar {...args} />
|
|
75
|
-
<div className="flex-1 p-8 text-zinc-500 font-medium">Contenido principal simulado. Pasa el cursor por los íconos para ver el efecto de glassmorphism en los tooltips flotantes.</div>
|
|
76
|
-
</div>
|
|
77
|
-
),
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export const Collapsed: Story = {
|
|
81
|
-
args: {
|
|
82
|
-
navigationItems: baseNavigationItems,
|
|
83
|
-
isCollapsed: true,
|
|
84
|
-
visibleOnMobile: true,
|
|
85
|
-
},
|
|
86
|
-
render: (args) => (
|
|
87
|
-
<div className="h-screen bg-gray-50 flex">
|
|
88
|
-
<ITSidebar {...args} />
|
|
89
|
-
<div className="flex-1 p-8 text-zinc-500 font-medium">Contenido principal... ¡Pasa el cursor sobre los íconos del sidebar para ver el efecto de glassmorphism en los tooltips flotantes!</div>
|
|
90
|
-
</div>
|
|
91
|
-
),
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
export const WithActiveSubmenu: Story = {
|
|
95
|
-
args: {
|
|
96
|
-
navigationItems: [
|
|
97
|
-
...baseNavigationItems.slice(0, 1).map(i => ({...i, isActive: false})),
|
|
98
|
-
{
|
|
99
|
-
...baseNavigationItems[1],
|
|
100
|
-
isActive: true,
|
|
101
|
-
subitems: [
|
|
102
|
-
{ id: 'users-list', label: 'Lista de Usuarios', action: () => console.log('Users list'), isActive: true },
|
|
103
|
-
{ id: 'users-roles', label: 'Roles y Permisos', action: () => console.log('Roles'), isActive: false },
|
|
104
|
-
]
|
|
105
|
-
},
|
|
106
|
-
...baseNavigationItems.slice(2),
|
|
107
|
-
],
|
|
108
|
-
isCollapsed: false,
|
|
109
|
-
visibleOnMobile: true,
|
|
110
|
-
},
|
|
111
|
-
render: (args) => (
|
|
112
|
-
<div className="h-screen bg-gray-50 flex">
|
|
113
|
-
<ITSidebar {...args} />
|
|
114
|
-
<div className="flex-1 p-8 text-zinc-500 font-medium">El menú de usuarios está expandido y activo, mostrando el conector visual sutil.</div>
|
|
115
|
-
</div>
|
|
116
|
-
),
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const groupedSubItemActionSpy = fn();
|
|
120
|
-
|
|
121
|
-
export const Grouped: Story = {
|
|
122
|
-
args: {
|
|
123
|
-
navigationItems: [
|
|
124
|
-
{ id: 'dashboard', label: 'Dashboard', icon: <FaHome />, isActive: false },
|
|
125
|
-
{
|
|
126
|
-
id: 'ventas',
|
|
127
|
-
label: 'Ventas',
|
|
128
|
-
icon: <FaShoppingCart />,
|
|
129
|
-
subitems: [
|
|
130
|
-
{ id: 'ventas-resumen', label: 'Resumen', action: fn() },
|
|
131
|
-
{
|
|
132
|
-
id: 'gestion',
|
|
133
|
-
label: 'Gestión',
|
|
134
|
-
items: [
|
|
135
|
-
{ id: 'ordenes', label: 'Órdenes', action: groupedSubItemActionSpy },
|
|
136
|
-
{ id: 'facturas', label: 'Facturas', action: fn() },
|
|
137
|
-
],
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
id: 'catalogo',
|
|
141
|
-
label: 'Catálogo',
|
|
142
|
-
items: [
|
|
143
|
-
{ id: 'productos', label: 'Productos', action: fn() },
|
|
144
|
-
{ id: 'cotizaciones', label: 'Cotizaciones', action: fn() },
|
|
145
|
-
],
|
|
146
|
-
},
|
|
147
|
-
],
|
|
148
|
-
},
|
|
149
|
-
{ id: 'settings', label: 'Configuración', icon: <FaCog />, action: fn() },
|
|
150
|
-
],
|
|
151
|
-
isCollapsed: false,
|
|
152
|
-
visibleOnMobile: true,
|
|
153
|
-
},
|
|
154
|
-
render: (args) => (
|
|
155
|
-
<div className="h-screen bg-gray-50 flex">
|
|
156
|
-
<ITSidebar {...args} />
|
|
157
|
-
<div className="flex-1 p-8 text-zinc-500 font-medium">Los subítems de Ventas se agrupan bajo los títulos “Gestión” y “Catálogo”; los títulos no son interactivos.</div>
|
|
158
|
-
</div>
|
|
159
|
-
),
|
|
160
|
-
play: async ({ canvas }) => {
|
|
161
|
-
await userEvent.click(canvas.getByRole('button', { name: 'Ventas' }));
|
|
162
|
-
|
|
163
|
-
const heading = canvas.getByText('Gestión');
|
|
164
|
-
// Wait out the 400ms expand transition before asserting visibility.
|
|
165
|
-
await waitFor(() => expect(heading).toBeVisible());
|
|
166
|
-
|
|
167
|
-
// The group <ul> is named by its heading via aria-labelledby.
|
|
168
|
-
await expect(canvas.getByRole('list', { name: 'Gestión' })).toBeInTheDocument();
|
|
169
|
-
|
|
170
|
-
// The heading is not focusable and is not inside anything with a tabindex.
|
|
171
|
-
await expect(heading.closest('[tabindex]')).toBeNull();
|
|
172
|
-
|
|
173
|
-
await userEvent.click(canvas.getByRole('button', { name: 'Órdenes' }));
|
|
174
|
-
await expect(groupedSubItemActionSpy).toHaveBeenCalled();
|
|
175
|
-
},
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
export const WithNotificationBadges: Story = {
|
|
179
|
-
args: {
|
|
180
|
-
navigationItems: [
|
|
181
|
-
{ id: 'dashboard', label: 'Dashboard', icon: <FaHome />, isActive: true },
|
|
182
|
-
{ id: 'inbox', label: 'Bandeja', icon: <FaUsers />, badge: 12 },
|
|
183
|
-
{
|
|
184
|
-
id: 'alerts',
|
|
185
|
-
label: 'Alertas',
|
|
186
|
-
icon: <FaShieldAlt />,
|
|
187
|
-
badge: 3,
|
|
188
|
-
badgeProps: { color: 'warning', variant: 'outlined' },
|
|
189
|
-
},
|
|
190
|
-
{ id: 'settings', label: 'Configuración', icon: <FaCog />, action: fn() },
|
|
191
|
-
],
|
|
192
|
-
notification: {
|
|
193
|
-
count: 5,
|
|
194
|
-
icon: <FaRegBell />,
|
|
195
|
-
label: 'Notificaciones',
|
|
196
|
-
onClick: fn(),
|
|
197
|
-
},
|
|
198
|
-
isCollapsed: false,
|
|
199
|
-
visibleOnMobile: true,
|
|
200
|
-
},
|
|
201
|
-
render: (args) => (
|
|
202
|
-
<div className="h-screen bg-gray-50 flex">
|
|
203
|
-
<ITSidebar {...args} />
|
|
204
|
-
<div className="flex-1 p-8 text-zinc-500 font-medium">
|
|
205
|
-
Cada ítem puede llevar un ITBadget con número (`badge` + `badgeProps`) y el sidebar admite una fila de notificación con contador (`notification`).
|
|
206
|
-
</div>
|
|
207
|
-
</div>
|
|
208
|
-
),
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
export const CollapsedNotifications: Story = {
|
|
212
|
-
args: {
|
|
213
|
-
navigationItems: [
|
|
214
|
-
{ id: 'dashboard', label: 'Dashboard', icon: <FaHome />, isActive: true },
|
|
215
|
-
{ id: 'inbox', label: 'Bandeja', icon: <FaUsers />, badge: 12 },
|
|
216
|
-
{ id: 'settings', label: 'Configuración', icon: <FaCog /> },
|
|
217
|
-
],
|
|
218
|
-
notification: {
|
|
219
|
-
count: 9,
|
|
220
|
-
icon: <FaRegBell />,
|
|
221
|
-
label: 'Notificaciones',
|
|
222
|
-
},
|
|
223
|
-
isCollapsed: true,
|
|
224
|
-
visibleOnMobile: true,
|
|
225
|
-
},
|
|
226
|
-
render: (args) => (
|
|
227
|
-
<div className="h-screen bg-gray-50 flex">
|
|
228
|
-
<ITSidebar {...args} />
|
|
229
|
-
<div className="flex-1 p-8 text-zinc-500 font-medium">
|
|
230
|
-
Al colapsar, la fila de notificación queda como icono + contador, y los badges de cada ítem siguen visibles como píldoras con número.
|
|
231
|
-
</div>
|
|
232
|
-
</div>
|
|
233
|
-
),
|
|
234
|
-
};
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks';
|
|
2
|
-
import * as StoriesData from './toast.stories';
|
|
3
|
-
|
|
4
|
-
<Meta of={StoriesData} />
|
|
5
|
-
|
|
6
|
-
# ITToast
|
|
7
|
-
|
|
8
|
-
Floating notification with automatic dismiss and severity-based styling. Renders a positioned alert with an icon, message, and optional action button. Supports six on-screen positions and four semantic types — success, error, warning, and info — plus primary and danger variants.
|
|
9
|
-
|
|
10
|
-
## Props
|
|
11
|
-
|
|
12
|
-
| Prop | Type | Default | Description |
|
|
13
|
-
|------|------|---------|-------------|
|
|
14
|
-
| `message` | `string` | — | Toast message text to display. |
|
|
15
|
-
| `type` | `"success" \| "error" \| "warning" \| "info" \| "primary" \| "danger" \| string` | `"info"` | Severity type determining icon and background color. |
|
|
16
|
-
| `duration` | `number` | `1500` | Auto-dismiss duration in milliseconds. |
|
|
17
|
-
| `position` | `"top-right" \| "top-center" \| "top-left" \| "bottom-right" \| "bottom-center" \| "bottom-left"` | `"top-right"` | On-screen placement of the toast. |
|
|
18
|
-
| `onClose` | `() => void` | — | Callback invoked after the toast finishes its dismiss transition animation. |
|
|
19
|
-
|
|
20
|
-
## Usage
|
|
21
|
-
|
|
22
|
-
```tsx
|
|
23
|
-
import { ITToast } from '@axzydev/axzy_ui_system';
|
|
24
|
-
|
|
25
|
-
<ITToast message="Operation completed successfully!" type="success" />
|
|
26
|
-
|
|
27
|
-
<ITToast
|
|
28
|
-
message="There was a critical error processing your request."
|
|
29
|
-
type="error"
|
|
30
|
-
position="top-center"
|
|
31
|
-
duration={5000}
|
|
32
|
-
onClose={() => console.log("dismissed")}
|
|
33
|
-
/>
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Notes
|
|
37
|
-
|
|
38
|
-
- **type** values map to icons: `success` → check circle, `error` → times circle, `warning` → exclamation triangle, `info` → info circle. Unknown types fall back to the info icon.
|
|
39
|
-
- **duration** starts counting after mount; the toast fades out with a 300ms transition after the timer expires.
|
|
40
|
-
- The toast renders with `position: fixed`, so it overlays all page content at the chosen screen edge.
|
|
41
|
-
- A close button (`×`) is always present for manual dismissal.
|
|
42
|
-
- **onClose** fires after the fade-out transition completes — useful for unmounting the toast from a list.
|
|
43
|
-
- For managing multiple toasts simultaneously, wrap with a toast provider context pattern outside `ITToast`.
|
|
44
|
-
- All types also accept raw hex color strings, which get applied as background behind the themed icon.
|
|
45
|
-
|
|
46
|
-
## Stories
|
|
47
|
-
|
|
48
|
-
<Primary />
|
|
49
|
-
<Controls />
|
|
50
|
-
<Stories />
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import ITToast from "@/components/organisms/toast/toast";
|
|
3
|
-
import { useState } from "react";
|
|
4
|
-
import ITButton from "@/components/atoms/button/button";
|
|
5
|
-
|
|
6
|
-
const meta: Meta<typeof ITToast> = {
|
|
7
|
-
title: "Components/Feedback/ITToast",
|
|
8
|
-
component: ITToast,
|
|
9
|
-
parameters: {
|
|
10
|
-
layout: "centered",
|
|
11
|
-
},
|
|
12
|
-
argTypes: {
|
|
13
|
-
type: {
|
|
14
|
-
control: "select",
|
|
15
|
-
options: ["success", "error", "warning", "info", "primary", "danger"],
|
|
16
|
-
},
|
|
17
|
-
position: {
|
|
18
|
-
control: "select",
|
|
19
|
-
options: [
|
|
20
|
-
"top-right",
|
|
21
|
-
"top-center",
|
|
22
|
-
"top-left",
|
|
23
|
-
"bottom-right",
|
|
24
|
-
"bottom-center",
|
|
25
|
-
"bottom-left",
|
|
26
|
-
],
|
|
27
|
-
},
|
|
28
|
-
duration: {
|
|
29
|
-
control: { type: "number", min: 1000, max: 10000, step: 500 },
|
|
30
|
-
},
|
|
31
|
-
message: {
|
|
32
|
-
control: "text",
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export default meta;
|
|
38
|
-
type Story = StoryObj<typeof ITToast>;
|
|
39
|
-
|
|
40
|
-
const ToastTrigger = (args: any) => {
|
|
41
|
-
const [show, setShow] = useState(false);
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<div className="flex items-center justify-center p-12">
|
|
45
|
-
<ITButton
|
|
46
|
-
variant="solid"
|
|
47
|
-
color={args.type in ["success", "error", "warning", "info", "primary"] ? args.type : "primary"}
|
|
48
|
-
onClick={() => {
|
|
49
|
-
setShow(false);
|
|
50
|
-
// Small delay to allow react to unmount and remount a fresh toast for demo purposes
|
|
51
|
-
setTimeout(() => setShow(true), 10);
|
|
52
|
-
}}
|
|
53
|
-
>
|
|
54
|
-
Show Toast ({args.type})
|
|
55
|
-
</ITButton>
|
|
56
|
-
|
|
57
|
-
{show && (
|
|
58
|
-
<ITToast
|
|
59
|
-
{...args}
|
|
60
|
-
onClose={() => {
|
|
61
|
-
setShow(false);
|
|
62
|
-
if (args.onClose) args.onClose();
|
|
63
|
-
}}
|
|
64
|
-
/>
|
|
65
|
-
)}
|
|
66
|
-
</div>
|
|
67
|
-
);
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
export const Default: Story = {
|
|
71
|
-
render: (args) => <ToastTrigger {...args} />,
|
|
72
|
-
args: {
|
|
73
|
-
message: "This is a default information message.",
|
|
74
|
-
type: "info",
|
|
75
|
-
position: "top-right",
|
|
76
|
-
duration: 3000,
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export const Success: Story = {
|
|
81
|
-
render: (args) => <ToastTrigger {...args} />,
|
|
82
|
-
args: {
|
|
83
|
-
message: "Operation completed successfully!",
|
|
84
|
-
type: "success",
|
|
85
|
-
position: "top-right",
|
|
86
|
-
duration: 3000,
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
export const Error: Story = {
|
|
91
|
-
render: (args) => <ToastTrigger {...args} />,
|
|
92
|
-
args: {
|
|
93
|
-
message: "There was a critical error processing your request.",
|
|
94
|
-
type: "error", // Uses theme.colors.error or danger
|
|
95
|
-
position: "top-center",
|
|
96
|
-
duration: 5000,
|
|
97
|
-
},
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
export const Warning: Story = {
|
|
101
|
-
render: (args) => <ToastTrigger {...args} />,
|
|
102
|
-
args: {
|
|
103
|
-
message: "Please check your input values before proceeding.",
|
|
104
|
-
type: "warning",
|
|
105
|
-
position: "bottom-left",
|
|
106
|
-
duration: 4000,
|
|
107
|
-
},
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Multiple Toasts Preview
|
|
112
|
-
* Note: A real implementation would manage multiple toasts via a Toast Provider Context.
|
|
113
|
-
* This just shows how the colors resolve visually.
|
|
114
|
-
*/
|
|
115
|
-
export const AllTypesPreview = () => {
|
|
116
|
-
const types = ["primary", "success", "error", "warning", "info"] as const;
|
|
117
|
-
|
|
118
|
-
return (
|
|
119
|
-
<div className="flex flex-col gap-8 w-[400px]">
|
|
120
|
-
<h3 className="text-gray-500 text-sm font-semibold mb-2">Static Preview (Not positioned fixed)</h3>
|
|
121
|
-
<div className="flex flex-col gap-4 relative">
|
|
122
|
-
{types.map((type) => (
|
|
123
|
-
// We inline style it simply to bypass the fixed positioning just for this preview story block.
|
|
124
|
-
<div key={type} className="relative z-0">
|
|
125
|
-
<ITToast
|
|
126
|
-
message={`This is a ${type} notification message`}
|
|
127
|
-
type={type}
|
|
128
|
-
duration={999999}
|
|
129
|
-
position="top-right"
|
|
130
|
-
/>
|
|
131
|
-
</div>
|
|
132
|
-
))}
|
|
133
|
-
</div>
|
|
134
|
-
<p className="text-xs text-gray-400 mt-4">Note: Actual ITToasts are position: fixed and rendered at the edges of the screen according to their position prop.</p>
|
|
135
|
-
</div>
|
|
136
|
-
);
|
|
137
|
-
};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks';
|
|
2
|
-
import * as StoriesData from './topbar.stories';
|
|
3
|
-
|
|
4
|
-
<Meta of={StoriesData} />
|
|
5
|
-
|
|
6
|
-
# ITTopBar
|
|
7
|
-
|
|
8
|
-
Sticky top navigation bar with glassmorphism effect, logo, breadcrumb-style nav items, and a floating user avatar dropdown. Themed via CSS variables. Designed as a full-width header for dashboards and admin panels.
|
|
9
|
-
|
|
10
|
-
## Props
|
|
11
|
-
|
|
12
|
-
| Prop | Type | Default | Description |
|
|
13
|
-
|------|------|---------|-------------|
|
|
14
|
-
| `logo` | `ReactNode` | — | Optional logo element (e.g. an `<img>` or SVG component). |
|
|
15
|
-
| `logoText` | `string` | — | Text displayed next to the logo as the brand/title. |
|
|
16
|
-
| `centerContent` | `ReactNode` | — | Content rendered in the centered region between the left (logo / nav) and right (user menu) areas — e.g. a global search box. Rendered only when provided, and only from the `lg` breakpoint up. |
|
|
17
|
-
| `children` | `ReactNode` | — | Actions rendered in the right area, immediately before the user menu — e.g. a notification bell, a help link, a theme switcher. The component owns the placement; the caller only supplies the controls. The area renders only when this prop or `userMenu` is provided. |
|
|
18
|
-
| `userMenu` | `object` | — | User dropdown configuration with name, email, avatar, and menu items. |
|
|
19
|
-
| `userMenu.userName` | `string` | — | Display name shown in the trigger button and dropdown header. |
|
|
20
|
-
| `userMenu.userEmail` | `string` | — | User email shown in the trigger button and dropdown header. |
|
|
21
|
-
| `userMenu.userImage` | `string` | — | Optional avatar image URL. Falls back to a user-circle icon when omitted. |
|
|
22
|
-
| `userMenu.menuItems` | `{ label: string; onClick: () => void }[]` | — | Array of dropdown menu actions. Items containing "salir", "cerrar", or "logout" are styled as destructive. |
|
|
23
|
-
| `navItems` | `ITTopBarNavItem[]` | — | Desktop navigation items rendered beside the logo. Each has `id`, `label`, `icon`, and `action`. |
|
|
24
|
-
| `onNavItemClick` | `(id: string) => void` | — | Callback fired when a navigation item is clicked. Receives the item's `id`. |
|
|
25
|
-
| `showMobileMenuButton` | `boolean` | `false` | Whether to show the mobile hamburger menu toggle button. |
|
|
26
|
-
| `onToggleMobileMenu` | `() => void` | — | Callback fired when the mobile menu toggle button is clicked. |
|
|
27
|
-
|
|
28
|
-
## Usage
|
|
29
|
-
|
|
30
|
-
```tsx
|
|
31
|
-
import { ITTopBar } from '@axzydev/axzy_ui_system';
|
|
32
|
-
import { FaChartBar, FaUserCog } from 'react-icons/fa';
|
|
33
|
-
|
|
34
|
-
<ITTopBar
|
|
35
|
-
logoText="AXZY SYSTEM"
|
|
36
|
-
showMobileMenuButton
|
|
37
|
-
userMenu={{
|
|
38
|
-
userName: 'Alejandro G.',
|
|
39
|
-
userEmail: 'alejandro@axzy.io',
|
|
40
|
-
userImage: 'https://i.pravatar.cc/48',
|
|
41
|
-
menuItems: [
|
|
42
|
-
{ label: 'Mi Perfil', onClick: () => {} },
|
|
43
|
-
{ label: 'Configuración', onClick: () => {} },
|
|
44
|
-
{ label: 'Cerrar Sesión', onClick: () => {} },
|
|
45
|
-
],
|
|
46
|
-
}}
|
|
47
|
-
navItems={[
|
|
48
|
-
{ id: '1', label: 'Monitor', icon: <FaChartBar />, action: () => {} },
|
|
49
|
-
{ id: '2', label: 'Admin', icon: <FaUserCog />, action: () => {} },
|
|
50
|
-
]}
|
|
51
|
-
onNavItemClick={(id) => console.log('Nav:', id)}
|
|
52
|
-
onToggleMobileMenu={() => setSidebarOpen(v => !v)}
|
|
53
|
-
/>
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## Notes
|
|
57
|
-
|
|
58
|
-
- The `centerContent` slot renders in a centered `flex-1` (basis 0) region that absorbs all the slack, so the left and right areas stay flush with the row edges. It is `hidden` below `lg`, which leaves the below-`lg` layout exactly as before (logo + user menu).
|
|
59
|
-
- The bar uses a **glassmorphism** backdrop blur effect (`backdrop-blur-xl`), giving it a translucent appearance over scrolling content.
|
|
60
|
-
- Navigation items support **icons** and highlight the active item with the primary color and an underline indicator.
|
|
61
|
-
- The **user menu** dropdown opens on avatar click and closes on outside click (via `useClickOutside` hook).
|
|
62
|
-
- Menu items containing "salir", "cerrar", or "logout" (case-insensitive) are automatically styled red as destructive actions.
|
|
63
|
-
- When `userImage` is omitted, a `FaUserCircle` fallback icon is displayed.
|
|
64
|
-
- **showMobileMenuButton** renders a hamburger icon (`<FaBars />`) for toggling a sidebar — the actual sidebar is managed externally via `onToggleMobileMenu`.
|
|
65
|
-
- All color tokens are sourced from CSS custom properties set by `ITThemeProvider`.
|
|
66
|
-
- The bar is `sticky` by default and sits at `top: 0` with a high z-index.
|
|
67
|
-
|
|
68
|
-
## Stories
|
|
69
|
-
|
|
70
|
-
<Primary />
|
|
71
|
-
<Controls />
|
|
72
|
-
<Stories />
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import ITTopBar from '@/components/organisms/topbar/topbar';
|
|
3
|
-
import { FaShieldAlt, FaChartBar, FaUserCog } from 'react-icons/fa';
|
|
4
|
-
|
|
5
|
-
const meta: Meta<typeof ITTopBar> = {
|
|
6
|
-
title: 'Components/Layout & Navigation/ITTopBar',
|
|
7
|
-
component: ITTopBar,
|
|
8
|
-
parameters: {
|
|
9
|
-
layout: 'fullscreen',
|
|
10
|
-
docs: {
|
|
11
|
-
description: {
|
|
12
|
-
component: 'Un Header moderno, con efecto glassmorphism, sombras suaves y un submenú de usuario flotante con diseño premium. Totalmente integrado a theme.ts.',
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export default meta;
|
|
19
|
-
type Story = StoryObj<typeof ITTopBar>;
|
|
20
|
-
|
|
21
|
-
const mockUserMenu = {
|
|
22
|
-
userName: 'Alejandro G.',
|
|
23
|
-
userEmail: 'alejandro@axzy.io',
|
|
24
|
-
userImage: 'https://i.pravatar.cc/150?u=a042581f4e29026024d',
|
|
25
|
-
menuItems: [
|
|
26
|
-
{ label: 'Mi Perfil', onClick: () => console.log('Perfil clicked') },
|
|
27
|
-
{ label: 'Configuración de Cuenta', onClick: () => console.log('Config clicked') },
|
|
28
|
-
{ label: 'Preferencias', onClick: () => console.log('Preferencias clicked') },
|
|
29
|
-
{ label: 'Cerrar Sesión', onClick: () => console.log('Logout clicked') },
|
|
30
|
-
],
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const mockNavItems = [
|
|
34
|
-
{ id: '1', label: 'Monitor', icon: <FaChartBar />, action: () => console.log('Monitor') },
|
|
35
|
-
{ id: '2', label: 'Seguridad', icon: <FaShieldAlt />, action: () => console.log('Seguridad') },
|
|
36
|
-
{ id: '3', label: 'Admin', icon: <FaUserCog />, action: () => console.log('Admin') },
|
|
37
|
-
];
|
|
38
|
-
|
|
39
|
-
export const Default: Story = {
|
|
40
|
-
args: {
|
|
41
|
-
logoText: 'AXZY SYSTEM',
|
|
42
|
-
showMobileMenuButton: true,
|
|
43
|
-
userMenu: mockUserMenu,
|
|
44
|
-
navItems: mockNavItems,
|
|
45
|
-
onToggleMobileMenu: () => console.log('Toggle Mobile Menu'),
|
|
46
|
-
},
|
|
47
|
-
render: (args) => (
|
|
48
|
-
<div className="h-[400px] w-full bg-slate-50 overflow-y-auto">
|
|
49
|
-
<ITTopBar {...args} />
|
|
50
|
-
<div className="p-8">
|
|
51
|
-
<h1 className="text-2xl font-bold text-slate-800 mb-4">Contenido de ejemplo</h1>
|
|
52
|
-
<p className="text-slate-500 max-w-2xl leading-relaxed mb-6">
|
|
53
|
-
Haz scroll hacia abajo para ver cómo el ITTopBar mantiene su efecto glassmorphism
|
|
54
|
-
(fondo desenfocado) mientras se superpone al contenido. Prueba también a hacer clic
|
|
55
|
-
en el avatar del usuario a la derecha para ver el nuevo menú desplegable flotante.
|
|
56
|
-
</p>
|
|
57
|
-
{[1, 2, 3, 4, 5].map(i => (
|
|
58
|
-
<div key={i} className="h-24 bg-white rounded-xl border border-slate-200 shadow-sm mb-4"></div>
|
|
59
|
-
))}
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
)
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export const WithoutNavigation: Story = {
|
|
66
|
-
args: {
|
|
67
|
-
logoText: 'AXZY Simple',
|
|
68
|
-
showMobileMenuButton: true,
|
|
69
|
-
userMenu: {
|
|
70
|
-
...mockUserMenu,
|
|
71
|
-
userImage: undefined, // Test without avatar image
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
render: (args) => (
|
|
75
|
-
<div className="h-[250px] w-full bg-slate-50">
|
|
76
|
-
<ITTopBar {...args} />
|
|
77
|
-
</div>
|
|
78
|
-
)
|
|
79
|
-
};
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks';
|
|
2
|
-
import * as StoriesData from './tripleFilter.stories';
|
|
3
|
-
|
|
4
|
-
<Meta of={StoriesData} />
|
|
5
|
-
|
|
6
|
-
# ITTripleFilter
|
|
7
|
-
|
|
8
|
-
Generic segmented toggle filter bar for quick data filtering. Renders a row of pill-shaped buttons where exactly one is active at a time. Supports any string or boolean value type, configurable color theming, and full-width mode. Commonly used for "All / Active / Inactive" or similar tri-state filters in tables, lists, and dashboards.
|
|
9
|
-
|
|
10
|
-
## Props
|
|
11
|
-
|
|
12
|
-
| Prop | Type | Default | Description |
|
|
13
|
-
|------|------|---------|-------------|
|
|
14
|
-
| `value` | `T extends string \| boolean` | — | Currently selected value. Must match one of the option values. |
|
|
15
|
-
| `onChange` | `(value: T) => void` | — | Called when the user selects a different option. Receives the new value. |
|
|
16
|
-
| `options` | `ITTripleFilterOption<T>[]` | — | Array of filter options to render (typically 2–4 items). Each has `label: string` and `value: T`. |
|
|
17
|
-
| `color` | `ColorsTypes` | `"primary"` | Color theme for the active indicator. One of `primary`, `secondary`, `success`, `danger`, `warning`, `info`, `purple`, `error`, `gray`. |
|
|
18
|
-
| `className` | `string` | — | Additional CSS classes applied to the outermost container. |
|
|
19
|
-
|
|
20
|
-
## Usage
|
|
21
|
-
|
|
22
|
-
```tsx
|
|
23
|
-
import { ITTripleFilter } from '@axzydev/axzy_ui_system';
|
|
24
|
-
|
|
25
|
-
<ITTripleFilter<string>
|
|
26
|
-
value={status}
|
|
27
|
-
onChange={setStatus}
|
|
28
|
-
options={[
|
|
29
|
-
{ label: 'All', value: 'all' },
|
|
30
|
-
{ label: 'Active', value: 'active' },
|
|
31
|
-
{ label: 'Inactive', value: 'inactive' },
|
|
32
|
-
]}
|
|
33
|
-
color="success"
|
|
34
|
-
/>
|
|
35
|
-
|
|
36
|
-
<ITTripleFilter<boolean>
|
|
37
|
-
value={showActive}
|
|
38
|
-
onChange={setShowActive}
|
|
39
|
-
options={[
|
|
40
|
-
{ label: 'All', value: false },
|
|
41
|
-
{ label: 'Active', value: true },
|
|
42
|
-
]}
|
|
43
|
-
color="danger"
|
|
44
|
-
/>
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Notes
|
|
48
|
-
|
|
49
|
-
- Generic component — works with `string` or `boolean` value types.
|
|
50
|
-
- Active option receives a full background fill matching the `color` prop, while inactive options use a subtle outlined style.
|
|
51
|
-
- Exactly **one** option is always active; selecting the already-active option is a no-op.
|
|
52
|
-
- **color** accepts all semantic color tokens: `primary`, `secondary`, `success`, `danger`, `warning`, `info`, `purple`, `error`, `gray`.
|
|
53
|
-
- Both `error` and `danger` map to the same danger color.
|
|
54
|
-
- Use `className` to control width — for full-width mode, apply `w-full`.
|
|
55
|
-
- The filter bar is rendered as a horizontal inline-flex row; options wrap naturally on narrow containers.
|
|
56
|
-
- Ideal for filter bars above data tables, alongside search inputs and date pickers.
|
|
57
|
-
|
|
58
|
-
## Stories
|
|
59
|
-
|
|
60
|
-
<Primary />
|
|
61
|
-
<Controls />
|
|
62
|
-
<Stories />
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import ITTripleFilter from './tripleFilter';
|
|
3
|
-
|
|
4
|
-
const meta: Meta<typeof ITTripleFilter> = {
|
|
5
|
-
title: 'Components/ITTripleFilter',
|
|
6
|
-
component: ITTripleFilter,
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export default meta;
|
|
10
|
-
type Story = StoryObj<typeof ITTripleFilter>;
|
|
11
|
-
|
|
12
|
-
export const Default: Story = {
|
|
13
|
-
args: {
|
|
14
|
-
value: 'all',
|
|
15
|
-
options: [
|
|
16
|
-
{ label: 'Todos', value: 'all' },
|
|
17
|
-
{ label: 'Activos', value: 'active' },
|
|
18
|
-
{ label: 'Inactivos', value: 'inactive' },
|
|
19
|
-
],
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const Boolean: Story = {
|
|
24
|
-
args: {
|
|
25
|
-
value: true,
|
|
26
|
-
options: [
|
|
27
|
-
{ label: 'Sí', value: true },
|
|
28
|
-
{ label: 'No', value: false },
|
|
29
|
-
],
|
|
30
|
-
},
|
|
31
|
-
};
|