content, blurthing
This commit is contained in:
@@ -23,6 +23,7 @@ import { Slider } from '@/components/ui/slider';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import type { NameType, ValueType } from 'recharts/types/component/DefaultTooltipContent';
|
||||
import { Calculator, Percent } from 'lucide-react';
|
||||
import BlurThing from './blur-thing';
|
||||
|
||||
// Schema for form validation
|
||||
const formSchema = z.object({
|
||||
@@ -334,6 +335,7 @@ export default function FireCalculatorForm() {
|
||||
return (
|
||||
<>
|
||||
<Card className="border-primary/15 bg-background/90 shadow-primary/10 mb-6 border shadow-lg backdrop-blur">
|
||||
<BlurThing />
|
||||
<CardHeader>
|
||||
<CardTitle className="text-2xl">FIRE Calculator</CardTitle>
|
||||
<CardDescription className="text-muted-foreground text-sm">
|
||||
|
||||
11
src/app/components/blur-thing.tsx
Normal file
11
src/app/components/blur-thing.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
export default function BlurThing() {
|
||||
return (
|
||||
<>
|
||||
{/* Decorative background elements */}
|
||||
<div className="pointer-events-none absolute inset-0 overflow-hidden rounded-xl">
|
||||
<div className="from-primary/25 to-primary/15 absolute -top-24 -right-24 h-64 w-64 rounded-full bg-gradient-to-br blur-3xl" />
|
||||
<div className="absolute -bottom-24 -left-24 h-64 w-64 rounded-full bg-gradient-to-br from-orange-500/25 to-red-500/15 blur-3xl" />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
ChartTooltipContent,
|
||||
type ChartConfig,
|
||||
} from '@/components/ui/chart';
|
||||
import BlurThing from '../blur-thing';
|
||||
|
||||
// Simulation
|
||||
// Standard: Start 25, Retire 65. Save $10k/yr.
|
||||
@@ -57,6 +58,8 @@ const chartConfig = {
|
||||
export function CoastFireChart() {
|
||||
return (
|
||||
<Card className="w-full">
|
||||
{/* Decorative background elements */}
|
||||
<BlurThing />
|
||||
<CardHeader>
|
||||
<CardTitle>Coast FIRE vs. Standard Path</CardTitle>
|
||||
<CardDescription>
|
||||
|
||||
@@ -1,71 +1,113 @@
|
||||
import { ArrowRight, Banknote, Coins, Landmark, TrendingUp, Wallet } from "lucide-react";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Banknote, Coins, Flame, Landmark, TrendingUp, Wallet } from 'lucide-react';
|
||||
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import BlurThing from '../blur-thing';
|
||||
|
||||
const steps = [
|
||||
{
|
||||
icon: Banknote,
|
||||
title: 'Income',
|
||||
description: 'Maximize earnings & side hustles',
|
||||
color: 'from-emerald-400 to-teal-500',
|
||||
glow: 'shadow-emerald-500/30',
|
||||
},
|
||||
{
|
||||
icon: Wallet,
|
||||
title: 'Low Expenses',
|
||||
description: 'Frugality & mindful spending',
|
||||
color: 'from-rose-400 to-pink-500',
|
||||
glow: 'shadow-rose-500/30',
|
||||
},
|
||||
{
|
||||
icon: Coins,
|
||||
title: 'Savings Gap',
|
||||
description: 'The difference is your fuel',
|
||||
color: 'from-sky-400 to-blue-500',
|
||||
glow: 'shadow-sky-500/30',
|
||||
},
|
||||
{
|
||||
icon: TrendingUp,
|
||||
title: 'Investments',
|
||||
description: 'Index funds & compounding',
|
||||
color: 'from-violet-400 to-purple-500',
|
||||
glow: 'shadow-violet-500/30',
|
||||
},
|
||||
{
|
||||
icon: Landmark,
|
||||
title: 'Freedom',
|
||||
description: 'Work becomes optional',
|
||||
color: 'from-amber-400 to-orange-500',
|
||||
glow: 'shadow-amber-500/30',
|
||||
},
|
||||
];
|
||||
|
||||
export function FireFlowchart() {
|
||||
return (
|
||||
<Card className="w-full overflow-hidden">
|
||||
<CardHeader className="pb-2 text-center">
|
||||
<CardTitle>The FIRE Engine</CardTitle>
|
||||
<Card className="relative w-full overflow-hidden">
|
||||
<BlurThing />
|
||||
<CardHeader className="relative pb-0 text-center">
|
||||
<CardTitle className="flex items-center justify-center gap-3 text-2xl">
|
||||
<Flame className="h-7 w-7 text-orange-500" />
|
||||
The FIRE Engine
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="p-6">
|
||||
<div className="flex flex-col items-center justify-center gap-4 md:flex-row md:items-start">
|
||||
|
||||
{/* Step 1: Income */}
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-green-100 text-green-600 dark:bg-green-900 dark:text-green-300">
|
||||
<Banknote className="h-8 w-8" />
|
||||
|
||||
<CardContent className="relative">
|
||||
{/* Connecting line - visible on md+ */}
|
||||
<div className="absolute top-10 right-12 left-12 hidden h-0.5 bg-gradient-to-r from-emerald-400 via-purple-400 to-orange-400 opacity-30 md:block" />
|
||||
|
||||
{/* Steps */}
|
||||
<div className="relative grid grid-cols-1 gap-6 md:grid-cols-5 md:gap-4">
|
||||
{steps.map((step, index) => (
|
||||
<div key={step.title} className="group relative flex flex-col items-center">
|
||||
{/* Step number badge */}
|
||||
<div className="absolute -top-2 -left-2 z-10 flex h-6 w-6 items-center justify-center rounded-full bg-zinc-900 text-xs font-bold text-white md:-top-1 md:-left-1">
|
||||
{index + 1}
|
||||
</div>
|
||||
|
||||
{/* Icon container */}
|
||||
<div
|
||||
className={`relative flex h-20 w-20 items-center justify-center rounded-2xl bg-gradient-to-br ${step.color} shadow-lg ${step.glow} transition-all duration-300 group-hover:scale-105 group-hover:shadow-xl`}
|
||||
>
|
||||
<step.icon className="h-9 w-9 text-white" strokeWidth={1.5} />
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="mt-4 text-center">
|
||||
<h4 className="font-semibold tracking-tight">{step.title}</h4>
|
||||
<p className="text-muted-foreground mt-1 max-w-[140px] text-xs leading-relaxed">
|
||||
{step.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Arrow connector for mobile */}
|
||||
{index < steps.length - 1 && (
|
||||
<div className="my-2 flex items-center justify-center md:hidden">
|
||||
<svg
|
||||
className="text-muted-foreground h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M19 14l-7 7m0 0l-7-7m7 7V3"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<span className="font-bold">Income</span>
|
||||
<p className="w-32 text-center text-xs text-muted-foreground">Maximize earnings & side hustles</p>
|
||||
</div>
|
||||
|
||||
<ArrowRight className="hidden h-8 w-8 text-muted-foreground md:block rotate-90 md:rotate-0" />
|
||||
|
||||
{/* Step 2: Expenses */}
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-red-100 text-red-600 dark:bg-red-900 dark:text-red-300">
|
||||
<Wallet className="h-8 w-8" />
|
||||
</div>
|
||||
<span className="font-bold">Low Expenses</span>
|
||||
<p className="w-32 text-center text-xs text-muted-foreground">Frugality & mindful spending</p>
|
||||
</div>
|
||||
|
||||
<ArrowRight className="hidden h-8 w-8 text-muted-foreground md:block rotate-90 md:rotate-0" />
|
||||
|
||||
{/* Step 3: Savings Gap */}
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-blue-100 text-blue-600 dark:bg-blue-900 dark:text-blue-300">
|
||||
<Coins className="h-8 w-8" />
|
||||
</div>
|
||||
<span className="font-bold">Savings Gap</span>
|
||||
<p className="w-32 text-center text-xs text-muted-foreground">The difference is your fuel</p>
|
||||
</div>
|
||||
|
||||
<ArrowRight className="hidden h-8 w-8 text-muted-foreground md:block rotate-90 md:rotate-0" />
|
||||
|
||||
{/* Step 4: Investments */}
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-purple-100 text-purple-600 dark:bg-purple-900 dark:text-purple-300">
|
||||
<TrendingUp className="h-8 w-8" />
|
||||
</div>
|
||||
<span className="font-bold">Investments</span>
|
||||
<p className="w-32 text-center text-xs text-muted-foreground">Index funds & compounding</p>
|
||||
</div>
|
||||
|
||||
<ArrowRight className="hidden h-8 w-8 text-muted-foreground md:block rotate-90 md:rotate-0" />
|
||||
|
||||
{/* Step 5: Freedom */}
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-orange-100 text-orange-600 dark:bg-orange-900 dark:text-orange-300">
|
||||
<Landmark className="h-8 w-8" />
|
||||
</div>
|
||||
<span className="font-bold">Freedom</span>
|
||||
<p className="w-32 text-center text-xs text-muted-foreground">Work becomes optional</p>
|
||||
</div>
|
||||
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Bottom tagline */}
|
||||
<CardFooter>
|
||||
<p className="text-muted-foreground mx-auto mt-8 text-center text-sm">
|
||||
Build the gap. Invest the gap. Let time do the rest.
|
||||
</p>
|
||||
</CardFooter>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
ChartTooltipContent,
|
||||
type ChartConfig,
|
||||
} from '@/components/ui/chart';
|
||||
import BlurThing from '../blur-thing';
|
||||
|
||||
// Simulation data for 4% rule
|
||||
const storyData = [
|
||||
@@ -47,6 +48,7 @@ const chartConfig = {
|
||||
export function FourPercentRuleChart() {
|
||||
return (
|
||||
<Card className="w-full">
|
||||
<BlurThing />
|
||||
<CardHeader>
|
||||
<CardTitle>Portfolio Survival Scenarios</CardTitle>
|
||||
<CardDescription>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Link from 'next/link';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import BlurThing from '../components/blur-thing';
|
||||
|
||||
export const metadata = {
|
||||
title: 'Learn FIRE | Financial Independence Guides & Resources',
|
||||
@@ -20,7 +21,8 @@ export default function LearnHubPage() {
|
||||
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||
{/* Article 1 */}
|
||||
<Link href="/learn/what-is-fire" className="transition-transform hover:scale-[1.02]">
|
||||
<Card className="hover:border-primary/50 h-full cursor-pointer border-2">
|
||||
<Card className="hover:border-primary/50 h-full cursor-pointer border-2 transition-all">
|
||||
<BlurThing />
|
||||
<CardHeader>
|
||||
<div className="mb-2">
|
||||
<span className="rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800 dark:bg-green-900 dark:text-green-300">
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
import * as React from "react";
|
||||
import * as React from 'react';
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
function Card({ className, ...props }: React.ComponentProps<"div">) {
|
||||
function Card({ className, children, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card"
|
||||
className={cn(
|
||||
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
||||
'bg-card text-card-foreground relative flex flex-col gap-6 overflow-hidden rounded-xl border py-6 shadow-sm',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||
function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-header"
|
||||
className={cn(
|
||||
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
||||
'@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@@ -28,65 +30,44 @@ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||
);
|
||||
}
|
||||
|
||||
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
||||
function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-title"
|
||||
className={cn("leading-none font-semibold", className)}
|
||||
{...props}
|
||||
/>
|
||||
<div data-slot="card-title" className={cn('leading-none font-semibold', className)} {...props} />
|
||||
);
|
||||
}
|
||||
|
||||
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
||||
function CardDescription({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-description"
|
||||
className={cn("text-muted-foreground text-sm", className)}
|
||||
className={cn('text-muted-foreground text-sm', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
||||
function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-action"
|
||||
className={cn(
|
||||
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
||||
className,
|
||||
)}
|
||||
className={cn('col-start-2 row-span-2 row-start-1 self-start justify-self-end', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-content"
|
||||
className={cn("px-6", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return <div data-slot="card-content" className={cn('px-6', className)} {...props} />;
|
||||
}
|
||||
|
||||
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||
function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-footer"
|
||||
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
|
||||
className={cn('flex items-center px-6 [.border-t]:pt-6', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
CardAction,
|
||||
CardDescription,
|
||||
CardContent,
|
||||
};
|
||||
export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import * as React from "react";
|
||||
import * as React from 'react';
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
||||
function Input({ className, type, ...props }: React.ComponentProps<'input'>) {
|
||||
return (
|
||||
<input
|
||||
type={type}
|
||||
data-slot="input"
|
||||
className={cn(
|
||||
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
||||
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground border-input bg-background flex h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||
'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
|
||||
'aria-invalid:ring-destructive/20 aria-invalid:border-destructive',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -1,43 +1,37 @@
|
||||
"use client";
|
||||
'use client';
|
||||
|
||||
import * as React from "react";
|
||||
import * as SelectPrimitive from "@radix-ui/react-select";
|
||||
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
||||
import * as React from 'react';
|
||||
import * as SelectPrimitive from '@radix-ui/react-select';
|
||||
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-react';
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
function Select({
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
||||
function Select({ ...props }: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
||||
return <SelectPrimitive.Root data-slot="select" {...props} />;
|
||||
}
|
||||
|
||||
function SelectGroup({
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Group>) {
|
||||
function SelectGroup({ ...props }: React.ComponentProps<typeof SelectPrimitive.Group>) {
|
||||
return <SelectPrimitive.Group data-slot="select-group" {...props} />;
|
||||
}
|
||||
|
||||
function SelectValue({
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Value>) {
|
||||
function SelectValue({ ...props }: React.ComponentProps<typeof SelectPrimitive.Value>) {
|
||||
return <SelectPrimitive.Value data-slot="select-value" {...props} />;
|
||||
}
|
||||
|
||||
function SelectTrigger({
|
||||
className,
|
||||
size = "default",
|
||||
size = 'default',
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
|
||||
size?: "sm" | "default";
|
||||
size?: 'sm' | 'default';
|
||||
}) {
|
||||
return (
|
||||
<SelectPrimitive.Trigger
|
||||
data-slot="select-trigger"
|
||||
data-size={size}
|
||||
className={cn(
|
||||
"border-input data-placeholder:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
"border-input data-placeholder:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 aria-invalid:border-destructive bg-background flex w-fit items-center justify-between gap-2 rounded-md border px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@@ -53,7 +47,7 @@ function SelectTrigger({
|
||||
function SelectContent({
|
||||
className,
|
||||
children,
|
||||
position = "popper",
|
||||
position = 'popper',
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
|
||||
return (
|
||||
@@ -61,9 +55,9 @@ function SelectContent({
|
||||
<SelectPrimitive.Content
|
||||
data-slot="select-content"
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-32 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
|
||||
position === "popper" &&
|
||||
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
||||
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-32 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md',
|
||||
position === 'popper' &&
|
||||
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
|
||||
className,
|
||||
)}
|
||||
position={position}
|
||||
@@ -72,9 +66,9 @@ function SelectContent({
|
||||
<SelectScrollUpButton />
|
||||
<SelectPrimitive.Viewport
|
||||
className={cn(
|
||||
"p-1",
|
||||
position === "popper" &&
|
||||
"h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width) scroll-my-1",
|
||||
'p-1',
|
||||
position === 'popper' &&
|
||||
'h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width) scroll-my-1',
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
@@ -85,14 +79,11 @@ function SelectContent({
|
||||
);
|
||||
}
|
||||
|
||||
function SelectLabel({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Label>) {
|
||||
function SelectLabel({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Label>) {
|
||||
return (
|
||||
<SelectPrimitive.Label
|
||||
data-slot="select-label"
|
||||
className={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
|
||||
className={cn('text-muted-foreground px-2 py-1.5 text-xs', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
@@ -129,7 +120,7 @@ function SelectSeparator({
|
||||
return (
|
||||
<SelectPrimitive.Separator
|
||||
data-slot="select-separator"
|
||||
className={cn("bg-border pointer-events-none -mx-1 my-1 h-px", className)}
|
||||
className={cn('bg-border pointer-events-none -mx-1 my-1 h-px', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
@@ -142,10 +133,7 @@ function SelectScrollUpButton({
|
||||
return (
|
||||
<SelectPrimitive.ScrollUpButton
|
||||
data-slot="select-scroll-up-button"
|
||||
className={cn(
|
||||
"flex cursor-default items-center justify-center py-1",
|
||||
className,
|
||||
)}
|
||||
className={cn('flex cursor-default items-center justify-center py-1', className)}
|
||||
{...props}
|
||||
>
|
||||
<ChevronUpIcon className="size-4" />
|
||||
@@ -160,10 +148,7 @@ function SelectScrollDownButton({
|
||||
return (
|
||||
<SelectPrimitive.ScrollDownButton
|
||||
data-slot="select-scroll-down-button"
|
||||
className={cn(
|
||||
"flex cursor-default items-center justify-center py-1",
|
||||
className,
|
||||
)}
|
||||
className={cn('flex cursor-default items-center justify-center py-1', className)}
|
||||
{...props}
|
||||
>
|
||||
<ChevronDownIcon className="size-4" />
|
||||
|
||||
Reference in New Issue
Block a user