@squadbase/vantage 0.6.2-dev1.ac99e02 → 0.6.2-dev1.d7c0911
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{build-MFWRPYKW.js → build-X5NVCQKT.js} +4 -4
- package/dist/{build-MFWRPYKW.js.map → build-X5NVCQKT.js.map} +1 -1
- package/dist/{chunk-IBGOCWJB.js → chunk-2ICNHUG6.js} +186 -82
- package/dist/chunk-2ICNHUG6.js.map +1 -0
- package/dist/{chunk-5ZOP4SQR.js → chunk-2N72FKLB.js} +12 -7
- package/dist/chunk-2N72FKLB.js.map +1 -0
- package/dist/{chunk-PXRX5PEC.js → chunk-PDOBHMUQ.js} +3 -3
- package/dist/chunk-PDOBHMUQ.js.map +1 -0
- package/dist/{chunk-A2UUGASH.js → chunk-U736PVHY.js} +2 -2
- package/dist/chunk-U736PVHY.js.map +1 -0
- package/dist/{chunk-QEWCYW3I.js → chunk-WAMZWZJB.js} +13 -3
- package/dist/chunk-WAMZWZJB.js.map +1 -0
- package/dist/chunk-WRSX2MDK.js +7866 -0
- package/dist/chunk-WRSX2MDK.js.map +1 -0
- package/dist/{chunk-OB6UBJXF.js → chunk-XPQSTZUU.js} +125 -35
- package/dist/chunk-XPQSTZUU.js.map +1 -0
- package/dist/cli.js +3 -3
- package/dist/components/index.d.ts +1831 -99
- package/dist/components/index.js +4 -4
- package/dist/{dev-DCTOHQ6W.js → dev-4XEDTELV.js} +4 -4
- package/dist/{dev-DCTOHQ6W.js.map → dev-4XEDTELV.js.map} +1 -1
- package/dist/doc/index.js +2 -2
- package/dist/doc/index.js.map +1 -1
- package/dist/markdown/index.js +1 -1
- package/dist/markdown/index.js.map +1 -1
- package/dist/table/index.js +5 -5
- package/dist/table/index.js.map +1 -1
- package/dist/ui/index.d.ts +4 -1
- package/dist/ui/index.js +21 -111
- package/dist/ui/index.js.map +1 -1
- package/dist/{upgrade-DBBE6GIR.js → upgrade-JHXZBGQS.js} +3 -3
- package/dist/{upgrade-DBBE6GIR.js.map → upgrade-JHXZBGQS.js.map} +1 -1
- package/dist/vite/index.js +2 -2
- package/docs/en/components.md +29 -15
- package/docs/en/parts/data-table.md +22 -0
- package/docs/en/parts/delta.md +50 -0
- package/docs/en/parts/format.md +43 -0
- package/docs/en/parts/kpi-card.md +57 -0
- package/docs/en/parts/metric-value.md +3 -2
- package/docs/en/parts/sparkline.md +1 -1
- package/docs/en/parts/trend-indicator.md +17 -1
- package/docs/en/ui-and-theming.md +1 -1
- package/docs/index.json +92 -32
- package/docs/ja/changelog.md +5 -0
- package/docs/ja/components.md +27 -15
- package/docs/ja/parts/data-table.md +22 -0
- package/docs/ja/parts/delta.md +50 -0
- package/docs/ja/parts/format.md +44 -0
- package/docs/ja/parts/kpi-card.md +55 -0
- package/docs/ja/parts/metric-value.md +3 -2
- package/docs/ja/parts/sparkline.md +1 -1
- package/docs/ja/parts/trend-indicator.md +17 -1
- package/docs/ja/ui-and-theming.md +2 -2
- package/package.json +2 -1
- package/registry/ui/accordion.tsx +4 -2
- package/registry/ui/alert-dialog.tsx +3 -3
- package/registry/ui/alert.tsx +3 -1
- package/registry/ui/app-shell.tsx +7 -1
- package/registry/ui/area-chart.tsx +2781 -157
- package/registry/ui/avatar.tsx +1 -1
- package/registry/ui/badge.tsx +3 -1
- package/registry/ui/bar-chart.tsx +2780 -157
- package/registry/ui/bar-list.tsx +3471 -93
- package/registry/ui/breadcrumb.tsx +3 -1
- package/registry/ui/button.tsx +3 -1
- package/registry/ui/calendar.tsx +3 -1
- package/registry/ui/card.tsx +4 -2
- package/registry/ui/category-bar.tsx +990 -16
- package/registry/ui/chart-frame.tsx +1358 -0
- package/registry/ui/checkbox.tsx +3 -1
- package/registry/ui/collapsible.tsx +3 -1
- package/registry/ui/combobox.tsx +2 -2
- package/registry/ui/command.tsx +3 -1
- package/registry/ui/dashboard-card.tsx +69 -26
- package/registry/ui/data-table.tsx +678 -56
- package/registry/ui/date-range-picker.tsx +245 -64
- package/registry/ui/delta.tsx +188 -0
- package/registry/ui/dialog.tsx +5 -3
- package/registry/ui/donut-chart.tsx +2857 -173
- package/registry/ui/drawer.tsx +1 -1
- package/registry/ui/dropdown-menu.tsx +5 -3
- package/registry/ui/echart.tsx +448 -44
- package/registry/ui/field.tsx +1 -1
- package/registry/ui/filter-bar.tsx +33 -6
- package/registry/ui/funnel-steps.tsx +3316 -49
- package/registry/ui/heatmap.tsx +1752 -0
- package/registry/ui/hover-card.tsx +2 -2
- package/registry/ui/input-group.tsx +3 -1
- package/registry/ui/input.tsx +3 -1
- package/registry/ui/kbd.tsx +3 -1
- package/registry/ui/kpi-card.tsx +677 -0
- package/registry/ui/label.tsx +3 -1
- package/registry/ui/legend.tsx +3500 -0
- package/registry/ui/line-chart.tsx +2781 -151
- package/registry/ui/metric-value.tsx +9 -1
- package/registry/ui/multi-select.tsx +11 -5
- package/registry/ui/page-shell.tsx +104 -49
- package/registry/ui/pagination.tsx +3 -1
- package/registry/ui/placeholder.tsx +8 -2
- package/registry/ui/popover.tsx +4 -2
- package/registry/ui/progress-circle.tsx +607 -12
- package/registry/ui/progress.tsx +3 -1
- package/registry/ui/radio-group.tsx +1 -1
- package/registry/ui/sample-data.tsx +86 -0
- package/registry/ui/scatter-chart.tsx +4150 -0
- package/registry/ui/scroll-area.tsx +3 -2
- package/registry/ui/searchable-select.tsx +8 -3
- package/registry/ui/section-header.tsx +4 -2
- package/registry/ui/segmented-control.tsx +7 -2
- package/registry/ui/select.tsx +4 -2
- package/registry/ui/separator.tsx +3 -1
- package/registry/ui/sheet.tsx +4 -2
- package/registry/ui/sidebar.tsx +4 -2
- package/registry/ui/skeleton.tsx +4 -2
- package/registry/ui/slider.tsx +3 -1
- package/registry/ui/sparkline.tsx +84 -9
- package/registry/ui/spinner.tsx +3 -1
- package/registry/ui/states.tsx +34 -5
- package/registry/ui/status-badge.tsx +81 -39
- package/registry/ui/switch.tsx +3 -1
- package/registry/ui/table.tsx +4 -2
- package/registry/ui/tabs.tsx +5 -3
- package/registry/ui/textarea.tsx +3 -1
- package/registry/ui/toast.tsx +2 -2
- package/registry/ui/toggle-group.tsx +3 -1
- package/registry/ui/toggle.tsx +3 -1
- package/registry/ui/tooltip.tsx +4 -2
- package/registry/ui/tracker.tsx +624 -17
- package/registry/ui/trend-indicator.tsx +13 -1
- package/registry/ui/updated-at.tsx +122 -0
- package/registry/ui/waterfall-chart.tsx +4186 -0
- package/templates/AGENTS.md +13 -1
- package/theme.css +237 -136
- package/dist/chunk-5ZOP4SQR.js.map +0 -1
- package/dist/chunk-A2UUGASH.js.map +0 -1
- package/dist/chunk-AG6RZ2RR.js +0 -3208
- package/dist/chunk-AG6RZ2RR.js.map +0 -1
- package/dist/chunk-IBGOCWJB.js.map +0 -1
- package/dist/chunk-OB6UBJXF.js.map +0 -1
- package/dist/chunk-PXRX5PEC.js.map +0 -1
- package/dist/chunk-QEWCYW3I.js.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Copied by `vantage add ui scroll-area`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
3
|
-
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/scroll-area.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
4
5
|
import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area"
|
|
5
6
|
|
|
6
7
|
import { cn } from "@squadbase/vantage/ui"
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Copied by `vantage add ui searchable-select`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/components/searchable-select.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* SearchableSelect — a single-select combobox with a filter box. Filtering runs
|
|
5
7
|
* client-side over the given options; pass `onSearch` to take it over yourself
|
|
@@ -17,7 +19,7 @@ import { CheckIcon, LoaderIcon, XIcon } from "lucide-react"
|
|
|
17
19
|
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@squadbase/vantage/ui"
|
|
18
20
|
import { isGroupedOptions, type SelectOption } from "@squadbase/vantage/components"
|
|
19
21
|
|
|
20
|
-
/* ---------- inlined from
|
|
22
|
+
/* ---------- inlined from @squadbase/squadkit registry/components/option-command.tsx (internal to @squadbase/vantage) ---------- */
|
|
21
23
|
|
|
22
24
|
interface OptionCommandListProps {
|
|
23
25
|
options: SelectOptions
|
|
@@ -134,10 +136,13 @@ export interface SearchableSelectProps {
|
|
|
134
136
|
className?: string
|
|
135
137
|
}
|
|
136
138
|
|
|
139
|
+
/** Not given yet (a draft fills props in steps): render empty, keep the same value between renders. */
|
|
140
|
+
const NO_OPTIONS: never[] = []
|
|
141
|
+
|
|
137
142
|
export const SearchableSelect = forwardRef<HTMLDivElement, SearchableSelectProps>(
|
|
138
143
|
function SearchableSelect(
|
|
139
144
|
{
|
|
140
|
-
options,
|
|
145
|
+
options = NO_OPTIONS,
|
|
141
146
|
value,
|
|
142
147
|
onChange,
|
|
143
148
|
onSearch,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Copied by `vantage add ui section-header`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/components/section-header.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* SectionHeader — a titled divider inside a page: heading, optional
|
|
5
7
|
* description, and right-aligned actions that wrap below on narrow screens.
|
|
@@ -10,7 +12,7 @@ import { cn } from "@squadbase/vantage/ui"
|
|
|
10
12
|
|
|
11
13
|
const headingStyles = {
|
|
12
14
|
h1: "text-3xl font-bold tracking-tight",
|
|
13
|
-
h2: "text-
|
|
15
|
+
h2: "text-xl font-semibold tracking-tight",
|
|
14
16
|
h3: "text-xl font-semibold",
|
|
15
17
|
h4: "text-lg font-semibold",
|
|
16
18
|
} as const
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Copied by `vantage add ui segmented-control`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/components/segmented-control.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* SegmentedControl — a single-select row of buttons over `ToggleGroup`. Base
|
|
5
7
|
* UI's toggle group is multi-value by default, so this wrapper narrows it to
|
|
@@ -27,9 +29,12 @@ export interface SegmentedControlProps {
|
|
|
27
29
|
className?: string
|
|
28
30
|
}
|
|
29
31
|
|
|
32
|
+
/** Not given yet (a draft fills props in steps): render empty, keep the same value between renders. */
|
|
33
|
+
const NO_OPTIONS: never[] = []
|
|
34
|
+
|
|
30
35
|
export const SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(
|
|
31
36
|
function SegmentedControl(
|
|
32
|
-
{ options, value, onChange, size = "default", fullWidth = false, ariaLabel, className },
|
|
37
|
+
{ options = NO_OPTIONS, value, onChange, size = "default", fullWidth = false, ariaLabel, className },
|
|
33
38
|
ref,
|
|
34
39
|
) {
|
|
35
40
|
return (
|
package/registry/ui/select.tsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Copied by `vantage add ui select`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/select.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
import * as React from "react"
|
|
4
6
|
import { Select as SelectPrimitive } from "@base-ui/react/select"
|
|
5
7
|
|
|
@@ -128,7 +130,7 @@ function SelectContent({
|
|
|
128
130
|
data-slot="select-content"
|
|
129
131
|
data-align-trigger={alignItemWithTrigger}
|
|
130
132
|
className={cn(
|
|
131
|
-
"cn-menu-target cn-menu-translucent relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
133
|
+
"cn-menu-target cn-menu-translucent relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in motion-reduce:animate-none! data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
132
134
|
className
|
|
133
135
|
)}
|
|
134
136
|
{...props}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Copied by `vantage add ui separator`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/separator.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
import { Separator as SeparatorPrimitive } from "@base-ui/react/separator"
|
|
4
6
|
|
|
5
7
|
import { cn } from "@squadbase/vantage/ui"
|
package/registry/ui/sheet.tsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Copied by `vantage add ui sheet`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/sheet.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
import * as React from "react"
|
|
4
6
|
import { Dialog as SheetPrimitive } from "@base-ui/react/dialog"
|
|
5
7
|
|
|
@@ -53,7 +55,7 @@ function SheetContent({
|
|
|
53
55
|
data-slot="sheet-content"
|
|
54
56
|
data-side={side}
|
|
55
57
|
className={cn(
|
|
56
|
-
"fixed z-50 flex flex-col gap-4 bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg transition duration-200 ease-
|
|
58
|
+
"fixed z-50 flex flex-col gap-4 bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg transition duration-200 ease-out data-ending-style:opacity-0 data-starting-style:opacity-0 motion-reduce:data-ending-style:translate-none! motion-reduce:data-starting-style:translate-none! data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=bottom]:data-ending-style:translate-y-[2.5rem] data-[side=bottom]:data-starting-style:translate-y-[2.5rem] data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=left]:data-ending-style:translate-x-[-2.5rem] data-[side=left]:data-starting-style:translate-x-[-2.5rem] data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=right]:data-ending-style:translate-x-[2.5rem] data-[side=right]:data-starting-style:translate-x-[2.5rem] data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=top]:data-ending-style:translate-y-[-2.5rem] data-[side=top]:data-starting-style:translate-y-[-2.5rem] data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm",
|
|
57
59
|
className
|
|
58
60
|
)}
|
|
59
61
|
{...props}
|
package/registry/ui/sidebar.tsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Copied by `vantage add ui sidebar`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/sidebar.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
import * as React from "react"
|
|
4
6
|
import { mergeProps } from "@base-ui/react/merge-props"
|
|
5
7
|
import { useRender } from "@base-ui/react/use-render"
|
|
@@ -289,7 +291,7 @@ function SidebarRail({ className, ...props }: React.ComponentProps<"button">) {
|
|
|
289
291
|
onClick={toggleSidebar}
|
|
290
292
|
title="Toggle Sidebar"
|
|
291
293
|
className={cn(
|
|
292
|
-
"absolute inset-y-0 z-20 hidden w-4 transition-
|
|
294
|
+
"absolute inset-y-0 z-20 hidden w-4 transition-[background-color,translate,left,right] ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] hover:after:bg-sidebar-border sm:flex ltr:-translate-x-1/2 rtl:-translate-x-1/2",
|
|
293
295
|
"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
|
|
294
296
|
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
|
|
295
297
|
"group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar",
|
package/registry/ui/skeleton.tsx
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
// Copied by `vantage add ui skeleton`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/skeleton.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
import { cn } from "@squadbase/vantage/ui"
|
|
4
6
|
|
|
5
7
|
function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
|
|
6
8
|
return (
|
|
7
9
|
<div
|
|
8
10
|
data-slot="skeleton"
|
|
9
|
-
className={cn("animate-pulse rounded-md bg-muted", className)}
|
|
11
|
+
className={cn("animate-pulse motion-reduce:animate-none rounded-md bg-muted", className)}
|
|
10
12
|
{...props}
|
|
11
13
|
/>
|
|
12
14
|
)
|
package/registry/ui/slider.tsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Copied by `vantage add ui slider`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/slider.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
import { Slider as SliderPrimitive } from "@base-ui/react/slider"
|
|
4
6
|
|
|
5
7
|
import { cn } from "@squadbase/vantage/ui"
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Copied by `vantage add ui sparkline`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/charts/sparkline.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* Sparkline — an inline trend micro-chart. Deliberately *not* an `EChart`: a
|
|
5
7
|
* sparkline sits inside table cells and KPI tiles by the dozen, where one
|
|
@@ -9,6 +11,7 @@
|
|
|
9
11
|
import { forwardRef, useEffect, useState, type SVGAttributes } from "react"
|
|
10
12
|
|
|
11
13
|
import { cn } from "@squadbase/vantage/ui"
|
|
14
|
+
import type { ChartHighlight } from "@squadbase/vantage/components"
|
|
12
15
|
|
|
13
16
|
export type SparklineVariant = "line" | "bar"
|
|
14
17
|
|
|
@@ -24,7 +27,15 @@ export interface SparklineProps extends SVGAttributes<SVGSVGElement> {
|
|
|
24
27
|
/** Tailwind text-colour class; drives both stroke and fill via `currentColor`. */
|
|
25
28
|
color?: string
|
|
26
29
|
area?: boolean
|
|
30
|
+
/** マウント時に線を引く / 棒を伸ばす。既定 `false`(`prefers-reduced-motion` では常に無効)。 */
|
|
27
31
|
animate?: boolean
|
|
32
|
+
/**
|
|
33
|
+
* 点の強調(Tufte 流)。`"auto"` は最新・最大・最小の 3 点だけに小さな点を打つ
|
|
34
|
+
* (最新は系列の色、最大・最小は muted)。`"latest"` は最新の 1 点だけ、`"none"` は線だけ。`variant="line"` のときだけ効く。既定 `"auto"`。
|
|
35
|
+
*/
|
|
36
|
+
highlight?: ChartHighlight | "latest"
|
|
37
|
+
/** 指定すると `role="img"` で読み上げ対象にする。省略時は装飾として `aria-hidden`。 */
|
|
38
|
+
"aria-label"?: string
|
|
28
39
|
className?: string
|
|
29
40
|
}
|
|
30
41
|
|
|
@@ -55,6 +66,37 @@ function buildAreaPath(ys: number[], height: number): string {
|
|
|
55
66
|
return `${buildLinePath(ys)} L${lastX},${height} L0,${height} Z`
|
|
56
67
|
}
|
|
57
68
|
|
|
69
|
+
export type SparklinePointKind = "latest" | "max" | "min"
|
|
70
|
+
|
|
71
|
+
export interface SparklinePoint {
|
|
72
|
+
kind: SparklinePointKind
|
|
73
|
+
index: number
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The points a Tufte-style sparkline marks: the latest, the max and the min.
|
|
78
|
+
* A point that is both latest and max/min is drawn once, as `latest`; a flat
|
|
79
|
+
* series marks only the latest. Ties pick the most recent occurrence.
|
|
80
|
+
*/
|
|
81
|
+
export function sparklineHighlightPoints(values: number[]): SparklinePoint[] {
|
|
82
|
+
if (values.length === 0) return []
|
|
83
|
+
const last = values.length - 1
|
|
84
|
+
const points: SparklinePoint[] = [{ kind: "latest", index: last }]
|
|
85
|
+
let maxI = 0
|
|
86
|
+
let minI = 0
|
|
87
|
+
let max = values[0] as number
|
|
88
|
+
let min = max
|
|
89
|
+
values.forEach((v, i) => {
|
|
90
|
+
if (v >= max) [max, maxI] = [v, i]
|
|
91
|
+
if (v <= min) [min, minI] = [v, i]
|
|
92
|
+
})
|
|
93
|
+
const latest = values[last] as number
|
|
94
|
+
if (max === min) return points
|
|
95
|
+
if (max !== latest) points.push({ kind: "max", index: maxI })
|
|
96
|
+
if (min !== latest) points.push({ kind: "min", index: minI })
|
|
97
|
+
return points
|
|
98
|
+
}
|
|
99
|
+
|
|
58
100
|
interface BarRect {
|
|
59
101
|
x: number
|
|
60
102
|
y: number
|
|
@@ -67,14 +109,19 @@ function buildBarRects(ys: number[], height: number, gap = 1): BarRect[] {
|
|
|
67
109
|
return ys.map((y, i) => ({ x: i * (barW + gap), y, w: barW, h: height - y }))
|
|
68
110
|
}
|
|
69
111
|
|
|
112
|
+
/** Rows not given yet (a draft fills props in steps): draw the empty state, keep the same array between renders. */
|
|
113
|
+
const NO_ROWS: never[] = []
|
|
114
|
+
|
|
70
115
|
export const Sparkline = forwardRef<SVGSVGElement, SparklineProps>(function Sparkline(
|
|
71
116
|
{
|
|
72
|
-
data,
|
|
117
|
+
data = NO_ROWS,
|
|
73
118
|
variant = "line",
|
|
74
119
|
height = 40,
|
|
75
120
|
color = "text-chart-1",
|
|
76
121
|
area = false,
|
|
77
122
|
animate = false,
|
|
123
|
+
highlight = "auto",
|
|
124
|
+
"aria-label": ariaLabel,
|
|
78
125
|
className,
|
|
79
126
|
...props
|
|
80
127
|
},
|
|
@@ -88,10 +135,17 @@ export const Sparkline = forwardRef<SVGSVGElement, SparklineProps>(function Spar
|
|
|
88
135
|
|
|
89
136
|
if (data.length === 0) return null
|
|
90
137
|
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
138
|
+
const values = data.map((d) => d.value)
|
|
139
|
+
const ys = normalizeData(values, height)
|
|
140
|
+
const step = ys.length > 1 ? VB_WIDTH / (ys.length - 1) : 0
|
|
141
|
+
const points =
|
|
142
|
+
variant !== "line"
|
|
143
|
+
? []
|
|
144
|
+
: highlight === "auto"
|
|
145
|
+
? sparklineHighlightPoints(values)
|
|
146
|
+
: highlight === "latest"
|
|
147
|
+
? [{ kind: "latest" as const, index: values.length - 1 }]
|
|
148
|
+
: []
|
|
95
149
|
|
|
96
150
|
return (
|
|
97
151
|
<svg
|
|
@@ -101,7 +155,9 @@ export const Sparkline = forwardRef<SVGSVGElement, SparklineProps>(function Spar
|
|
|
101
155
|
preserveAspectRatio="none"
|
|
102
156
|
width="100%"
|
|
103
157
|
height={height}
|
|
104
|
-
|
|
158
|
+
role={ariaLabel ? "img" : undefined}
|
|
159
|
+
aria-label={ariaLabel}
|
|
160
|
+
aria-hidden={ariaLabel ? undefined : true}
|
|
105
161
|
className={cn("overflow-visible", className)}
|
|
106
162
|
{...props}
|
|
107
163
|
>
|
|
@@ -124,9 +180,28 @@ export const Sparkline = forwardRef<SVGSVGElement, SparklineProps>(function Spar
|
|
|
124
180
|
pathLength={animate ? 1 : undefined}
|
|
125
181
|
strokeDasharray={animate ? 1 : undefined}
|
|
126
182
|
strokeDashoffset={animate ? (mounted ? 0 : 1) : undefined}
|
|
127
|
-
className={cn("stroke-current", color)}
|
|
183
|
+
className={cn("stroke-current", animate && "motion-reduce:transition-none!", color)}
|
|
128
184
|
style={animate ? { transition: "stroke-dashoffset 0.6s ease-in-out" } : undefined}
|
|
129
185
|
/>
|
|
186
|
+
{/* A zero-length round-capped stroke with a non-scaling width stays a
|
|
187
|
+
circle even though the viewBox stretches (`preserveAspectRatio="none"`). */}
|
|
188
|
+
{points.map((p) => {
|
|
189
|
+
const x = (p.index * step).toFixed(2)
|
|
190
|
+
const y = (ys[p.index] ?? 0).toFixed(2)
|
|
191
|
+
return (
|
|
192
|
+
<path
|
|
193
|
+
key={p.kind}
|
|
194
|
+
data-slot="sparkline-point"
|
|
195
|
+
data-point={p.kind}
|
|
196
|
+
d={`M${x},${y} L${x},${y}`}
|
|
197
|
+
fill="none"
|
|
198
|
+
strokeWidth={p.kind === "latest" ? 5 : 4}
|
|
199
|
+
strokeLinecap="round"
|
|
200
|
+
vectorEffect="non-scaling-stroke"
|
|
201
|
+
className={cn("stroke-current", p.kind === "latest" ? color : "text-muted-foreground")}
|
|
202
|
+
/>
|
|
203
|
+
)
|
|
204
|
+
})}
|
|
130
205
|
</>
|
|
131
206
|
)}
|
|
132
207
|
|
|
@@ -139,7 +214,7 @@ export const Sparkline = forwardRef<SVGSVGElement, SparklineProps>(function Spar
|
|
|
139
214
|
width={rect.w}
|
|
140
215
|
height={animate ? (mounted ? rect.h : 0) : rect.h}
|
|
141
216
|
rx={0.5}
|
|
142
|
-
className={cn("fill-current", color)}
|
|
217
|
+
className={cn("fill-current", animate && "motion-reduce:transition-none!", color)}
|
|
143
218
|
style={
|
|
144
219
|
animate
|
|
145
220
|
? {
|
package/registry/ui/spinner.tsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Copied by `vantage add ui spinner`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/spinner.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
import { cn } from "@squadbase/vantage/ui"
|
|
4
6
|
import { Loader2Icon } from "lucide-react"
|
|
5
7
|
|
package/registry/ui/states.tsx
CHANGED
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
// Copied by `vantage add ui states`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/states.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Loading / Empty / ErrorState — the three non-data states of a panel, worded for
|
|
7
|
+
* business users. Defaults are Japanese and say what is happening, not why the
|
|
8
|
+
* system failed: keep raw errors ("upstream timeout after 30s") in `details`,
|
|
9
|
+
* which stays folded behind "詳細を表示".
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* import { ErrorState } from "@/components/ui/states"
|
|
13
|
+
* // Vantage: import { ErrorState } from "@squadbase/vantage/ui"
|
|
14
|
+
*
|
|
15
|
+
* <ErrorState
|
|
16
|
+
* title="売上を読み込めませんでした"
|
|
17
|
+
* message="データソースから時間内に応答がありませんでした。しばらくしてから再試行してください。"
|
|
18
|
+
* details={error.message}
|
|
19
|
+
* action={<Button variant="outline" onClick={retry}>再試行する</Button>}
|
|
20
|
+
* />
|
|
21
|
+
*/
|
|
3
22
|
import type { ReactNode } from "react"
|
|
4
23
|
import { cn } from "@squadbase/vantage/ui"
|
|
5
24
|
|
|
6
|
-
export function Loading({ label = "
|
|
25
|
+
export function Loading({ label = "読み込んでいます…", className }: { label?: string; className?: string }) {
|
|
7
26
|
return (
|
|
8
27
|
<div className={cn("flex min-h-[30vh] items-center justify-center", className)} role="status" aria-live="polite">
|
|
9
28
|
<div className="flex items-center gap-3 text-sm text-muted-foreground">
|
|
@@ -15,7 +34,7 @@ export function Loading({ label = "Loading…", className }: { label?: string; c
|
|
|
15
34
|
}
|
|
16
35
|
|
|
17
36
|
export function Empty({
|
|
18
|
-
title = "
|
|
37
|
+
title = "表示できるデータがありません",
|
|
19
38
|
description,
|
|
20
39
|
icon,
|
|
21
40
|
action,
|
|
@@ -38,13 +57,17 @@ export function Empty({
|
|
|
38
57
|
}
|
|
39
58
|
|
|
40
59
|
export function ErrorState({
|
|
41
|
-
title = "
|
|
42
|
-
message,
|
|
60
|
+
title = "データを読み込めませんでした",
|
|
61
|
+
message = "時間をおいて再試行してください。解決しない場合は管理者にお問い合わせください。",
|
|
62
|
+
details,
|
|
43
63
|
action,
|
|
44
64
|
className,
|
|
45
65
|
}: {
|
|
46
66
|
title?: string
|
|
67
|
+
/** What happened and what to do next, in plain words. */
|
|
47
68
|
message?: ReactNode
|
|
69
|
+
/** Technical detail (error message, status code), folded behind "詳細を表示". */
|
|
70
|
+
details?: ReactNode
|
|
48
71
|
action?: ReactNode
|
|
49
72
|
className?: string
|
|
50
73
|
}) {
|
|
@@ -55,6 +78,12 @@ export function ErrorState({
|
|
|
55
78
|
>
|
|
56
79
|
<p className="font-semibold text-destructive">{title}</p>
|
|
57
80
|
{message ? <p className="mt-1 text-sm text-muted-foreground">{message}</p> : null}
|
|
81
|
+
{details ? (
|
|
82
|
+
<details className="mt-2 text-xs text-muted-foreground">
|
|
83
|
+
<summary className="cursor-pointer select-none">詳細を表示</summary>
|
|
84
|
+
<div className="mt-1 font-mono break-all">{details}</div>
|
|
85
|
+
</details>
|
|
86
|
+
) : null}
|
|
58
87
|
{action ? <div className="mt-3">{action}</div> : null}
|
|
59
88
|
</div>
|
|
60
89
|
)
|
|
@@ -1,55 +1,98 @@
|
|
|
1
1
|
// Copied by `vantage add ui status-badge`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/components/status-badge.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
|
-
* StatusBadge — a dot-plus-label badge for row/record status. Statuses map to
|
|
5
|
-
*
|
|
6
|
+
* StatusBadge — a dot-plus-label badge for row/record status. Statuses map to a
|
|
7
|
+
* tone through `defaultColorMap`; pass `colorMap` to extend or override it.
|
|
8
|
+
*
|
|
9
|
+
* Tones are the theme's semantic tokens — `positive` | `negative` | `warning` |
|
|
10
|
+
* `info` | `neutral` — drawn as a `--<tone>` dot and text on a `--<tone>-subtle`
|
|
11
|
+
* background. The legacy colour names `green` / `red` / `yellow` / `blue` /
|
|
12
|
+
* `gray` are still accepted and map to positive / negative / warning / info /
|
|
13
|
+
* neutral. Unknown statuses and tones fall back to `neutral`.
|
|
14
|
+
*
|
|
15
|
+
* The default label comes from `STATUS_VOCABULARY` (one table of status, 日本語ラベル and tone), so the same
|
|
16
|
+
* state is worded the same everywhere (Tracker legends import it too):
|
|
17
|
+
*
|
|
18
|
+
* | status | ラベル | 色調 |
|
|
19
|
+
* |---|---|---|
|
|
20
|
+
* | `success` | 正常 | positive |
|
|
21
|
+
* | `partial` | 一部失敗 | warning |
|
|
22
|
+
* | `failed` | 失敗 | negative |
|
|
23
|
+
* | `delayed` | 遅延 | warning |
|
|
24
|
+
* | `running` | 実行中 | info |
|
|
25
|
+
* | `stopped` | 停止中 | neutral |
|
|
26
|
+
* | `active` / `inactive` | 有効 / 無効 | positive / neutral |
|
|
27
|
+
* | `warning` / `error` / `pending` | 警告 / エラー / 保留中 | warning / negative / info |
|
|
6
28
|
*/
|
|
7
29
|
import { forwardRef } from "react"
|
|
8
30
|
|
|
9
31
|
import { cn } from "@squadbase/vantage/ui"
|
|
10
32
|
import { Badge } from "@squadbase/vantage/ui"
|
|
11
33
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
34
|
+
type StatusTone = "positive" | "negative" | "warning" | "info" | "neutral"
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 状態の語彙の正本: status → 日本語ラベルと色調。StatusBadge の既定の表示と、Tracker の凡例など
|
|
38
|
+
* 同じ状態を語る他の場所が、同じ語を使うためにここから参照する。
|
|
39
|
+
*/
|
|
40
|
+
export const STATUS_VOCABULARY = {
|
|
41
|
+
success: { label: "正常", tone: "positive" },
|
|
42
|
+
partial: { label: "一部失敗", tone: "warning" },
|
|
43
|
+
failed: { label: "失敗", tone: "negative" },
|
|
44
|
+
delayed: { label: "遅延", tone: "warning" },
|
|
45
|
+
running: { label: "実行中", tone: "info" },
|
|
46
|
+
stopped: { label: "停止中", tone: "neutral" },
|
|
47
|
+
active: { label: "有効", tone: "positive" },
|
|
48
|
+
inactive: { label: "無効", tone: "neutral" },
|
|
49
|
+
warning: { label: "警告", tone: "warning" },
|
|
50
|
+
error: { label: "エラー", tone: "negative" },
|
|
51
|
+
pending: { label: "保留中", tone: "info" },
|
|
52
|
+
} as const satisfies Record<string, { label: string; tone: StatusTone }>
|
|
53
|
+
|
|
54
|
+
export type StatusKey = keyof typeof STATUS_VOCABULARY
|
|
55
|
+
|
|
56
|
+
/** 状態の日本語ラベル。語彙に無い status は渡された文字列のまま返す。 */
|
|
57
|
+
export function statusLabel(status: string): string {
|
|
58
|
+
return Object.hasOwn(STATUS_VOCABULARY, status) ? STATUS_VOCABULARY[status as StatusKey].label : status
|
|
18
59
|
}
|
|
19
60
|
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
bg: "bg-blue-50 dark:bg-blue-950",
|
|
44
|
-
text: "text-blue-700 dark:text-blue-300",
|
|
45
|
-
},
|
|
61
|
+
const defaultColorMap: Record<string, string> = Object.fromEntries(
|
|
62
|
+
Object.entries(STATUS_VOCABULARY).map(([key, { tone }]) => [key, tone]),
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
/** Legacy colour names → tones. */
|
|
66
|
+
const legacyColorTones: Record<string, StatusTone> = {
|
|
67
|
+
green: "positive",
|
|
68
|
+
gray: "neutral",
|
|
69
|
+
yellow: "warning",
|
|
70
|
+
red: "negative",
|
|
71
|
+
blue: "info",
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* One literal class set per tone — Tailwind only emits classes it can see
|
|
76
|
+
* literally in the source.
|
|
77
|
+
*/
|
|
78
|
+
const toneStyles: Record<StatusTone, { dot: string; bg: string; text: string }> = {
|
|
79
|
+
positive: { dot: "bg-positive", bg: "bg-positive-subtle", text: "text-positive" },
|
|
80
|
+
negative: { dot: "bg-negative", bg: "bg-negative-subtle", text: "text-negative" },
|
|
81
|
+
warning: { dot: "bg-warning", bg: "bg-warning-subtle", text: "text-warning" },
|
|
82
|
+
info: { dot: "bg-info", bg: "bg-info-subtle", text: "text-info" },
|
|
83
|
+
neutral: { dot: "bg-neutral", bg: "bg-neutral-subtle", text: "text-neutral" },
|
|
46
84
|
}
|
|
47
85
|
|
|
48
|
-
const
|
|
86
|
+
const resolveTone = (color: string | undefined): StatusTone => {
|
|
87
|
+
if (color === undefined) return "neutral"
|
|
88
|
+
if (Object.hasOwn(toneStyles, color)) return color as StatusTone
|
|
89
|
+
return legacyColorTones[color] ?? "neutral"
|
|
90
|
+
}
|
|
49
91
|
|
|
50
92
|
export interface StatusBadgeProps {
|
|
51
93
|
status: string
|
|
52
94
|
label?: string
|
|
95
|
+
/** status → tone (`positive` | `negative` | `warning` | `info` | `neutral`) or legacy colour name. */
|
|
53
96
|
colorMap?: Partial<Record<string, string>>
|
|
54
97
|
className?: string
|
|
55
98
|
}
|
|
@@ -59,9 +102,8 @@ export const StatusBadge = forwardRef<HTMLSpanElement, StatusBadgeProps>(functio
|
|
|
59
102
|
ref,
|
|
60
103
|
) {
|
|
61
104
|
const mergedColorMap = { ...defaultColorMap, ...colorMap }
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
const displayLabel = label ?? status
|
|
105
|
+
const style = toneStyles[resolveTone(mergedColorMap[status])]
|
|
106
|
+
const displayLabel = label ?? statusLabel(status)
|
|
65
107
|
|
|
66
108
|
return (
|
|
67
109
|
<Badge
|
package/registry/ui/switch.tsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Copied by `vantage add ui switch`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/switch.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
import { Switch as SwitchPrimitive } from "@base-ui/react/switch"
|
|
4
6
|
|
|
5
7
|
import { cn } from "@squadbase/vantage/ui"
|
package/registry/ui/table.tsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Copied by `vantage add ui table`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/table.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
import * as React from "react"
|
|
4
6
|
|
|
5
7
|
import { cn } from "@squadbase/vantage/ui"
|
|
@@ -70,7 +72,7 @@ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
|
|
70
72
|
<th
|
|
71
73
|
data-slot="table-head"
|
|
72
74
|
className={cn(
|
|
73
|
-
"h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0",
|
|
75
|
+
"h-10 px-2 text-left align-middle text-xs font-medium whitespace-nowrap text-muted-foreground [&:has([role=checkbox])]:pr-0",
|
|
74
76
|
className
|
|
75
77
|
)}
|
|
76
78
|
{...props}
|
package/registry/ui/tabs.tsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Copied by `vantage add ui tabs`. This file is yours to edit.
|
|
2
|
-
// Generated from @squadbase/
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/tabs.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
3
5
|
import { Tabs as TabsPrimitive } from "@base-ui/react/tabs"
|
|
4
6
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
5
7
|
|
|
@@ -58,7 +60,7 @@ function TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {
|
|
|
58
60
|
<TabsPrimitive.Tab
|
|
59
61
|
data-slot="tabs-trigger"
|
|
60
62
|
className={cn(
|
|
61
|
-
"relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-
|
|
63
|
+
"relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-[color,background-color,border-color,box-shadow] group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 aria-disabled:pointer-events-none aria-disabled:opacity-50 dark:text-muted-foreground dark:hover:text-foreground group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
62
64
|
"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent",
|
|
63
65
|
"data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground",
|
|
64
66
|
"after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100",
|
|
@@ -73,7 +75,7 @@ function TabsContent({ className, ...props }: TabsPrimitive.Panel.Props) {
|
|
|
73
75
|
return (
|
|
74
76
|
<TabsPrimitive.Panel
|
|
75
77
|
data-slot="tabs-content"
|
|
76
|
-
className={cn("flex-1 text-sm outline-none", className)}
|
|
78
|
+
className={cn("flex-1 text-sm outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50", className)}
|
|
77
79
|
{...props}
|
|
78
80
|
/>
|
|
79
81
|
)
|