Openstatus
www.openstatus.dev
1import {
2 Card,
3 CardContent,
4 CardDescription,
5 CardFooter,
6 CardHeader,
7 CardTitle,
8} from "@/components/ui/card";
9import { Separator } from "@/components/ui/separator";
10import { cn } from "@/lib/utils";
11
12import { type VariantProps, cva } from "class-variance-authority";
13
14// py-0
15const formCardVariants = cva(
16 "group relative w-full overflow-hidden py-0 shadow-none gap-4",
17 {
18 variants: {
19 variant: {
20 default: "",
21 destructive: "border-destructive",
22 info: "border-info",
23 },
24 defaultVariants: {
25 variant: "default",
26 },
27 },
28 },
29);
30
31// NOTE: Add a formcardprovider to share the variant prop
32
33export function FormCard({
34 children,
35 className,
36 variant,
37 ...props
38}: React.ComponentProps<"div"> & VariantProps<typeof formCardVariants>) {
39 return (
40 <Card className={cn(formCardVariants({ variant }), className)} {...props}>
41 {children}
42 </Card>
43 );
44}
45
46export function FormCardHeader({
47 children,
48 className,
49 ...props
50}: React.ComponentProps<"div">) {
51 return (
52 <CardHeader
53 className={cn(
54 "px-4 pt-4 group-has-data-[slot=card-upgrade]:pointer-events-none group-has-data-[slot=card-upgrade]:opacity-50 [.border-b]:pb-4",
55 className,
56 )}
57 {...props}
58 >
59 {children}
60 </CardHeader>
61 );
62}
63
64export function FormCardTitle({ children }: { children: React.ReactNode }) {
65 return <CardTitle>{children}</CardTitle>;
66}
67
68export function FormCardDescription({
69 children,
70}: {
71 children: React.ReactNode;
72}) {
73 return <CardDescription>{children}</CardDescription>;
74}
75
76export function FormCardContent({
77 children,
78 className,
79 ...props
80}: React.ComponentProps<"div">) {
81 return (
82 <CardContent
83 className={cn(
84 "px-4 group-has-data-[slot=card-upgrade]:pointer-events-none group-has-data-[slot=card-upgrade]:opacity-50",
85 "has-data-[slot=card-content-upgrade]:pointer-events-none has-data-[slot=card-content-upgrade]:opacity-50",
86 className,
87 )}
88 {...props}
89 >
90 {children}
91 </CardContent>
92 );
93}
94
95export function FormCardSeparator({
96 ...props
97}: React.ComponentProps<typeof Separator>) {
98 return <Separator {...props} />;
99}
100
101const formCardFooterVariants = cva(
102 "border-t flex items-center gap-2 pb-4 px-4 [&>:last-child]:ml-auto [.border-t]:pt-4",
103 {
104 variants: {
105 variant: {
106 default: "",
107 destructive: "border-destructive bg-destructive/5",
108 info: "border-info bg-info/5",
109 },
110 defaultVariants: {
111 variant: "default",
112 },
113 },
114 },
115);
116
117export function FormCardFooter({
118 children,
119 className,
120 variant,
121 ...props
122}: React.ComponentProps<"div"> & VariantProps<typeof formCardFooterVariants>) {
123 return (
124 <CardFooter
125 className={cn(formCardFooterVariants({ variant }), className)}
126 {...props}
127 >
128 {children}
129 </CardFooter>
130 );
131}
132
133export function FormCardFooterInfo({
134 children,
135 className,
136 ...props
137}: React.ComponentProps<"div">) {
138 return (
139 <div
140 data-slot="card-footer-info"
141 className={cn("text-muted-foreground text-sm", className)}
142 {...props}
143 >
144 {children}
145 </div>
146 );
147}
148
149export function FormCardGroup({
150 children,
151 className,
152 ...props
153}: React.ComponentProps<"div">) {
154 return (
155 <div
156 data-slot="card-group"
157 className={cn("flex flex-col gap-4", className)}
158 {...props}
159 >
160 {children}
161 </div>
162 );
163}
164
165export function FormCardUpgrade({
166 children,
167 className,
168 ...props
169}: React.ComponentProps<"div">) {
170 return (
171 <div
172 data-slot="card-upgrade"
173 className={cn("hidden", className)}
174 {...props}
175 >
176 {children}
177 </div>
178 );
179}
180
181// NOTE; this is for a very specific case where we don't want to disable the whole content
182// and instead disable specpfic card content (e.g. for add-ons)
183export function FormCardContentUpgrade({
184 children,
185 className,
186 ...props
187}: React.ComponentProps<"div">) {
188 return (
189 <div
190 data-slot="card-content-upgrade"
191 className={cn("hidden", className)}
192 {...props}
193 >
194 {children}
195 </div>
196 );
197}
198
199export function FormCardEmpty({
200 children,
201 className,
202 ...props
203}: React.ComponentProps<"div">) {
204 return (
205 <div
206 data-slot="card-empty"
207 className={cn(
208 "pointer-events-none absolute inset-0 z-10 bg-background opacity-70 blur",
209 className,
210 )}
211 {...props}
212 >
213 {children}
214 </div>
215 );
216}