Preview
Full width desktop view
Code
confidential-5.tsx
1"use client";
2
3import * as React from "react";
4import { cva, type VariantProps } from "class-variance-authority";
5import { CreditCard, ArrowRight } from "lucide-react";
6import { Button } from "@/components/ui/button";
7import {
8 Dialog,
9 DialogClose,
10 DialogContent,
11 DialogDescription,
12 DialogFooter,
13 DialogHeader,
14 DialogTitle,
15} from "@/components/ui/dialog";
16
17const cn = (...classes: (string | undefined)[]) =>
18 classes.filter(Boolean).join(" ");
19
20const alertVariants = cva("relative rounded-lg border", {
21 variants: {
22 variant: {
23 default: "border-border bg-background",
24 warning: "border-amber-500/50 text-amber-600",
25 error: "border-red-500/50 text-red-600",
26 success: "border-emerald-500/50",
27 info: "border-blue-500/50 text-blue-600",
28 },
29 size: {
30 sm: "px-4 py-3",
31 lg: "p-4",
32 },
33 isNotification: {
34 true: "z-[100] max-w-[400px] bg-background shadow-lg shadow-black/5",
35 false: "",
36 },
37 },
38 defaultVariants: {
39 variant: "default",
40 size: "sm",
41 isNotification: false,
42 },
43});
44
45interface AlertProps
46 extends React.HTMLAttributes<HTMLDivElement>,
47 VariantProps<typeof alertVariants> {
48 icon?: React.ReactNode;
49 action?: React.ReactNode;
50 layout?: "row" | "complex";
51}
52
53const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
54 (
55 {
56 className,
57 variant,
58 size,
59 isNotification,
60 icon,
61 action,
62 layout = "row",
63 children,
64 ...props
65 },
66 ref
67 ) => (
68 <div
69 ref={ref}
70 role="alert"
71 className={cn(
72 alertVariants({ variant, size, isNotification }),
73 className
74 )}
75 {...props}
76 >
77 {layout === "row" ? (
78 <div className="flex items-center gap-2">
79 <div className="grow flex items-center">
80 {icon && <span className="me-3 inline-flex">{icon}</span>}
81 {children}
82 </div>
83 {action && <div className="flex items-center shrink-0">{action}</div>}
84 </div>
85 ) : (
86 <div className="flex gap-2">
87 {icon && children ? (
88 <div className="flex grow gap-3">
89 <span className="mt-0.5 shrink-0">{icon}</span>
90 <div className="grow">{children}</div>
91 </div>
92 ) : (
93 <div className="grow">
94 {icon && <span className="me-3 inline-flex">{icon}</span>}
95 {children}
96 </div>
97 )}
98 {action && <div className="shrink-0">{action}</div>}
99 </div>
100 )}
101 </div>
102 )
103);
104Alert.displayName = "Alert";
105
106const AddOnRequiredPage = () => {
107 const [showUpgradeDialog, setShowUpgradeDialog] = React.useState(false);
108
109 return (
110 <div className="min-h-screen bg-background flex items-center justify-center p-4">
111 <div className="w-full max-w-md space-y-8">
112 <div className="text-center">
113 <div className="mx-auto w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mb-4">
114 <CreditCard className="w-8 h-8 text-blue-600" />
115 </div>
116 <h1 className="text-2xl font-bold text-foreground mb-2">
117 Premium Feature
118 </h1>
119 <p className="text-muted-foreground">
120 This feature requires a premium add-on to access.
121 </p>
122 </div>
123
124 <Alert variant="info" layout="complex" icon={<CreditCard size={16} />}>
125 <div>
126 <h3 className="font-medium text-sm mb-1">Add-on Required</h3>
127 <p className="text-xs text-muted-foreground">
128 Upgrade your plan to unlock this premium feature.
129 </p>
130 </div>
131 </Alert>
132
133 <div className="space-y-4">
134 <div className="bg-gradient-to-r from-blue-50 to-purple-50 rounded-lg p-4 border border-blue-200">
135 <h3 className="font-semibold text-sm mb-2">
136 Premium Add-on Benefits
137 </h3>
138 <ul className="space-y-1 text-xs text-muted-foreground">
139 <li>• Advanced analytics and reporting</li>
140 <li>• Priority customer support</li>
141 <li>• Extended storage capacity</li>
142 <li>• Custom integrations</li>
143 </ul>
144 </div>
145
146 <div className="space-y-3">
147 <Button
148 className="w-full group"
149 onClick={() => setShowUpgradeDialog(true)}
150 >
151 Upgrade Now
152 <ArrowRight className="w-4 h-4 ml-2 transition-transform group-hover:translate-x-0.5" />
153 </Button>
154 <Button className="w-full" variant="outline">
155 Learn More
156 </Button>
157 </div>
158 </div>
159
160 <Dialog open={showUpgradeDialog} onOpenChange={setShowUpgradeDialog}>
161 <DialogContent>
162 <DialogHeader>
163 <DialogTitle>Upgrade to Premium</DialogTitle>
164 <DialogDescription>
165 Choose a plan that works best for you and unlock all premium
166 features.
167 </DialogDescription>
168 </DialogHeader>
169
170 <div className="space-y-4">
171 <div className="border rounded-lg p-4 space-y-2">
172 <div className="flex justify-between items-center">
173 <h4 className="font-medium">Premium Add-on</h4>
174 <span className="text-lg font-bold">$19/mo</span>
175 </div>
176 <p className="text-sm text-muted-foreground">
177 All premium features included
178 </p>
179 </div>
180 </div>
181
182 <DialogFooter>
183 <DialogClose asChild>
184 <Button variant="outline">Cancel</Button>
185 </DialogClose>
186 <Button>Subscribe Now</Button>
187 </DialogFooter>
188 </DialogContent>
189 </Dialog>
190 </div>
191 </div>
192 );
193};
194
195const ConfidentialAccessDemo = () => {
196 return (
197 <div className="space-y-4">
198 <AddOnRequiredPage />
199 </div>
200 );
201};
202
203export default ConfidentialAccessDemo;
Dependencies
External Libraries
class-variance-authoritylucide-reactreact
Shadcn/UI Components
buttondialog