polymorph-ui-components-mcp 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/build/docs/Accordion.md +45 -0
  2. package/build/docs/Avatar.md +80 -0
  3. package/build/docs/Badge.md +58 -0
  4. package/build/docs/Banner.md +134 -0
  5. package/build/docs/Book.md +111 -0
  6. package/build/docs/Browser.md +92 -0
  7. package/build/docs/Button.md +154 -0
  8. package/build/docs/CHANGELOG.md +0 -0
  9. package/build/docs/Calendar.md +129 -0
  10. package/build/docs/Carousel.md +73 -0
  11. package/build/docs/CheckListItem.md +76 -0
  12. package/build/docs/Checkbox.md +84 -0
  13. package/build/docs/Choicebox.md +71 -0
  14. package/build/docs/ColorPicker.md +83 -0
  15. package/build/docs/Combobox.md +336 -0
  16. package/build/docs/CommandMenu.md +208 -0
  17. package/build/docs/ContextMenu.md +132 -0
  18. package/build/docs/GUIDELINES.md +380 -0
  19. package/build/docs/Gauge.md +46 -0
  20. package/build/docs/GridItem.md +78 -0
  21. package/build/docs/Icon.md +66 -0
  22. package/build/docs/IconStack.md +68 -0
  23. package/build/docs/Img.md +56 -0
  24. package/build/docs/Input.md +151 -0
  25. package/build/docs/InputButton.md +246 -0
  26. package/build/docs/KeyboardInput.md +104 -0
  27. package/build/docs/ListItem.md +156 -0
  28. package/build/docs/Loader.md +55 -0
  29. package/build/docs/LoadingDots.md +45 -0
  30. package/build/docs/Menu.md +139 -0
  31. package/build/docs/Modal.md +221 -0
  32. package/build/docs/ModalAnimation.md +29 -0
  33. package/build/docs/OverlayAnimation.md +21 -0
  34. package/build/docs/Pagination.md +102 -0
  35. package/build/docs/Phone.md +82 -0
  36. package/build/docs/Pill.md +122 -0
  37. package/build/docs/Progress.md +53 -0
  38. package/build/docs/Radio.md +75 -0
  39. package/build/docs/RelativeTime.md +76 -0
  40. package/build/docs/Scroller.md +194 -0
  41. package/build/docs/Select.md +177 -0
  42. package/build/docs/Sheet.md +133 -0
  43. package/build/docs/Shimmer.md +76 -0
  44. package/build/docs/Slider.md +68 -0
  45. package/build/docs/Snippet.md +99 -0
  46. package/build/docs/SplitButton.md +157 -0
  47. package/build/docs/SplitInput.md +157 -0
  48. package/build/docs/Step.md +52 -0
  49. package/build/docs/Stepper.md +85 -0
  50. package/build/docs/Table.md +252 -0
  51. package/build/docs/Tabs.md +117 -0
  52. package/build/docs/ThemeSwitcher.md +125 -0
  53. package/build/docs/Toast.md +140 -0
  54. package/build/docs/Toggle.md +70 -0
  55. package/build/docs/Toolbar.md +100 -0
  56. package/build/docs/Tooltip.md +86 -0
  57. package/build/docs/_index.json +218 -0
  58. package/build/docs/templates/changelog.hbs +36 -0
  59. package/build/index.d.ts +2 -0
  60. package/build/index.js +163 -0
  61. package/build/index.js.map +1 -0
  62. package/build/services/registry.d.ts +11 -0
  63. package/build/types.d.ts +4 -0
  64. package/package.json +34 -0
@@ -0,0 +1,157 @@
1
+ # SplitInput
2
+
3
+ A generic segmented input component for capturing structured multi-field values such as OTP/PIN codes, RGB/HSL color channels, or IP addresses. Each segment is an independent `Input` instance with its own validation, data type, and constraints configured via `FieldConfig`. The `values` prop is a bindable `string[]` where each element corresponds to one field. When `autoAdvance` is enabled the cursor automatically moves to the next field after a character is entered, enabling rapid single-character entry (e.g., OTP). Supports paste distribution across fields, keyboard navigation with arrow keys and Tab, and optional separators and per-field labels. Validation is fully delegated to the underlying Input component.
4
+
5
+ ## Usage
6
+
7
+ ```svelte
8
+ <script>
9
+ import { SplitInput } from 'polymorph-ui-components';
10
+
11
+ let otpValues = $state(['', '', '', '', '', '']);
12
+ let rgbValues = $state(['', '', '']);
13
+ let ipValues = $state(['', '', '', '']);
14
+ </script>
15
+
16
+ <!-- OTP / PIN entry (6 digits, auto-advance) -->
17
+ <SplitInput bind:values={otpValues} length={6} autoAdvance />
18
+
19
+ <!-- RGB color channels with labels and separator -->
20
+ <SplitInput
21
+ bind:values={rgbValues}
22
+ separator=","
23
+ fields={[
24
+ { dataType: 'number', maxLength: 3, min: 0, max: 255, placeholder: '0', label: 'R' },
25
+ { dataType: 'number', maxLength: 3, min: 0, max: 255, placeholder: '0', label: 'G' },
26
+ { dataType: 'number', maxLength: 3, min: 0, max: 255, placeholder: '0', label: 'B' }
27
+ ]}
28
+ />
29
+
30
+ <!-- IP address with dot separators -->
31
+ <SplitInput
32
+ bind:values={ipValues}
33
+ separator="."
34
+ fields={[
35
+ { dataType: 'number', maxLength: 3, min: 0, max: 255, placeholder: '0' },
36
+ { dataType: 'number', maxLength: 3, min: 0, max: 255, placeholder: '0' },
37
+ { dataType: 'number', maxLength: 3, min: 0, max: 255, placeholder: '0' },
38
+ { dataType: 'number', maxLength: 3, min: 0, max: 255, placeholder: '0' }
39
+ ]}
40
+ />
41
+ ```
42
+
43
+ ## Props
44
+
45
+ | Prop | Type | Required | Default | Description |
46
+ | ----------- | --------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
47
+ | values | `string[]` | Yes | `[]` | Bindable. Array of current field values where each element corresponds to one input segment. The array length matches `fieldCount` (derived from `fields.length` or `length`). |
48
+ | fields | `FieldConfig[]` | No | `-` | Array of per-field configuration objects. When provided, `fields.length` determines the number of segments and each entry controls that field's data type, constraints, placeholder, validation, and label. When omitted, the component creates `length` fields defaulting to `dataType: 'tel'` and `maxLength: 1`. |
49
+ | length | `number` | No | `4` | Number of input fields to render when `fields` is not provided. Ignored when `fields` is supplied since the array length takes precedence. |
50
+ | disabled | `boolean` | No | `false` | Whether all fields are disabled. When true, no field accepts input or fires events. |
51
+ | autoAdvance | `boolean` | No | `false` | When true and a field's `maxLength` is 1, focus automatically moves to the next field after a character is entered. Also enables paste distribution where pasted text is spread one character per field starting from the focused field. |
52
+ | separator | `string` | No | `-` | A string rendered between each pair of adjacent fields as a visual separator (e.g., `"."` for IP addresses, `","` for RGB, `"-"` for formatted codes). |
53
+ | testId | `string` | No | `-` | Value for the `data-pw` attribute on the top-level container element, used for end-to-end testing selectors. |
54
+ | classes | `string` | No | `-` | CSS class string applied to the component's top-level element. Useful for theming -- define classes with CSS variable overrides and pass them to create variant styles. |
55
+
56
+ ## Methods
57
+
58
+ | Method | Signature | Description |
59
+ | ------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------- |
60
+ | clear() | `() => void` | Clears all field values to empty strings, fires `oninput` and `onchange` with the cleared array, and focuses the first field. |
61
+ | focus() | `() => void` | Moves focus to the first input field. |
62
+
63
+ ## Events
64
+
65
+ | Event | Type | Description |
66
+ | ---------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
67
+ | oninput | `(values: string[]) => void` | Fires on every value change as the user types, pastes, or clears. Receives a copy of the current `values` array. Use this for live preview updates. |
68
+ | onchange | `(values: string[]) => void` | Fires alongside `oninput` on every value change. Receives a copy of the current `values` array. Use this for committing values or triggering side effects. |
69
+ | oncomplete | `(values: string[]) => void` | Fires when every field contains a non-empty value (i.e., all segments are filled). Receives a copy of the completed `values` array. Use this to trigger submission or validation of the full input. |
70
+
71
+ ## CSS Variables
72
+
73
+ Override these custom properties to theme the component.
74
+
75
+ | Variable | Default | CSS Property | Description |
76
+ | ----------------------------------- | ------------------- | ------------- | -------------------------------------------------------------------------------------------- |
77
+ | `--split-input-gap` | `8px` | gap | Horizontal spacing between field segments (and separators). |
78
+ | `--split-input-width` | `fit-content` | width | Width of the overall field group container. |
79
+ | `--split-input-label-gap` | `3px` | gap | Vertical spacing between a field input and its label below. |
80
+ | `--split-input-border` | `1px solid currentColor` | border | Border applied to each individual input field. |
81
+ | `--split-input-border-radius` | `6px` | border-radius | Corner rounding of each individual input field. |
82
+ | `--split-input-focus-border` | `1px solid currentColor` | border | Border applied to a field when it receives focus. |
83
+ | `--split-input-input-width` | `100%` | width | Width of each individual input field. |
84
+ | `--split-input-input-height` | `36px` | height | Height of each individual input field. Also sets the height of separator elements. |
85
+ | `--split-input-text-align` | `center` | text-align | Text alignment within each input field. |
86
+ | `--split-input-font-size` | `14px` | font-size | Font size of input text within each field. |
87
+ | `--split-input-font-weight` | `500` | font-weight | Font weight of input text within each field. |
88
+ | `--split-input-font-family` | (inherited) | font-family | Font family of input text within each field. Falls through to the Input component's default. |
89
+ | `--split-input-input-padding` | `0 6px` | padding | Padding inside each individual input field. |
90
+ | `--split-input-label-font-size` | `12px` | font-size | Font size of per-field labels displayed below each input. |
91
+ | `--split-input-label-font-weight` | `500` | font-weight | Font weight of per-field labels. |
92
+ | `--split-input-label-color` | `currentColor` | color | Text color of per-field labels. |
93
+ | `--split-input-separator-font-size` | `16px` | font-size | Font size of separator characters rendered between fields. |
94
+ | `--split-input-separator-color` | `currentColor` | color | Text color of separator characters. |
95
+
96
+ ## Internal Dependencies
97
+
98
+ - `Input` -- each field segment is rendered as an Input component instance with validation, data type, and constraint props delegated from the corresponding `FieldConfig`.
99
+
100
+ ## Type Reference
101
+
102
+ ### FieldConfig
103
+
104
+ Per-field configuration object. Picked from `OptionalInputProperties`.
105
+
106
+ ```typescript
107
+ type FieldConfig = {
108
+ dataType?: 'text' | 'tel' | 'password' | 'email' | 'number';
109
+ maxLength?: number;
110
+ min?: number;
111
+ max?: number;
112
+ placeholder?: string | null;
113
+ validationPattern?: RegExp | null;
114
+ validators?: CustomValidator[];
115
+ label?: string | null;
116
+ };
117
+ ```
118
+
119
+ - `dataType` -- The HTML input type for the field. Controls keyboard behavior on mobile (e.g., `'tel'` shows numeric pad). Defaults to `'text'`; when `fields` is omitted, auto-generated configs use `'tel'`.
120
+ - `maxLength` -- Maximum number of characters allowed in the field. Defaults to `1000`; when `fields` is omitted, auto-generated configs use `1`.
121
+ - `min` -- Minimum numeric value (only effective when `dataType` is `'number'`).
122
+ - `max` -- Maximum numeric value (only effective when `dataType` is `'number'`).
123
+ - `placeholder` -- Placeholder text shown when the field is empty.
124
+ - `validationPattern` -- A `RegExp` used by the underlying Input to validate the field value. Defaults to `null` (no pattern validation).
125
+ - `validators` -- Array of `CustomValidator` functions for custom validation logic. Each receives the input value and current validation state and returns a new `ValidationState`.
126
+ - `label` -- Text label displayed below the field (e.g., `'R'`, `'G'`, `'B'` for color channels).
127
+
128
+ ### CustomValidator
129
+
130
+ ```typescript
131
+ type CustomValidator = (
132
+ inputValue: string,
133
+ currentValidationState: ValidationState
134
+ ) => ValidationState;
135
+ ```
136
+
137
+ ### ValidationState
138
+
139
+ ```typescript
140
+ type ValidationState = 'Valid' | 'InProgress' | 'Invalid';
141
+ ```
142
+
143
+ ## Web Component
144
+
145
+ Tag: `<pui-split-input>`
146
+
147
+ ```html
148
+ <pui-split-input length="6" auto-advance></pui-split-input>
149
+
150
+ <script>
151
+ const el = document.querySelector('pui-split-input');
152
+ el.values = ['', '', '', '', '', ''];
153
+ el.addEventListener('complete', (e) => console.log(e.detail));
154
+ </script>
155
+ ```
156
+
157
+ > **Note:** The `values` and `fields` props are arrays — set them via JavaScript properties, not HTML attributes.
@@ -0,0 +1,52 @@
1
+ # Step
2
+
3
+ An individual step within a Stepper. Displays either a numbered circle or an icon image, a text label, and a dashed separator line. When clicked, fires the `onclick` event with `{ selectedIndex }`. The separator is hidden for the last step via CSS `--step-separator-display: none`.
4
+
5
+ ## Usage
6
+
7
+ ```svelte
8
+ <script>
9
+ import { Step } from 'polymorph-ui-components';
10
+ </script>
11
+
12
+ <Step />
13
+ ```
14
+
15
+ ## Props
16
+
17
+ | Prop | Type | Required | Default | Description |
18
+ | --------- | -------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
19
+ | stepIndex | `number` | Yes | `-` | The 1-based step number displayed inside the circle (when no icon is provided). |
20
+ | label | `string` | Yes | `-` | Text label displayed next to the step circle. |
21
+ | icon | `string` | No | `-` | Optional URL of an icon image that replaces the step number circle. |
22
+ | classes | `string` | No | `-` | CSS class string applied to the component's top-level element. Useful for theming — define classes with CSS variable overrides and pass them to create variant styles. |
23
+
24
+ ## Events
25
+
26
+ | Event | Type | Description |
27
+ | --------- | -------------------------------------------- | ----------------------------------------------------------------------------------------- |
28
+ | onclick | `(event: { selectedIndex: number }) => void` | Fires when the step is clicked. Receives { selectedIndex: number } with the step's index. |
29
+ | onkeydown | `(event: KeyboardEvent) => void` | Fires when a key is pressed while the step has focus. |
30
+
31
+ ## CSS Variables
32
+
33
+ Override these custom properties to theme the component.
34
+
35
+ | Variable | Default | CSS Property | Description |
36
+ | ----------------------------------------- | ------------------- | ---------------- | ---------------------------------------------------------------------- |
37
+ | `--step-flex-direction` | `row` | flex-direction | Layout direction of the step (row for horizontal layout). |
38
+ | `--step-index-container-height` | `30px` | height | Height of the step number circle. |
39
+ | `--step-index-container-width` | `30px` | width | Width of the step number circle. |
40
+ | `--step-index-container-radius` | `50%` | border-radius | Corner rounding of the step number circle. |
41
+ | `--step-index-container-background-color` | `#798fa5cc` | background-color | Background color of the step number circle. |
42
+ | `--step-separator-display` | `block` | display | Display mode of the separator line (set 'none' to hide for last step). |
43
+ | `--step-separator-height` | `1px` | height | Height (thickness) of the separator line. |
44
+ | `--step-separator-width` | `50px` | width | Width of the separator line. |
45
+ | `--step-separator-margin` | `0px 12px 0px 12px` | margin | Margin around the separator line. |
46
+ | `--step-text-margin` | `0px 0px 0px 12px` | margin | Margin around the step label text. |
47
+ | `--step-text-font-size` | `inherit` | font-size | Font size of the step label text. |
48
+ | `--step-text-color` | `inherit` | color | Color of the step label text. |
49
+ | `--step-index-font-size` | `14px` | font-size | Font size of the step number inside the circle. |
50
+ | `--step-index-color` | `white` | color | Color of the step number text. |
51
+ | `--step-separator-background-image` | `repeating-linear-gradient(...)` | background-image | Background image pattern for the step separator line. |
52
+ | `--step-separator-background-image-color` | `#798fa5cc` | color (in gradient) | Color of the dashed separator line between steps. |
@@ -0,0 +1,85 @@
1
+ # Stepper
2
+
3
+ A progress indicator showing numbered steps with completion and active states. Each step shows either a step number or a custom icon, a label, and a dashed separator line to the next step. Steps before `currentStepIndex` are styled as completed, the step at `currentStepIndex` is active (both inherit the current text color by default), and remaining steps are inactive (grey). Each step is clickable, firing `onhandlestepclick` with the selected index.
4
+
5
+ ## Usage
6
+
7
+ ```svelte
8
+ <script>
9
+ import { Stepper } from 'polymorph-ui-components';
10
+ </script>
11
+
12
+ <Stepper />
13
+ ```
14
+
15
+ ## Props
16
+
17
+ | Prop | Type | Required | Default | Description |
18
+ | ---------------- | --------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
19
+ | steps | `Array<Step>` | Yes | `-` | Array of Step objects defining each step. Each Step has a `label` string and optional `icon` URL. |
20
+ | currentStepIndex | `number` | Yes | `-` | The 0-based index of the currently active step. Steps before this index are styled as completed, the step at this index is active. |
21
+ | classes | `string` | No | `-` | CSS class string applied to the component's top-level element. Useful for theming — define classes with CSS variable overrides and pass them to create variant styles. |
22
+ | testId | `string` | No | `-` | Test selector value applied as `data-pw` on the outermost element. |
23
+
24
+ ## Events
25
+
26
+ | Event | Type | Description |
27
+ | ----------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------- |
28
+ | onhandlestepclick | `(event: { selectedIndex: number }) => void` | Fires when any step is clicked. Receives { selectedIndex: number } with the 1-based step index. |
29
+
30
+ ## CSS Variables
31
+
32
+ Override these custom properties to theme the component.
33
+
34
+ | Variable | Default | CSS Property | Description |
35
+ | --------------------------------------------------- | --------- | ---------------------------------- | ------------------------------------------------------------------------ |
36
+ | `--stepper-flex-direction` | `row` | flex-direction | Layout direction of the steps (row for horizontal, column for vertical). |
37
+ | `--step-text-active-color` | `currentColor` | --step-text-color | Text color of the active step label. |
38
+ | `--step-separator-background-image-active-color` | `currentColor` | --step-separator-background-image-color | Color of the separator line for active steps. |
39
+ | `--step-text-completed-color` | `currentColor` | --step-text-color | Text color of completed step labels. |
40
+ | `--step-separator-background-image-completed-color` | `currentColor` | --step-separator-background-image-color | Color of the separator line for completed steps. |
41
+ | `--step-index-container-active-background-color` | `currentColor` | background-color | Background color of the active step circle. |
42
+ | `--step-index-container-completed-background-color` | `currentColor` | background-color | Background color of completed step circles. |
43
+
44
+ ### Step Sub-component CSS Variables
45
+
46
+ These CSS variables are defined in the `Step` sub-component and control individual step styling.
47
+
48
+ | Variable | Default | CSS Property | Description |
49
+ | ----------------------------------------- | ------------------- | ---------------- | -------------------------------------------- |
50
+ | `--step-flex-direction` | `row` | flex-direction | Layout direction of each step. |
51
+ | `--step-index-container-height` | `30px` | height | Height of the step number circle. |
52
+ | `--step-index-container-width` | `30px` | width | Width of the step number circle. |
53
+ | `--step-index-container-radius` | `50%` | border-radius | Border radius of the step number circle. |
54
+ | `--step-index-container-background-color` | `currentColor` | background-color | Background color of inactive step circles. |
55
+ | `--step-index-font-size` | `14px` | font-size | Font size of the step number. |
56
+ | `--step-index-color` | `white` | color | Text color of the step number. |
57
+ | `--step-separator-display` | `block` | display | Display mode of the step separator. |
58
+ | `--step-separator-height` | `1px` | height | Height of the separator line. |
59
+ | `--step-separator-width` | `50px` | width | Width of the separator line. |
60
+ | `--step-separator-margin` | `0px 12px 0px 12px` | margin | Margin around the separator. |
61
+ | `--step-separator-background-image` | `repeating-linear-gradient(...)` | background-image | Background image pattern for the step separator line. |
62
+ | `--step-separator-background-image-color` | `currentColor` | (gradient color) | Color used in the dashed separator gradient. |
63
+ | `--step-text-margin` | `0px 0px 0px 12px` | margin | Margin around the step label text. |
64
+ | `--step-text-font-size` | `inherit` | font-size | Font size of the step label. |
65
+ | `--step-text-color` | `inherit` | color | Color of the step label text. |
66
+
67
+ ## Type Reference
68
+
69
+ Custom types used by this component's props and events:
70
+
71
+ ### Step
72
+
73
+ ```typescript
74
+ type Step = { label: string; icon?: string };
75
+ ```
76
+
77
+ ## Web Component
78
+
79
+ Tag: `<pui-stepper>`
80
+
81
+ ```html
82
+ <pui-stepper current-step-index="1"></pui-stepper>
83
+ ```
84
+
85
+ > **Note:** The `steps` prop is an array — set it via JavaScript property.
@@ -0,0 +1,252 @@
1
+ # Table
2
+
3
+ A sortable data table with clean, modern defaults. Supports column sorting (ascending/descending) for string, number, and boolean values. Features sticky headers, custom cell rendering via Svelte 5 snippets, row click interaction, and customizable sort icons. Table data is an array of arrays (rows x columns).
4
+
5
+ ## Usage
6
+
7
+ ```svelte
8
+ <script>
9
+ import { Table } from 'polymorph-ui-components';
10
+ </script>
11
+
12
+ <Table
13
+ tableHeaders={['Name', 'Email', 'Role']}
14
+ tableData={[
15
+ ['Alice', 'alice@example.com', 'Admin'],
16
+ ['Bob', 'bob@example.com', 'Editor']
17
+ ]}
18
+ />
19
+ ```
20
+
21
+ ### Custom Cell Rendering
22
+
23
+ Use the `cell` snippet to render components (Pills, links, badges) inside cells instead of plain text:
24
+
25
+ ```svelte
26
+ <script>
27
+ import { Table, Pill } from 'polymorph-ui-components';
28
+ </script>
29
+
30
+ <Table
31
+ tableHeaders={['Name', 'Status']}
32
+ tableData={[
33
+ ['Alice', 'Active'],
34
+ ['Bob', 'Inactive']
35
+ ]}
36
+ >
37
+ {#snippet cell(value, rowIndex, colIndex)}
38
+ {#if colIndex === 1}
39
+ <Pill text={String(value)} classes={value === 'Active' ? 'pill-success' : 'pill-error'} />
40
+ {:else}
41
+ {value}
42
+ {/if}
43
+ {/snippet}
44
+ </Table>
45
+ ```
46
+
47
+ ### Sticky Header
48
+
49
+ Use `stickyHeader` to keep headers fixed while scrolling. Works with `isTableScrollable` (table's own scroll area) or a parent scroll container.
50
+
51
+ ```svelte
52
+ <Table
53
+ stickyHeader
54
+ isTableScrollable
55
+ tableHeaders={['Name', 'Score']}
56
+ tableData={largeDataset}
57
+ --table-container-height="400px"
58
+ />
59
+ ```
60
+
61
+ ### Custom Sort Icons
62
+
63
+ Replace the default SVG chevron icons with custom snippets:
64
+
65
+ ```svelte
66
+ <Table tableHeaders={['Name', 'Score']} tableData={data}>
67
+ {#snippet sortAscIcon()}<span>↑</span>{/snippet}
68
+ {#snippet sortDescIcon()}<span>↓</span>{/snippet}
69
+ {#snippet sortDefaultIcon()}<span>↕</span>{/snippet}
70
+ </Table>
71
+ ```
72
+
73
+ ### Per-Column Widths
74
+
75
+ Control individual column widths via CSS using the `classes` prop and `nth-child` selectors:
76
+
77
+ ```css
78
+ /* app.css */
79
+ .my-table th:nth-child(1),
80
+ .my-table td:nth-child(1) {
81
+ width: 200px;
82
+ }
83
+ .my-table th:nth-child(2),
84
+ .my-table td:nth-child(2) {
85
+ width: 30%;
86
+ }
87
+ .my-table th:nth-child(3),
88
+ .my-table td:nth-child(3) {
89
+ width: 100px;
90
+ }
91
+ ```
92
+
93
+ ```svelte
94
+ <Table classes="my-table" tableHeaders={['Name', 'Email', 'Role']} tableData={data} />
95
+ ```
96
+
97
+ For a uniform column width across all columns, use the `--table-column-width` CSS variable instead.
98
+
99
+ ### Empty State
100
+
101
+ Show a placeholder when `tableData` is empty:
102
+
103
+ ```svelte
104
+ <Table tableHeaders={['Name', 'Email']} tableData={[]}>
105
+ {#snippet empty()}
106
+ <p>No records found.</p>
107
+ {/snippet}
108
+ </Table>
109
+ ```
110
+
111
+ ## Props
112
+
113
+ | Prop | Type | Required | Default | Description |
114
+ | ------------------- | -------------------------------------- | -------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
115
+ | tableTitle | `string \| null` | No | `''` | Optional title text displayed above the table. |
116
+ | tableHeaders | `string[]` | No | `[]` | Array of column header strings. Each header is clickable for sorting (when sortable). |
117
+ | tableData | `Array<TableCellValue[]>` | No | `[]` | Array of row arrays. Each row is an array of cell values (string, number, or boolean). Columns correspond to tableHeaders by index. |
118
+ | sortable | `boolean` | No | `true` | When false, disables sorting on all columns. Sort buttons are hidden. |
119
+ | sortableColumns | `number[]` | No | `-` | Array of column indices that are sortable. When provided, only these columns show sort buttons. Other columns are non-sortable regardless of the `sortable` prop. |
120
+ | stickyHeader | `boolean` | No | `false` | When true, the header row sticks to the top during scroll. Works with `isTableScrollable` or any parent scroll container. Offset via `--table-header-sticky-top`. |
121
+ | isTableScrollable | `boolean` | No | `false` | When true, creates a bounded scroll area on the table container. Headers are automatically sticky. Use `--table-container-height` to set the scroll area height. |
122
+ | isContentScrollable | `boolean` | No | `false` | When true, individual cell content scrolls vertically if it overflows the fixed cell height. |
123
+ | testId | `string` | No | `-` | Value for the data-pw attribute on the table container, used for end-to-end testing selectors. |
124
+ | caption | `string` | No | `-` | Accessible caption for screen readers. Rendered as a visually hidden `<caption>` element. |
125
+ | sortAscIcon | `Snippet` | No | SVG chevron up | Custom snippet rendered for the ascending sort indicator. |
126
+ | sortDescIcon | `Snippet` | No | SVG chevron down | Custom snippet rendered for the descending sort indicator. |
127
+ | sortDefaultIcon | `Snippet` | No | SVG chevron pair | Custom snippet rendered for columns that haven't been sorted yet. Default is a dimmed up/down chevron pair. |
128
+ | cell | `Snippet<[TableCellValue, number, number]>` | No | `-` | Custom cell renderer. Receives `(value, rowIndex, colIndex)`. When not provided, cells render the raw value as text. |
129
+ | empty | `Snippet` | No | `-` | Content to show when `tableData` is empty. Rendered inside a full-width table row. |
130
+ | classes | `string` | No | `-` | CSS class string applied to the component's top-level element. Useful for theming — define classes with CSS variable overrides and pass them to create variant styles. |
131
+
132
+ ## Events
133
+
134
+ | Event | Type | Description |
135
+ | ---------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
136
+ | onrowclick | `(rowIndex: number, rowData: TableCellValue[]) => void` | Fires when a data row is clicked. The row becomes focusable and keyboard-navigable when provided. |
137
+ | onsort | `(columnIndex: number, direction: SortDirection) => void` | Fires after a column sort is toggled. `direction` is `'asc'` or `'desc'`. |
138
+
139
+ ## CSS Variables
140
+
141
+ Override these custom properties to theme the component.
142
+
143
+ ### Title
144
+
145
+ | Variable | Default | CSS Property | Description |
146
+ | --------------------------- | ------------ | ------------ | ------------------------------- |
147
+ | `--table-title-margin` | `0px 0px 12px 0px` | margin | Margin around the table title. |
148
+ | `--table-title-font-size` | `18px` | font-size | Font size of the table title. |
149
+ | `--table-title-font-weight` | `600` | font-weight | Font weight of the table title. |
150
+ | `--table-title-color` | `currentColor` | color | Text color of the table title. |
151
+ | `--table-title-font-family` | `-` | font-family | Font family of the table title. |
152
+ | `--table-title-padding` | `-` | padding | Padding of the table title. |
153
+
154
+ ### Container & Layout
155
+
156
+ | Variable | Default | CSS Property | Description |
157
+ | -------------------------- | ------------------- | --------------- | ------------------------------------------------------------------ |
158
+ | `--table-border` | `1px solid currentColor` | border | Border of the table container. |
159
+ | `--table-border-radius` | `8px` | border-radius | Border radius of the table container. |
160
+ | `--table-container-width` | `100%` | width | Width of the table container. |
161
+ | `--table-container-height` | `143px` | height | Height of the scrollable table container (when isTableScrollable). |
162
+ | `--table-width` | `100%` | width | Width of the table element. |
163
+ | `--table-border-collapse` | `collapse` | border-collapse | Border collapse mode of the table. |
164
+
165
+ ### Cell Grid
166
+
167
+ | Variable | Default | CSS Property | Description |
168
+ | ---------------------------- | ------------------- | ------------- | ---------------------------------------------------------------------------------------------------------- |
169
+ | `--table-inner-border` | `none` | border | Border of individual table cells. Set to `1px solid #ccc` for full grid. |
170
+ | `--table-row-border` | `1px solid #e4e4e7` | border-bottom | Border on the bottom of each data row. Subtle row separators. |
171
+ | `--table-row-last-border` | `none` | border-bottom | Border on the last data row. Set to match `--table-row-border` if needed. |
172
+ | `--table-padding` | `12px 16px` | padding | Padding inside table cells. |
173
+ | `--table-text-align` | `left` | text-align | Text alignment inside table cells. |
174
+ | `--table-column-width` | `-` | width | Sets a uniform width for all table columns. Unset lets the table auto-size columns. |
175
+ | `--table-scrollable-column-height` | `20px` | height | Height of scrollable cell content (when isContentScrollable). |
176
+
177
+ ### Header Cells
178
+
179
+ | Variable | Default | CSS Property | Description |
180
+ | ------------------------------- | --------- | ---------------- | -------------------------------------------------------------------------------- |
181
+ | `--table-header-background` | `transparent` | background-color | Background color of header cells. Falls back to `--table-header-border-bgcolor`. |
182
+ | `--table-header-font-size` | `14px` | font-size | Font size of header cells. |
183
+ | `--table-header-font-family` | `-` | font-family | Font family of header cells. |
184
+ | `--table-header-font-weight` | `600` | font-weight | Font weight of header cells. |
185
+ | `--table-header-letter-spacing` | `0.02em` | letter-spacing | Letter spacing of header text. |
186
+ | `--table-header-text-transform` | `-` | text-transform | Text transform of header cells (e.g. `uppercase`, `capitalize`). |
187
+ | `--table-header-color` | `currentColor` | color | Text color of header cells. Falls back to `--table-header-font-color`. |
188
+ | `--table-header-sticky-top` | `0` | top | Top offset for sticky headers. Use when a fixed navbar is above the table. |
189
+
190
+ ### Data Cells
191
+
192
+ | Variable | Default | CSS Property | Description |
193
+ | ----------------------------- | --------- | ---------------- | ------------------------------------------------------------------------------- |
194
+ | `--table-content-background` | `-` | background-color | Background color of data cells. Falls back to `--table-content-border-bgcolor`. |
195
+ | `--table-content-font-size` | `14px` | font-size | Font size of data cells. |
196
+ | `--table-content-font-family` | `-` | font-family | Font family of data cells. |
197
+ | `--table-content-color` | `currentColor` | color | Text color of data cells. Falls back to `--table-content-font-color`. |
198
+
199
+ ### Rows
200
+
201
+ | Variable | Default | CSS Property | Description |
202
+ | ------------------------------ | --------- | ---------------- | -------------------------------------------------------------------------------------------- |
203
+ | `--table-row-background` | `-` | background-color | Background color of data rows. |
204
+ | `--table-row-alt-background` | `-` | background-color | Background of even-numbered rows for striped effect. Falls back to `--table-row-background`. |
205
+ | `--table-row-hover-background` | `-` | background-color | Background color of data rows on hover. |
206
+ | `--table-focus-outline-color` | `currentColor` | outline | Outline color for focused clickable rows. |
207
+
208
+ ### Sort Controls
209
+
210
+ | Variable | Default | CSS Property | Description |
211
+ | -------------------------------------- | ------------------ | ---------------- | ------------------------------------------------- |
212
+ | `--table-sort-button-color` | `inherit` | color | Color of the sort button icon. |
213
+ | `--table-sort-button-hover-color` | `-` | color | Color of the sort button icon on hover. |
214
+ | `--table-sort-button-hover-background` | `rgba(0,0,0,0.05)` | background-color | Background of the sort button on hover. |
215
+ | `--table-sort-icon-size` | `14px` | width, height | Size of the sort indicator SVG icons. |
216
+ | `--table-sort-idle-opacity` | `0.3` | opacity | Opacity of the default (unsorted) sort indicator. |
217
+
218
+ ### Empty State
219
+
220
+ | Variable | Default | CSS Property | Description |
221
+ | ----------------------- | ----------- | ------------ | --------------------------------------- |
222
+ | `--table-empty-padding` | `32px 24px` | padding | Padding around the empty state content. |
223
+ | `--table-empty-color` | `currentColor` | color | Text color of the empty state content. |
224
+
225
+ ## Type Reference
226
+
227
+ ```typescript
228
+ type SortDirection = 'asc' | 'desc';
229
+
230
+ type TableCellValue = string | number | boolean | null | Record<string, unknown> | unknown[];
231
+ ```
232
+
233
+ ## Web Component
234
+
235
+ Tag: `<pui-table>`
236
+
237
+ ```html
238
+ <pui-table table-title="Users" sortable sticky-header>
239
+ <div slot="empty">No data found</div>
240
+ </pui-table>
241
+ ```
242
+
243
+ ### Slots
244
+
245
+ | Slot Name | Maps to Snippet | Description |
246
+ | ------------------- | ----------------- | ----------------------------------------- |
247
+ | `empty` | `empty` | Content shown when the table has no data. |
248
+ | `sort-asc-icon` | `sortAscIcon` | Custom ascending sort icon. |
249
+ | `sort-desc-icon` | `sortDescIcon` | Custom descending sort icon. |
250
+ | `sort-default-icon` | `sortDefaultIcon` | Custom default (unsorted) sort icon. |
251
+
252
+ > **Note:** `tableHeaders`, `tableData`, and `sortableColumns` are arrays — set them via JavaScript properties. The `cell` snippet is parameterized and only available via JavaScript.