parthenon-ui 1.0.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 +74 -0
- package/src/components/.gitkeep +0 -0
- package/src/components/avatar.tsx +109 -0
- package/src/components/badge.tsx +52 -0
- package/src/components/button.tsx +122 -0
- package/src/components/card.tsx +108 -0
- package/src/components/checkbox.tsx +37 -0
- package/src/components/collapsible.tsx +21 -0
- package/src/components/color-picker.tsx +270 -0
- package/src/components/command.tsx +195 -0
- package/src/components/context-menu.tsx +270 -0
- package/src/components/dialog.tsx +169 -0
- package/src/components/dropdown-menu.tsx +279 -0
- package/src/components/empty.tsx +104 -0
- package/src/components/index.ts +27 -0
- package/src/components/input-group.tsx +155 -0
- package/src/components/input.tsx +27 -0
- package/src/components/label.tsx +18 -0
- package/src/components/popover.tsx +88 -0
- package/src/components/scroll-area.tsx +55 -0
- package/src/components/select.tsx +201 -0
- package/src/components/separator.tsx +23 -0
- package/src/components/sheet.tsx +138 -0
- package/src/components/sidebar.tsx +729 -0
- package/src/components/skeleton.tsx +13 -0
- package/src/components/sonner.tsx +59 -0
- package/src/components/switch.tsx +51 -0
- package/src/components/table.tsx +375 -0
- package/src/components/tabs.tsx +80 -0
- package/src/components/textarea.tsx +18 -0
- package/src/components/tooltip.tsx +64 -0
- package/src/hooks/.gitkeep +0 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/lib/.gitkeep +0 -0
- package/src/lib/utils.ts +6 -0
- package/src/styles/globals.css +654 -0
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "parthenon-ui",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": false,
|
|
6
|
+
"description": "A beautiful, modern UI library built with React and Tailwind CSS",
|
|
7
|
+
"main": "./src/components/index.ts",
|
|
8
|
+
"types": "./src/components/index.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"src/**/*"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"lint": "eslint",
|
|
14
|
+
"format": "prettier --write \"**/*.{ts,tsx}\"",
|
|
15
|
+
"typecheck": "tsc --noEmit",
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"dev": "tsc --watch"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"react",
|
|
21
|
+
"ui",
|
|
22
|
+
"components",
|
|
23
|
+
"tailwindcss",
|
|
24
|
+
"design-system",
|
|
25
|
+
"parthenon"
|
|
26
|
+
],
|
|
27
|
+
"author": "Athena AI",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/athena-ai/parthenon-ui"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@base-ui/react": "^1.6.0",
|
|
35
|
+
"@fontsource-variable/geist": "^5.2.9",
|
|
36
|
+
"@hugeicons/core-free-icons": "^4.2.0",
|
|
37
|
+
"@hugeicons/react": "^1.1.6",
|
|
38
|
+
"@radix-ui/react-use-controllable-state": "^1.2.3",
|
|
39
|
+
"class-variance-authority": "^0.7.1",
|
|
40
|
+
"clsx": "^2.1.1",
|
|
41
|
+
"cmdk": "^1.1.1",
|
|
42
|
+
"lucide-react": "^1.22.0",
|
|
43
|
+
"next-themes": "^0.4.6",
|
|
44
|
+
"react": "^19.2.6",
|
|
45
|
+
"react-dom": "^19.2.6",
|
|
46
|
+
"shadcn": "^4.11.0",
|
|
47
|
+
"sonner": "^2.0.7",
|
|
48
|
+
"tailwind-merge": "^3.6.0",
|
|
49
|
+
"tw-animate-css": "^1.4.0",
|
|
50
|
+
"zod": "^4.4.3"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@eslint/js": "^10",
|
|
54
|
+
"@tailwindcss/vite": "^4",
|
|
55
|
+
"@turbo/gen": "^2.9.15",
|
|
56
|
+
"@types/node": "^24",
|
|
57
|
+
"@types/react": "^19",
|
|
58
|
+
"@types/react-dom": "^19",
|
|
59
|
+
"eslint": "^10",
|
|
60
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
61
|
+
"eslint-plugin-react-refresh": "^0.5.2",
|
|
62
|
+
"globals": "^17",
|
|
63
|
+
"tailwindcss": "^4",
|
|
64
|
+
"typescript": "~6",
|
|
65
|
+
"typescript-eslint": "^8"
|
|
66
|
+
},
|
|
67
|
+
"exports": {
|
|
68
|
+
"./globals.css": "./src/styles/globals.css",
|
|
69
|
+
"./lib/*": "./src/lib/*.ts",
|
|
70
|
+
"./components": "./src/components/index.ts",
|
|
71
|
+
"./components/*": "./src/components/*.tsx",
|
|
72
|
+
"./hooks/*": "./src/hooks/*.ts"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@workspace/ui/lib/utils"
|
|
7
|
+
|
|
8
|
+
function Avatar({
|
|
9
|
+
className,
|
|
10
|
+
size = "default",
|
|
11
|
+
...props
|
|
12
|
+
}: AvatarPrimitive.Root.Props & {
|
|
13
|
+
size?: "default" | "sm" | "lg"
|
|
14
|
+
}) {
|
|
15
|
+
return (
|
|
16
|
+
<AvatarPrimitive.Root
|
|
17
|
+
data-slot="avatar"
|
|
18
|
+
data-size={size}
|
|
19
|
+
className={cn(
|
|
20
|
+
"group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten",
|
|
21
|
+
className
|
|
22
|
+
)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) {
|
|
29
|
+
return (
|
|
30
|
+
<AvatarPrimitive.Image
|
|
31
|
+
data-slot="avatar-image"
|
|
32
|
+
className={cn(
|
|
33
|
+
"aspect-square size-full rounded-full object-cover",
|
|
34
|
+
className
|
|
35
|
+
)}
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function AvatarFallback({
|
|
42
|
+
className,
|
|
43
|
+
...props
|
|
44
|
+
}: AvatarPrimitive.Fallback.Props) {
|
|
45
|
+
return (
|
|
46
|
+
<AvatarPrimitive.Fallback
|
|
47
|
+
data-slot="avatar-fallback"
|
|
48
|
+
className={cn(
|
|
49
|
+
"flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs",
|
|
50
|
+
className
|
|
51
|
+
)}
|
|
52
|
+
{...props}
|
|
53
|
+
/>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) {
|
|
58
|
+
return (
|
|
59
|
+
<span
|
|
60
|
+
data-slot="avatar-badge"
|
|
61
|
+
className={cn(
|
|
62
|
+
"absolute end-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none",
|
|
63
|
+
"group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden",
|
|
64
|
+
"group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2",
|
|
65
|
+
"group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2",
|
|
66
|
+
className
|
|
67
|
+
)}
|
|
68
|
+
{...props}
|
|
69
|
+
/>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function AvatarGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
74
|
+
return (
|
|
75
|
+
<div
|
|
76
|
+
data-slot="avatar-group"
|
|
77
|
+
className={cn(
|
|
78
|
+
"group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background",
|
|
79
|
+
className
|
|
80
|
+
)}
|
|
81
|
+
{...props}
|
|
82
|
+
/>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function AvatarGroupCount({
|
|
87
|
+
className,
|
|
88
|
+
...props
|
|
89
|
+
}: React.ComponentProps<"div">) {
|
|
90
|
+
return (
|
|
91
|
+
<div
|
|
92
|
+
data-slot="avatar-group-count"
|
|
93
|
+
className={cn(
|
|
94
|
+
"relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3",
|
|
95
|
+
className
|
|
96
|
+
)}
|
|
97
|
+
{...props}
|
|
98
|
+
/>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export {
|
|
103
|
+
Avatar,
|
|
104
|
+
AvatarImage,
|
|
105
|
+
AvatarFallback,
|
|
106
|
+
AvatarGroup,
|
|
107
|
+
AvatarGroupCount,
|
|
108
|
+
AvatarBadge,
|
|
109
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { mergeProps } from "@base-ui/react/merge-props"
|
|
2
|
+
import { useRender } from "@base-ui/react/use-render"
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@workspace/ui/lib/utils"
|
|
6
|
+
|
|
7
|
+
const badgeVariants = cva(
|
|
8
|
+
"group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
|
13
|
+
secondary:
|
|
14
|
+
"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
|
|
15
|
+
destructive:
|
|
16
|
+
"bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
|
|
17
|
+
outline:
|
|
18
|
+
"border-border bg-input/30 text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
|
|
19
|
+
ghost:
|
|
20
|
+
"hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
|
|
21
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
defaultVariants: {
|
|
25
|
+
variant: "default",
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
function Badge({
|
|
31
|
+
className,
|
|
32
|
+
variant = "default",
|
|
33
|
+
render,
|
|
34
|
+
...props
|
|
35
|
+
}: useRender.ComponentProps<"span"> & VariantProps<typeof badgeVariants>) {
|
|
36
|
+
return useRender({
|
|
37
|
+
defaultTagName: "span",
|
|
38
|
+
props: mergeProps<"span">(
|
|
39
|
+
{
|
|
40
|
+
className: cn(badgeVariants({ variant }), className),
|
|
41
|
+
},
|
|
42
|
+
props
|
|
43
|
+
),
|
|
44
|
+
render,
|
|
45
|
+
state: {
|
|
46
|
+
slot: "badge",
|
|
47
|
+
variant,
|
|
48
|
+
},
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { Badge, badgeVariants }
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Button as ButtonPrimitive } from "@base-ui/react/button"
|
|
4
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
5
|
+
import { HugeiconsIcon } from "@hugeicons/react"
|
|
6
|
+
import { ArrowRight01Icon } from "@hugeicons/core-free-icons"
|
|
7
|
+
|
|
8
|
+
import { cn } from "@workspace/ui/lib/utils"
|
|
9
|
+
|
|
10
|
+
const buttonVariants = cva(
|
|
11
|
+
"group/button relative inline-flex shrink-0 items-center justify-center gap-2 rounded-4xl text-[13px] leading-[18px] font-normal whitespace-nowrap transition-all duration-100 outline-none select-none disabled:pointer-events-none disabled:opacity-40 active:scale-[0.97] active:ring-[3px] active:ring-ring/50 active:ring-offset-2 active:ring-offset-background focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
12
|
+
{
|
|
13
|
+
variants: {
|
|
14
|
+
variant: {
|
|
15
|
+
default: [
|
|
16
|
+
"bg-primary text-primary-foreground",
|
|
17
|
+
"shadow-[0_1px_1px_0_rgba(0,0,0,0.24),0_2px_3px_0_rgba(0,0,0,0.20),inset_0_1px_1px_0_rgba(255,255,255,0.07),0_0_0_1px_var(--primary)]",
|
|
18
|
+
"before:absolute before:inset-0 before:rounded-4xl before:bg-linear-[180deg,rgba(255,255,255,0.1)_0%,rgba(255,255,255,0)_100%] before:content-['']",
|
|
19
|
+
"hover:bg-primary/80",
|
|
20
|
+
"hover:shadow-[0_1px_1px_0_rgba(0,0,0,0.24),0_2px_3px_0_rgba(0,0,0,0.20),inset_0_1px_1px_0_rgba(255,255,255,0.07),0_0_0_1px_var(--primary)]",
|
|
21
|
+
"hover:before:bg-linear-[180deg,rgba(255,255,255,0)_0%,rgba(255,255,255,0.1)_100%]",
|
|
22
|
+
],
|
|
23
|
+
secondary: [
|
|
24
|
+
"bg-secondary text-secondary-foreground",
|
|
25
|
+
"shadow-[0_1px_1px_0_rgba(0,0,0,0.24),0_2px_3px_0_rgba(0,0,0,0.20),inset_0_1px_1px_0_rgba(255,255,255,0.07),0_0_0_1px_var(--secondary)]",
|
|
26
|
+
"before:absolute before:inset-0 before:rounded-4xl before:bg-linear-[180deg,rgba(255,255,255,0.1)_0%,rgba(255,255,255,0)_100%] before:content-['']",
|
|
27
|
+
"hover:bg-secondary/80",
|
|
28
|
+
"hover:shadow-[0_1px_1px_0_rgba(0,0,0,0.24),0_2px_3px_0_rgba(0,0,0,0.20),inset_0_1px_1px_0_rgba(255,255,255,0.07),0_0_0_1px_var(--secondary)]",
|
|
29
|
+
"hover:before:bg-linear-[180deg,rgba(255,255,255,0)_0%,rgba(255,255,255,0.1)_100%]",
|
|
30
|
+
],
|
|
31
|
+
outline: [
|
|
32
|
+
"bg-background text-foreground",
|
|
33
|
+
"shadow-[0_0_1px_rgba(0,0,0,0.08),0_1px_0_rgba(0,0,0,0.02),0_2px_3px_-1px_rgba(0,0,0,0.08)]",
|
|
34
|
+
"hover:bg-accent",
|
|
35
|
+
"hover:shadow-[0_0_4px_rgba(0,0,0,0.12),0_0_1px_rgba(0,0,0,0.08),0_1px_0_rgba(0,0,0,0.02),0_2px_3px_-1px_rgba(0,0,0,0.08)]",
|
|
36
|
+
],
|
|
37
|
+
ghost: [
|
|
38
|
+
"bg-transparent text-foreground",
|
|
39
|
+
"hover:bg-accent",
|
|
40
|
+
],
|
|
41
|
+
destructive: [
|
|
42
|
+
"bg-destructive text-white",
|
|
43
|
+
"shadow-[0_1px_1px_0_rgba(0,0,0,0.08),0_2px_3px_0_rgba(0,0,0,0.20),inset_0_1px_1px_0_rgba(255,255,255,0.07),0_0_0_1px_var(--destructive)]",
|
|
44
|
+
"before:absolute before:inset-0 before:rounded-4xl before:bg-linear-[180deg,rgba(255,255,255,0.1)_0%,rgba(255,255,255,0)_100%] before:content-['']",
|
|
45
|
+
"hover:bg-destructive/80",
|
|
46
|
+
"hover:shadow-[0_1px_1px_0_rgba(0,0,0,0.08),0_2px_3px_0_rgba(0,0,0,0.20),inset_0_1px_1px_0_rgba(255,255,255,0.07),0_0_0_1px_var(--destructive)]",
|
|
47
|
+
"hover:before:bg-linear-[180deg,rgba(255,255,255,0)_0%,rgba(255,255,255,0.1)_100%]",
|
|
48
|
+
],
|
|
49
|
+
"destructive-ghost": [
|
|
50
|
+
"bg-destructive/10 text-destructive",
|
|
51
|
+
"shadow-[0_0_1px_rgba(0,0,0,0.08),0_0_0_1px_var(--destructive)]",
|
|
52
|
+
"hover:bg-destructive/20",
|
|
53
|
+
"hover:shadow-[0_0_8px_rgba(0,0,0,0.15),0_0_1px_rgba(0,0,0,0.08),0_0_0_1px_var(--destructive)]",
|
|
54
|
+
],
|
|
55
|
+
link: [
|
|
56
|
+
"text-foreground underline-offset-4",
|
|
57
|
+
"hover:underline",
|
|
58
|
+
"bg-transparent shadow-none hover:shadow-none",
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
size: {
|
|
62
|
+
default: "h-8 px-3",
|
|
63
|
+
xs: "h-6 px-2 text-xs",
|
|
64
|
+
sm: "h-8 px-3",
|
|
65
|
+
lg: "h-10 px-4",
|
|
66
|
+
icon: "size-8",
|
|
67
|
+
"icon-xs": "size-6",
|
|
68
|
+
"icon-sm": "size-8",
|
|
69
|
+
"icon-lg": "size-10",
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
defaultVariants: {
|
|
73
|
+
variant: "default",
|
|
74
|
+
size: "default",
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
interface ButtonProps extends ButtonPrimitive.Props, VariantProps<typeof buttonVariants> {
|
|
80
|
+
leftIcon?: React.ReactNode
|
|
81
|
+
rightIcon?: React.ReactNode
|
|
82
|
+
showArrow?: boolean
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function Button({
|
|
86
|
+
className,
|
|
87
|
+
variant = "default",
|
|
88
|
+
size = "default",
|
|
89
|
+
leftIcon,
|
|
90
|
+
rightIcon,
|
|
91
|
+
showArrow = false,
|
|
92
|
+
children,
|
|
93
|
+
...props
|
|
94
|
+
}: ButtonProps) {
|
|
95
|
+
return (
|
|
96
|
+
<ButtonPrimitive
|
|
97
|
+
data-slot="button"
|
|
98
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
99
|
+
{...props}
|
|
100
|
+
>
|
|
101
|
+
{leftIcon && (
|
|
102
|
+
<span className="relative z-10 shrink-0 opacity-60 inline-flex [&_svg]:size-4">
|
|
103
|
+
{leftIcon}
|
|
104
|
+
</span>
|
|
105
|
+
)}
|
|
106
|
+
<span className="relative z-10 inline-flex items-center gap-2">{children}</span>
|
|
107
|
+
{rightIcon && (
|
|
108
|
+
<span className="relative z-10 shrink-0 opacity-60 inline-flex [&_svg]:size-4">
|
|
109
|
+
{rightIcon}
|
|
110
|
+
</span>
|
|
111
|
+
)}
|
|
112
|
+
{showArrow && !rightIcon && (
|
|
113
|
+
<span className="relative z-10 shrink-0 opacity-60 transition-transform group-hover/button:translate-x-0.5 [&_svg]:size-4">
|
|
114
|
+
<HugeiconsIcon icon={ArrowRight01Icon} />
|
|
115
|
+
</span>
|
|
116
|
+
)}
|
|
117
|
+
</ButtonPrimitive>
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export { Button, buttonVariants }
|
|
122
|
+
export type { ButtonProps }
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "@workspace/ui/lib/utils"
|
|
4
|
+
|
|
5
|
+
function Card({
|
|
6
|
+
className,
|
|
7
|
+
size = "default",
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
|
|
10
|
+
return (
|
|
11
|
+
<div
|
|
12
|
+
data-slot="card"
|
|
13
|
+
data-size={size}
|
|
14
|
+
className={cn(
|
|
15
|
+
"group/card relative flex flex-col gap-(--card-spacing) overflow-hidden rounded-2xl bg-[#f0f0f0] dark:bg-[#111111] py-(--card-spacing) text-sm text-card-foreground",
|
|
16
|
+
"transition-all duration-150",
|
|
17
|
+
"border border-[#e0e0e0] dark:border-[#222222]",
|
|
18
|
+
"shadow-[inset_0_1px_0_0_rgba(255,255,255,0.7),inset_0_-1px_0_0_rgba(0,0,0,0.04),0_1px_3px_0_rgba(0,0,0,0.06),0_2px_0_0_rgba(0,0,0,0.03)]",
|
|
19
|
+
"before:absolute before:inset-x-0 before:top-0 before:h-24 before:rounded-t-2xl before:z-0 before:content-['']",
|
|
20
|
+
"before:bg-[linear-gradient(180deg,rgba(255,255,255,0.5)_0%,rgba(255,255,255,0.15)_30%,rgba(255,255,255,0)_100%)]",
|
|
21
|
+
"dark:shadow-[inset_0_1px_0_0_rgba(255,255,255,0.04),inset_0_-1px_0_0_rgba(0,0,0,0.4),0_0_0_1px_rgba(0,0,0,0.5),0_1px_3px_0_rgba(0,0,0,0.6),0_2px_0_0_rgba(0,0,0,0.3)]",
|
|
22
|
+
"dark:before:bg-[linear-gradient(180deg,rgba(255,255,255,0.03)_0%,rgba(255,255,255,0.005)_30%,rgba(255,255,255,0)_100%)]",
|
|
23
|
+
"[--card-spacing:--spacing(6)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(4)] *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
|
|
24
|
+
className
|
|
25
|
+
)}
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
32
|
+
return (
|
|
33
|
+
<div
|
|
34
|
+
data-slot="card-header"
|
|
35
|
+
className={cn(
|
|
36
|
+
"group/card-header @container/card-header grid auto-rows-min items-start gap-2 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)",
|
|
37
|
+
className
|
|
38
|
+
)}
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
45
|
+
return (
|
|
46
|
+
<div
|
|
47
|
+
data-slot="card-title"
|
|
48
|
+
className={cn("font-heading text-base font-medium", className)}
|
|
49
|
+
{...props}
|
|
50
|
+
/>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
|
55
|
+
return (
|
|
56
|
+
<div
|
|
57
|
+
data-slot="card-description"
|
|
58
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
59
|
+
{...props}
|
|
60
|
+
/>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
65
|
+
return (
|
|
66
|
+
<div
|
|
67
|
+
data-slot="card-action"
|
|
68
|
+
className={cn(
|
|
69
|
+
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
|
70
|
+
className
|
|
71
|
+
)}
|
|
72
|
+
{...props}
|
|
73
|
+
/>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
78
|
+
return (
|
|
79
|
+
<div
|
|
80
|
+
data-slot="card-content"
|
|
81
|
+
className={cn("px-(--card-spacing)", className)}
|
|
82
|
+
{...props}
|
|
83
|
+
/>
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
88
|
+
return (
|
|
89
|
+
<div
|
|
90
|
+
data-slot="card-footer"
|
|
91
|
+
className={cn(
|
|
92
|
+
"flex items-center rounded-b-xl px-(--card-spacing) [.border-t]:pt-(--card-spacing)",
|
|
93
|
+
className
|
|
94
|
+
)}
|
|
95
|
+
{...props}
|
|
96
|
+
/>
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export {
|
|
101
|
+
Card,
|
|
102
|
+
CardHeader,
|
|
103
|
+
CardFooter,
|
|
104
|
+
CardTitle,
|
|
105
|
+
CardAction,
|
|
106
|
+
CardDescription,
|
|
107
|
+
CardContent,
|
|
108
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@workspace/ui/lib/utils"
|
|
6
|
+
import { HugeiconsIcon } from "@hugeicons/react"
|
|
7
|
+
import { Tick02Icon } from "@hugeicons/core-free-icons"
|
|
8
|
+
|
|
9
|
+
function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
|
|
10
|
+
return (
|
|
11
|
+
<CheckboxPrimitive.Root
|
|
12
|
+
data-slot="checkbox"
|
|
13
|
+
className={cn(
|
|
14
|
+
"peer relative flex size-4 shrink-0 items-center justify-center rounded-[6px] border border-input transition-all duration-150 outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 active:ring-[3px] active:ring-ring/50 active:ring-offset-2 active:ring-offset-background",
|
|
15
|
+
"shadow-[0_1px_1px_0_rgba(0,0,0,0.24),0_2px_3px_0_rgba(0,0,0,0.20),inset_0_1px_1px_0_rgba(255,255,255,0.07),0_0_0_1px_var(--input)]",
|
|
16
|
+
"before:absolute before:inset-0 before:rounded-[6px] before:bg-linear-[180deg,rgba(255,255,255,0.1)_0%,rgba(255,255,255,0)_100%] before:content-[''] before:pointer-events-none",
|
|
17
|
+
"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:shadow-[0_1px_1px_0_rgba(0,0,0,0.24),0_2px_3px_0_rgba(0,0,0,0.20),inset_0_1px_1px_0_rgba(255,255,255,0.07),0_0_0_1px_var(--ring)]",
|
|
18
|
+
"focus-visible:before:bg-linear-[180deg,rgba(255,255,255,0)_0%,rgba(255,255,255,0.1)_100%]",
|
|
19
|
+
"disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
|
|
20
|
+
"data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary",
|
|
21
|
+
"data-checked:shadow-[inset_0_1px_1px_0_rgba(0,0,0,0.24),inset_0_2px_3px_0_rgba(0,0,0,0.20),0_1px_1px_0_rgba(255,255,255,0.07),0_0_0_1px_var(--primary)]",
|
|
22
|
+
"data-checked:before:bg-linear-[180deg,rgba(255,255,255,0)_0%,rgba(255,255,255,0.1)_100%]",
|
|
23
|
+
className
|
|
24
|
+
)}
|
|
25
|
+
{...props}
|
|
26
|
+
>
|
|
27
|
+
<CheckboxPrimitive.Indicator
|
|
28
|
+
data-slot="checkbox-indicator"
|
|
29
|
+
className="grid place-content-center text-current transition-none [&>svg]:size-3.5"
|
|
30
|
+
>
|
|
31
|
+
<HugeiconsIcon icon={Tick02Icon} strokeWidth={2} />
|
|
32
|
+
</CheckboxPrimitive.Indicator>
|
|
33
|
+
</CheckboxPrimitive.Root>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { Checkbox }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible"
|
|
4
|
+
|
|
5
|
+
function Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {
|
|
6
|
+
return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {
|
|
10
|
+
return (
|
|
11
|
+
<CollapsiblePrimitive.Trigger data-slot="collapsible-trigger" {...props} />
|
|
12
|
+
)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {
|
|
16
|
+
return (
|
|
17
|
+
<CollapsiblePrimitive.Panel data-slot="collapsible-content" {...props} />
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { Collapsible, CollapsibleTrigger, CollapsibleContent }
|