@eifi1/ui-kit 0.7.0 → 0.8.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 +32 -17
- package/dist/chart.d.ts +3 -2
- package/dist/components/alert-banner.d.ts +59 -10
- package/dist/components/alert-banner.js +114 -8
- package/dist/components/alert-banner.js.map +1 -1
- package/dist/components/amount-input.d.ts +5 -0
- package/dist/components/button-group.d.ts +26 -0
- package/dist/components/button-group.js +49 -0
- package/dist/components/button-group.js.map +1 -0
- package/dist/components/calculator.d.ts +5 -0
- package/dist/components/chart-zoom.d.ts +63 -14
- package/dist/components/chart-zoom.js +82 -16
- package/dist/components/chart-zoom.js.map +1 -1
- package/dist/components/chip.d.ts +67 -2
- package/dist/components/chip.js +73 -8
- package/dist/components/chip.js.map +1 -1
- package/dist/components/confirm-dialog.d.ts +120 -0
- package/dist/components/confirm-dialog.js +96 -0
- package/dist/components/confirm-dialog.js.map +1 -0
- package/dist/components/copy-button.d.ts +62 -0
- package/dist/components/copy-button.js +95 -0
- package/dist/components/copy-button.js.map +1 -0
- package/dist/components/data-table-filter-popover.d.ts +1 -1
- package/dist/components/data-table-filters.d.ts +1 -1
- package/dist/components/data-table-pagination.d.ts +5 -1
- package/dist/components/data-table-pagination.js +71 -58
- package/dist/components/data-table-pagination.js.map +1 -1
- package/dist/components/data-table-sort.d.ts +28 -5
- package/dist/components/data-table-sort.js +11 -7
- package/dist/components/data-table-sort.js.map +1 -1
- package/dist/components/data-table.d.ts +1 -1
- package/dist/components/data-table.js +544 -423
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.d.ts +51 -5
- package/dist/components/date-picker.js +152 -40
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/description-list.d.ts +60 -0
- package/dist/components/description-list.js +112 -0
- package/dist/components/description-list.js.map +1 -0
- package/dist/components/disclosure.d.ts +37 -2
- package/dist/components/disclosure.js +14 -5
- package/dist/components/disclosure.js.map +1 -1
- package/dist/components/facing-pair.d.ts +2 -0
- package/dist/components/file-button.d.ts +19 -1
- package/dist/components/file-button.js +8 -1
- package/dist/components/file-button.js.map +1 -1
- package/dist/components/file-dropzone.d.ts +56 -9
- package/dist/components/file-dropzone.js +100 -70
- package/dist/components/file-dropzone.js.map +1 -1
- package/dist/components/floating-panel.d.ts +107 -0
- package/dist/components/floating-panel.js +206 -0
- package/dist/components/floating-panel.js.map +1 -0
- package/dist/components/full-bleed-dialog.d.ts +12 -1
- package/dist/components/full-bleed-dialog.js +26 -5
- package/dist/components/full-bleed-dialog.js.map +1 -1
- package/dist/components/modal.d.ts +6 -2
- package/dist/components/modal.js +2 -1
- package/dist/components/modal.js.map +1 -1
- package/dist/components/number-field.d.ts +5 -0
- package/dist/components/number-input.d.ts +5 -0
- package/dist/components/numpad-sheet.d.ts +5 -0
- package/dist/components/progress-bar.d.ts +54 -0
- package/dist/components/progress-bar.js +94 -0
- package/dist/components/progress-bar.js.map +1 -0
- package/dist/components/scroll-area.d.ts +53 -0
- package/dist/components/scroll-area.js +86 -0
- package/dist/components/scroll-area.js.map +1 -0
- package/dist/components/separator.d.ts +23 -0
- package/dist/components/separator.js +24 -0
- package/dist/components/separator.js.map +1 -0
- package/dist/components/series-chart-ticks.d.ts +34 -1
- package/dist/components/series-chart-ticks.js +83 -1
- package/dist/components/series-chart-ticks.js.map +1 -1
- package/dist/components/series-chart.d.ts +314 -19
- package/dist/components/series-chart.js +510 -120
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/settings-fields.d.ts +2 -0
- package/dist/components/skeleton.d.ts +36 -0
- package/dist/components/skeleton.js +35 -0
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/stat-tile.d.ts +60 -6
- package/dist/components/stat-tile.js +60 -26
- package/dist/components/stat-tile.js.map +1 -1
- package/dist/components/table.d.ts +83 -0
- package/dist/components/table.js +166 -0
- package/dist/components/table.js.map +1 -0
- package/dist/components/time-input.d.ts +2 -0
- package/dist/components/toggle-legend.d.ts +3 -2
- package/dist/components/toggle-legend.js +1 -1
- package/dist/components/toggle-legend.js.map +1 -1
- package/dist/components/tooltip.d.ts +10 -4
- package/dist/components/tooltip.js +23 -6
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/tree-view.d.ts +129 -0
- package/dist/components/tree-view.js +376 -0
- package/dist/components/tree-view.js.map +1 -0
- package/dist/components/treemap.d.ts +9 -2
- package/dist/components/treemap.js +2 -1
- package/dist/components/treemap.js.map +1 -1
- package/dist/components/ui.d.ts +92 -14
- package/dist/components/ui.js +112 -30
- package/dist/components/ui.js.map +1 -1
- package/dist/components/use-table-state.d.ts +1 -1
- package/dist/{data-table-filters-noy0Abvi.d.ts → data-table-filters-CF1PXqjQ.d.ts} +73 -3
- package/dist/data-table.d.ts +2 -2
- package/dist/data-table.js.map +1 -1
- package/dist/hooks/use-copy-to-clipboard.d.ts +28 -0
- package/dist/hooks/use-copy-to-clipboard.js +81 -0
- package/dist/hooks/use-copy-to-clipboard.js.map +1 -0
- package/dist/hooks/use-debounce.d.ts +43 -0
- package/dist/hooks/use-debounce.js +56 -0
- package/dist/hooks/use-debounce.js.map +1 -0
- package/dist/hooks/use-file-drop.d.ts +72 -0
- package/dist/hooks/use-file-drop.js +57 -0
- package/dist/hooks/use-file-drop.js.map +1 -0
- package/dist/i18n/defaults.d.ts +5 -0
- package/dist/i18n/defaults.js +7 -1
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +17 -0
- package/dist/i18n/kit-labels.js +6 -2
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/de-CH-informal.d.ts +43 -0
- package/dist/i18n/locales/de-CH-informal.js +8 -0
- package/dist/i18n/locales/de-CH-informal.js.map +1 -0
- package/dist/i18n/locales/de-CH.d.ts +5 -0
- package/dist/i18n/locales/de-CH.js +1 -14
- package/dist/i18n/locales/de-CH.js.map +1 -1
- package/dist/i18n/locales/de-informal.d.ts +64 -0
- package/dist/i18n/locales/de-informal.js +37 -0
- package/dist/i18n/locales/de-informal.js.map +1 -0
- package/dist/i18n/locales/de.d.ts +5 -0
- package/dist/i18n/locales/de.js +25 -0
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +5 -0
- package/dist/i18n/locales/es.js +25 -0
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +5 -0
- package/dist/i18n/locales/fr.js +25 -0
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +5 -0
- package/dist/i18n/locales/hu.js +25 -0
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +5 -0
- package/dist/i18n/locales/it.js +25 -0
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +5 -0
- package/dist/i18n/locales/zh.js +25 -0
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/swiss.d.ts +13 -0
- package/dist/i18n/swiss.js +19 -0
- package/dist/i18n/swiss.js.map +1 -0
- package/dist/index.d.ts +26 -11
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/dates.d.ts +37 -1
- package/dist/lib/dates.js +19 -0
- package/dist/lib/dates.js.map +1 -1
- package/dist/rhf/form.d.ts +2 -0
- package/dist/rhf.d.ts +2 -0
- package/dist/search/command-palette.d.ts +15 -1
- package/dist/search/command-palette.js +10 -2
- package/dist/search/command-palette.js.map +1 -1
- package/dist/shell/app-shell.js +2 -2
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/wizard/stepper-nav.d.ts +35 -2
- package/dist/wizard/stepper-nav.js +54 -22
- package/dist/wizard/stepper-nav.js.map +1 -1
- package/dist/wizard/types.d.ts +107 -5
- package/dist/wizard/types.js +2 -1
- package/dist/wizard/types.js.map +1 -1
- package/dist/wizard/use-wizard.js +141 -21
- package/dist/wizard/use-wizard.js.map +1 -1
- package/dist/wizard/wizard-summary.d.ts +10 -2
- package/dist/wizard/wizard-summary.js +3 -1
- package/dist/wizard/wizard-summary.js.map +1 -1
- package/dist/wizard.d.ts +4 -1
- package/dist/wizard.js.map +1 -1
- package/package.json +1 -1
- package/src/components/alert-banner.tsx +211 -20
- package/src/components/button-group.tsx +75 -0
- package/src/components/chart-zoom.tsx +158 -20
- package/src/components/chip.tsx +160 -9
- package/src/components/confirm-dialog.tsx +242 -0
- package/src/components/copy-button.tsx +158 -0
- package/src/components/data-table-pagination.tsx +19 -6
- package/src/components/data-table-sort.ts +49 -10
- package/src/components/data-table.tsx +293 -24
- package/src/components/date-picker.tsx +262 -57
- package/src/components/description-list.tsx +174 -0
- package/src/components/disclosure.tsx +58 -5
- package/src/components/file-button.tsx +22 -2
- package/src/components/file-dropzone.tsx +198 -100
- package/src/components/floating-panel.tsx +341 -0
- package/src/components/full-bleed-dialog.tsx +48 -5
- package/src/components/modal.tsx +9 -2
- package/src/components/progress-bar.tsx +163 -0
- package/src/components/scroll-area.tsx +129 -0
- package/src/components/separator.tsx +37 -0
- package/src/components/series-chart-ticks.ts +135 -0
- package/src/components/series-chart.tsx +934 -67
- package/src/components/skeleton.tsx +65 -0
- package/src/components/stat-tile.tsx +160 -27
- package/src/components/table.tsx +263 -0
- package/src/components/toggle-legend.tsx +4 -3
- package/src/components/tooltip.tsx +40 -12
- package/src/components/tree-view.tsx +589 -0
- package/src/components/treemap.tsx +10 -2
- package/src/components/ui.tsx +268 -42
- package/src/data-table.ts +2 -0
- package/src/hooks/use-copy-to-clipboard.ts +122 -0
- package/src/hooks/use-debounce.ts +105 -0
- package/src/hooks/use-file-drop.ts +123 -0
- package/src/i18n/defaults.ts +6 -0
- package/src/i18n/kit-labels.tsx +19 -0
- package/src/i18n/locales/de-CH-informal.ts +10 -0
- package/src/i18n/locales/de-CH.ts +1 -16
- package/src/i18n/locales/de-informal.ts +61 -0
- package/src/i18n/locales/de.ts +25 -0
- package/src/i18n/locales/es.ts +25 -0
- package/src/i18n/locales/fr.ts +25 -0
- package/src/i18n/locales/hu.ts +25 -0
- package/src/i18n/locales/it.ts +25 -0
- package/src/i18n/locales/zh.ts +25 -0
- package/src/i18n/swiss.ts +25 -0
- package/src/index.ts +29 -0
- package/src/lib/dates.ts +48 -0
- package/src/search/command-palette.tsx +29 -3
- package/src/shell/app-shell.tsx +2 -2
- package/src/wizard/stepper-nav.tsx +102 -28
- package/src/wizard/types.ts +106 -4
- package/src/wizard/use-wizard.ts +211 -31
- package/src/wizard/wizard-summary.tsx +24 -12
- package/src/wizard.ts +3 -2
package/dist/components/ui.js
CHANGED
|
@@ -7,24 +7,38 @@ import { horizontalStep } from "../lib/direction.js";
|
|
|
7
7
|
import { useMediaQuery } from "../hooks/use-media-query.js";
|
|
8
8
|
import { Tooltip } from "./tooltip.js";
|
|
9
9
|
import { DEFAULT_COMMON_LABELS, useKitLabels } from "../i18n/kit-labels.js";
|
|
10
|
-
const BUTTON_BASE = "inline-flex items-center justify-center
|
|
10
|
+
const BUTTON_BASE = "inline-flex items-center justify-center rounded-md font-medium transition-colors focus:outline-none focus:ring-2 disabled:opacity-50 disabled:cursor-not-allowed";
|
|
11
|
+
const BUTTON_SIZES = {
|
|
12
|
+
md: "gap-2 px-3 py-2 text-sm",
|
|
13
|
+
sm: "gap-1.5 px-2 py-1 text-xs"
|
|
14
|
+
};
|
|
11
15
|
const buttonVariantClasses = {
|
|
12
16
|
primary: "border border-[var(--border)] bg-[var(--bg-surface-2)] text-[var(--text-primary)] hover:bg-[var(--border)] focus:ring-[var(--brand)]",
|
|
13
17
|
secondary: "border border-[var(--border)] bg-transparent text-[var(--text-primary)] hover:bg-[var(--bg-surface-2)] focus:ring-[var(--brand)]",
|
|
14
18
|
ghost: "bg-transparent text-[var(--text-primary)] hover:bg-[var(--bg-surface-2)] focus:ring-[var(--brand)]",
|
|
15
19
|
danger: "bg-[var(--danger)] text-[var(--danger-contrast)] hover:bg-[var(--danger-hover)] focus:ring-[var(--danger-border)]",
|
|
16
|
-
brand: "bg-[var(--brand)] text-[var(--brand-contrast)] hover:bg-[var(--brand-hover)] focus:ring-[var(--brand)]"
|
|
20
|
+
brand: "bg-[var(--brand)] text-[var(--brand-contrast)] hover:bg-[var(--brand-hover)] focus:ring-[var(--brand)]",
|
|
21
|
+
// A text link that is still a `<button>` — keksdose's six hand-rolled
|
|
22
|
+
// `<button className="text-brand underline">` sites ("Resend code", "Show all",
|
|
23
|
+
// "Undo" in a toast…), which act rather than navigate and so must not be anchors.
|
|
24
|
+
// The box padding goes (`p-0`) so it sits in a sentence at the text's own size, but
|
|
25
|
+
// the base's `focus:ring-2` stays: those copies had `outline-none` and no ring, so
|
|
26
|
+
// a keyboard user tabbing onto them saw nothing at all. `rounded-sm` keeps that
|
|
27
|
+
// ring hugging the word instead of drawing a pill round it.
|
|
28
|
+
link: "rounded-sm p-0 bg-transparent text-[var(--brand)] underline-offset-4 hover:underline focus:ring-[var(--brand)]"
|
|
17
29
|
};
|
|
18
|
-
function buttonClasses(variant = "primary",
|
|
19
|
-
|
|
30
|
+
function buttonClasses(variant = "primary", classNameOrOptions) {
|
|
31
|
+
const { size = "md", className } = typeof classNameOrOptions === "object" ? classNameOrOptions : { className: classNameOrOptions };
|
|
32
|
+
return cn(BUTTON_BASE, BUTTON_SIZES[size], buttonVariantClasses[variant], className);
|
|
20
33
|
}
|
|
21
|
-
function Button({ variant = "primary", stretch, className, ...rest }) {
|
|
34
|
+
function Button({ variant = "primary", size = "md", stretch, className, ...rest }) {
|
|
22
35
|
return /* @__PURE__ */ jsx(
|
|
23
36
|
"button",
|
|
24
37
|
{
|
|
25
38
|
...rest,
|
|
26
39
|
className: cn(
|
|
27
40
|
BUTTON_BASE,
|
|
41
|
+
BUTTON_SIZES[size],
|
|
28
42
|
// In a flex row next to a taller labelled field, `stretch` makes the button
|
|
29
43
|
// fill the field's height so the two line up (self-stretch overrides the row's
|
|
30
44
|
// align-items). No effect outside a flex row / when it's already the tallest.
|
|
@@ -37,6 +51,9 @@ function Button({ variant = "primary", stretch, className, ...rest }) {
|
|
|
37
51
|
}
|
|
38
52
|
const ICON_BUTTON_BASE = "inline-flex items-center justify-center rounded-md transition-colors focus:outline-none focus:ring-2 disabled:opacity-50 disabled:cursor-not-allowed";
|
|
39
53
|
const ICON_BUTTON_SIZES = {
|
|
54
|
+
// The 44px touch target (WCAG 2.5.5's size) with the same 20px glyph — keksdose's
|
|
55
|
+
// bulk-action bars write `size-11` by hand over an `md` button to get it on phones.
|
|
56
|
+
lg: "size-11 [&_svg]:size-5",
|
|
40
57
|
md: "size-9 [&_svg]:size-5",
|
|
41
58
|
sm: "size-8 [&_svg]:size-5",
|
|
42
59
|
xs: "size-7 rounded [&_svg]:size-4",
|
|
@@ -45,14 +62,39 @@ const ICON_BUTTON_SIZES = {
|
|
|
45
62
|
const ICON_BUTTON_TONES = {
|
|
46
63
|
default: "",
|
|
47
64
|
muted: "text-[var(--text-placeholder)] hover:bg-[var(--bg-surface-2)] hover:text-[var(--text-primary)]",
|
|
48
|
-
danger: "text-[var(--text-placeholder)] hover:bg-[var(--danger-bg)] hover:text-[var(--danger)] focus:ring-[var(--danger-border)]"
|
|
65
|
+
danger: "text-[var(--text-placeholder)] hover:bg-[var(--danger-bg)] hover:text-[var(--danger)] focus:ring-[var(--danger-border)]",
|
|
66
|
+
// Amber AT REST, unlike `danger`: a warning icon button is the one on the row that
|
|
67
|
+
// needs attention (keksdose's "needs review" flag on a transaction, the stale-rate
|
|
68
|
+
// marker), not an action repeated down a list — quiet grey would hide the very
|
|
69
|
+
// thing it is there to point out.
|
|
70
|
+
warning: "text-[var(--warning)] hover:bg-[var(--warning-bg)] focus:ring-[var(--warning-border)]",
|
|
71
|
+
// Sky at rest, for the same reason as `warning`: keksdose's reconcile action on an
|
|
72
|
+
// account row (accounts-page:867) is the one on the row to notice, and it is
|
|
73
|
+
// informational rather than a problem, so it takes the `--info` family.
|
|
74
|
+
info: "text-[var(--info)] hover:bg-[var(--info-bg)] focus:ring-[var(--info-border)]"
|
|
75
|
+
};
|
|
76
|
+
const ICON_BUTTON_DISABLED_REST = {
|
|
77
|
+
primary: "disabled:hover:bg-[var(--bg-surface-2)]",
|
|
78
|
+
secondary: "disabled:hover:bg-transparent",
|
|
79
|
+
ghost: "disabled:hover:bg-transparent",
|
|
80
|
+
danger: "disabled:hover:bg-[var(--danger)]",
|
|
81
|
+
brand: "disabled:hover:bg-[var(--brand)]",
|
|
82
|
+
link: "disabled:hover:bg-transparent disabled:hover:no-underline",
|
|
83
|
+
overlay: "disabled:hover:bg-[color-mix(in_srgb,var(--bg-inverse)_60%,transparent)]"
|
|
49
84
|
};
|
|
50
|
-
const
|
|
85
|
+
const ICON_BUTTON_TONES_DISABLED_REST = {
|
|
86
|
+
muted: "disabled:hover:text-[var(--text-placeholder)]",
|
|
87
|
+
danger: "disabled:hover:text-[var(--text-placeholder)]"
|
|
88
|
+
};
|
|
89
|
+
const ICON_BUTTON_PRESSED = "bg-[var(--brand-bg)] text-[var(--brand)] hover:bg-[var(--brand-bg-hover)] hover:text-[var(--brand)] disabled:hover:bg-[var(--brand-bg)] disabled:hover:text-[var(--brand)]";
|
|
90
|
+
const ICON_BUTTON_OVERLAY = "rounded-full bg-[color-mix(in_srgb,var(--bg-inverse)_60%,transparent)] text-[var(--text-inverse)] backdrop-blur-sm hover:bg-[color-mix(in_srgb,var(--bg-inverse)_75%,transparent)] focus:ring-[var(--text-inverse)]";
|
|
91
|
+
const IconButton = forwardRef(function IconButton2({ variant = "ghost", size = "md", tone = "default", pressed, stopPropagation, className, onClick, onKeyDown, ...rest }, ref) {
|
|
51
92
|
return /* @__PURE__ */ jsx(
|
|
52
93
|
"button",
|
|
53
94
|
{
|
|
54
95
|
ref,
|
|
55
96
|
...rest,
|
|
97
|
+
"aria-pressed": pressed ?? rest["aria-pressed"],
|
|
56
98
|
onClick: (e) => {
|
|
57
99
|
if (stopPropagation) e.stopPropagation();
|
|
58
100
|
onClick?.(e);
|
|
@@ -64,8 +106,12 @@ const IconButton = forwardRef(function IconButton2({ variant = "ghost", size = "
|
|
|
64
106
|
className: cn(
|
|
65
107
|
ICON_BUTTON_BASE,
|
|
66
108
|
ICON_BUTTON_SIZES[size],
|
|
67
|
-
|
|
109
|
+
// After the size, so the overlay's `rounded-full` beats the small sizes' `rounded`.
|
|
110
|
+
variant === "overlay" ? ICON_BUTTON_OVERLAY : buttonVariantClasses[variant],
|
|
111
|
+
ICON_BUTTON_DISABLED_REST[variant],
|
|
68
112
|
ICON_BUTTON_TONES[tone],
|
|
113
|
+
ICON_BUTTON_TONES_DISABLED_REST[tone],
|
|
114
|
+
pressed && ICON_BUTTON_PRESSED,
|
|
69
115
|
className
|
|
70
116
|
)
|
|
71
117
|
}
|
|
@@ -165,7 +211,7 @@ function FloatingField({
|
|
|
165
211
|
}
|
|
166
212
|
function FieldHint({
|
|
167
213
|
label,
|
|
168
|
-
side = "
|
|
214
|
+
side = "start",
|
|
169
215
|
className,
|
|
170
216
|
"aria-label": ariaLabel,
|
|
171
217
|
...rest
|
|
@@ -439,17 +485,19 @@ const Textarea = forwardRef(function Textarea2({ className, label, id, placehold
|
|
|
439
485
|
) }) });
|
|
440
486
|
});
|
|
441
487
|
Textarea.displayName = "Textarea";
|
|
442
|
-
function Card({ className, children, flush, ...rest }) {
|
|
488
|
+
function Card({ className, children, flush, variant = "default", ...rest }) {
|
|
443
489
|
return /* @__PURE__ */ jsx(
|
|
444
490
|
"div",
|
|
445
491
|
{
|
|
446
492
|
...rest,
|
|
447
493
|
className: cn(
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
494
|
+
variant === "inset" ? "rounded-md bg-[var(--bg-surface-2)] p-3" : cn(
|
|
495
|
+
// Surface + border are theme tokens so the palette switcher (feedback
|
|
496
|
+
// #307) can re-skin every card; a caller's own bg-*/border-* override
|
|
497
|
+
// still wins via tailwind-merge.
|
|
498
|
+
"bg-[var(--bg-surface)]",
|
|
499
|
+
flush ? "border-y border-[var(--border)] md:rounded-lg md:border md:shadow-sm" : "rounded-lg border border-[var(--border)] shadow-sm"
|
|
500
|
+
),
|
|
453
501
|
className
|
|
454
502
|
),
|
|
455
503
|
children
|
|
@@ -528,7 +576,7 @@ function Spinner({ className, label, ...rest }) {
|
|
|
528
576
|
" "
|
|
529
577
|
] }) });
|
|
530
578
|
}
|
|
531
|
-
function EmptyState({ title, hint, className, ...rest }) {
|
|
579
|
+
function EmptyState({ title, hint, icon, action, className, ...rest }) {
|
|
532
580
|
return /* @__PURE__ */ jsxs(
|
|
533
581
|
"div",
|
|
534
582
|
{
|
|
@@ -538,8 +586,10 @@ function EmptyState({ title, hint, className, ...rest }) {
|
|
|
538
586
|
className
|
|
539
587
|
),
|
|
540
588
|
children: [
|
|
589
|
+
icon != null && /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "mb-3 text-[var(--text-placeholder)] [&_svg]:size-8", children: icon }),
|
|
541
590
|
/* @__PURE__ */ jsx("div", { className: "font-medium text-[var(--text-secondary)]", children: title }),
|
|
542
|
-
hint && /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs", children: hint })
|
|
591
|
+
hint && /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs", children: hint }),
|
|
592
|
+
action != null && /* @__PURE__ */ jsx("div", { className: "mt-4 flex flex-wrap items-center justify-center gap-2", children: action })
|
|
543
593
|
]
|
|
544
594
|
}
|
|
545
595
|
);
|
|
@@ -549,6 +599,10 @@ const DEFAULT_TABS_LABELS = {
|
|
|
549
599
|
remove: (tab) => `Remove ${tab}`
|
|
550
600
|
};
|
|
551
601
|
const TABLIST_CLASSES = "flex gap-1 overflow-x-auto overflow-y-hidden border-b border-[var(--border)]";
|
|
602
|
+
const TABLIST_VERTICAL_CLASSES = "flex flex-col gap-0.5";
|
|
603
|
+
const TAB_VERTICAL_CLASSES = "flex w-full items-center rounded-md px-3 py-2 text-start text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-[var(--border-strong)]";
|
|
604
|
+
const TAB_VERTICAL_ACTIVE_CLASSES = "bg-[var(--bg-active)] text-[var(--text-primary)]";
|
|
605
|
+
const TAB_VERTICAL_INACTIVE_CLASSES = "text-[var(--text-muted)] hover:bg-[var(--bg-hover)] hover:text-[var(--text-primary)]";
|
|
552
606
|
const TABLIST_WRAP_CLASSES = "flex flex-wrap gap-1.5 md:flex-nowrap md:gap-1 md:overflow-x-auto md:overflow-y-hidden md:border-b md:border-[var(--border)]";
|
|
553
607
|
const TAB_CLASSES = "whitespace-nowrap px-3 py-2 text-sm font-medium transition-colors border-b-2 -mb-px focus:outline-none focus:ring-2 focus:ring-[var(--border-strong)]";
|
|
554
608
|
const TAB_ACTIVE_CLASSES = "border-[var(--text-primary)] text-[var(--text-primary)]";
|
|
@@ -574,10 +628,13 @@ function Tabs({
|
|
|
574
628
|
addLabel,
|
|
575
629
|
labels,
|
|
576
630
|
busy = false,
|
|
631
|
+
orientation = "horizontal",
|
|
577
632
|
"aria-label": ariaLabel,
|
|
578
633
|
...rest
|
|
579
634
|
}) {
|
|
580
635
|
const text = useKitLabels("tabs", DEFAULT_TABS_LABELS, labels);
|
|
636
|
+
const phone = useMediaQuery(PHONE_QUERY, false);
|
|
637
|
+
const vertical = orientation === "vertical" && !phone;
|
|
581
638
|
const stripRef = useRef(null);
|
|
582
639
|
const isRemovable = (tab) => onRemove !== void 0 && tab.removable !== false;
|
|
583
640
|
const deletesOnKey = (tab) => isRemovable(tab) && (removeOn === "every" || tab.id === active);
|
|
@@ -610,7 +667,7 @@ function Tabs({
|
|
|
610
667
|
if (!busy) requestRemove(tab.id);
|
|
611
668
|
return;
|
|
612
669
|
}
|
|
613
|
-
const step = horizontalStep(e.key, e.currentTarget);
|
|
670
|
+
const step = vertical ? e.key === "ArrowDown" ? 1 : e.key === "ArrowUp" ? -1 : 0 : horizontalStep(e.key, e.currentTarget);
|
|
614
671
|
if (step === 0 && e.key !== "Home" && e.key !== "End") return;
|
|
615
672
|
const strip = e.currentTarget.closest('[role="tablist"]');
|
|
616
673
|
if (!strip) return;
|
|
@@ -628,8 +685,9 @@ function Tabs({
|
|
|
628
685
|
ref: stripRef,
|
|
629
686
|
role: "tablist",
|
|
630
687
|
"aria-label": ariaLabel ?? label,
|
|
688
|
+
"aria-orientation": vertical ? "vertical" : void 0,
|
|
631
689
|
className: cn(
|
|
632
|
-
wrap ? TABLIST_WRAP_CLASSES : TABLIST_CLASSES,
|
|
690
|
+
vertical ? TABLIST_VERTICAL_CLASSES : wrap ? TABLIST_WRAP_CLASSES : TABLIST_CLASSES,
|
|
633
691
|
onAdd ? "min-w-0" : className
|
|
634
692
|
),
|
|
635
693
|
children: tabs.map((tab) => {
|
|
@@ -656,21 +714,36 @@ function Tabs({
|
|
|
656
714
|
id: isActive && panelId ? `${panelId}-tab` : void 0,
|
|
657
715
|
"aria-keyshortcuts": deletesOnKey(tab) ? "Delete" : void 0,
|
|
658
716
|
onKeyDown: (e) => onTabKeyDown(e, tab),
|
|
659
|
-
className: cn(
|
|
717
|
+
className: vertical ? cn(
|
|
718
|
+
TAB_VERTICAL_CLASSES,
|
|
719
|
+
isActive ? TAB_VERTICAL_ACTIVE_CLASSES : TAB_VERTICAL_INACTIVE_CLASSES,
|
|
720
|
+
removable && "pe-8"
|
|
721
|
+
) : cn(
|
|
660
722
|
wrap ? TAB_WRAP_CLASSES : TAB_CLASSES,
|
|
661
723
|
wrap ? isActive ? TAB_WRAP_ACTIVE_CLASSES : TAB_WRAP_INACTIVE_CLASSES : isActive ? TAB_ACTIVE_CLASSES : TAB_INACTIVE_CLASSES,
|
|
662
724
|
removable && TAB_REMOVABLE_CLASSES
|
|
663
725
|
)
|
|
664
726
|
};
|
|
665
|
-
const inner = /* @__PURE__ */ jsxs(
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
727
|
+
const inner = /* @__PURE__ */ jsxs(
|
|
728
|
+
"span",
|
|
729
|
+
{
|
|
730
|
+
className: cn(
|
|
731
|
+
// In a side nav the row is the full width, so the label takes it and a
|
|
732
|
+
// badge lands at the row's end, where a column of counts lines up.
|
|
733
|
+
vertical ? "flex min-w-0 flex-1 items-center gap-1.5" : "inline-flex items-center gap-1.5",
|
|
734
|
+
tab.empty && TAB_EMPTY_CLASSES
|
|
735
|
+
),
|
|
736
|
+
children: [
|
|
737
|
+
tab.icon != null && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "inline-flex shrink-0 items-center gap-0.5", children: tab.icon }),
|
|
738
|
+
tab.detail != null ? /* @__PURE__ */ jsxs("span", { className: "flex flex-col items-start text-start", children: [
|
|
739
|
+
/* @__PURE__ */ jsx("span", { children: tab.label }),
|
|
740
|
+
" ",
|
|
741
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-normal leading-tight text-[var(--text-muted)]", children: tab.detail })
|
|
742
|
+
] }) : tab.label,
|
|
743
|
+
tab.badge != null ? vertical ? /* @__PURE__ */ jsx("span", { className: "ms-auto flex shrink-0 items-center", children: tab.badge }) : tab.badge : null
|
|
744
|
+
]
|
|
745
|
+
}
|
|
746
|
+
);
|
|
674
747
|
const element = tab.href ? /* @__PURE__ */ jsx(
|
|
675
748
|
"a",
|
|
676
749
|
{
|
|
@@ -697,7 +770,7 @@ function Tabs({
|
|
|
697
770
|
// The × cannot go INSIDE the tab: a button in a button is invalid HTML, and
|
|
698
771
|
// a tab's children are presentational, so a reader would flatten it into the
|
|
699
772
|
// tab's name. It sits beside the tab, over the gutter the tab reserves.
|
|
700
|
-
/* @__PURE__ */ jsxs("div", { className: "relative flex shrink-0", children: [
|
|
773
|
+
/* @__PURE__ */ jsxs("div", { className: cn("relative flex", !vertical && "shrink-0"), children: [
|
|
701
774
|
element,
|
|
702
775
|
isActive && /* @__PURE__ */ jsx(
|
|
703
776
|
IconButton,
|
|
@@ -724,6 +797,15 @@ function Tabs({
|
|
|
724
797
|
}
|
|
725
798
|
);
|
|
726
799
|
if (!onAdd) return tablist;
|
|
800
|
+
if (vertical) {
|
|
801
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-0.5", className), children: [
|
|
802
|
+
tablist,
|
|
803
|
+
/* @__PURE__ */ jsxs("button", { type: "button", onClick: onAdd, disabled: busy, className: TAB_ADD_CLASSES, children: [
|
|
804
|
+
/* @__PURE__ */ jsx(Plus, { "aria-hidden": true }),
|
|
805
|
+
addLabel ?? text.add
|
|
806
|
+
] })
|
|
807
|
+
] });
|
|
808
|
+
}
|
|
727
809
|
return /* @__PURE__ */ jsxs(
|
|
728
810
|
"div",
|
|
729
811
|
{
|