@naeil/ui 0.1.0 → 0.2.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.
Files changed (73) hide show
  1. package/README.md +60 -21
  2. package/dist/chunk-JBTDRVZ7.js +46 -0
  3. package/dist/chunk-SYI3IKIC.js +355 -0
  4. package/dist/components/index.d.ts +87 -0
  5. package/dist/components/index.js +832 -0
  6. package/dist/components/ui/index.d.ts +83 -0
  7. package/dist/components/ui/index.js +481 -0
  8. package/dist/lib/utils.d.ts +5 -0
  9. package/dist/lib/utils.js +7 -0
  10. package/package.json +52 -11
  11. package/src/app/globals.css +1 -1
  12. package/src/styles/theme.css +206 -0
  13. package/postcss.config.mjs +0 -7
  14. package/src/app/[locale]/(content)/baby-agent/page.tsx +0 -30
  15. package/src/app/[locale]/(content)/blog/page.tsx +0 -68
  16. package/src/app/[locale]/(content)/cc/page.tsx +0 -216
  17. package/src/app/[locale]/(content)/design/page.tsx +0 -703
  18. package/src/app/[locale]/(content)/layout.tsx +0 -7
  19. package/src/app/[locale]/(content)/pkm/page.tsx +0 -31
  20. package/src/app/[locale]/(content)/projects/page.tsx +0 -100
  21. package/src/app/[locale]/(content)/sa/page.tsx +0 -179
  22. package/src/app/[locale]/(landing)/page.tsx +0 -157
  23. package/src/app/[locale]/layout.tsx +0 -72
  24. package/src/app/[locale]/login/actions.ts +0 -10
  25. package/src/app/[locale]/login/oauth-buttons.tsx +0 -78
  26. package/src/app/[locale]/login/page.tsx +0 -85
  27. package/src/app/auth/callback/route.ts +0 -78
  28. package/src/app/favicon.ico +0 -0
  29. package/src/app/layout.tsx +0 -22
  30. package/src/app/sitemap.ts +0 -26
  31. package/src/components/accent-picker.tsx +0 -62
  32. package/src/components/auth-slot.tsx +0 -96
  33. package/src/components/footer-wrapper.tsx +0 -8
  34. package/src/components/footer.tsx +0 -193
  35. package/src/components/hero-scene.tsx +0 -948
  36. package/src/components/hero-section.tsx +0 -57
  37. package/src/components/locale-switcher.tsx +0 -74
  38. package/src/components/logo.tsx +0 -51
  39. package/src/components/nav-server-wrapper.tsx +0 -22
  40. package/src/components/nav-wrapper.tsx +0 -45
  41. package/src/components/nav.tsx +0 -550
  42. package/src/components/paraglider-cursor.tsx +0 -112
  43. package/src/components/project-layout.tsx +0 -194
  44. package/src/components/theme-provider.tsx +0 -10
  45. package/src/components/theme-toggle-icon.tsx +0 -62
  46. package/src/components/theme-toggle.tsx +0 -39
  47. package/src/components/typography.tsx +0 -27
  48. package/src/components/ui/avatar.tsx +0 -109
  49. package/src/components/ui/badge.tsx +0 -47
  50. package/src/components/ui/button.tsx +0 -65
  51. package/src/components/ui/card.tsx +0 -106
  52. package/src/components/ui/dialog.tsx +0 -158
  53. package/src/components/ui/dropdown-menu.tsx +0 -257
  54. package/src/components/ui/input.tsx +0 -21
  55. package/src/components/ui/sonner.tsx +0 -54
  56. package/src/components/workflow-diagram.tsx +0 -414
  57. package/src/i18n/config.ts +0 -8
  58. package/src/i18n/request.ts +0 -16
  59. package/src/i18n/routing.ts +0 -12
  60. package/src/lib/supabase/client.ts +0 -18
  61. package/src/lib/supabase/middleware.ts +0 -42
  62. package/src/lib/supabase/server.ts +0 -37
  63. package/src/lib/utils.ts +0 -6
  64. package/src/proxy.ts +0 -62
  65. package/src/tokens/.gitkeep +0 -0
  66. package/src/tokens/color.json +0 -56
  67. package/src/tokens/radius.json +0 -9
  68. package/src/tokens/semantic.json +0 -81
  69. package/src/tokens/shadow.json +0 -7
  70. package/src/tokens/spacing.json +0 -16
  71. package/src/tokens/typography.json +0 -34
  72. package/src/types/i18n.d.ts +0 -6
  73. package/src/utils/.gitkeep +0 -0
@@ -1,194 +0,0 @@
1
- "use client";
2
-
3
- import {
4
- WorkflowDiagram,
5
- type WorkflowNode,
6
- type WorkflowEdge,
7
- } from "@/components/workflow-diagram";
8
- import { PageTitle, SectionTitle } from "@/components/typography";
9
- import Image from "next/image";
10
-
11
- /* ------------------------------------------------------------------ */
12
- /* Types */
13
- /* ------------------------------------------------------------------ */
14
-
15
- export interface ProjectFeature {
16
- icon: string;
17
- title: string;
18
- description: string;
19
- }
20
-
21
- export interface ProjectStackItem {
22
- icon: string;
23
- name: string;
24
- }
25
-
26
- export interface ProjectData {
27
- icon: string;
28
- name: string;
29
- description: string;
30
- accent: string;
31
- tags: string[];
32
- github?: string;
33
- demo?: string;
34
- comingSoon?: boolean;
35
- overview?: string;
36
- features?: ProjectFeature[];
37
- workflow?: {
38
- nodes: WorkflowNode[];
39
- edges: WorkflowEdge[];
40
- };
41
- stack?: ProjectStackItem[];
42
- }
43
-
44
- /* ------------------------------------------------------------------ */
45
- /* Component */
46
- /* ------------------------------------------------------------------ */
47
-
48
- export function ProjectLayout({ data }: { data: ProjectData }) {
49
- return (
50
- <>
51
- {/* Hero */}
52
- <section className="mx-auto max-w-4xl px-6 pb-16">
53
- <div className="flex flex-col-reverse items-start gap-8 md:flex-row md:items-start md:justify-between">
54
- {/* Text */}
55
- <div className="flex-1">
56
- <PageTitle className="mb-3">{data.name}</PageTitle>
57
- <p className="text-muted-foreground mb-5 max-w-lg text-lg leading-relaxed">
58
- {data.description}
59
- </p>
60
-
61
- {/* Tags */}
62
- <div className="mb-6 flex flex-wrap gap-2">
63
- {data.tags.map((tag) => (
64
- <span
65
- key={tag}
66
- className="rounded-full border border-black/[0.08] px-2.5 py-1 text-[11px] text-zinc-400 dark:border-white/[0.08]"
67
- >
68
- {tag}
69
- </span>
70
- ))}
71
- </div>
72
-
73
- {/* Links */}
74
- <div className="flex flex-wrap items-center gap-3">
75
- {data.github && (
76
- <a
77
- href={data.github}
78
- target="_blank"
79
- rel="noopener noreferrer"
80
- className="inline-flex items-center gap-2 rounded-lg px-5 py-2.5 text-sm font-medium transition-colors"
81
- style={{
82
- background: data.accent,
83
- color: "var(--background)",
84
- }}
85
- >
86
- GitHub →
87
- </a>
88
- )}
89
- {data.demo && (
90
- <a
91
- href={data.demo}
92
- target="_blank"
93
- rel="noopener noreferrer"
94
- className="text-muted-foreground hover:text-foreground inline-flex items-center gap-2 rounded-lg border border-border px-5 py-2.5 text-sm font-medium transition-colors"
95
- >
96
- Live Demo
97
- </a>
98
- )}
99
- </div>
100
- </div>
101
-
102
- {/* Animal visual */}
103
- <div className="flex-shrink-0">
104
- <Image
105
- src={data.icon}
106
- alt=""
107
- width={220}
108
- height={220}
109
- className="animate-float object-contain"
110
- style={{
111
- filter: `drop-shadow(0 4px 12px color-mix(in oklch, ${data.accent} 15%, transparent))`,
112
- }}
113
- />
114
- </div>
115
- </div>
116
- </section>
117
-
118
- {/* Coming Soon */}
119
- {data.comingSoon && (
120
- <section className="mx-auto max-w-4xl px-6 pb-24">
121
- <div className="rounded-2xl border border-dashed border-black/[0.08] p-12 text-center dark:border-white/[0.08]">
122
- <p className="text-muted-foreground text-sm">
123
- Coming Soon
124
- </p>
125
- </div>
126
- </section>
127
- )}
128
-
129
- {/* Overview */}
130
- {data.overview && (
131
- <section className="mx-auto max-w-4xl px-6 pb-16">
132
- <SectionTitle className="mb-3">Overview</SectionTitle>
133
- <p className="text-muted-foreground max-w-2xl text-sm leading-7 whitespace-pre-line">
134
- {data.overview}
135
- </p>
136
- </section>
137
- )}
138
-
139
- {/* Features */}
140
- {data.features && data.features.length > 0 && (
141
- <section className="mx-auto max-w-4xl px-6 pb-16">
142
- <SectionTitle className="mb-6">Features</SectionTitle>
143
- <div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
144
- {data.features.map((feat) => (
145
- <div
146
- key={feat.title}
147
- className="rounded-2xl border border-border-subtle bg-surface-subtle p-6 transition-colors hover:border-border-subtle-hover"
148
- >
149
- <span className="mb-3 block text-2xl">{feat.icon}</span>
150
- <h3 className="text-foreground mb-1 text-sm font-semibold">
151
- {feat.title}
152
- </h3>
153
- <p className="text-muted-foreground text-[13px] leading-relaxed">
154
- {feat.description}
155
- </p>
156
- </div>
157
- ))}
158
- </div>
159
- </section>
160
- )}
161
-
162
- {/* Architecture */}
163
- {data.workflow && (
164
- <section className="mx-auto max-w-4xl px-6 pb-16">
165
- <SectionTitle className="mb-8">Architecture</SectionTitle>
166
- <WorkflowDiagram
167
- nodes={data.workflow.nodes}
168
- edges={data.workflow.edges}
169
- accent={data.accent}
170
- />
171
- </section>
172
- )}
173
-
174
- {/* Stack */}
175
- {data.stack && data.stack.length > 0 && (
176
- <section className="mx-auto max-w-4xl px-6 pb-24">
177
- <SectionTitle className="mb-6">Stack</SectionTitle>
178
- <div className="flex flex-wrap gap-2">
179
- {data.stack.map((item) => (
180
- <div
181
- key={item.name}
182
- className="flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-[13px]"
183
- >
184
- <span className="text-base">{item.icon}</span>
185
- <span className="text-muted-foreground">{item.name}</span>
186
- </div>
187
- ))}
188
- </div>
189
- </section>
190
- )}
191
-
192
- </>
193
- );
194
- }
@@ -1,10 +0,0 @@
1
- "use client";
2
-
3
- import { ThemeProvider as NextThemesProvider } from "next-themes";
4
-
5
- export function ThemeProvider({
6
- children,
7
- ...props
8
- }: React.ComponentProps<typeof NextThemesProvider>) {
9
- return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
10
- }
@@ -1,62 +0,0 @@
1
- "use client";
2
-
3
- import { useTheme } from "next-themes";
4
- import { useSyncExternalStore } from "react";
5
-
6
- const emptySubscribe = () => () => {};
7
-
8
- function useIsMounted() {
9
- return useSyncExternalStore(
10
- emptySubscribe,
11
- () => true,
12
- () => false,
13
- );
14
- }
15
-
16
- export function ThemeToggleIcon() {
17
- const { theme, setTheme } = useTheme();
18
- const mounted = useIsMounted();
19
-
20
- if (!mounted) {
21
- return <div className="h-4 w-4" />;
22
- }
23
-
24
- const isDark = theme === "dark";
25
-
26
- return (
27
- <button
28
- onClick={() => setTheme(isDark ? "light" : "dark")}
29
- className="text-muted-foreground hover:text-foreground transition-colors"
30
- aria-label={isDark ? "Switch to light mode" : "Switch to dark mode"}
31
- >
32
- {isDark ? (
33
- <svg
34
- width="16"
35
- height="16"
36
- viewBox="0 0 24 24"
37
- fill="none"
38
- stroke="currentColor"
39
- strokeWidth="1.5"
40
- strokeLinecap="round"
41
- strokeLinejoin="round"
42
- >
43
- <circle cx="12" cy="12" r="5" />
44
- <path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" />
45
- </svg>
46
- ) : (
47
- <svg
48
- width="16"
49
- height="16"
50
- viewBox="0 0 24 24"
51
- fill="none"
52
- stroke="currentColor"
53
- strokeWidth="1.5"
54
- strokeLinecap="round"
55
- strokeLinejoin="round"
56
- >
57
- <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
58
- </svg>
59
- )}
60
- </button>
61
- );
62
- }
@@ -1,39 +0,0 @@
1
- "use client";
2
-
3
- import { useTheme } from "next-themes";
4
- import { useSyncExternalStore } from "react";
5
- import { Button } from "@/components/ui/button";
6
-
7
- const emptySubscribe = () => () => {};
8
-
9
- function useIsMounted() {
10
- return useSyncExternalStore(
11
- emptySubscribe,
12
- () => true,
13
- () => false
14
- );
15
- }
16
-
17
- export function ThemeToggle() {
18
- const { theme, setTheme } = useTheme();
19
- const mounted = useIsMounted();
20
-
21
- if (!mounted) {
22
- return (
23
- <Button variant="outline" size="sm" className="w-24">
24
- …
25
- </Button>
26
- );
27
- }
28
-
29
- return (
30
- <Button
31
- variant="outline"
32
- size="sm"
33
- className="w-24"
34
- onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
35
- >
36
- {theme === "dark" ? "☀️ Light" : "🌙 Dark"}
37
- </Button>
38
- );
39
- }
@@ -1,27 +0,0 @@
1
- import * as React from "react";
2
- import { cn } from "@/lib/utils";
3
-
4
- type HeadingProps = React.HTMLAttributes<HTMLHeadingElement> & {
5
- children: React.ReactNode;
6
- };
7
-
8
- export const pageTitleClass =
9
- "text-foreground text-4xl font-bold tracking-tight lg:text-5xl";
10
-
11
- export const sectionTitleClass = "text-foreground text-lg font-bold";
12
-
13
- export function PageTitle({ className, children, ...props }: HeadingProps) {
14
- return (
15
- <h1 className={cn(pageTitleClass, className)} {...props}>
16
- {children}
17
- </h1>
18
- );
19
- }
20
-
21
- export function SectionTitle({ className, children, ...props }: HeadingProps) {
22
- return (
23
- <h2 className={cn(sectionTitleClass, className)} {...props}>
24
- {children}
25
- </h2>
26
- );
27
- }
@@ -1,109 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import { Avatar as AvatarPrimitive } from "radix-ui"
5
-
6
- import { cn } from "../../lib/utils"
7
-
8
- function Avatar({
9
- className,
10
- size = "default",
11
- ...props
12
- }: React.ComponentProps<typeof AvatarPrimitive.Root> & {
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 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6 focus-visible:ring-accent/25 focus-visible:ring-[2px] focus-visible:outline-none",
21
- className
22
- )}
23
- {...props}
24
- />
25
- )
26
- }
27
-
28
- function AvatarImage({
29
- className,
30
- ...props
31
- }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
32
- return (
33
- <AvatarPrimitive.Image
34
- data-slot="avatar-image"
35
- className={cn("aspect-square size-full", className)}
36
- {...props}
37
- />
38
- )
39
- }
40
-
41
- function AvatarFallback({
42
- className,
43
- ...props
44
- }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
45
- return (
46
- <AvatarPrimitive.Fallback
47
- data-slot="avatar-fallback"
48
- className={cn(
49
- "bg-accent/15 text-accent flex size-full items-center justify-center rounded-full font-medium text-xs group-data-[size=sm]/avatar:text-[10px]",
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
- "bg-primary text-primary-foreground ring-background absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full ring-2 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
- "*:data-[slot=avatar]:ring-background group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2",
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
- "bg-muted text-muted-foreground ring-background relative flex size-8 shrink-0 items-center justify-center rounded-full text-sm ring-2 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
- AvatarBadge,
107
- AvatarGroup,
108
- AvatarGroupCount,
109
- }
@@ -1,47 +0,0 @@
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 items-center justify-center rounded-sm border px-2 py-0.5 text-[11px] font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:ring-accent/25 focus-visible:ring-[2px] focus-visible:outline-none aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors overflow-hidden",
9
- {
10
- variants: {
11
- variant: {
12
- default:
13
- "bg-primary text-primary-foreground border-transparent [a&]:hover:bg-primary/90",
14
- secondary:
15
- "bg-secondary text-secondary-foreground border-transparent [a&]:hover:bg-secondary/80",
16
- outline:
17
- "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
18
- destructive:
19
- "bg-destructive text-destructive-foreground border-transparent [a&]:hover:bg-destructive/90",
20
- },
21
- },
22
- defaultVariants: {
23
- variant: "default",
24
- },
25
- }
26
- )
27
-
28
- function Badge({
29
- className,
30
- variant = "default",
31
- asChild = false,
32
- ...props
33
- }: React.ComponentProps<"span"> &
34
- VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
35
- const Comp = asChild ? Slot.Root : "span"
36
-
37
- return (
38
- <Comp
39
- data-slot="badge"
40
- data-variant={variant}
41
- className={cn(badgeVariants({ variant }), className)}
42
- {...props}
43
- />
44
- )
45
- }
46
-
47
- export { Badge, badgeVariants }
@@ -1,65 +0,0 @@
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 items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all duration-150 cursor-pointer active:scale-[0.98] disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-accent focus-visible:ring-accent/25 focus-visible:ring-[2px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
9
- {
10
- variants: {
11
- variant: {
12
- default:
13
- "bg-primary text-primary-foreground shadow-[inset_0_1px_0_0_oklch(1_0_0/0.1)] hover:bg-primary/90",
14
- destructive:
15
- "bg-destructive text-destructive-foreground hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
16
- outline:
17
- "border border-border-subtle bg-background hover:bg-surface-subtle",
18
- secondary:
19
- "bg-secondary text-secondary-foreground hover:bg-secondary/80",
20
- ghost:
21
- "hover:bg-surface-subtle",
22
- link: "text-primary underline-offset-4 hover:underline",
23
- },
24
- size: {
25
- default: "h-9 px-4 py-2 has-[>svg]:px-3",
26
- xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
27
- sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
28
- lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
29
- icon: "size-9",
30
- "icon-xs": "size-6 rounded-md [&_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 }
@@ -1,106 +0,0 @@
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
- "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border border-border-subtle py-6 transition-colors duration-150",
11
- className
12
- )}
13
- {...props}
14
- />
15
- )
16
- }
17
-
18
- function CardElevated({ className, ...props }: React.ComponentProps<"div">) {
19
- return (
20
- <div
21
- data-slot="card"
22
- className={cn(
23
- "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border border-border-subtle py-6 shadow-sm dark:bg-[oklch(0.18_0_0)] transition-colors duration-150", // ok-hardcoded
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
- "@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",
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("leading-none font-semibold", 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-muted-foreground text-sm", 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-6", 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("flex items-center px-6 [.border-t]:pt-6", className)}
92
- {...props}
93
- />
94
- )
95
- }
96
-
97
- export {
98
- Card,
99
- CardElevated,
100
- CardHeader,
101
- CardFooter,
102
- CardTitle,
103
- CardAction,
104
- CardDescription,
105
- CardContent,
106
- }