minka-ds 0.1.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/package.json +25 -0
- package/src/components/ui/badge.tsx +63 -0
- package/src/components/ui/breadcrumb.tsx +109 -0
- package/src/components/ui/button-group.tsx +89 -0
- package/src/components/ui/button.tsx +65 -0
- package/src/components/ui/card.tsx +92 -0
- package/src/components/ui/cell.tsx +104 -0
- package/src/components/ui/collapsible.tsx +33 -0
- package/src/components/ui/combobox.tsx +310 -0
- package/src/components/ui/data-table.tsx +275 -0
- package/src/components/ui/dialog.tsx +160 -0
- package/src/components/ui/dropdown-menu.tsx +257 -0
- package/src/components/ui/input-group.tsx +170 -0
- package/src/components/ui/input.tsx +21 -0
- package/src/components/ui/label.tsx +26 -0
- package/src/components/ui/pagination.tsx +127 -0
- package/src/components/ui/select.tsx +198 -0
- package/src/components/ui/separator.tsx +28 -0
- package/src/components/ui/sheet.tsx +145 -0
- package/src/components/ui/sidebar.tsx +726 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/table.tsx +142 -0
- package/src/components/ui/tabs.tsx +109 -0
- package/src/components/ui/textarea.tsx +18 -0
- package/src/components/ui/tooltip.tsx +57 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/index.ts +28 -0
- package/src/lib/utils.ts +33 -0
- package/tokens/primitives.css +227 -0
- package/tokens/text-utilities.css +44 -0
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "minka-ds",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Minka product design system — tokenized component library",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"files": ["src", "tokens"],
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.ts",
|
|
9
|
+
"./tokens/*": "./tokens/*"
|
|
10
|
+
},
|
|
11
|
+
"peerDependencies": {
|
|
12
|
+
"react": ">=19",
|
|
13
|
+
"react-dom": ">=19"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@base-ui/react": "^1.4.1",
|
|
17
|
+
"@tanstack/react-table": "^8.21.3",
|
|
18
|
+
"class-variance-authority": "^0.7.1",
|
|
19
|
+
"clsx": "^2.1.1",
|
|
20
|
+
"lucide-react": "^1.14.0",
|
|
21
|
+
"radix-ui": "^1.4.3",
|
|
22
|
+
"tailwind-merge": "^3.5.0",
|
|
23
|
+
"tw-animate-css": "^1.4.0"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
3
|
+
import { Slot } from "radix-ui"
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../lib/utils"
|
|
6
|
+
|
|
7
|
+
const badgeVariants = cva(
|
|
8
|
+
"inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden [border-radius:var(--radius-badge)] border px-2 py-0.5 text-label-sm whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 [&>svg]:pointer-events-none [&>svg]:size-3",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default:
|
|
13
|
+
"bg-[var(--color-bg-raised)] text-[var(--color-text-default)] border-transparent [a&]:hover:bg-[var(--color-action-secondary-hover)]",
|
|
14
|
+
filled:
|
|
15
|
+
"bg-[var(--color-action-primary-default)] text-[var(--color-action-primary-foreground)] border-transparent [a&]:hover:bg-[var(--color-action-primary-hover)]",
|
|
16
|
+
secondary:
|
|
17
|
+
"bg-[var(--color-bg-disabled)] text-[var(--color-text-default)] border-transparent",
|
|
18
|
+
destructive:
|
|
19
|
+
"bg-[var(--color-action-destructive-default)] text-[var(--color-action-destructive-foreground)] border-transparent focus-visible:ring-destructive/20 [a&]:hover:bg-[var(--color-action-destructive-hover)]",
|
|
20
|
+
success:
|
|
21
|
+
"bg-[var(--color-bg-success)] text-[var(--color-feedback-success)] border-transparent",
|
|
22
|
+
warning:
|
|
23
|
+
"bg-[var(--color-bg-warning)] text-[var(--color-text-default)] border-transparent",
|
|
24
|
+
error:
|
|
25
|
+
"bg-[var(--color-bg-error)] text-[var(--color-feedback-error)] border-transparent",
|
|
26
|
+
info:
|
|
27
|
+
"bg-[var(--color-bg-info)] text-[var(--color-feedback-info)] border-transparent",
|
|
28
|
+
pending:
|
|
29
|
+
"bg-[var(--color-bg-warning)] text-[var(--color-text-default)] border-transparent",
|
|
30
|
+
outline:
|
|
31
|
+
"border-[var(--color-border-default)] text-[var(--color-text-default)] [a&]:hover:bg-[var(--color-action-ghost-hover)]",
|
|
32
|
+
ghost:
|
|
33
|
+
"border-transparent text-[var(--color-text-default)] [a&]:hover:bg-[var(--color-action-ghost-hover)]",
|
|
34
|
+
link:
|
|
35
|
+
"border-transparent text-[var(--color-text-link)] underline-offset-4 [a&]:hover:text-[var(--color-text-link-hover)] [a&]:hover:underline",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
defaultVariants: {
|
|
39
|
+
variant: "default",
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
function Badge({
|
|
45
|
+
className,
|
|
46
|
+
variant = "default",
|
|
47
|
+
asChild = false,
|
|
48
|
+
...props
|
|
49
|
+
}: React.ComponentProps<"span"> &
|
|
50
|
+
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
|
|
51
|
+
const Comp = asChild ? Slot.Root : "span"
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Comp
|
|
55
|
+
data-slot="badge"
|
|
56
|
+
data-variant={variant}
|
|
57
|
+
className={cn(badgeVariants({ variant }), className)}
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { Badge, badgeVariants }
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { ChevronRight, MoreHorizontal } from "lucide-react"
|
|
3
|
+
import { Slot } from "radix-ui"
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../lib/utils"
|
|
6
|
+
|
|
7
|
+
function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
|
|
8
|
+
return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
|
|
12
|
+
return (
|
|
13
|
+
<ol
|
|
14
|
+
data-slot="breadcrumb-list"
|
|
15
|
+
className={cn(
|
|
16
|
+
"flex flex-wrap items-center gap-1.5 text-body-sm break-words text-[var(--color-text-muted)] sm:gap-2.5",
|
|
17
|
+
className
|
|
18
|
+
)}
|
|
19
|
+
{...props}
|
|
20
|
+
/>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
|
|
25
|
+
return (
|
|
26
|
+
<li
|
|
27
|
+
data-slot="breadcrumb-item"
|
|
28
|
+
className={cn("inline-flex items-center gap-1.5", className)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function BreadcrumbLink({
|
|
35
|
+
asChild,
|
|
36
|
+
className,
|
|
37
|
+
...props
|
|
38
|
+
}: React.ComponentProps<"a"> & {
|
|
39
|
+
asChild?: boolean
|
|
40
|
+
}) {
|
|
41
|
+
const Comp = asChild ? Slot.Root : "a"
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Comp
|
|
45
|
+
data-slot="breadcrumb-link"
|
|
46
|
+
className={cn("transition-colors hover:text-[var(--color-text-default)]", className)}
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
|
|
53
|
+
return (
|
|
54
|
+
<span
|
|
55
|
+
data-slot="breadcrumb-page"
|
|
56
|
+
role="link"
|
|
57
|
+
aria-disabled="true"
|
|
58
|
+
aria-current="page"
|
|
59
|
+
className={cn("text-[var(--color-text-default)]", className)}
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function BreadcrumbSeparator({
|
|
66
|
+
children,
|
|
67
|
+
className,
|
|
68
|
+
...props
|
|
69
|
+
}: React.ComponentProps<"li">) {
|
|
70
|
+
return (
|
|
71
|
+
<li
|
|
72
|
+
data-slot="breadcrumb-separator"
|
|
73
|
+
role="presentation"
|
|
74
|
+
aria-hidden="true"
|
|
75
|
+
className={cn("[&>svg]:size-3.5", className)}
|
|
76
|
+
{...props}
|
|
77
|
+
>
|
|
78
|
+
{children ?? <ChevronRight />}
|
|
79
|
+
</li>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function BreadcrumbEllipsis({
|
|
84
|
+
className,
|
|
85
|
+
...props
|
|
86
|
+
}: React.ComponentProps<"span">) {
|
|
87
|
+
return (
|
|
88
|
+
<span
|
|
89
|
+
data-slot="breadcrumb-ellipsis"
|
|
90
|
+
role="presentation"
|
|
91
|
+
aria-hidden="true"
|
|
92
|
+
className={cn("flex size-9 items-center justify-center", className)}
|
|
93
|
+
{...props}
|
|
94
|
+
>
|
|
95
|
+
<MoreHorizontal className="size-4" />
|
|
96
|
+
<span className="sr-only">More</span>
|
|
97
|
+
</span>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
Breadcrumb,
|
|
103
|
+
BreadcrumbList,
|
|
104
|
+
BreadcrumbItem,
|
|
105
|
+
BreadcrumbLink,
|
|
106
|
+
BreadcrumbPage,
|
|
107
|
+
BreadcrumbSeparator,
|
|
108
|
+
BreadcrumbEllipsis,
|
|
109
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
2
|
+
import { Slot } from "radix-ui"
|
|
3
|
+
|
|
4
|
+
import { cn } from "../../lib/utils"
|
|
5
|
+
import { Separator } from "./separator"
|
|
6
|
+
|
|
7
|
+
const buttonGroupVariants = cva(
|
|
8
|
+
"flex w-fit items-stretch [border-radius:var(--radius-button)] has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
orientation: {
|
|
12
|
+
horizontal:
|
|
13
|
+
"[&>*:not([data-slot=button-group]):not(:first-child)]:rounded-l-none [&>*:not([data-slot=button-group]):not(:first-child)]:border-l-0 [&>*:not([data-slot=button-group]):not(:last-child)]:rounded-r-none",
|
|
14
|
+
vertical:
|
|
15
|
+
"flex-col [&>*:not([data-slot=button-group]):not(:first-child)]:rounded-t-none [&>*:not([data-slot=button-group]):not(:first-child)]:border-t-0 [&>*:not([data-slot=button-group]):not(:last-child)]:rounded-b-none",
|
|
16
|
+
},
|
|
17
|
+
variant: {
|
|
18
|
+
elevated: "bg-[var(--color-bg-raised)]",
|
|
19
|
+
flat: "bg-transparent",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
defaultVariants: {
|
|
23
|
+
orientation: "horizontal",
|
|
24
|
+
variant: "elevated",
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
function ButtonGroup({
|
|
30
|
+
className,
|
|
31
|
+
orientation,
|
|
32
|
+
variant,
|
|
33
|
+
...props
|
|
34
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof buttonGroupVariants>) {
|
|
35
|
+
return (
|
|
36
|
+
<div
|
|
37
|
+
role="group"
|
|
38
|
+
data-slot="button-group"
|
|
39
|
+
data-orientation={orientation}
|
|
40
|
+
className={cn(buttonGroupVariants({ orientation, variant }), className)}
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function ButtonGroupText({
|
|
47
|
+
className,
|
|
48
|
+
asChild = false,
|
|
49
|
+
...props
|
|
50
|
+
}: React.ComponentProps<"div"> & {
|
|
51
|
+
asChild?: boolean
|
|
52
|
+
}) {
|
|
53
|
+
const Comp = asChild ? Slot.Root : "div"
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<Comp
|
|
57
|
+
className={cn(
|
|
58
|
+
"flex items-center gap-2 [border-radius:var(--radius-button)] border border-[var(--color-border-default)] bg-[var(--color-bg-raised)] px-4 text-label text-[var(--color-text-muted)] [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
|
|
59
|
+
className
|
|
60
|
+
)}
|
|
61
|
+
{...props}
|
|
62
|
+
/>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function ButtonGroupSeparator({
|
|
67
|
+
className,
|
|
68
|
+
orientation = "vertical",
|
|
69
|
+
...props
|
|
70
|
+
}: React.ComponentProps<typeof Separator>) {
|
|
71
|
+
return (
|
|
72
|
+
<Separator
|
|
73
|
+
data-slot="button-group-separator"
|
|
74
|
+
orientation={orientation}
|
|
75
|
+
className={cn(
|
|
76
|
+
"relative m-0! self-stretch bg-input data-[orientation=vertical]:h-auto",
|
|
77
|
+
className
|
|
78
|
+
)}
|
|
79
|
+
{...props}
|
|
80
|
+
/>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
ButtonGroup,
|
|
86
|
+
ButtonGroupSeparator,
|
|
87
|
+
ButtonGroupText,
|
|
88
|
+
buttonGroupVariants,
|
|
89
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
3
|
+
import { Slot } from "radix-ui"
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../lib/utils"
|
|
6
|
+
|
|
7
|
+
const buttonVariants = cva(
|
|
8
|
+
"inline-flex shrink-0 items-center justify-center gap-2 [border-radius:var(--radius-button)] text-label whitespace-nowrap transition-all outline-none focus-visible:border-[var(--color-border-focus)] focus-visible:ring-[3px] focus-visible:ring-[var(--color-border-focus)]/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-[var(--color-border-error)] aria-invalid:ring-[3px] aria-invalid:ring-[var(--color-border-error)]/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default:
|
|
13
|
+
"bg-[var(--color-action-primary-default)] text-[var(--color-action-primary-foreground)] hover:bg-[var(--color-action-primary-hover)]",
|
|
14
|
+
destructive:
|
|
15
|
+
"bg-[var(--color-action-destructive-default)] text-[var(--color-action-destructive-foreground)] hover:bg-[var(--color-action-destructive-hover)] focus-visible:ring-[var(--color-border-error)]/20",
|
|
16
|
+
outline:
|
|
17
|
+
"border border-[var(--color-border-default)] bg-[var(--color-bg-raised)] shadow-xs hover:bg-[var(--color-action-ghost-hover)] hover:text-[var(--color-text-default)]",
|
|
18
|
+
secondary:
|
|
19
|
+
"bg-[var(--color-action-secondary-default)] text-[var(--color-action-secondary-foreground)] hover:bg-[var(--color-action-secondary-hover)]",
|
|
20
|
+
ghost:
|
|
21
|
+
"hover:bg-[var(--color-action-ghost-hover)] hover:text-[var(--color-text-default)]",
|
|
22
|
+
link: "text-[var(--color-text-link)] underline-offset-4 hover:underline hover:text-[var(--color-text-link-hover)]",
|
|
23
|
+
},
|
|
24
|
+
size: {
|
|
25
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
26
|
+
xs: "h-6 gap-1 px-2 text-caption has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
27
|
+
sm: "h-8 gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
28
|
+
lg: "h-10 px-6 has-[>svg]:px-4",
|
|
29
|
+
icon: "size-9",
|
|
30
|
+
"icon-xs": "size-6 [&_svg:not([class*='size-'])]:size-3",
|
|
31
|
+
"icon-sm": "size-8",
|
|
32
|
+
"icon-lg": "size-10",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
defaultVariants: {
|
|
36
|
+
variant: "default",
|
|
37
|
+
size: "default",
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
function Button({
|
|
43
|
+
className,
|
|
44
|
+
variant = "default",
|
|
45
|
+
size = "default",
|
|
46
|
+
asChild = false,
|
|
47
|
+
...props
|
|
48
|
+
}: React.ComponentProps<"button"> &
|
|
49
|
+
VariantProps<typeof buttonVariants> & {
|
|
50
|
+
asChild?: boolean
|
|
51
|
+
}) {
|
|
52
|
+
const Comp = asChild ? Slot.Root : "button"
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<Comp
|
|
56
|
+
data-slot="button"
|
|
57
|
+
data-variant={variant}
|
|
58
|
+
data-size={size}
|
|
59
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export { Button, buttonVariants }
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "../../lib/utils"
|
|
4
|
+
|
|
5
|
+
function Card({ className, ...props }: React.ComponentProps<"div">) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
data-slot="card"
|
|
9
|
+
className={cn(
|
|
10
|
+
"flex flex-col gap-6 [border-radius:var(--radius-card)] border bg-card py-6 text-card-foreground shadow-[var(--shadow-card)]",
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
data-slot="card-header"
|
|
22
|
+
className={cn(
|
|
23
|
+
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
|
24
|
+
className
|
|
25
|
+
)}
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
32
|
+
return (
|
|
33
|
+
<div
|
|
34
|
+
data-slot="card-title"
|
|
35
|
+
className={cn("text-heading-4", className)}
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
data-slot="card-description"
|
|
45
|
+
className={cn("text-body-sm text-[var(--color-text-muted)]", className)}
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
52
|
+
return (
|
|
53
|
+
<div
|
|
54
|
+
data-slot="card-action"
|
|
55
|
+
className={cn(
|
|
56
|
+
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
|
57
|
+
className
|
|
58
|
+
)}
|
|
59
|
+
{...props}
|
|
60
|
+
/>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
65
|
+
return (
|
|
66
|
+
<div
|
|
67
|
+
data-slot="card-content"
|
|
68
|
+
className={cn("px-6", className)}
|
|
69
|
+
{...props}
|
|
70
|
+
/>
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
75
|
+
return (
|
|
76
|
+
<div
|
|
77
|
+
data-slot="card-footer"
|
|
78
|
+
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
|
|
79
|
+
{...props}
|
|
80
|
+
/>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
Card,
|
|
86
|
+
CardHeader,
|
|
87
|
+
CardFooter,
|
|
88
|
+
CardTitle,
|
|
89
|
+
CardAction,
|
|
90
|
+
CardDescription,
|
|
91
|
+
CardContent,
|
|
92
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { cn } from "../../lib/utils"
|
|
5
|
+
|
|
6
|
+
// ── TextStack ─────────────────────────────────────────────────────────────────
|
|
7
|
+
// Two-line cell content: a primary label and an optional muted secondary line.
|
|
8
|
+
// Use inside <TableCell> for entity columns (sender, receiver, etc.)
|
|
9
|
+
|
|
10
|
+
interface TextStackProps {
|
|
11
|
+
primary: React.ReactNode
|
|
12
|
+
secondary?: React.ReactNode
|
|
13
|
+
className?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function TextStack({ primary, secondary, className }: TextStackProps) {
|
|
17
|
+
return (
|
|
18
|
+
<div className={cn("flex flex-col gap-0.5", className)}>
|
|
19
|
+
<span className="text-caption-light text-[var(--color-text-default)]">{primary}</span>
|
|
20
|
+
{secondary && (
|
|
21
|
+
<span className="text-caption-sm-light text-[var(--color-text-muted)]">{secondary}</span>
|
|
22
|
+
)}
|
|
23
|
+
</div>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ── MonoCell ──────────────────────────────────────────────────────────────────
|
|
28
|
+
// Single-line monospace text. Use for IDs, codes, hashes.
|
|
29
|
+
|
|
30
|
+
interface MonoCellProps {
|
|
31
|
+
children: React.ReactNode
|
|
32
|
+
className?: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function MonoCell({ children, className }: MonoCellProps) {
|
|
36
|
+
return (
|
|
37
|
+
<span
|
|
38
|
+
className={cn(
|
|
39
|
+
"text-body-sm-light text-[var(--color-text-default)]",
|
|
40
|
+
className
|
|
41
|
+
)}
|
|
42
|
+
>
|
|
43
|
+
{children}
|
|
44
|
+
</span>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ── AmountCell ────────────────────────────────────────────────────────────────
|
|
49
|
+
// Right-aligned numeric/currency value.
|
|
50
|
+
|
|
51
|
+
interface AmountCellProps {
|
|
52
|
+
children: React.ReactNode
|
|
53
|
+
className?: string
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function AmountCell({ children, className }: AmountCellProps) {
|
|
57
|
+
return (
|
|
58
|
+
<span
|
|
59
|
+
className={cn(
|
|
60
|
+
"text-body-sm text-[var(--color-text-default)] tabular-nums tracking-tight",
|
|
61
|
+
className
|
|
62
|
+
)}
|
|
63
|
+
>
|
|
64
|
+
{children}
|
|
65
|
+
</span>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ── BadgeCell ─────────────────────────────────────────────────────────────────
|
|
70
|
+
// Centered wrapper for one or more badges inside a table cell.
|
|
71
|
+
|
|
72
|
+
interface BadgeCellProps {
|
|
73
|
+
children: React.ReactNode
|
|
74
|
+
className?: string
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function BadgeCell({ children, className }: BadgeCellProps) {
|
|
78
|
+
return (
|
|
79
|
+
<div className={cn("flex items-center gap-1", className)}>{children}</div>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ── ActionCell ────────────────────────────────────────────────────────────────
|
|
84
|
+
// Flex row for action buttons inside a table cell.
|
|
85
|
+
|
|
86
|
+
interface ActionCellProps {
|
|
87
|
+
children: React.ReactNode
|
|
88
|
+
className?: string
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function ActionCell({ children, className }: ActionCellProps) {
|
|
92
|
+
return (
|
|
93
|
+
<div className={cn("flex items-center gap-1", className)}>{children}</div>
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { TextStack, MonoCell, AmountCell, BadgeCell, ActionCell }
|
|
98
|
+
export type {
|
|
99
|
+
TextStackProps,
|
|
100
|
+
MonoCellProps,
|
|
101
|
+
AmountCellProps,
|
|
102
|
+
BadgeCellProps,
|
|
103
|
+
ActionCellProps,
|
|
104
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Collapsible as CollapsiblePrimitive } from "radix-ui"
|
|
4
|
+
|
|
5
|
+
function Collapsible({
|
|
6
|
+
...props
|
|
7
|
+
}: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {
|
|
8
|
+
return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function CollapsibleTrigger({
|
|
12
|
+
...props
|
|
13
|
+
}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {
|
|
14
|
+
return (
|
|
15
|
+
<CollapsiblePrimitive.CollapsibleTrigger
|
|
16
|
+
data-slot="collapsible-trigger"
|
|
17
|
+
{...props}
|
|
18
|
+
/>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function CollapsibleContent({
|
|
23
|
+
...props
|
|
24
|
+
}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {
|
|
25
|
+
return (
|
|
26
|
+
<CollapsiblePrimitive.CollapsibleContent
|
|
27
|
+
data-slot="collapsible-content"
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { Collapsible, CollapsibleTrigger, CollapsibleContent }
|