@axzydev/axzy_ui_system 1.4.7 → 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 +2174 -1570
- 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 +232 -19
- package/dist/index.d.ts +232 -19
- package/dist/index.js +1838 -1238
- 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.props.ts +10 -2
- package/src/components/molecules/table/table.tsx +163 -114
- 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.props.ts +3 -2
- package/src/components/organisms/data-table/dataTable.tsx +149 -81
- 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 +9 -3
- 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 +201 -80
- 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/types/table.types.ts +110 -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 -123
- 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 -115
- 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,123 +0,0 @@
|
|
|
1
|
-
import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks';
|
|
2
|
-
import * as StoriesData from './table.stories';
|
|
3
|
-
|
|
4
|
-
<Meta of={StoriesData} />
|
|
5
|
-
|
|
6
|
-
# ITTable
|
|
7
|
-
|
|
8
|
-
Basic data table with column definitions, sorting, and configurable visual variants.
|
|
9
|
-
|
|
10
|
-
## Props
|
|
11
|
-
|
|
12
|
-
| Prop | Type | Default | Description |
|
|
13
|
-
|------|------|---------|-------------|
|
|
14
|
-
| `columns` | `Column<T>[]` | — | Column definitions: key, label, type, sortable, filter, render, actions, plus layout fields `width` (`number` px or CSS `string`), `minWidth` (px), `align` (`"left" \| "center" \| "right"`), `truncate` (ellipsis + native `title`), and `pinned` (`"left" \| "right"`). |
|
|
15
|
-
| `data` | `T[]` | `[]` | Row data array. |
|
|
16
|
-
| `variant` | `"default" \| "striped" \| "bordered"` | `"default"` | Visual style variant. |
|
|
17
|
-
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Font-size preset (does not change padding). |
|
|
18
|
-
| `containerClassName` | `string` | — | CSS classes for the outermost container. |
|
|
19
|
-
| `className` | `string` | — | Declared for API compatibility but **currently not applied** by ITTable. Use `containerClassName` for the outer wrapper. |
|
|
20
|
-
| `itemsPerPageOptions` | `number[]` | `[5, 10, 20]` | Page-size options shown in the paginator. |
|
|
21
|
-
| `defaultItemsPerPage` | `number` | `10` | Initial rows per page. |
|
|
22
|
-
| `title` | `string` | — | Optional heading rendered above the table. |
|
|
23
|
-
| `renderCard` | `(row: T) => ReactNode` | — | Custom card renderer for the cards view. |
|
|
24
|
-
| `defaultView` | `"table" \| "cards"` | `"table"` | Initial view mode. |
|
|
25
|
-
| `showVerticalBorder` | `boolean` | `true` | Show vertical borders between columns. |
|
|
26
|
-
| `verticalBorderClassname` | `string` | — | Custom class for the vertical borders. |
|
|
27
|
-
| `onRowClick` | `(row: T, event: MouseEvent<HTMLElement> \| KeyboardEvent<HTMLElement>) => void` | — | Row/card activation. `MouseEvent` for pointer, `KeyboardEvent` for Enter/Space. Skipped when the interaction starts inside an interactive child. |
|
|
28
|
-
| `layout` | `"auto" \| "fixed"` | `"auto"` | Table layout algorithm. `"fixed"` honors column `width` values and drops the `min-w-max` / `min-w-[150px]` floors so content no longer forces horizontal scrolling. |
|
|
29
|
-
| `density` | `"compact" \| "normal" \| "comfortable"` | `"normal"` | Cell padding / row-height preset. Independent of `size`, which only controls font-size. |
|
|
30
|
-
| `autoCardBreakpoint` | `number` | `0` | Container width (px) below which the table automatically falls back to the cards view. `0` disables the fallback. |
|
|
31
|
-
| `virtualized` | `boolean` | `false` | Renders only the visible row window with spacer rows preserving scroll height. Table view only; cards view is never virtualized. |
|
|
32
|
-
| `virtualizedMaxHeight` | `number` | `400` | Max height (px) of the virtualized scroll container. Only used when `virtualized` is true. |
|
|
33
|
-
| `rowHeight` | `number` | `getRowHeight(size, density)` | Assumed uniform row height (px). Size-aware: `size="md"` baseline is 33 / 45 / 53 for compact / normal / comfortable; `size` shifts it by the font-size line box (sm 16px / md 20px / lg 28px). |
|
|
34
|
-
| `overscan` | `number` | `5` | Extra rows rendered above and below the viewport to avoid blank gaps. |
|
|
35
|
-
| `stickyHeader` | `boolean` | `false` | Keeps header cells sticky while the virtualized body scrolls. Only effective when `virtualized` is true. |
|
|
36
|
-
|
|
37
|
-
### Column fields
|
|
38
|
-
|
|
39
|
-
| Field | Type | Default | Description |
|
|
40
|
-
|-------|------|---------|-------------|
|
|
41
|
-
| `width` | `number \| string` | — | Fixed column width. `number` = px, `string` = any CSS length (e.g. `"20%"`). A `<colgroup>` is only emitted when at least one column sets it. |
|
|
42
|
-
| `minWidth` | `number` | — | Minimum column width in px, applied to header and body cells via inline style. |
|
|
43
|
-
| `align` | `"left" \| "center" \| "right"` | `"left"` | Horizontal alignment of the column's header and cells. |
|
|
44
|
-
| `truncate` | `boolean` | `false` | Truncates overflowing cell content with an ellipsis and exposes the raw string/number via the native `title` attribute. |
|
|
45
|
-
| `pinned` | `"left" \| "right"` | `undefined` | Freezes the column to the given horizontal edge while the table scrolls sideways. `"left"` keeps it flush to the left edge, `"right"` to the right edge. Omit to leave the column unpinned (identical to the previous behavior). Offsets accumulate from each preceding pinned column's pixel `width` / `minWidth`, so give every pinned column of a side a pixel `width`. The pinned cell gets an opaque background (row background + row hover) and a 1px separator shadow on its frozen edge. One pinned column per side is the supported contract. |
|
|
46
|
-
| `filter` | `true \| "catalog" \| "search" \| "date" \| "date-range"` | `false` | Filter control rendered in the header. `true` = text/number input (or boolean toggle when `type: "boolean"`); `"catalog"` = `ITSelect` fed by `catalogOptions.data`; `"search"` = `ITSearchSelect` typeahead fed by `catalogOptions.data` (optional `catalogOptions.onSearch` for server-side search); `"date"` / `"date-range"` = `ITDatePicker` single/range, bounded by `dateFilterOptions`. |
|
|
47
|
-
|
|
48
|
-
## Usage
|
|
49
|
-
|
|
50
|
-
```tsx
|
|
51
|
-
import { ITTable } from '@axzydev/axzy_ui_system';
|
|
52
|
-
|
|
53
|
-
const columns = [
|
|
54
|
-
{ key: 'name', label: 'Name', type: 'string', sortable: true, filter: true },
|
|
55
|
-
{ key: 'role', label: 'Role', type: 'string', filter: 'catalog', catalogOptions: { data: roles } },
|
|
56
|
-
{ key: 'status', label: 'Status', type: 'boolean', filter: true },
|
|
57
|
-
];
|
|
58
|
-
const data = [
|
|
59
|
-
{ name: 'Alice', role: 'ADMIN', status: true },
|
|
60
|
-
{ name: 'Bob', role: 'EDITOR', status: false },
|
|
61
|
-
];
|
|
62
|
-
|
|
63
|
-
<ITTable columns={columns} data={data} title="Users" />
|
|
64
|
-
<ITTable columns={columns} data={data} variant="striped" size="sm" defaultItemsPerPage={5} />
|
|
65
|
-
<ITTable
|
|
66
|
-
columns={columns}
|
|
67
|
-
data={data}
|
|
68
|
-
defaultView="cards"
|
|
69
|
-
onRowClick={(row, event) => console.log(row, event.type)}
|
|
70
|
-
/>
|
|
71
|
-
|
|
72
|
-
// Filter modes: ITSearchSelect typeahead + ITDatePicker single / range
|
|
73
|
-
const filterColumns = [
|
|
74
|
-
{ key: 'role', label: 'Role', type: 'string', filter: 'search', catalogOptions: { data: roles } },
|
|
75
|
-
{ key: 'lastLogin', label: 'Last login', type: 'date', filter: 'date', dateFilterOptions: { maxDate: new Date() } },
|
|
76
|
-
{ key: 'hiredAt', label: 'Hired', type: 'date', filter: 'date-range', dateFilterOptions: { maxDate: new Date() } },
|
|
77
|
-
];
|
|
78
|
-
|
|
79
|
-
<ITTable columns={filterColumns} data={data} />
|
|
80
|
-
|
|
81
|
-
// No horizontal scroll: fixed layout + per-column widths + truncation
|
|
82
|
-
const fixedColumns = [
|
|
83
|
-
{ key: 'name', label: 'Name', type: 'string', width: '30%', truncate: true },
|
|
84
|
-
{ key: 'email', label: 'Email', type: 'string', width: 220, truncate: true },
|
|
85
|
-
{ key: 'role', label: 'Role', type: 'string', width: 140, align: 'center' },
|
|
86
|
-
];
|
|
87
|
-
|
|
88
|
-
<ITTable columns={fixedColumns} data={data} layout="fixed" density="compact" />
|
|
89
|
-
|
|
90
|
-
// Pinned columns: freeze the first column left and the last one right
|
|
91
|
-
const pinnedColumns = [
|
|
92
|
-
{ key: 'id', label: 'ID', type: 'number', width: 72, pinned: 'left' },
|
|
93
|
-
{ key: 'name', label: 'Name', type: 'string', width: 240, truncate: true },
|
|
94
|
-
{ key: 'actions', label: 'Actions', type: 'actions', width: 104, pinned: 'right' },
|
|
95
|
-
];
|
|
96
|
-
|
|
97
|
-
<ITTable columns={pinnedColumns} data={data} layout="fixed" density="compact" />
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## Notes
|
|
101
|
-
|
|
102
|
-
- `columns[].render` provides custom cell rendering via render function
|
|
103
|
-
- `columns[].sortable` enables column header sort toggles
|
|
104
|
-
- `columns[].filter` supports `true` (text/number input, or boolean toggle for `type: "boolean"`), `"catalog"` (`ITSelect`), `"search"` (`ITSearchSelect` typeahead; add `catalogOptions.onSearch` for server-side search), and `"date"` / `"date-range"` (`ITDatePicker`; bound with `dateFilterOptions: { minDate, maxDate }`). Filtering is client-side: `"date"` matches the whole day, `"date-range"` includes both ends (`startOfDay` / `endOfDay`).
|
|
105
|
-
- `onRowClick` fires in **both** the table and cards views. The event is a `MouseEvent` for pointer interaction and a `KeyboardEvent` for Enter/Space activation.
|
|
106
|
-
- Clicks/keys that start inside an interactive child (`button`, `a`, `input`, `select`, `textarea`, `[role="button"]`, `[role="link"]`, `[data-row-click-ignore]`) do **not** trigger `onRowClick`.
|
|
107
|
-
- When `onRowClick` is omitted no `cursor-pointer`, focus ring, `tabIndex`, or `role` is added.
|
|
108
|
-
- `density` controls padding/row height (`compact` 33px / `normal` 45px / `comfortable` 53px at `size="md"`); `size` changes font-size and shifts the row height by the line box (sm 16px / md 20px / lg 28px).
|
|
109
|
-
- **Anti horizontal scroll recipe:** `layout="fixed"` + a `width` on every column + `truncate` on long text + `density="compact"`. `width` accepts a `number` (px) or any CSS length string (`"20%"`, `"12rem"`). A `<colgroup>` is only emitted when at least one column defines a `width`.
|
|
110
|
-
- **Pinned columns:** set `columns[].pinned: "left" | "right"` to freeze a column to that edge during horizontal scroll (`position: sticky`; the wrapper needs no `relative`). Omitting `pinned` renders exactly as before. Sticky offsets accumulate from each preceding pinned column's pixel `width` / `minWidth`; a non-px width contributes `minWidth ?? 0`, so give every pinned column of a side a pixel `width`. The pinned cell gets an opaque background (`--color-table-rowBg`, row hover `--color-table-rowHover`) and a 1px separator shadow on its frozen edge. Z-layering: pinned body cell `z-[1]` < sticky header `z-10` < pinned header `z-[15]`; it composes with `stickyHeader` and `virtualized`. One pinned column per side is the supported contract. Known limitation: with `variant="striped"` the opaque pinned background covers that column's stripe tint.
|
|
111
|
-
- With the default `layout="auto"`, `min-w-max` stays active so column widths can still reflow as different cell content enters the window during vertical scroll. Use `layout="fixed"` + column `width` for stable widths.
|
|
112
|
-
- `autoCardBreakpoint` swaps to the cards view when the container (not the viewport) is narrower than the given px value; the Table toggle is disabled while forced, the Cards toggle stays enabled.
|
|
113
|
-
- **Virtualization** applies to the **table view only** — the cards view is never virtualized. It only pays off with a large page size: raise `defaultItemsPerPage` and `itemsPerPageOptions` (defaults are `10` and `[5, 10, 20]`). Rows are assumed to have a uniform `rowHeight`; use `truncate` + `layout="fixed"` for predictable heights.
|
|
114
|
-
- Scroll resets to the top on page or items-per-page change, but **not** on filter change (known limitation). `aria-rowcount` reflects the current page (+1), not the whole dataset, because pagination is independent.
|
|
115
|
-
- `virtualizedMaxHeight`, `rowHeight`, `overscan`, and `stickyHeader` only take effect when `virtualized` is true. `stickyHeader` makes each `<th>` sticky using the `--color-table-headerBg` token (fallback `#f8fafc`).
|
|
116
|
-
- `TableDensity` is exported from the package. `ITSearchTable` does **not** support `layout`, `density`, `autoCardBreakpoint`, `virtualized`, or per-column `width` — do not assume parity.
|
|
117
|
-
- Three visual variants: default (no borders), striped (alternating rows), bordered (full grid)
|
|
118
|
-
|
|
119
|
-
## Stories
|
|
120
|
-
|
|
121
|
-
<Primary />
|
|
122
|
-
<Controls />
|
|
123
|
-
<Stories />
|
|
@@ -1,402 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import ITTable from "@/components/molecules/table/table";
|
|
3
|
-
import { Column } from "./table.props";
|
|
4
|
-
import ITBadget from "@/components/atoms/badget/badget";
|
|
5
|
-
import ITButton from "@/components/atoms/button/button";
|
|
6
|
-
import { FaTrash } from "react-icons/fa";
|
|
7
|
-
import { useState } from "react";
|
|
8
|
-
|
|
9
|
-
const meta: Meta<typeof ITTable> = {
|
|
10
|
-
title: "Components/Data Display/ITTable",
|
|
11
|
-
component: ITTable,
|
|
12
|
-
parameters: {
|
|
13
|
-
layout: "padded", // Tables need more space
|
|
14
|
-
},
|
|
15
|
-
argTypes: {
|
|
16
|
-
variant: {
|
|
17
|
-
control: "select",
|
|
18
|
-
options: ["default", "striped", "bordered"],
|
|
19
|
-
},
|
|
20
|
-
size: {
|
|
21
|
-
control: "select",
|
|
22
|
-
options: ["sm", "md", "lg"],
|
|
23
|
-
},
|
|
24
|
-
density: {
|
|
25
|
-
control: "select",
|
|
26
|
-
options: ["compact", "normal", "comfortable"],
|
|
27
|
-
},
|
|
28
|
-
layout: {
|
|
29
|
-
control: "select",
|
|
30
|
-
options: ["auto", "fixed"],
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export default meta;
|
|
36
|
-
type Story = StoryObj<typeof ITTable>;
|
|
37
|
-
|
|
38
|
-
// --- MOCK DATA & COLUMNS ---
|
|
39
|
-
|
|
40
|
-
interface User {
|
|
41
|
-
id: number;
|
|
42
|
-
name: string;
|
|
43
|
-
email: string;
|
|
44
|
-
roleId: number;
|
|
45
|
-
balance: number;
|
|
46
|
-
isActive: boolean;
|
|
47
|
-
lastLogin: string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const mockRoles = [
|
|
51
|
-
{ id: 1, name: "Administrator" },
|
|
52
|
-
{ id: 2, name: "Editor" },
|
|
53
|
-
{ id: 3, name: "Viewer" },
|
|
54
|
-
];
|
|
55
|
-
|
|
56
|
-
const generateMockData = (count: number): User[] => {
|
|
57
|
-
return Array.from({ length: count }, (_, i) => ({
|
|
58
|
-
id: i + 1,
|
|
59
|
-
name: `User ${i + 1}`,
|
|
60
|
-
email: `user${i + 1}@example.com`,
|
|
61
|
-
roleId: (i % 3) + 1,
|
|
62
|
-
balance: Math.random() * 10000,
|
|
63
|
-
isActive: i % 4 !== 0,
|
|
64
|
-
lastLogin: new Date(Date.now() - Math.random() * 10000000000).toISOString(),
|
|
65
|
-
}));
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const mockData = generateMockData(25);
|
|
69
|
-
|
|
70
|
-
const basicColumns: Column<User>[] = [
|
|
71
|
-
{ key: "id", label: "ID", type: "number" },
|
|
72
|
-
{ key: "name", label: "Name", type: "string" },
|
|
73
|
-
{ key: "email", label: "Email", type: "string" },
|
|
74
|
-
];
|
|
75
|
-
|
|
76
|
-
const advancedColumns: Column<User>[] = [
|
|
77
|
-
{ key: "id", label: "ID", type: "number", sortable: true, filter: true },
|
|
78
|
-
{ key: "name", label: "Name", type: "string", sortable: true, filter: true },
|
|
79
|
-
{ key: "email", label: "Email", type: "string", sortable: true, filter: true },
|
|
80
|
-
{
|
|
81
|
-
key: "roleId",
|
|
82
|
-
label: "Role",
|
|
83
|
-
type: "catalog",
|
|
84
|
-
sortable: true,
|
|
85
|
-
filter: "catalog",
|
|
86
|
-
catalogOptions: { data: mockRoles }
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
key: "balance",
|
|
90
|
-
label: "Balance",
|
|
91
|
-
type: "number",
|
|
92
|
-
sortable: true,
|
|
93
|
-
currencyMX: true
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
key: "isActive",
|
|
97
|
-
label: "Status",
|
|
98
|
-
type: "boolean",
|
|
99
|
-
sortable: true,
|
|
100
|
-
filter: true,
|
|
101
|
-
render: (row) => (
|
|
102
|
-
<ITBadget
|
|
103
|
-
label={row.isActive ? "Active" : "Inactive"}
|
|
104
|
-
color={row.isActive ? "success" : "danger"}
|
|
105
|
-
/>
|
|
106
|
-
)
|
|
107
|
-
},
|
|
108
|
-
];
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
// --- STORIES ---
|
|
112
|
-
|
|
113
|
-
export const Default: Story = {
|
|
114
|
-
args: {
|
|
115
|
-
columns: basicColumns,
|
|
116
|
-
data: mockData.slice(0, 5), // Just a few
|
|
117
|
-
title: "Basic Users Table",
|
|
118
|
-
} as any,
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
export const WithPagination: Story = {
|
|
122
|
-
args: {
|
|
123
|
-
columns: basicColumns,
|
|
124
|
-
data: mockData,
|
|
125
|
-
title: "Paginated Table",
|
|
126
|
-
defaultItemsPerPage: 5,
|
|
127
|
-
itemsPerPageOptions: [5, 10, 20],
|
|
128
|
-
} as any,
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
export const WithSortingAndFiltering: Story = {
|
|
132
|
-
args: {
|
|
133
|
-
columns: advancedColumns.map(col => ({ ...col, render: undefined })), // Remove custom render to show raw formatting
|
|
134
|
-
data: mockData,
|
|
135
|
-
title: "Data Management (Sort & Filter)",
|
|
136
|
-
} as any,
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
export const CustomRendering: Story = {
|
|
140
|
-
args: {
|
|
141
|
-
columns: advancedColumns,
|
|
142
|
-
data: mockData,
|
|
143
|
-
title: "Custom Rendering (Badges & Catalogs)",
|
|
144
|
-
} as any,
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
// Wrapper for interactive actions
|
|
148
|
-
const ActionsTableWrapper = (args: any) => {
|
|
149
|
-
const [data, setData] = useState(mockData.slice(0, 5));
|
|
150
|
-
|
|
151
|
-
const actions: Column<User> = {
|
|
152
|
-
key: "actions",
|
|
153
|
-
label: "Actions",
|
|
154
|
-
type: "actions",
|
|
155
|
-
actions: (row) => (
|
|
156
|
-
<>
|
|
157
|
-
<ITButton size="sm" variant="text" color="danger" ariaLabel="Delete" onClick={() => setData(d => d.filter(item => item.id !== row.id))}>
|
|
158
|
-
<FaTrash />
|
|
159
|
-
</ITButton>
|
|
160
|
-
</>
|
|
161
|
-
),
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
return <ITTable {...args} data={data} columns={[...basicColumns, actions]} />;
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
export const WithActions: Story = {
|
|
168
|
-
render: (args) => <ActionsTableWrapper {...args} />,
|
|
169
|
-
args: {
|
|
170
|
-
title: "Table with Actions",
|
|
171
|
-
} as any,
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
export const EmptyState: Story = {
|
|
175
|
-
args: {
|
|
176
|
-
columns: basicColumns,
|
|
177
|
-
data: [],
|
|
178
|
-
title: "No Data Available",
|
|
179
|
-
} as any,
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
// Wrapper for clickable rows/cards
|
|
183
|
-
const RowClickWrapper = (args: any) => {
|
|
184
|
-
const [selected, setSelected] = useState<User | null>(null);
|
|
185
|
-
|
|
186
|
-
return (
|
|
187
|
-
<div className="space-y-3">
|
|
188
|
-
<p className="text-sm font-medium text-slate-500">
|
|
189
|
-
{selected
|
|
190
|
-
? `Selected: ${selected.name} (id ${selected.id})`
|
|
191
|
-
: "Click a row/card or press Enter/Space while focused"}
|
|
192
|
-
</p>
|
|
193
|
-
<ITTable
|
|
194
|
-
{...args}
|
|
195
|
-
onRowClick={(row: User) => setSelected(row)}
|
|
196
|
-
/>
|
|
197
|
-
</div>
|
|
198
|
-
);
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
export const WithRowClick: Story = {
|
|
202
|
-
render: (args) => <RowClickWrapper {...args} />,
|
|
203
|
-
args: {
|
|
204
|
-
columns: basicColumns,
|
|
205
|
-
data: mockData.slice(0, 5),
|
|
206
|
-
title: "Clickable Rows",
|
|
207
|
-
} as any,
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
export const WithRowClickCards: Story = {
|
|
211
|
-
render: (args) => <RowClickWrapper {...args} />,
|
|
212
|
-
args: {
|
|
213
|
-
columns: basicColumns,
|
|
214
|
-
data: mockData.slice(0, 5),
|
|
215
|
-
title: "Clickable Cards",
|
|
216
|
-
defaultView: "cards",
|
|
217
|
-
} as any,
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
// --- CONFIGURABLE LAYOUT / DENSITY ---
|
|
221
|
-
|
|
222
|
-
const longCellData: User[] = [
|
|
223
|
-
{
|
|
224
|
-
id: 1,
|
|
225
|
-
name: "Extraordinariamente Largo Nombre de Usuario Que No Cabe",
|
|
226
|
-
email: "usuario.con.un.correo.extremadamente.largo@example-enterprise-domain.com",
|
|
227
|
-
roleId: 1,
|
|
228
|
-
balance: 28400,
|
|
229
|
-
isActive: true,
|
|
230
|
-
lastLogin: "2026-07-18T09:30:00",
|
|
231
|
-
},
|
|
232
|
-
{
|
|
233
|
-
id: 2,
|
|
234
|
-
name: "Otra Persona Con Un Nombre Bastante Extenso Para Probar",
|
|
235
|
-
email: "otra.persona.con.correo.extenso@example-enterprise-domain.com",
|
|
236
|
-
roleId: 2,
|
|
237
|
-
balance: 15200,
|
|
238
|
-
isActive: false,
|
|
239
|
-
lastLogin: "2026-07-17T14:22:00",
|
|
240
|
-
},
|
|
241
|
-
];
|
|
242
|
-
|
|
243
|
-
const fixedColumns: Column<User>[] = [
|
|
244
|
-
{ key: "id", label: "ID", type: "number", width: 64, minWidth: 48, align: "center" },
|
|
245
|
-
{ key: "name", label: "Name", type: "string", width: "35%", truncate: true },
|
|
246
|
-
{ key: "email", label: "Email", type: "string", width: "45%", truncate: true },
|
|
247
|
-
];
|
|
248
|
-
|
|
249
|
-
export const CompactDensity: Story = {
|
|
250
|
-
args: {
|
|
251
|
-
columns: advancedColumns.map(col => ({ ...col, render: undefined })),
|
|
252
|
-
data: mockData,
|
|
253
|
-
title: "Compact Density",
|
|
254
|
-
density: "compact",
|
|
255
|
-
defaultItemsPerPage: 8,
|
|
256
|
-
} as any,
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
export const FixedLayoutWithWidths: Story = {
|
|
260
|
-
render: (args: any) => (
|
|
261
|
-
<div style={{ width: 480 }} className="rounded-lg border border-dashed border-slate-300">
|
|
262
|
-
<ITTable {...args} />
|
|
263
|
-
</div>
|
|
264
|
-
),
|
|
265
|
-
args: {
|
|
266
|
-
columns: fixedColumns,
|
|
267
|
-
data: longCellData,
|
|
268
|
-
title: "Fixed layout · no horizontal scroll",
|
|
269
|
-
layout: "fixed",
|
|
270
|
-
density: "compact",
|
|
271
|
-
defaultItemsPerPage: 5,
|
|
272
|
-
} as any,
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
// Pixel widths force the total past the 520px wrapper, so the ID (left) and
|
|
276
|
-
// Actions (right) columns stay frozen while the middle scrolls sideways.
|
|
277
|
-
const pinnedColumns: Column<User>[] = [
|
|
278
|
-
{ key: "id", label: "ID", type: "number", width: 72, minWidth: 56, align: "center", pinned: "left" },
|
|
279
|
-
{ key: "name", label: "Name", type: "string", width: 240, truncate: true },
|
|
280
|
-
{ key: "email", label: "Email", type: "string", width: 280, truncate: true },
|
|
281
|
-
{ key: "balance", label: "Balance", type: "number", width: 160, currencyMX: true },
|
|
282
|
-
{ key: "lastLogin", label: "Last login", type: "string", width: 160, truncate: true },
|
|
283
|
-
{
|
|
284
|
-
key: "isActive",
|
|
285
|
-
label: "Status",
|
|
286
|
-
type: "boolean",
|
|
287
|
-
width: 104,
|
|
288
|
-
align: "center",
|
|
289
|
-
},
|
|
290
|
-
{
|
|
291
|
-
key: "actions",
|
|
292
|
-
label: "Actions",
|
|
293
|
-
type: "actions",
|
|
294
|
-
width: 104,
|
|
295
|
-
pinned: "right",
|
|
296
|
-
actions: () => (
|
|
297
|
-
<ITButton size="sm" variant="text" color="danger" ariaLabel="Delete">
|
|
298
|
-
<FaTrash />
|
|
299
|
-
</ITButton>
|
|
300
|
-
),
|
|
301
|
-
},
|
|
302
|
-
];
|
|
303
|
-
|
|
304
|
-
export const PinnedColumns: Story = {
|
|
305
|
-
render: (args: any) => (
|
|
306
|
-
<div style={{ width: 520 }} className="rounded-lg border border-dashed border-slate-300">
|
|
307
|
-
<ITTable {...args} />
|
|
308
|
-
</div>
|
|
309
|
-
),
|
|
310
|
-
args: {
|
|
311
|
-
columns: pinnedColumns,
|
|
312
|
-
data: mockData.slice(0, 6),
|
|
313
|
-
title: "Pinned left (ID) & right (Actions)",
|
|
314
|
-
layout: "fixed",
|
|
315
|
-
density: "compact",
|
|
316
|
-
defaultItemsPerPage: 6,
|
|
317
|
-
} as any,
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
export const AutoCardsNarrowContainer: Story = {
|
|
321
|
-
render: (args: any) => (
|
|
322
|
-
<div style={{ width: 420 }} className="rounded-lg border border-dashed border-slate-300">
|
|
323
|
-
<ITTable {...args} />
|
|
324
|
-
</div>
|
|
325
|
-
),
|
|
326
|
-
args: {
|
|
327
|
-
columns: basicColumns,
|
|
328
|
-
data: mockData.slice(0, 6),
|
|
329
|
-
title: "Auto cards under 640px",
|
|
330
|
-
autoCardBreakpoint: 640,
|
|
331
|
-
defaultItemsPerPage: 6,
|
|
332
|
-
} as any,
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
// --- VIRTUALIZATION ---
|
|
336
|
-
|
|
337
|
-
const virtualColumns: Column<User>[] = [
|
|
338
|
-
{ key: "id", label: "ID", type: "number", width: 72, minWidth: 56, align: "center" },
|
|
339
|
-
{ key: "name", label: "Name", type: "string", width: "30%", truncate: true },
|
|
340
|
-
{ key: "email", label: "Email", type: "string", width: "40%", truncate: true },
|
|
341
|
-
{
|
|
342
|
-
key: "roleId",
|
|
343
|
-
label: "Role",
|
|
344
|
-
type: "catalog",
|
|
345
|
-
width: "30%",
|
|
346
|
-
truncate: true,
|
|
347
|
-
catalogOptions: { data: mockRoles },
|
|
348
|
-
},
|
|
349
|
-
];
|
|
350
|
-
|
|
351
|
-
export const VirtualizedLargeDataset: Story = {
|
|
352
|
-
render: (args: any) => (
|
|
353
|
-
<div className="space-y-2">
|
|
354
|
-
<p className="text-xs text-slate-500">
|
|
355
|
-
250 rows · only the visible window is mounted (~10–20 <tr> + at most 2 spacer rows)
|
|
356
|
-
</p>
|
|
357
|
-
<ITTable {...args} />
|
|
358
|
-
</div>
|
|
359
|
-
),
|
|
360
|
-
args: {
|
|
361
|
-
columns: virtualColumns,
|
|
362
|
-
data: generateMockData(250),
|
|
363
|
-
title: "Virtualized · 250 rows",
|
|
364
|
-
virtualized: true,
|
|
365
|
-
stickyHeader: true,
|
|
366
|
-
layout: "fixed",
|
|
367
|
-
density: "compact",
|
|
368
|
-
virtualizedMaxHeight: 360,
|
|
369
|
-
defaultItemsPerPage: 250,
|
|
370
|
-
itemsPerPageOptions: [50, 100, 250],
|
|
371
|
-
} as any,
|
|
372
|
-
};
|
|
373
|
-
|
|
374
|
-
// --- COLUMN FILTER MODES ---
|
|
375
|
-
|
|
376
|
-
const filterModeColumns: Column<User>[] = [
|
|
377
|
-
{ key: "name", label: "Name", type: "string", filter: true },
|
|
378
|
-
{
|
|
379
|
-
key: "roleId",
|
|
380
|
-
label: "Role (ITSearchSelect)",
|
|
381
|
-
type: "catalog",
|
|
382
|
-
filter: "search",
|
|
383
|
-
catalogOptions: { data: mockRoles },
|
|
384
|
-
},
|
|
385
|
-
{
|
|
386
|
-
key: "lastLogin",
|
|
387
|
-
label: "Last login (ITDatePicker range)",
|
|
388
|
-
type: "date",
|
|
389
|
-
filter: "date-range",
|
|
390
|
-
dateFilterOptions: { maxDate: new Date() },
|
|
391
|
-
render: (row) => new Date(row.lastLogin).toLocaleDateString("es-MX"),
|
|
392
|
-
},
|
|
393
|
-
];
|
|
394
|
-
|
|
395
|
-
export const WithSearchAndDateFilters: Story = {
|
|
396
|
-
args: {
|
|
397
|
-
columns: filterModeColumns,
|
|
398
|
-
data: generateMockData(25),
|
|
399
|
-
title: "Filtros: ITSearchSelect + ITDatePicker (rango)",
|
|
400
|
-
defaultItemsPerPage: 8,
|
|
401
|
-
} as any,
|
|
402
|
-
};
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks';
|
|
2
|
-
import * as StoriesData from './tabs.stories';
|
|
3
|
-
|
|
4
|
-
<Meta of={StoriesData} />
|
|
5
|
-
|
|
6
|
-
# ITTabs
|
|
7
|
-
|
|
8
|
-
Tab navigation component with multiple visual variants, orientation options, and color themes.
|
|
9
|
-
|
|
10
|
-
## Props
|
|
11
|
-
|
|
12
|
-
| Prop | Type | Default | Description |
|
|
13
|
-
|------|------|---------|-------------|
|
|
14
|
-
| `tabs` | `{ label: string; icon?: ReactNode; disabled?: boolean }[]` | — | Tab definitions |
|
|
15
|
-
| `activeTab` | `number` | `0` | Zero-indexed active tab |
|
|
16
|
-
| `onChange` | `(index: number) => void` | — | Tab change handler |
|
|
17
|
-
| `variant` | `'default' \| 'pills' \| 'underline' \| 'enclosed'` | `'default'` | Visual style variant |
|
|
18
|
-
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Tab layout orientation |
|
|
19
|
-
| `fullWidth` | `boolean` | `false` | Stretch tabs to fill container |
|
|
20
|
-
| `color` | `'primary' \| 'secondary' \| 'success' \| 'warning' \| 'danger' \| 'info' \| 'neutral'` | `'primary'` | Color theme |
|
|
21
|
-
|
|
22
|
-
## Usage
|
|
23
|
-
|
|
24
|
-
```tsx
|
|
25
|
-
import { ITTabs } from '@axzydev/axzy_ui_system';
|
|
26
|
-
|
|
27
|
-
const tabs = [
|
|
28
|
-
{ label: 'General' },
|
|
29
|
-
{ label: 'Security', icon: <LockIcon /> },
|
|
30
|
-
{ label: 'Billing', disabled: true },
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
<ITTabs tabs={tabs} activeTab={0} onChange={(i) => console.log(i)} />
|
|
34
|
-
<ITTabs tabs={tabs} variant="pills" fullWidth />
|
|
35
|
-
<ITTabs tabs={tabs} variant="underline" orientation="vertical" color="success" />
|
|
36
|
-
<ITTabs tabs={tabs} variant="enclosed" />
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Notes
|
|
40
|
-
|
|
41
|
-
- Four visual variants: default, pills, underline, enclosed
|
|
42
|
-
- Horizontal or vertical tab layout
|
|
43
|
-
- `fullWidth` makes tabs span the full container width
|
|
44
|
-
- Icons rendered alongside tab labels via the `icon` prop
|
|
45
|
-
- Individual tabs can be disabled
|
|
46
|
-
- Seven color themes available
|
|
47
|
-
|
|
48
|
-
## Stories
|
|
49
|
-
|
|
50
|
-
<Primary />
|
|
51
|
-
<Controls />
|
|
52
|
-
<Stories />
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import ITTabs from '@/components/molecules/tabs/tabs';
|
|
3
|
-
|
|
4
|
-
const meta: Meta<typeof ITTabs> = {
|
|
5
|
-
title: 'Components/ITTabs',
|
|
6
|
-
component: ITTabs,
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export default meta;
|
|
10
|
-
type Story = StoryObj<typeof ITTabs>;
|
|
11
|
-
|
|
12
|
-
export const Line: Story = {
|
|
13
|
-
args: {
|
|
14
|
-
variant: 'line',
|
|
15
|
-
items: [
|
|
16
|
-
{ id: '1', label: 'Tab 1', content: <div className="p-4">Content 1</div> },
|
|
17
|
-
{ id: '2', label: 'Tab 2', content: <div className="p-4">Content 2</div> },
|
|
18
|
-
{ id: '3', label: 'Disabled', content: <div>X</div>, disabled: true },
|
|
19
|
-
],
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const Pill: Story = {
|
|
24
|
-
args: {
|
|
25
|
-
variant: 'pill',
|
|
26
|
-
items: [
|
|
27
|
-
{ id: '1', label: 'Overview', content: <div className="p-4">Dashboard Overview</div> },
|
|
28
|
-
{ id: '2', label: 'Settings', content: <div className="p-4">Account Settings</div> },
|
|
29
|
-
],
|
|
30
|
-
},
|
|
31
|
-
};
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks';
|
|
2
|
-
import * as StoriesData from './timePicker.stories';
|
|
3
|
-
|
|
4
|
-
<Meta of={StoriesData} />
|
|
5
|
-
|
|
6
|
-
# ITTimePicker
|
|
7
|
-
|
|
8
|
-
Time selection input with a dual-column dropdown (hours / minutes). Supports manual typing with auto-formatting to `HH:MM`, validation, 12h and 24h format display, configurable minute steps, and keyboard-friendly picker navigation.
|
|
9
|
-
|
|
10
|
-
## Props
|
|
11
|
-
|
|
12
|
-
| Prop | Type | Default | Description |
|
|
13
|
-
|------|------|---------|-------------|
|
|
14
|
-
| `name` | `string` | — | Form field name attribute and key for the change event. |
|
|
15
|
-
| `value` | `string` | — | Controlled time value in `"HH:MM"` format. |
|
|
16
|
-
| `label` | `string` | — | Label text displayed above the input. |
|
|
17
|
-
| `placeholder` | `string` | `"HH:MM"` | Placeholder text when no value is set. |
|
|
18
|
-
| `onChange` | `(e: any) => void` | — | Callback fired on valid time selection, receives event-like object with `target.name` and `target.value`. |
|
|
19
|
-
| `onBlur` | `(e: any) => void` | — | Callback fired when the input loses focus. |
|
|
20
|
-
| `required` | `boolean` | — | Marks the field as required. |
|
|
21
|
-
| `touched` | `boolean` | — | Whether the input has been interacted with. |
|
|
22
|
-
| `error` | `string \| boolean` | — | Validation error message or boolean to show error state. |
|
|
23
|
-
| `disabled` | `boolean` | `false` | Disables the time picker when true. |
|
|
24
|
-
| `className` | `string` | — | Additional CSS classes for the wrapper. |
|
|
25
|
-
| `size` | `SizesTypes` | `"md"` | Size preset: `"sm"`, `"md"`, `"lg"`. |
|
|
26
|
-
| `variant` | `"primary" \| "secondary" \| "danger" \| "success" \| "warning" \| "info" \| "purple"` | `"primary"` | Style variant for the input. |
|
|
27
|
-
| `color` | `"primary" \| "secondary" \| "danger" \| "success" \| "warning" \| "info" \| "purple" \| string` | `"primary"` | Theme color used for the dropdown highlight and confirm button. Accepts semantic keys or raw hex. |
|
|
28
|
-
|
|
29
|
-
## Usage
|
|
30
|
-
|
|
31
|
-
```tsx
|
|
32
|
-
import { ITTimePicker } from '@axzydev/axzy_ui_system';
|
|
33
|
-
|
|
34
|
-
<ITTimePicker
|
|
35
|
-
name="startTime"
|
|
36
|
-
label="Start Time"
|
|
37
|
-
value={startTime}
|
|
38
|
-
onChange={(e) => setStartTime(e.target.value)}
|
|
39
|
-
color="primary"
|
|
40
|
-
/>
|
|
41
|
-
|
|
42
|
-
<ITTimePicker
|
|
43
|
-
name="endTime"
|
|
44
|
-
label="End Time"
|
|
45
|
-
value={endTime}
|
|
46
|
-
onChange={(e) => setEndTime(e.target.value)}
|
|
47
|
-
error={isInvalid ? "Invalid time range" : undefined}
|
|
48
|
-
touched={true}
|
|
49
|
-
/>
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Notes
|
|
53
|
-
|
|
54
|
-
- The dropdown opens on input focus and can be navigated via scroll or keyboard.
|
|
55
|
-
- Hour and minute columns scroll independently for quick selection.
|
|
56
|
-
- A **Set** button at the bottom of the dropdown confirms the selection.
|
|
57
|
-
- Supports both 12-hour and 24-hour format display via the internal formatting logic.
|
|
58
|
-
- **minuteStep** is available internally (1, 5, 10, 15, 30 minutes) for granular control over the minute column.
|
|
59
|
-
- Invalid times (e.g., "25:99") trigger validation and display an error state.
|
|
60
|
-
- **touched** prop combined with an empty value or bad time forces error visibility.
|
|
61
|
-
- Clearable via clearing the input field; the dropdown resets accordingly.
|
|
62
|
-
- Colors available: primary, secondary, success, danger, warning, info, purple — plus any raw hex string.
|
|
63
|
-
|
|
64
|
-
## Stories
|
|
65
|
-
|
|
66
|
-
<Primary />
|
|
67
|
-
<Controls />
|
|
68
|
-
<Stories />
|