mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-24 21:25:55 +00:00
feat: update dark mode colors (#6903)
* feat: update dark colors * feat(v4): update dark mode colors * fix * fix * fix: slate and stone mismatches * feat(v4): update skeleton and switch colors * feat(v4): add dashboard example * fix(v4): update dashboard components * fix: themes * feat: update sonner * feat(v4): update dashboard buttons * fix: test new colors * fix: build commands * feat(v4): more color updates * feat(v4): update theme selector * fix(v4): minor component fixes
This commit is contained in:
@@ -2,8 +2,13 @@ import { FormsDemo } from "@/components/forms-demo"
|
||||
|
||||
export default function FormsPage() {
|
||||
return (
|
||||
<div className="flex flex-1 items-center justify-center p-4">
|
||||
<FormsDemo />
|
||||
<div className="flex flex-1 flex-col items-center justify-center gap-12 p-4 lg:flex-row">
|
||||
<div className="">
|
||||
<FormsDemo />
|
||||
</div>
|
||||
<div className="theme-small">
|
||||
<FormsDemo />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { cookies } from "next/headers"
|
||||
import { AppSidebar } from "@/components/app-sidebar"
|
||||
import { ModeSwitcher } from "@/components/mode-switcher"
|
||||
import { NavHeader } from "@/components/nav-header"
|
||||
import { ThemeSelector } from "@/components/theme-selector"
|
||||
import { Separator } from "@/registry/new-york-v4/ui/separator"
|
||||
import {
|
||||
SidebarInset,
|
||||
@@ -31,6 +32,7 @@ export default async function AppLayout({
|
||||
/>
|
||||
<NavHeader />
|
||||
<div className="ml-auto flex items-center gap-2">
|
||||
<ThemeSelector />
|
||||
<ModeSwitcher />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@ export default function LoginPage() {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"bg-muted flex flex-1 flex-col items-center justify-center gap-16 p-6 md:p-10",
|
||||
"bg-muted dark:bg-background flex flex-1 flex-col items-center justify-center gap-16 p-6 md:p-10",
|
||||
fontSans.variable,
|
||||
fontSerif.variable,
|
||||
fontManrope.variable
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { addDays, format } from "date-fns"
|
||||
import { CalendarIcon } from "lucide-react"
|
||||
import { DateRange } from "react-day-picker"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
||||
import { Calendar } from "@/registry/new-york-v4/ui/calendar"
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/registry/new-york-v4/ui/popover"
|
||||
|
||||
export function AnalyticsDatePicker() {
|
||||
const [date, setDate] = React.useState<DateRange | undefined>({
|
||||
from: new Date(new Date().getFullYear(), 0, 20),
|
||||
to: addDays(new Date(new Date().getFullYear(), 0, 20), 20),
|
||||
})
|
||||
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
id="date"
|
||||
variant="outline"
|
||||
className={cn(
|
||||
"w-fit justify-start px-2 font-normal",
|
||||
!date && "text-muted-foreground"
|
||||
)}
|
||||
>
|
||||
<CalendarIcon className="text-muted-foreground" />
|
||||
{date?.from ? (
|
||||
date.to ? (
|
||||
<>
|
||||
{format(date.from, "LLL dd, y")} -{" "}
|
||||
{format(date.to, "LLL dd, y")}
|
||||
</>
|
||||
) : (
|
||||
format(date.from, "LLL dd, y")
|
||||
)
|
||||
) : (
|
||||
<span>Pick a date</span>
|
||||
)}
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-auto p-0" align="end">
|
||||
<Calendar
|
||||
initialFocus
|
||||
mode="range"
|
||||
defaultMonth={date?.from}
|
||||
selected={date}
|
||||
onSelect={setDate}
|
||||
numberOfMonths={2}
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
84
apps/v4/app/(examples)/dashboard/components/app-sidebar.tsx
Normal file
84
apps/v4/app/(examples)/dashboard/components/app-sidebar.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import {
|
||||
ChartLineIcon,
|
||||
FileIcon,
|
||||
HomeIcon,
|
||||
LifeBuoy,
|
||||
Send,
|
||||
Settings2Icon,
|
||||
ShoppingBagIcon,
|
||||
ShoppingCartIcon,
|
||||
UserIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
import { Sidebar, SidebarContent } from "@/registry/new-york-v4/ui/sidebar"
|
||||
import { NavMain } from "@/app/(examples)/dashboard/components/nav-main"
|
||||
import { NavSecondary } from "@/app/(examples)/dashboard/components/nav-secondary"
|
||||
|
||||
const data = {
|
||||
navMain: [
|
||||
{
|
||||
title: "Dashboard",
|
||||
url: "/dashboard",
|
||||
icon: HomeIcon,
|
||||
},
|
||||
{
|
||||
title: "Analytics",
|
||||
url: "/dashboard/analytics",
|
||||
icon: ChartLineIcon,
|
||||
},
|
||||
{
|
||||
title: "Orders",
|
||||
url: "/dashboard/orders",
|
||||
icon: ShoppingBagIcon,
|
||||
},
|
||||
{
|
||||
title: "Products",
|
||||
url: "/dashboard/products",
|
||||
icon: ShoppingCartIcon,
|
||||
},
|
||||
{
|
||||
title: "Invoices",
|
||||
url: "/dashboard/invoices",
|
||||
icon: FileIcon,
|
||||
},
|
||||
{
|
||||
title: "Customers",
|
||||
url: "/dashboard/customers",
|
||||
icon: UserIcon,
|
||||
},
|
||||
{
|
||||
title: "Settings",
|
||||
url: "/dashboard/settings",
|
||||
icon: Settings2Icon,
|
||||
},
|
||||
],
|
||||
navSecondary: [
|
||||
{
|
||||
title: "Support",
|
||||
url: "#",
|
||||
icon: LifeBuoy,
|
||||
},
|
||||
{
|
||||
title: "Feedback",
|
||||
url: "#",
|
||||
icon: Send,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||
return (
|
||||
<Sidebar
|
||||
className="top-(--header-height) h-[calc(100svh-var(--header-height))]!"
|
||||
{...props}
|
||||
>
|
||||
<SidebarContent>
|
||||
<NavMain items={data.navMain} />
|
||||
<NavSecondary items={data.navSecondary} className="mt-auto" />
|
||||
</SidebarContent>
|
||||
</Sidebar>
|
||||
)
|
||||
}
|
||||
110
apps/v4/app/(examples)/dashboard/components/chart-revenue.tsx
Normal file
110
apps/v4/app/(examples)/dashboard/components/chart-revenue.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
"use client"
|
||||
|
||||
import { TrendingUp } from "lucide-react"
|
||||
import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts"
|
||||
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/registry/new-york-v4/ui/card"
|
||||
import {
|
||||
ChartConfig,
|
||||
ChartContainer,
|
||||
ChartTooltip,
|
||||
ChartTooltipContent,
|
||||
} from "@/registry/new-york-v4/ui/chart"
|
||||
|
||||
const chartData = [
|
||||
{ month: "January", desktop: 186, mobile: 80 },
|
||||
{ month: "February", desktop: 305, mobile: 200 },
|
||||
{ month: "March", desktop: 237, mobile: 120 },
|
||||
{ month: "April", desktop: 73, mobile: 190 },
|
||||
{ month: "May", desktop: 209, mobile: 130 },
|
||||
{ month: "June", desktop: 346, mobile: 140 },
|
||||
{ month: "July", desktop: 321, mobile: 275 },
|
||||
{ month: "August", desktop: 132, mobile: 95 },
|
||||
{ month: "September", desktop: 189, mobile: 225 },
|
||||
{ month: "October", desktop: 302, mobile: 248 },
|
||||
{ month: "November", desktop: 342, mobile: 285 },
|
||||
{ month: "December", desktop: 328, mobile: 290 },
|
||||
]
|
||||
|
||||
const chartConfig = {
|
||||
desktop: {
|
||||
label: "Desktop",
|
||||
color: "var(--chart-1)",
|
||||
},
|
||||
mobile: {
|
||||
label: "Mobile",
|
||||
color: "var(--chart-2)",
|
||||
},
|
||||
} satisfies ChartConfig
|
||||
|
||||
export function ChartRevenue() {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardDescription>January - June 2024</CardDescription>
|
||||
<CardTitle className="text-3xl font-bold tracking-tight">
|
||||
$45,231.89
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ChartContainer config={chartConfig} className="aspect-[3/1]">
|
||||
<BarChart
|
||||
accessibilityLayer
|
||||
data={chartData}
|
||||
margin={{
|
||||
left: -16,
|
||||
right: 0,
|
||||
}}
|
||||
>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis
|
||||
dataKey="month"
|
||||
tickLine={false}
|
||||
tickMargin={10}
|
||||
axisLine={false}
|
||||
tickFormatter={(value) => value.slice(0, 3)}
|
||||
/>
|
||||
<YAxis
|
||||
tickLine={false}
|
||||
tickMargin={10}
|
||||
axisLine={false}
|
||||
tickFormatter={(value) => value.toLocaleString()}
|
||||
domain={[0, "dataMax"]}
|
||||
/>
|
||||
<ChartTooltip
|
||||
cursor={false}
|
||||
content={<ChartTooltipContent hideIndicator />}
|
||||
/>
|
||||
<Bar
|
||||
dataKey="desktop"
|
||||
fill="var(--color-desktop)"
|
||||
radius={[0, 0, 4, 4]}
|
||||
stackId={1}
|
||||
/>
|
||||
<Bar
|
||||
dataKey="mobile"
|
||||
fill="var(--color-mobile)"
|
||||
radius={[4, 4, 0, 0]}
|
||||
stackId={1}
|
||||
/>
|
||||
</BarChart>
|
||||
</ChartContainer>
|
||||
</CardContent>
|
||||
<CardFooter className="flex-col items-start gap-2 text-sm">
|
||||
<div className="flex gap-2 leading-none font-medium">
|
||||
Trending up by 5.2% this month <TrendingUp className="h-4 w-4" />
|
||||
</div>
|
||||
<div className="text-muted-foreground leading-none">
|
||||
Showing total visitors for the last 6 months
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
189
apps/v4/app/(examples)/dashboard/components/chart-visitors.tsx
Normal file
189
apps/v4/app/(examples)/dashboard/components/chart-visitors.tsx
Normal file
@@ -0,0 +1,189 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Label, Pie, PieChart, Sector } from "recharts"
|
||||
import { PieSectorDataItem } from "recharts/types/polar/Pie"
|
||||
|
||||
import {
|
||||
Card,
|
||||
CardAction,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/registry/new-york-v4/ui/card"
|
||||
import {
|
||||
ChartConfig,
|
||||
ChartContainer,
|
||||
ChartStyle,
|
||||
ChartTooltip,
|
||||
ChartTooltipContent,
|
||||
} from "@/registry/new-york-v4/ui/chart"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/registry/new-york-v4/ui/select"
|
||||
|
||||
const desktopData = [
|
||||
{ month: "january", desktop: 186, fill: "var(--color-january)" },
|
||||
{ month: "february", desktop: 305, fill: "var(--color-february)" },
|
||||
{ month: "march", desktop: 237, fill: "var(--color-march)" },
|
||||
{ month: "april", desktop: 173, fill: "var(--color-april)" },
|
||||
{ month: "may", desktop: 209, fill: "var(--color-may)" },
|
||||
]
|
||||
|
||||
const chartConfig = {
|
||||
visitors: {
|
||||
label: "Visitors",
|
||||
},
|
||||
desktop: {
|
||||
label: "Desktop",
|
||||
},
|
||||
mobile: {
|
||||
label: "Mobile",
|
||||
},
|
||||
january: {
|
||||
label: "January",
|
||||
color: "var(--chart-1)",
|
||||
},
|
||||
february: {
|
||||
label: "February",
|
||||
color: "var(--chart-2)",
|
||||
},
|
||||
march: {
|
||||
label: "March",
|
||||
color: "var(--chart-3)",
|
||||
},
|
||||
april: {
|
||||
label: "April",
|
||||
color: "var(--chart-4)",
|
||||
},
|
||||
may: {
|
||||
label: "May",
|
||||
color: "var(--chart-5)",
|
||||
},
|
||||
} satisfies ChartConfig
|
||||
|
||||
export function ChartVisitors() {
|
||||
const id = "pie-interactive"
|
||||
const [activeMonth, setActiveMonth] = React.useState(desktopData[0].month)
|
||||
|
||||
const activeIndex = React.useMemo(
|
||||
() => desktopData.findIndex((item) => item.month === activeMonth),
|
||||
[activeMonth]
|
||||
)
|
||||
const months = React.useMemo(() => desktopData.map((item) => item.month), [])
|
||||
|
||||
return (
|
||||
<Card data-chart={id}>
|
||||
<ChartStyle id={id} config={chartConfig} />
|
||||
<CardHeader>
|
||||
<CardDescription>January - June 2024</CardDescription>
|
||||
<CardTitle className="text-2xl font-bold">1,234 visitors</CardTitle>
|
||||
<CardAction>
|
||||
<Select value={activeMonth} onValueChange={setActiveMonth}>
|
||||
<SelectTrigger
|
||||
className="ml-auto h-8 w-[120px]"
|
||||
aria-label="Select a value"
|
||||
>
|
||||
<SelectValue placeholder="Select month" />
|
||||
</SelectTrigger>
|
||||
<SelectContent align="end">
|
||||
{months.map((key) => {
|
||||
const config = chartConfig[key as keyof typeof chartConfig]
|
||||
|
||||
if (!config) {
|
||||
return null
|
||||
}
|
||||
|
||||
const color = "color" in config ? config.color : undefined
|
||||
|
||||
return (
|
||||
<SelectItem key={key} value={key}>
|
||||
<div className="flex items-center gap-2 text-xs">
|
||||
<span
|
||||
className="flex h-3 w-3 shrink-0 rounded-sm"
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
}}
|
||||
/>
|
||||
{config?.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
)
|
||||
})}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</CardAction>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-1 justify-center pb-0">
|
||||
<ChartContainer
|
||||
id={id}
|
||||
config={chartConfig}
|
||||
className="mx-auto aspect-square w-full max-w-[300px]"
|
||||
>
|
||||
<PieChart>
|
||||
<ChartTooltip
|
||||
cursor={false}
|
||||
content={<ChartTooltipContent hideLabel />}
|
||||
/>
|
||||
<Pie
|
||||
data={desktopData}
|
||||
dataKey="desktop"
|
||||
nameKey="month"
|
||||
innerRadius={60}
|
||||
strokeWidth={5}
|
||||
activeIndex={activeIndex}
|
||||
activeShape={({
|
||||
outerRadius = 0,
|
||||
...props
|
||||
}: PieSectorDataItem) => (
|
||||
<g>
|
||||
<Sector {...props} outerRadius={outerRadius + 10} />
|
||||
<Sector
|
||||
{...props}
|
||||
outerRadius={outerRadius + 25}
|
||||
innerRadius={outerRadius + 12}
|
||||
/>
|
||||
</g>
|
||||
)}
|
||||
>
|
||||
<Label
|
||||
content={({ viewBox }) => {
|
||||
if (viewBox && "cx" in viewBox && "cy" in viewBox) {
|
||||
return (
|
||||
<text
|
||||
x={viewBox.cx}
|
||||
y={viewBox.cy}
|
||||
textAnchor="middle"
|
||||
dominantBaseline="middle"
|
||||
>
|
||||
<tspan
|
||||
x={viewBox.cx}
|
||||
y={viewBox.cy}
|
||||
className="fill-foreground text-3xl font-bold"
|
||||
>
|
||||
{desktopData[activeIndex].desktop.toLocaleString()}
|
||||
</tspan>
|
||||
<tspan
|
||||
x={viewBox.cx}
|
||||
y={(viewBox.cy || 0) + 24}
|
||||
className="fill-muted-foreground"
|
||||
>
|
||||
Visitors
|
||||
</tspan>
|
||||
</text>
|
||||
)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Pie>
|
||||
</PieChart>
|
||||
</ChartContainer>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
28
apps/v4/app/(examples)/dashboard/components/mode-toggle.tsx
Normal file
28
apps/v4/app/(examples)/dashboard/components/mode-toggle.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { MoonIcon, SunIcon } from "lucide-react"
|
||||
import { useTheme } from "next-themes"
|
||||
|
||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
||||
|
||||
export function ModeToggle() {
|
||||
const { setTheme, resolvedTheme } = useTheme()
|
||||
|
||||
const toggleTheme = React.useCallback(() => {
|
||||
setTheme(resolvedTheme === "dark" ? "light" : "dark")
|
||||
}, [resolvedTheme, setTheme])
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="icon"
|
||||
className="group/toggle size-8"
|
||||
onClick={toggleTheme}
|
||||
>
|
||||
<SunIcon className="hidden [html.dark_&]:block" />
|
||||
<MoonIcon className="hidden [html.light_&]:block" />
|
||||
<span className="sr-only">Toggle theme</span>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
91
apps/v4/app/(examples)/dashboard/components/nav-main.tsx
Normal file
91
apps/v4/app/(examples)/dashboard/components/nav-main.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
"use client"
|
||||
|
||||
import { usePathname } from "next/navigation"
|
||||
import { ChevronRight, type LucideIcon } from "lucide-react"
|
||||
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "@/registry/new-york-v4/ui/collapsible"
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuAction,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarMenuSub,
|
||||
SidebarMenuSubButton,
|
||||
SidebarMenuSubItem,
|
||||
} from "@/registry/new-york-v4/ui/sidebar"
|
||||
|
||||
export function NavMain({
|
||||
items,
|
||||
}: {
|
||||
items: {
|
||||
title: string
|
||||
url: string
|
||||
icon: LucideIcon
|
||||
isActive?: boolean
|
||||
items?: {
|
||||
title: string
|
||||
url: string
|
||||
}[]
|
||||
disabled?: boolean
|
||||
}[]
|
||||
}) {
|
||||
const pathname = usePathname()
|
||||
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Dashboard</SidebarGroupLabel>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => (
|
||||
<Collapsible key={item.title} asChild defaultOpen={item.isActive}>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton
|
||||
asChild
|
||||
tooltip={item.title}
|
||||
isActive={pathname === item.url}
|
||||
disabled={item.disabled}
|
||||
>
|
||||
<a
|
||||
href={item.disabled ? "#" : item.url}
|
||||
data-disabled={item.disabled}
|
||||
className="data-[disabled=true]:opacity-50"
|
||||
>
|
||||
<item.icon className="text-muted-foreground" />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
{item.items?.length ? (
|
||||
<>
|
||||
<CollapsibleTrigger asChild>
|
||||
<SidebarMenuAction className="data-[state=open]:rotate-90">
|
||||
<ChevronRight />
|
||||
<span className="sr-only">Toggle</span>
|
||||
</SidebarMenuAction>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
{item.items?.map((subItem) => (
|
||||
<SidebarMenuSubItem key={subItem.title}>
|
||||
<SidebarMenuSubButton asChild>
|
||||
<a href={subItem.url}>
|
||||
<span>{subItem.title}</span>
|
||||
</a>
|
||||
</SidebarMenuSubButton>
|
||||
</SidebarMenuSubItem>
|
||||
))}
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
</>
|
||||
) : null}
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroup>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import * as React from "react"
|
||||
import { type LucideIcon } from "lucide-react"
|
||||
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "@/registry/new-york-v4/ui/sidebar"
|
||||
|
||||
export function NavSecondary({
|
||||
items,
|
||||
...props
|
||||
}: {
|
||||
items: {
|
||||
title: string
|
||||
url: string
|
||||
icon: LucideIcon
|
||||
}[]
|
||||
} & React.ComponentPropsWithoutRef<typeof SidebarGroup>) {
|
||||
return (
|
||||
<SidebarGroup {...props}>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton asChild size="sm">
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
)
|
||||
}
|
||||
90
apps/v4/app/(examples)/dashboard/components/nav-user.tsx
Normal file
90
apps/v4/app/(examples)/dashboard/components/nav-user.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
"use client"
|
||||
|
||||
import { BadgeCheck, Bell, CreditCard, LogOut, Sparkles } from "lucide-react"
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
AvatarImage,
|
||||
} from "@/registry/new-york-v4/ui/avatar"
|
||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/registry/new-york-v4/ui/dropdown-menu"
|
||||
|
||||
export function NavUser({
|
||||
user,
|
||||
}: {
|
||||
user: {
|
||||
name: string
|
||||
email: string
|
||||
avatar: string
|
||||
}
|
||||
}) {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon">
|
||||
<Avatar className="size-8 rounded-md">
|
||||
<AvatarImage src={user.avatar} alt={user.name} />
|
||||
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
|
||||
</Avatar>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
className="w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg"
|
||||
side="bottom"
|
||||
align="end"
|
||||
sideOffset={4}
|
||||
>
|
||||
<DropdownMenuLabel className="p-0 font-normal">
|
||||
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
|
||||
<Avatar className="h-8 w-8 rounded-lg">
|
||||
<AvatarImage src={user.avatar} alt={user.name} />
|
||||
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="grid flex-1 text-left text-sm leading-tight">
|
||||
<span className="truncate font-medium">{user.name}</span>
|
||||
<span className="text-muted-foreground truncate text-xs">
|
||||
{user.email}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem>
|
||||
<Sparkles />
|
||||
Upgrade to Pro
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem>
|
||||
<BadgeCheck />
|
||||
Account
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<CreditCard />
|
||||
Billing
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Bell />
|
||||
Notifications
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
<LogOut />
|
||||
Log out
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
||||
217
apps/v4/app/(examples)/dashboard/components/products-table.tsx
Normal file
217
apps/v4/app/(examples)/dashboard/components/products-table.tsx
Normal file
@@ -0,0 +1,217 @@
|
||||
import {
|
||||
ArrowUpDownIcon,
|
||||
EllipsisVerticalIcon,
|
||||
ListFilterIcon,
|
||||
PlusIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
import { Badge } from "@/registry/new-york-v4/ui/badge"
|
||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
} from "@/registry/new-york-v4/ui/card"
|
||||
import { Checkbox } from "@/registry/new-york-v4/ui/checkbox"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/registry/new-york-v4/ui/dropdown-menu"
|
||||
import {
|
||||
Pagination,
|
||||
PaginationContent,
|
||||
PaginationEllipsis,
|
||||
PaginationItem,
|
||||
PaginationLink,
|
||||
PaginationNext,
|
||||
PaginationPrevious,
|
||||
} from "@/registry/new-york-v4/ui/pagination"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/registry/new-york-v4/ui/select"
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/registry/new-york-v4/ui/table"
|
||||
import { Tabs, TabsList, TabsTrigger } from "@/registry/new-york-v4/ui/tabs"
|
||||
|
||||
export function ProductsTable({
|
||||
products,
|
||||
}: {
|
||||
products: {
|
||||
id: string
|
||||
name: string
|
||||
price: number
|
||||
stock: number
|
||||
dateAdded: string
|
||||
status: string
|
||||
}[]
|
||||
}) {
|
||||
return (
|
||||
<Card className="flex w-full flex-col gap-4">
|
||||
<CardHeader className="flex flex-row items-center justify-between">
|
||||
<Tabs defaultValue="all">
|
||||
<TabsList className="w-full @3xl/page:w-fit">
|
||||
<TabsTrigger value="all">All Products</TabsTrigger>
|
||||
<TabsTrigger value="in-stock">In Stock</TabsTrigger>
|
||||
<TabsTrigger value="low-stock">Low Stock</TabsTrigger>
|
||||
<TabsTrigger value="add-product" asChild>
|
||||
<button>
|
||||
<PlusIcon />
|
||||
</button>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</Tabs>
|
||||
<div className="hidden items-center gap-2 **:data-[slot=button]:size-8 **:data-[slot=select-trigger]:h-8 @3xl/page:flex">
|
||||
<Select defaultValue="all">
|
||||
<SelectTrigger>
|
||||
<span className="text-muted-foreground text-sm">Category:</span>
|
||||
<SelectValue placeholder="Select a product" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">All</SelectItem>
|
||||
<SelectItem value="in-stock">In Stock</SelectItem>
|
||||
<SelectItem value="low-stock">Low Stock</SelectItem>
|
||||
<SelectItem value="archived">Archived</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select defaultValue="all">
|
||||
<SelectTrigger>
|
||||
<span className="text-muted-foreground text-sm">Price:</span>
|
||||
<SelectValue placeholder="Select a product" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">$100-$200</SelectItem>
|
||||
<SelectItem value="in-stock">$200-$300</SelectItem>
|
||||
<SelectItem value="low-stock">$300-$400</SelectItem>
|
||||
<SelectItem value="archived">$400-$500</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select defaultValue="all">
|
||||
<SelectTrigger>
|
||||
<span className="text-muted-foreground text-sm">Status:</span>
|
||||
<SelectValue placeholder="Select a product" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">In Stock</SelectItem>
|
||||
<SelectItem value="in-stock">Low Stock</SelectItem>
|
||||
<SelectItem value="low-stock">Archived</SelectItem>
|
||||
<SelectItem value="archived">Archived</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Button variant="outline" size="icon">
|
||||
<ListFilterIcon />
|
||||
</Button>
|
||||
<Button variant="outline" size="icon">
|
||||
<ArrowUpDownIcon />
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-12 px-4">
|
||||
<Checkbox />
|
||||
</TableHead>
|
||||
<TableHead>Product</TableHead>
|
||||
<TableHead className="text-right">Price</TableHead>
|
||||
<TableHead className="text-right">Stock</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
<TableHead>Date Added</TableHead>
|
||||
<TableHead />
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody className="**:data-[slot=table-cell]:py-2.5">
|
||||
{products.map((product) => (
|
||||
<TableRow key={product.id}>
|
||||
<TableCell className="px-4">
|
||||
<Checkbox />
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">{product.name}</TableCell>
|
||||
<TableCell className="text-right">
|
||||
${product.price.toFixed(2)}
|
||||
</TableCell>
|
||||
<TableCell className="text-right">{product.stock}</TableCell>
|
||||
<TableCell>
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className={
|
||||
product.status === "Low Stock"
|
||||
? "border-orange-700 bg-transparent text-orange-700 dark:border-orange-700 dark:bg-transparent dark:text-orange-700"
|
||||
: "bg-green-100 text-green-800 dark:bg-green-950 dark:text-green-100"
|
||||
}
|
||||
>
|
||||
{product.status}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{new Date(product.dateAdded).toLocaleDateString("en-US", {
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
})}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon" className="size-6">
|
||||
<EllipsisVerticalIcon />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem>Edit</DropdownMenuItem>
|
||||
<DropdownMenuItem variant="destructive">
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-col items-center justify-between border-t pt-6 @3xl/page:flex-row">
|
||||
<div className="text-muted-foreground hidden text-sm @3xl/page:block">
|
||||
Showing 1-10 of 100 products
|
||||
</div>
|
||||
<Pagination className="mx-0 w-fit">
|
||||
<PaginationContent>
|
||||
<PaginationItem>
|
||||
<PaginationPrevious href="#" />
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<PaginationLink href="#">1</PaginationLink>
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<PaginationLink href="#" isActive>
|
||||
2
|
||||
</PaginationLink>
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<PaginationLink href="#">3</PaginationLink>
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<PaginationEllipsis />
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<PaginationNext href="#" />
|
||||
</PaginationItem>
|
||||
</PaginationContent>
|
||||
</Pagination>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
22
apps/v4/app/(examples)/dashboard/components/search-form.tsx
Normal file
22
apps/v4/app/(examples)/dashboard/components/search-form.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Search } from "lucide-react"
|
||||
|
||||
import { Label } from "@/registry/new-york-v4/ui/label"
|
||||
import { SidebarInput } from "@/registry/new-york-v4/ui/sidebar"
|
||||
|
||||
export function SearchForm({ ...props }: React.ComponentProps<"form">) {
|
||||
return (
|
||||
<form {...props}>
|
||||
<div className="relative">
|
||||
<Label htmlFor="search" className="sr-only">
|
||||
Search
|
||||
</Label>
|
||||
<SidebarInput
|
||||
id="search"
|
||||
placeholder="Type to search..."
|
||||
className="h-8 pl-7"
|
||||
/>
|
||||
<Search className="pointer-events-none absolute top-1/2 left-2 size-4 -translate-y-1/2 opacity-50 select-none" />
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
103
apps/v4/app/(examples)/dashboard/components/site-header.tsx
Normal file
103
apps/v4/app/(examples)/dashboard/components/site-header.tsx
Normal file
@@ -0,0 +1,103 @@
|
||||
"use client"
|
||||
|
||||
import { Fragment, useMemo } from "react"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { SidebarIcon } from "lucide-react"
|
||||
|
||||
import { ThemeSelector } from "@/components/theme-selector"
|
||||
import { SearchForm } from "@/registry/new-york-v4/blocks/sidebar-16/components/search-form"
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from "@/registry/new-york-v4/ui/breadcrumb"
|
||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
||||
import { Separator } from "@/registry/new-york-v4/ui/separator"
|
||||
import { useSidebar } from "@/registry/new-york-v4/ui/sidebar"
|
||||
import { ModeToggle } from "@/app/(examples)/dashboard/components/mode-toggle"
|
||||
import { NavUser } from "@/app/(examples)/dashboard/components/nav-user"
|
||||
|
||||
export function SiteHeader() {
|
||||
const { toggleSidebar } = useSidebar()
|
||||
const pathname = usePathname()
|
||||
|
||||
// Faux breadcrumbs for demo.
|
||||
const breadcrumbs = useMemo(() => {
|
||||
return pathname
|
||||
.split("/")
|
||||
.filter((path) => path !== "")
|
||||
.map((path, index, array) => ({
|
||||
label: path,
|
||||
href: `/${array.slice(0, index + 1).join("/")}`,
|
||||
}))
|
||||
}, [pathname])
|
||||
|
||||
return (
|
||||
<header
|
||||
data-slot="site-header"
|
||||
className="bg-background sticky top-0 z-50 flex w-full items-center border-b"
|
||||
>
|
||||
<div className="flex h-(--header-height) w-full items-center gap-2 px-2 pr-4">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={toggleSidebar}
|
||||
className="gap-2.5 has-[>svg]:px-2"
|
||||
>
|
||||
<SidebarIcon />
|
||||
<span className="truncate font-medium">Acme Inc</span>
|
||||
</Button>
|
||||
<Separator
|
||||
orientation="vertical"
|
||||
className="mr-2 data-[orientation=vertical]:h-4"
|
||||
/>
|
||||
<Breadcrumb className="hidden sm:block">
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/" className="capitalize">
|
||||
Home
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
{breadcrumbs.map((breadcrumb, index) =>
|
||||
index === breadcrumbs.length - 1 ? (
|
||||
<BreadcrumbItem key={index}>
|
||||
<BreadcrumbPage className="capitalize">
|
||||
{breadcrumb.label}
|
||||
</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
) : (
|
||||
<Fragment key={index}>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink
|
||||
href={breadcrumb.href}
|
||||
className="capitalize"
|
||||
>
|
||||
{breadcrumb.label}
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
</Fragment>
|
||||
)
|
||||
)}
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
<div className="ml-auto flex items-center gap-2">
|
||||
<SearchForm className="w-fullsm:w-auto" />
|
||||
<ThemeSelector />
|
||||
<ModeToggle />
|
||||
<NavUser
|
||||
user={{
|
||||
name: "shadcn",
|
||||
email: "m@example.com",
|
||||
avatar: "/avatars/shadcn.jpg",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
8
apps/v4/app/(examples)/dashboard/customers/page.tsx
Normal file
8
apps/v4/app/(examples)/dashboard/customers/page.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
export default function CustomersPage() {
|
||||
return (
|
||||
<div className="p-6">
|
||||
<div className="bg-input p-4">Input</div>
|
||||
<div className="bg-input/30 p-4">Input 50</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
29
apps/v4/app/(examples)/dashboard/layout.tsx
Normal file
29
apps/v4/app/(examples)/dashboard/layout.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { cookies } from "next/headers"
|
||||
|
||||
import {
|
||||
SidebarInset,
|
||||
SidebarProvider,
|
||||
} from "@/registry/new-york-v4/ui/sidebar"
|
||||
import { AppSidebar } from "@/app/(examples)/dashboard/components/app-sidebar"
|
||||
import { SiteHeader } from "@/app/(examples)/dashboard/components/site-header"
|
||||
|
||||
export default async function DashboardLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
const cookieStore = await cookies()
|
||||
const defaultOpen = cookieStore.get("sidebar_state")?.value === "true"
|
||||
|
||||
return (
|
||||
<main className="[--header-height:calc(theme(spacing.14))]">
|
||||
<SidebarProvider defaultOpen={defaultOpen} className="flex flex-col">
|
||||
<SiteHeader />
|
||||
<div className="flex flex-1">
|
||||
<AppSidebar />
|
||||
<SidebarInset>{children}</SidebarInset>
|
||||
</div>
|
||||
</SidebarProvider>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
206
apps/v4/app/(examples)/dashboard/page.tsx
Normal file
206
apps/v4/app/(examples)/dashboard/page.tsx
Normal file
@@ -0,0 +1,206 @@
|
||||
import { Metadata } from "next"
|
||||
import {
|
||||
DownloadIcon,
|
||||
FilterIcon,
|
||||
TrendingDownIcon,
|
||||
TrendingUpIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
import { Badge } from "@/registry/new-york-v4/ui/badge"
|
||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
||||
import {
|
||||
Card,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/registry/new-york-v4/ui/card"
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "@/registry/new-york-v4/ui/tabs"
|
||||
import { AnalyticsDatePicker } from "@/app/(examples)/dashboard/components/analytics-date-picker"
|
||||
import { ChartRevenue } from "@/app/(examples)/dashboard/components/chart-revenue"
|
||||
import { ChartVisitors } from "@/app/(examples)/dashboard/components/chart-visitors"
|
||||
import { ProductsTable } from "@/app/(examples)/dashboard/components/products-table"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Dashboard",
|
||||
description: "An example dashboard to test the new components.",
|
||||
}
|
||||
|
||||
// Load from database.
|
||||
const products = [
|
||||
{
|
||||
id: "1",
|
||||
name: "BJÖRKSNÄS Dining Table",
|
||||
price: 599.99,
|
||||
stock: 12,
|
||||
dateAdded: "2023-06-15",
|
||||
status: "In Stock",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "POÄNG Armchair",
|
||||
price: 249.99,
|
||||
stock: 28,
|
||||
dateAdded: "2023-07-22",
|
||||
status: "In Stock",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
name: "MALM Bed Frame",
|
||||
price: 399.99,
|
||||
stock: 15,
|
||||
dateAdded: "2023-08-05",
|
||||
status: "In Stock",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
name: "KALLAX Shelf Unit",
|
||||
price: 179.99,
|
||||
stock: 32,
|
||||
dateAdded: "2023-09-12",
|
||||
status: "In Stock",
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
name: "STOCKHOLM Rug",
|
||||
price: 299.99,
|
||||
stock: 8,
|
||||
dateAdded: "2023-10-18",
|
||||
status: "Low Stock",
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
name: "KIVIK Sofa",
|
||||
price: 899.99,
|
||||
stock: 6,
|
||||
dateAdded: "2023-11-02",
|
||||
status: "Low Stock",
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
name: "LISABO Coffee Table",
|
||||
price: 149.99,
|
||||
stock: 22,
|
||||
dateAdded: "2023-11-29",
|
||||
status: "In Stock",
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
name: "HEMNES Bookcase",
|
||||
price: 249.99,
|
||||
stock: 17,
|
||||
dateAdded: "2023-12-10",
|
||||
status: "In Stock",
|
||||
},
|
||||
{
|
||||
id: "9",
|
||||
name: "EKEDALEN Dining Chairs (Set of 2)",
|
||||
price: 199.99,
|
||||
stock: 14,
|
||||
dateAdded: "2024-01-05",
|
||||
status: "In Stock",
|
||||
},
|
||||
{
|
||||
id: "10",
|
||||
name: "FRIHETEN Sleeper Sofa",
|
||||
price: 799.99,
|
||||
stock: 9,
|
||||
dateAdded: "2024-01-18",
|
||||
status: "Low Stock",
|
||||
},
|
||||
]
|
||||
|
||||
export default function DashboardPage() {
|
||||
return (
|
||||
<div className="@container/page flex flex-1 flex-col gap-8 p-6">
|
||||
<Tabs defaultValue="overview" className="gap-6">
|
||||
<div
|
||||
data-slot="dashboard-header"
|
||||
className="flex items-center justify-between"
|
||||
>
|
||||
<TabsList className="w-full @3xl/page:w-fit">
|
||||
<TabsTrigger value="overview">Overview</TabsTrigger>
|
||||
<TabsTrigger value="analytics">Analytics</TabsTrigger>
|
||||
<TabsTrigger value="reports">Reports</TabsTrigger>
|
||||
<TabsTrigger value="exports" disabled>
|
||||
Exports
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<div className="hidden items-center gap-2 @3xl/page:flex">
|
||||
<AnalyticsDatePicker />
|
||||
<Button variant="outline">
|
||||
<FilterIcon />
|
||||
Filter
|
||||
</Button>
|
||||
<Button variant="outline">
|
||||
<DownloadIcon />
|
||||
Export
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<TabsContent value="overview" className="flex flex-col gap-4">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Total Revenue</CardTitle>
|
||||
<CardDescription>$1,250.00 in the last 30 days</CardDescription>
|
||||
</CardHeader>
|
||||
<CardFooter>
|
||||
<Badge variant="outline">
|
||||
<TrendingUpIcon />
|
||||
+12.5%
|
||||
</Badge>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>New Customers</CardTitle>
|
||||
<CardDescription>-12 customers from last month</CardDescription>
|
||||
</CardHeader>
|
||||
<CardFooter>
|
||||
<Badge variant="outline">
|
||||
<TrendingDownIcon />
|
||||
-20%
|
||||
</Badge>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Active Accounts</CardTitle>
|
||||
<CardDescription>+2,345 users from last month</CardDescription>
|
||||
</CardHeader>
|
||||
<CardFooter>
|
||||
<Badge variant="outline">
|
||||
<TrendingUpIcon />
|
||||
+12.5%
|
||||
</Badge>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Growth Rate</CardTitle>
|
||||
<CardDescription>+12.5% increase per month</CardDescription>
|
||||
</CardHeader>
|
||||
<CardFooter>
|
||||
<Badge variant="outline">
|
||||
<TrendingUpIcon />
|
||||
+4.5%
|
||||
</Badge>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-4 @4xl/page:grid-cols-[2fr_1fr]">
|
||||
<ChartRevenue />
|
||||
<ChartVisitors />
|
||||
</div>
|
||||
<ProductsTable products={products} />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
500
apps/v4/app/(examples)/dashboard/settings/page.tsx
Normal file
500
apps/v4/app/(examples)/dashboard/settings/page.tsx
Normal file
@@ -0,0 +1,500 @@
|
||||
import { Metadata } from "next"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
||||
import {
|
||||
Card,
|
||||
CardAction,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/registry/new-york-v4/ui/card"
|
||||
import { Checkbox } from "@/registry/new-york-v4/ui/checkbox"
|
||||
import { Input } from "@/registry/new-york-v4/ui/input"
|
||||
import { Label } from "@/registry/new-york-v4/ui/label"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectLabel,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/registry/new-york-v4/ui/select"
|
||||
import { Switch } from "@/registry/new-york-v4/ui/switch"
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/registry/new-york-v4/ui/table"
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "@/registry/new-york-v4/ui/tabs"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Settings",
|
||||
description: "Manage your account settings",
|
||||
}
|
||||
|
||||
const timezones = [
|
||||
{
|
||||
label: "Americas",
|
||||
timezones: [
|
||||
{ value: "America/New_York", label: "(GMT-5) New York" },
|
||||
{ value: "America/Los_Angeles", label: "(GMT-8) Los Angeles" },
|
||||
{ value: "America/Chicago", label: "(GMT-6) Chicago" },
|
||||
{ value: "America/Toronto", label: "(GMT-5) Toronto" },
|
||||
{ value: "America/Vancouver", label: "(GMT-8) Vancouver" },
|
||||
{ value: "America/Sao_Paulo", label: "(GMT-3) São Paulo" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Europe",
|
||||
timezones: [
|
||||
{ value: "Europe/London", label: "(GMT+0) London" },
|
||||
{ value: "Europe/Paris", label: "(GMT+1) Paris" },
|
||||
{ value: "Europe/Berlin", label: "(GMT+1) Berlin" },
|
||||
{ value: "Europe/Rome", label: "(GMT+1) Rome" },
|
||||
{ value: "Europe/Madrid", label: "(GMT+1) Madrid" },
|
||||
{ value: "Europe/Amsterdam", label: "(GMT+1) Amsterdam" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Asia/Pacific",
|
||||
timezones: [
|
||||
{ value: "Asia/Tokyo", label: "(GMT+9) Tokyo" },
|
||||
{ value: "Asia/Shanghai", label: "(GMT+8) Shanghai" },
|
||||
{ value: "Asia/Singapore", label: "(GMT+8) Singapore" },
|
||||
{ value: "Asia/Dubai", label: "(GMT+4) Dubai" },
|
||||
{ value: "Australia/Sydney", label: "(GMT+11) Sydney" },
|
||||
{ value: "Asia/Seoul", label: "(GMT+9) Seoul" },
|
||||
],
|
||||
},
|
||||
] as const
|
||||
|
||||
const loginHistory = [
|
||||
{
|
||||
date: "2024-01-01",
|
||||
ip: "192.168.1.1",
|
||||
location: "New York, USA",
|
||||
},
|
||||
{
|
||||
date: "2023-12-29",
|
||||
ip: "172.16.0.100",
|
||||
location: "London, UK",
|
||||
},
|
||||
{
|
||||
date: "2023-12-28",
|
||||
ip: "10.0.0.50",
|
||||
location: "Toronto, Canada",
|
||||
},
|
||||
{
|
||||
date: "2023-12-25",
|
||||
ip: "192.168.2.15",
|
||||
location: "Sydney, Australia",
|
||||
},
|
||||
] as const
|
||||
|
||||
const activeSessions = [
|
||||
{
|
||||
device: "MacBook Pro",
|
||||
browser: "Chrome",
|
||||
os: "macOS",
|
||||
},
|
||||
{
|
||||
device: "iPhone",
|
||||
browser: "Safari",
|
||||
os: "iOS",
|
||||
},
|
||||
{
|
||||
device: "iPad",
|
||||
browser: "Safari",
|
||||
os: "iOS",
|
||||
},
|
||||
{
|
||||
device: "Android Phone",
|
||||
browser: "Chrome",
|
||||
os: "Android",
|
||||
},
|
||||
] as const
|
||||
|
||||
export default function SettingsPage() {
|
||||
return (
|
||||
<div className="@container/page flex flex-1 flex-col gap-8 p-6">
|
||||
<Tabs defaultValue="account" className="gap-6">
|
||||
<div
|
||||
data-slot="dashboard-header"
|
||||
className="flex items-center justify-between"
|
||||
>
|
||||
<TabsList>
|
||||
<TabsTrigger value="account">Account</TabsTrigger>
|
||||
<TabsTrigger value="security">Security</TabsTrigger>
|
||||
<TabsTrigger value="notifications">Notifications</TabsTrigger>
|
||||
<TabsTrigger value="privacy">Privacy</TabsTrigger>
|
||||
</TabsList>
|
||||
</div>
|
||||
<TabsContent value="account" className="grid gap-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Account Settings</CardTitle>
|
||||
<CardDescription>
|
||||
Make changes to your account here.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form id="form-account" className="@container">
|
||||
<FieldGroup>
|
||||
<Field>
|
||||
<Label htmlFor="name">Name</Label>
|
||||
<FieldControl>
|
||||
<Input
|
||||
id="name"
|
||||
placeholder="First and last name"
|
||||
required
|
||||
/>
|
||||
</FieldControl>
|
||||
<FieldDescription>
|
||||
This is your public display name.
|
||||
</FieldDescription>
|
||||
</Field>
|
||||
<Field>
|
||||
<Label htmlFor="email">Email</Label>
|
||||
<FieldControl>
|
||||
<Input
|
||||
id="email"
|
||||
placeholder="you@example.com"
|
||||
required
|
||||
/>
|
||||
</FieldControl>
|
||||
</Field>
|
||||
<Field>
|
||||
<Label htmlFor="timezone">Timezone</Label>
|
||||
<FieldControl>
|
||||
<Select>
|
||||
<SelectTrigger id="timezone">
|
||||
<SelectValue placeholder="Select a timezone" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{timezones.map((timezone) => (
|
||||
<SelectGroup key={timezone.label}>
|
||||
<SelectLabel>{timezone.label}</SelectLabel>
|
||||
{timezone.timezones.map((time) => (
|
||||
<SelectItem key={time.value} value={time.value}>
|
||||
{time.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FieldControl>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</form>
|
||||
</CardContent>
|
||||
<CardFooter className="border-t">
|
||||
<Button type="submit" form="form-account" variant="secondary">
|
||||
Save changes
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Notifications</CardTitle>
|
||||
<CardDescription>
|
||||
Manage how you receive notifications.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form id="form-notifications" className="@container">
|
||||
<FieldGroup>
|
||||
<Field>
|
||||
<Label htmlFor="channels">Notification Channels</Label>
|
||||
<FieldControl className="flex flex-col gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox id="notification-email" />
|
||||
<Label htmlFor="notification-email">Email</Label>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox id="notification-sms" />
|
||||
<Label htmlFor="notification-sms">SMS</Label>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox id="notification-push" />
|
||||
<Label htmlFor="notification-push">Push</Label>
|
||||
</div>
|
||||
</FieldControl>
|
||||
<FieldDescription>
|
||||
Choose how you want to receive notifications.
|
||||
</FieldDescription>
|
||||
</Field>
|
||||
<Field>
|
||||
<Label htmlFor="types">Notification Types</Label>
|
||||
<FieldControl className="flex flex-col gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox id="notification-account" />
|
||||
<Label htmlFor="notification-account">
|
||||
Account Activity
|
||||
</Label>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox
|
||||
id="notification-security"
|
||||
defaultChecked
|
||||
disabled
|
||||
/>
|
||||
<Label htmlFor="notification-security">
|
||||
Security Alerts
|
||||
</Label>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox id="notification-marketing" />
|
||||
<Label htmlFor="notification-marketing">
|
||||
Marketing & Promotions
|
||||
</Label>
|
||||
</div>
|
||||
</FieldControl>
|
||||
<FieldDescription>
|
||||
Choose how you want to receive notifications.
|
||||
</FieldDescription>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</form>
|
||||
</CardContent>
|
||||
<CardFooter className="border-t">
|
||||
<Button
|
||||
type="submit"
|
||||
form="form-notifications"
|
||||
variant="secondary"
|
||||
>
|
||||
Save changes
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
<TabsContent
|
||||
value="security"
|
||||
className="grid gap-6 @3xl/page:grid-cols-2"
|
||||
>
|
||||
<Card className="@3xl/page:col-span-2">
|
||||
<CardHeader>
|
||||
<CardTitle>Security Settings</CardTitle>
|
||||
<CardDescription>
|
||||
Make changes to your security settings here.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="@container">
|
||||
<form id="form-security">
|
||||
<FieldGroup>
|
||||
<Field>
|
||||
<Label htmlFor="current-password">Current Password</Label>
|
||||
<FieldControl>
|
||||
<Input
|
||||
id="current-password"
|
||||
placeholder="Current password"
|
||||
required
|
||||
/>
|
||||
</FieldControl>
|
||||
<FieldDescription>
|
||||
This is your current password.
|
||||
</FieldDescription>
|
||||
</Field>
|
||||
<Field>
|
||||
<Label htmlFor="new-password">New Password</Label>
|
||||
<FieldControl>
|
||||
<Input
|
||||
id="new-password"
|
||||
placeholder="New password"
|
||||
required
|
||||
/>
|
||||
</FieldControl>
|
||||
</Field>
|
||||
<Field>
|
||||
<Label htmlFor="confirm-password">Confirm Password</Label>
|
||||
<FieldControl>
|
||||
<Input
|
||||
id="confirm-password"
|
||||
placeholder="Confirm password"
|
||||
/>
|
||||
</FieldControl>
|
||||
</Field>
|
||||
<Field>
|
||||
<FieldControl>
|
||||
<Switch
|
||||
id="enable-two-factor-auth"
|
||||
className="self-start"
|
||||
/>
|
||||
</FieldControl>
|
||||
<Label htmlFor="enable-two-factor-auth">
|
||||
Enable two-factor authentication
|
||||
</Label>
|
||||
<FieldDescription>
|
||||
This will add an extra layer of security to your account.
|
||||
Make this an extra long description to test the layout.
|
||||
</FieldDescription>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</form>
|
||||
</CardContent>
|
||||
<CardFooter className="border-t">
|
||||
<Button type="submit" form="form-security" variant="secondary">
|
||||
Save changes
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Login History</CardTitle>
|
||||
<CardDescription>
|
||||
Recent login activities on your account.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Date</TableHead>
|
||||
<TableHead className="hidden @md/page:table-cell">
|
||||
IP
|
||||
</TableHead>
|
||||
<TableHead>Location</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{loginHistory.map((login) => (
|
||||
<TableRow key={login.date}>
|
||||
<TableCell>
|
||||
<div className="flex flex-col gap-1">
|
||||
{new Date(login.date).toLocaleDateString("en-US", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
})}
|
||||
<span className="flex @md/page:hidden">
|
||||
{login.ip}
|
||||
</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="hidden @md/page:table-cell">
|
||||
{login.ip}
|
||||
</TableCell>
|
||||
<TableCell>{login.location}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Active Sessions</CardTitle>
|
||||
<CardDescription>
|
||||
Current active sessions on your account.
|
||||
</CardDescription>
|
||||
<CardAction>
|
||||
<Button variant="outline" size="sm">
|
||||
<span className="hidden @md/card-header:block">
|
||||
Manage Sessions
|
||||
</span>
|
||||
<span className="block @md/card-header:hidden">Manage</span>
|
||||
</Button>
|
||||
</CardAction>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Device</TableHead>
|
||||
<TableHead>Browser</TableHead>
|
||||
<TableHead>OS</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{activeSessions.map((session) => (
|
||||
<TableRow key={session.device}>
|
||||
<TableCell>{session.device}</TableCell>
|
||||
<TableCell>{session.browser}</TableCell>
|
||||
<TableCell>{session.os}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function FieldGroup({ children }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="field-group"
|
||||
className="@container/field-group flex max-w-4xl min-w-0 flex-col gap-8 @3xl:gap-6"
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Field({ children, className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="field"
|
||||
className={cn(
|
||||
"grid auto-rows-min items-start gap-3 *:data-[slot=label]:col-start-1 *:data-[slot=label]:row-start-1 @3xl/field-group:grid-cols-2 @3xl/field-group:gap-6",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function FieldControl({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="field-control"
|
||||
className={cn(
|
||||
"@3xl/field-group:col-start-2 @3xl/field-group:row-span-2 @3xl/field-group:row-start-1 @3xl/field-group:self-start",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function FieldDescription({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"p">) {
|
||||
return (
|
||||
<p
|
||||
data-slot="field-description"
|
||||
className={cn(
|
||||
"text-muted-foreground text-sm @3xl/field-group:col-start-1 @3xl/field-group:row-start-1 @3xl/field-group:translate-y-6",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</p>
|
||||
)
|
||||
}
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
@import "./themes.css";
|
||||
|
||||
:root {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.145 0 0);
|
||||
--card: oklch(1 0 0);
|
||||
@@ -20,7 +23,6 @@
|
||||
--accent: oklch(0.97 0 0);
|
||||
--accent-foreground: oklch(0.205 0 0);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--destructive-foreground: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--ring: oklch(0.708 0 0);
|
||||
@@ -29,7 +31,6 @@
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--radius: 0.625rem;
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.205 0 0);
|
||||
@@ -43,22 +44,21 @@
|
||||
.dark {
|
||||
--background: oklch(0.145 0 0);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.145 0 0);
|
||||
--card: oklch(0.205 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.145 0 0);
|
||||
--popover: oklch(0.269 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.985 0 0);
|
||||
--primary: oklch(0.922 0 0);
|
||||
--primary-foreground: oklch(0.205 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--accent: oklch(0.371 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.396 0.141 25.723);
|
||||
--destructive-foreground: oklch(0.637 0.237 25.331);
|
||||
--border: oklch(0.269 0 0);
|
||||
--input: oklch(0.269 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.556 0 0);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
@@ -71,66 +71,15 @@
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(0.269 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.439 0 0);
|
||||
}
|
||||
|
||||
.theme-login-one {
|
||||
--primary: #ce2a2d;
|
||||
--primary-foreground: #fff;
|
||||
--ring: #ce2a2d9c;
|
||||
--radius: 0rem;
|
||||
@theme inline {
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
|
||||
font-family: var(--font-sans);
|
||||
|
||||
a {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
[data-slot="card"] {
|
||||
border-radius: 0rem;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-login-two {
|
||||
--primary: #035fa8;
|
||||
--primary-foreground: #fff;
|
||||
--ring: #035fa89c;
|
||||
font-family: var(--font-serif);
|
||||
|
||||
a {
|
||||
color: var(--primary);
|
||||
}
|
||||
}
|
||||
|
||||
.theme-login-three {
|
||||
--primary: #22c55e;
|
||||
--primary-foreground: #000;
|
||||
--ring: #22c55e;
|
||||
--radius: 1.5rem;
|
||||
|
||||
font-family: var(--font-manrope);
|
||||
|
||||
a {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
[data-slot="card"] {
|
||||
@apply shadow-xl;
|
||||
}
|
||||
|
||||
[data-slot="input"] {
|
||||
@apply dark:bg-input;
|
||||
}
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--font-sans: var(--font-sans);
|
||||
--font-mono: var(--font-mono);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
@@ -146,7 +95,6 @@
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-destructive-foreground: var(--destructive-foreground);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
@@ -155,10 +103,6 @@
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
@@ -167,26 +111,6 @@
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--animate-accordion-down: accordion-down 0.2s ease-out;
|
||||
--animate-accordion-up: accordion-up 0.2s ease-out;
|
||||
|
||||
@keyframes accordion-down {
|
||||
from {
|
||||
height: 0;
|
||||
}
|
||||
to {
|
||||
height: var(--radix-accordion-content-height);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes accordion-up {
|
||||
from {
|
||||
height: var(--radix-accordion-content-height);
|
||||
}
|
||||
to {
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
|
||||
@@ -1,23 +1,15 @@
|
||||
import type { Metadata, Viewport } from "next"
|
||||
import { Geist_Mono as FontMono, Inter as FontSans } from "next/font/google"
|
||||
import { cookies } from "next/headers"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { fontVariables } from "@/lib/fonts"
|
||||
import { Analytics } from "@/components/analytics"
|
||||
import { ThemeProvider } from "@/components/theme-provider"
|
||||
import { Toaster } from "@/registry/new-york-v4/ui/sonner"
|
||||
import { siteConfig } from "@/www/config/site"
|
||||
|
||||
import "./globals.css"
|
||||
|
||||
const fontSans = FontSans({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-sans",
|
||||
})
|
||||
|
||||
const fontMono = FontMono({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-mono",
|
||||
})
|
||||
import { cn } from "@/lib/utils"
|
||||
import { ActiveThemeProvider } from "@/components/active-theme"
|
||||
|
||||
const META_THEME_COLORS = {
|
||||
light: "#ffffff",
|
||||
@@ -80,11 +72,14 @@ export const viewport: Viewport = {
|
||||
themeColor: META_THEME_COLORS.light,
|
||||
}
|
||||
|
||||
export default function RootLayout({
|
||||
export default async function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode
|
||||
}>) {
|
||||
const cookieStore = await cookies()
|
||||
const activeThemeValue = cookieStore.get("active_theme")?.value
|
||||
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<head>
|
||||
@@ -103,8 +98,8 @@ export default function RootLayout({
|
||||
<body
|
||||
className={cn(
|
||||
"bg-background overscroll-none font-sans antialiased",
|
||||
fontSans.variable,
|
||||
fontMono.variable
|
||||
activeThemeValue ? `theme-${activeThemeValue}` : "",
|
||||
fontVariables
|
||||
)}
|
||||
>
|
||||
<ThemeProvider
|
||||
@@ -113,9 +108,11 @@ export default function RootLayout({
|
||||
enableSystem
|
||||
disableTransitionOnChange
|
||||
>
|
||||
{children}
|
||||
<Toaster />
|
||||
<Analytics />
|
||||
<ActiveThemeProvider initialTheme={activeThemeValue}>
|
||||
{children}
|
||||
<Toaster />
|
||||
<Analytics />
|
||||
</ActiveThemeProvider>
|
||||
</ThemeProvider>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
442
apps/v4/app/themes.css
Normal file
442
apps/v4/app/themes.css
Normal file
@@ -0,0 +1,442 @@
|
||||
.theme-stone {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.147 0.004 49.25);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.147 0.004 49.25);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.147 0.004 49.25);
|
||||
--primary: oklch(0.216 0.006 56.043);
|
||||
--primary-foreground: oklch(0.985 0.001 106.423);
|
||||
--secondary: oklch(0.97 0.001 106.424);
|
||||
--secondary-foreground: oklch(0.216 0.006 56.043);
|
||||
--muted: oklch(0.97 0.001 106.424);
|
||||
--muted-foreground: oklch(0.553 0.013 58.071);
|
||||
--accent: oklch(0.97 0.001 106.424);
|
||||
--accent-foreground: oklch(0.216 0.006 56.043);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.923 0.003 48.717);
|
||||
--input: oklch(0.923 0.003 48.717);
|
||||
--ring: oklch(0.709 0.01 56.259);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0.001 106.423);
|
||||
--sidebar-foreground: oklch(0.147 0.004 49.25);
|
||||
--sidebar-primary: oklch(0.216 0.006 56.043);
|
||||
--sidebar-primary-foreground: oklch(0.985 0.001 106.423);
|
||||
--sidebar-accent: oklch(0.97 0.001 106.424);
|
||||
--sidebar-accent-foreground: oklch(0.216 0.006 56.043);
|
||||
--sidebar-border: oklch(0.923 0.003 48.717);
|
||||
--sidebar-ring: oklch(0.709 0.01 56.259);
|
||||
|
||||
@variant dark {
|
||||
--background: oklch(0.147 0.004 49.25);
|
||||
--foreground: oklch(0.985 0.001 106.423);
|
||||
--card: oklch(0.216 0.006 56.043);
|
||||
--card-foreground: oklch(0.985 0.001 106.423);
|
||||
--popover: oklch(0.216 0.006 56.043);
|
||||
--popover-foreground: oklch(0.985 0.001 106.423);
|
||||
--primary: oklch(0.923 0.003 48.717);
|
||||
--primary-foreground: oklch(0.216 0.006 56.043);
|
||||
--secondary: oklch(0.268 0.007 34.298);
|
||||
--secondary-foreground: oklch(0.985 0.001 106.423);
|
||||
--muted: oklch(0.268 0.007 34.298);
|
||||
--muted-foreground: oklch(0.709 0.01 56.259);
|
||||
--accent: oklch(0.268 0.007 34.298);
|
||||
--accent-foreground: oklch(0.985 0.001 106.423);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.553 0.013 58.071);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.216 0.006 56.043);
|
||||
--sidebar-foreground: oklch(0.985 0.001 106.423);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0.001 106.423);
|
||||
--sidebar-accent: oklch(0.268 0.007 34.298);
|
||||
--sidebar-accent-foreground: oklch(0.985 0.001 106.423);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.553 0.013 58.071);
|
||||
}
|
||||
}
|
||||
|
||||
.theme-zinc {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.141 0.005 285.823);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.141 0.005 285.823);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.141 0.005 285.823);
|
||||
--primary: oklch(0.21 0.006 285.885);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.967 0.001 286.375);
|
||||
--secondary-foreground: oklch(0.21 0.006 285.885);
|
||||
--muted: oklch(0.967 0.001 286.375);
|
||||
--muted-foreground: oklch(0.552 0.016 285.938);
|
||||
--accent: oklch(0.967 0.001 286.375);
|
||||
--accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.92 0.004 286.32);
|
||||
--input: oklch(0.92 0.004 286.32);
|
||||
--ring: oklch(0.705 0.015 286.067);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.141 0.005 285.823);
|
||||
--sidebar-primary: oklch(0.21 0.006 285.885);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.967 0.001 286.375);
|
||||
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--sidebar-border: oklch(0.92 0.004 286.32);
|
||||
--sidebar-ring: oklch(0.705 0.015 286.067);
|
||||
|
||||
@variant dark {
|
||||
--background: oklch(0.141 0.005 285.823);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.21 0.006 285.885);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.21 0.006 285.885);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.92 0.004 286.32);
|
||||
--primary-foreground: oklch(0.21 0.006 285.885);
|
||||
--secondary: oklch(0.274 0.006 286.033);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.274 0.006 286.033);
|
||||
--muted-foreground: oklch(0.705 0.015 286.067);
|
||||
--accent: oklch(0.274 0.006 286.033);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.552 0.016 285.938);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.21 0.006 285.885);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.274 0.006 286.033);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.552 0.016 285.938);
|
||||
}
|
||||
}
|
||||
|
||||
.theme-neutral {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.145 0 0);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.145 0 0);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.145 0 0);
|
||||
--primary: oklch(0.205 0 0);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.97 0 0);
|
||||
--secondary-foreground: oklch(0.205 0 0);
|
||||
--muted: oklch(0.97 0 0);
|
||||
--muted-foreground: oklch(0.556 0 0);
|
||||
--accent: oklch(0.97 0 0);
|
||||
--accent-foreground: oklch(0.205 0 0);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--ring: oklch(0.708 0 0);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.205 0 0);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.97 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||
--sidebar-border: oklch(0.922 0 0);
|
||||
--sidebar-ring: oklch(0.708 0 0);
|
||||
|
||||
@variant dark {
|
||||
--background: oklch(0.145 0 0);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.205 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.205 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.922 0 0);
|
||||
--primary-foreground: oklch(0.205 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.556 0 0);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.205 0 0);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.556 0 0);
|
||||
}
|
||||
}
|
||||
|
||||
.theme-gray {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.13 0.028 261.692);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.13 0.028 261.692);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.13 0.028 261.692);
|
||||
--primary: oklch(0.21 0.034 264.665);
|
||||
--primary-foreground: oklch(0.985 0.002 247.839);
|
||||
--secondary: oklch(0.967 0.003 264.542);
|
||||
--secondary-foreground: oklch(0.21 0.034 264.665);
|
||||
--muted: oklch(0.967 0.003 264.542);
|
||||
--muted-foreground: oklch(0.551 0.027 264.364);
|
||||
--accent: oklch(0.967 0.003 264.542);
|
||||
--accent-foreground: oklch(0.21 0.034 264.665);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.928 0.006 264.531);
|
||||
--input: oklch(0.928 0.006 264.531);
|
||||
--ring: oklch(0.707 0.022 261.325);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0.002 247.839);
|
||||
--sidebar-foreground: oklch(0.13 0.028 261.692);
|
||||
--sidebar-primary: oklch(0.21 0.034 264.665);
|
||||
--sidebar-primary-foreground: oklch(0.985 0.002 247.839);
|
||||
--sidebar-accent: oklch(0.967 0.003 264.542);
|
||||
--sidebar-accent-foreground: oklch(0.21 0.034 264.665);
|
||||
--sidebar-border: oklch(0.928 0.006 264.531);
|
||||
--sidebar-ring: oklch(0.707 0.022 261.325);
|
||||
|
||||
@variant dark {
|
||||
--background: oklch(0.13 0.028 261.692);
|
||||
--foreground: oklch(0.985 0.002 247.839);
|
||||
--card: oklch(0.21 0.034 264.665);
|
||||
--card-foreground: oklch(0.985 0.002 247.839);
|
||||
--popover: oklch(0.21 0.034 264.665);
|
||||
--popover-foreground: oklch(0.985 0.002 247.839);
|
||||
--primary: oklch(0.928 0.006 264.531);
|
||||
--primary-foreground: oklch(0.21 0.034 264.665);
|
||||
--secondary: oklch(0.278 0.033 256.848);
|
||||
--secondary-foreground: oklch(0.985 0.002 247.839);
|
||||
--muted: oklch(0.278 0.033 256.848);
|
||||
--muted-foreground: oklch(0.707 0.022 261.325);
|
||||
--accent: oklch(0.278 0.033 256.848);
|
||||
--accent-foreground: oklch(0.985 0.002 247.839);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.551 0.027 264.364);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.21 0.034 264.665);
|
||||
--sidebar-foreground: oklch(0.985 0.002 247.839);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0.002 247.839);
|
||||
--sidebar-accent: oklch(0.278 0.033 256.848);
|
||||
--sidebar-accent-foreground: oklch(0.985 0.002 247.839);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.551 0.027 264.364);
|
||||
}
|
||||
}
|
||||
|
||||
.theme-slate {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.129 0.042 264.695);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.129 0.042 264.695);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.129 0.042 264.695);
|
||||
--primary: oklch(0.208 0.042 265.755);
|
||||
--primary-foreground: oklch(0.984 0.003 247.858);
|
||||
--secondary: oklch(0.968 0.007 247.896);
|
||||
--secondary-foreground: oklch(0.208 0.042 265.755);
|
||||
--muted: oklch(0.968 0.007 247.896);
|
||||
--muted-foreground: oklch(0.554 0.046 257.417);
|
||||
--accent: oklch(0.968 0.007 247.896);
|
||||
--accent-foreground: oklch(0.208 0.042 265.755);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.929 0.013 255.508);
|
||||
--input: oklch(0.929 0.013 255.508);
|
||||
--ring: oklch(0.704 0.04 256.788);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.984 0.003 247.858);
|
||||
--sidebar-foreground: oklch(0.129 0.042 264.695);
|
||||
--sidebar-primary: oklch(0.208 0.042 265.755);
|
||||
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
|
||||
--sidebar-accent: oklch(0.968 0.007 247.896);
|
||||
--sidebar-accent-foreground: oklch(0.208 0.042 265.755);
|
||||
--sidebar-border: oklch(0.929 0.013 255.508);
|
||||
--sidebar-ring: oklch(0.704 0.04 256.788);
|
||||
|
||||
@variant dark {
|
||||
--background: oklch(0.129 0.042 264.695);
|
||||
--foreground: oklch(0.984 0.003 247.858);
|
||||
--card: oklch(0.208 0.042 265.755);
|
||||
--card-foreground: oklch(0.984 0.003 247.858);
|
||||
--popover: oklch(0.208 0.042 265.755);
|
||||
--popover-foreground: oklch(0.984 0.003 247.858);
|
||||
--primary: oklch(0.929 0.013 255.508);
|
||||
--primary-foreground: oklch(0.208 0.042 265.755);
|
||||
--secondary: oklch(0.279 0.041 260.031);
|
||||
--secondary-foreground: oklch(0.984 0.003 247.858);
|
||||
--muted: oklch(0.279 0.041 260.031);
|
||||
--muted-foreground: oklch(0.704 0.04 256.788);
|
||||
--accent: oklch(0.279 0.041 260.031);
|
||||
--accent-foreground: oklch(0.984 0.003 247.858);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.551 0.027 264.364);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.208 0.042 265.755);
|
||||
--sidebar-foreground: oklch(0.984 0.003 247.858);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
|
||||
--sidebar-accent: oklch(0.279 0.041 260.031);
|
||||
--sidebar-accent-foreground: oklch(0.984 0.003 247.858);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.551 0.027 264.364);
|
||||
}
|
||||
}
|
||||
|
||||
.theme-blue {
|
||||
--font-sans: var(--font-inter);
|
||||
--text-sm: 0.85rem;
|
||||
--radius: 0rem;
|
||||
--spacing: 0.222222rem;
|
||||
--primary: var(--color-blue-600);
|
||||
--primary-foreground: var(--color-blue-50);
|
||||
--chart-1: var(--color-blue-800);
|
||||
--chart-2: var(--color-blue-700);
|
||||
--chart-3: var(--color-blue-600);
|
||||
--chart-4: var(--color-blue-500);
|
||||
--chart-5: var(--color-blue-400);
|
||||
|
||||
[data-slot="chart"] {
|
||||
--chart-1: var(--color-blue-800);
|
||||
--chart-2: var(--color-blue-700);
|
||||
--chart-3: var(--color-blue-600);
|
||||
--chart-4: var(--color-blue-500);
|
||||
--chart-5: var(--color-blue-400);
|
||||
}
|
||||
|
||||
.rounded-xl {
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
|
||||
.shadow-sm {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
@variant dark {
|
||||
--primary: var(--color-blue-600);
|
||||
--primary-foreground: var(--color-blue-50);
|
||||
--chart-1: var(--color-blue-800);
|
||||
--chart-2: var(--color-blue-700);
|
||||
--chart-3: var(--color-blue-600);
|
||||
--chart-4: var(--color-blue-500);
|
||||
--chart-5: var(--color-blue-400);
|
||||
|
||||
[data-slot="chart"] {
|
||||
--chart-1: var(--color-blue-800);
|
||||
--chart-2: var(--color-blue-700);
|
||||
--chart-3: var(--color-blue-600);
|
||||
--chart-4: var(--color-blue-500);
|
||||
--chart-5: var(--color-blue-400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.theme-lime {
|
||||
--font-sans: var(--font-noto-mono);
|
||||
--spacing: 0.225rem;
|
||||
--primary: var(--color-lime-600);
|
||||
--primary-foreground: var(--color-lime-50);
|
||||
--chart-1: var(--color-lime-800);
|
||||
--chart-2: var(--color-lime-700);
|
||||
--chart-3: var(--color-lime-600);
|
||||
--chart-4: var(--color-lime-500);
|
||||
--chart-5: var(--color-lime-400);
|
||||
|
||||
[data-slot="chart"] {
|
||||
--chart-1: var(--color-lime-800);
|
||||
--chart-2: var(--color-lime-700);
|
||||
--chart-3: var(--color-lime-600);
|
||||
--chart-4: var(--color-lime-500);
|
||||
--chart-5: var(--color-lime-400);
|
||||
}
|
||||
|
||||
.shadow-sm {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
@variant dark {
|
||||
--primary: var(--color-lime-600);
|
||||
--primary-foreground: var(--color-lime-50);
|
||||
--chart-1: var(--color-lime-900);
|
||||
--chart-2: var(--color-lime-800);
|
||||
--chart-3: var(--color-lime-700);
|
||||
--chart-4: var(--color-lime-600);
|
||||
--chart-5: var(--color-lime-500);
|
||||
|
||||
[data-slot="chart"] {
|
||||
--chart-1: var(--color-lime-900);
|
||||
--chart-2: var(--color-lime-800);
|
||||
--chart-3: var(--color-lime-700);
|
||||
--chart-4: var(--color-lime-600);
|
||||
--chart-5: var(--color-lime-500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.theme-small {
|
||||
--radius: 0.5rem;
|
||||
--text-lg: 1.05rem;
|
||||
--text-base: 0.85rem;
|
||||
--text-sm: 0.75rem;
|
||||
--spacing: 0.222222rem;
|
||||
}
|
||||
@@ -18,4 +18,4 @@
|
||||
"hooks": "@/hooks"
|
||||
},
|
||||
"iconLibrary": "lucide"
|
||||
}
|
||||
}
|
||||
62
apps/v4/components/active-theme.tsx
Normal file
62
apps/v4/components/active-theme.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
ReactNode,
|
||||
createContext,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState,
|
||||
} from "react"
|
||||
|
||||
const COOKIE_NAME = "active_theme"
|
||||
const DEFAULT_THEME = "default"
|
||||
|
||||
function setThemeCookie(theme: string) {
|
||||
if (typeof window === "undefined") return
|
||||
|
||||
document.cookie = `${COOKIE_NAME}=${theme}; path=/; max-age=31536000; SameSite=Lax; ${window.location.protocol === "https:" ? "Secure;" : ""}`
|
||||
}
|
||||
|
||||
type ThemeContextType = {
|
||||
activeTheme: string
|
||||
setActiveTheme: (theme: string) => void
|
||||
}
|
||||
|
||||
const ThemeContext = createContext<ThemeContextType | undefined>(undefined)
|
||||
|
||||
export function ActiveThemeProvider({
|
||||
children,
|
||||
initialTheme,
|
||||
}: {
|
||||
children: ReactNode
|
||||
initialTheme?: string
|
||||
}) {
|
||||
const [activeTheme, setActiveTheme] = useState<string>(
|
||||
() => initialTheme || DEFAULT_THEME
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
setThemeCookie(activeTheme)
|
||||
|
||||
document.body.classList.forEach((className) => {
|
||||
if (className.startsWith("theme-")) {
|
||||
document.body.classList.remove(className)
|
||||
}
|
||||
})
|
||||
document.body.classList.add(`theme-${activeTheme}`)
|
||||
}, [activeTheme])
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={{ activeTheme, setActiveTheme }}>
|
||||
{children}
|
||||
</ThemeContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export function useThemeConfig() {
|
||||
const context = useContext(ThemeContext)
|
||||
if (context === undefined) {
|
||||
throw new Error("useThemeConfig must be used within an ActiveThemeProvider")
|
||||
}
|
||||
return context
|
||||
}
|
||||
@@ -22,15 +22,15 @@ import { Label } from "@/registry/new-york-v4/ui/label"
|
||||
export function CardDemo() {
|
||||
return (
|
||||
<div className="flex flex-col items-start gap-4">
|
||||
<form>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Login to your account</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your email below to login to your account
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Card className="w-full max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle>Login to your account</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your email below to login to your account
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form>
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="email">Email</Label>
|
||||
@@ -54,23 +54,23 @@ export function CardDemo() {
|
||||
<Input id="password" type="password" required />
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex-col gap-2">
|
||||
<Button type="submit" className="w-full">
|
||||
Login
|
||||
</Button>
|
||||
<Button variant="outline" className="w-full">
|
||||
Login with Google
|
||||
</Button>
|
||||
<div className="mt-4 text-center text-sm">
|
||||
Don't have an account?{" "}
|
||||
<a href="#" className="underline underline-offset-4">
|
||||
Sign up
|
||||
</a>
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</form>
|
||||
</form>
|
||||
</CardContent>
|
||||
<CardFooter className="flex-col gap-2">
|
||||
<Button type="submit" className="w-full">
|
||||
Login
|
||||
</Button>
|
||||
<Button variant="outline" className="w-full">
|
||||
Login with Google
|
||||
</Button>
|
||||
<div className="mt-4 text-center text-sm">
|
||||
Don't have an account?{" "}
|
||||
<a href="#" className="underline underline-offset-4">
|
||||
Sign up
|
||||
</a>
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Meeting Notes</CardTitle>
|
||||
|
||||
@@ -39,7 +39,7 @@ export function ContextMenuDemo() {
|
||||
<ContextMenuSubTrigger inset>More Tools</ContextMenuSubTrigger>
|
||||
<ContextMenuSubContent className="w-48">
|
||||
<ContextMenuItem inset>
|
||||
Save Page As...
|
||||
Save Page...
|
||||
<ContextMenuShortcut>⇧⌘S</ContextMenuShortcut>
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem>
|
||||
|
||||
@@ -124,7 +124,7 @@ function DrawerBottom() {
|
||||
dataKey="goal"
|
||||
style={
|
||||
{
|
||||
fill: "hsl(var(--foreground))",
|
||||
fill: "var(--primary)",
|
||||
opacity: 0.9,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
|
||||
@@ -44,55 +44,52 @@ const plans = [
|
||||
] as const
|
||||
|
||||
const themes = {
|
||||
stone: {
|
||||
neutral: {
|
||||
light: {
|
||||
"--primary": "oklch(0.216 0.006 56.043)", // --color-stone-900
|
||||
"--primary-foreground": "oklch(0.985 0.001 106.423)", // --color-stone-50
|
||||
"--accent": "oklch(0.97 0.001 106.424)", // --color-stone-100
|
||||
"--ring": "oklch(0.869 0.005 56.366)", // --color-stone-300
|
||||
"--primary": "oklch(0.205 0 0)",
|
||||
"--primary-foreground": "oklch(0.985 0 0)",
|
||||
"--ring": "oklch(0.708 0 0)",
|
||||
},
|
||||
dark: {
|
||||
"--primary": "oklch(0.985 0.001 106.423)", // --color-stone-50
|
||||
"--primary-foreground": "oklch(0.216 0.006 56.043)", // --color-stone-900
|
||||
"--accent": "oklch(0.268 0.007 34.298)", // --color-stone-800
|
||||
"--accent-foreground": "oklch(0.985 0.001 106.423)", // --color-stone-50
|
||||
"--ring": "oklch(0.553 0.013 58.071)", // --color-stone-500
|
||||
"--primary": "oklch(0.922 0 0)",
|
||||
"--primary-foreground": "oklch(0.205 0 0)",
|
||||
"--ring": "oklch(0.556 0 0)",
|
||||
},
|
||||
},
|
||||
blue: {
|
||||
light: {
|
||||
"--primary": "oklch(0.546 0.245 262.881)", // --color-blue-600
|
||||
"--primary-foreground": "oklch(0.985 0.001 106.423)", // --color-blue-50
|
||||
"--ring": "oklch(0.707 0.165 254.624)", // --color-blue-400
|
||||
"--primary": "oklch(0.546 0.245 262.881)",
|
||||
"--primary-foreground": "oklch(0.985 0.001 106.423)",
|
||||
"--ring": "oklch(0.546 0.245 262.881)",
|
||||
},
|
||||
dark: {
|
||||
"--primary": "oklch(0.546 0.245 262.881)", // --color-blue-600
|
||||
"--primary-foreground": "oklch(0.985 0.001 106.423)", // --color-blue-50
|
||||
"--ring": "oklch(0.379 0.146 265.522)", // --color-blue-400
|
||||
"--primary": "oklch(0.623 0.214 259.815)",
|
||||
"--primary-foreground": "oklch(0.985 0.001 106.423)",
|
||||
"--ring": "oklch(0.623 0.214 259.815)",
|
||||
},
|
||||
},
|
||||
amber: {
|
||||
light: {
|
||||
"--primary": "oklch(0.769 0.188 70.08)", // --color-blue-600
|
||||
"--primary-foreground": "oklch(0.985 0.001 106.423)", // --color-blue-50
|
||||
"--ring": "oklch(0.82 0.13 92.25)", // --color-blue-400
|
||||
"--primary": "oklch(0.769 0.188 70.08)",
|
||||
"--primary-foreground": "oklch(0.985 0.001 106.423)",
|
||||
"--ring": "oklch(0.82 0.13 92.25)",
|
||||
},
|
||||
dark: {
|
||||
"--primary": "oklch(0.985 0.001 106.423)", // --color-stone-50
|
||||
"--primary-foreground": "oklch(0.216 0.006 56.043)", // --color-stone-900
|
||||
"--ring": "oklch(0.553 0.013 58.071)", // --color-stone-500
|
||||
"--primary": "oklch(0.769 0.188 70.08)",
|
||||
"--primary-foreground": "oklch(0.216 0.006 56.043)",
|
||||
"--ring": "oklch(0.666 0.179 58.318)",
|
||||
},
|
||||
},
|
||||
teal: {
|
||||
light: {
|
||||
"--primary": "oklch(0.627 0.194 149.214)", // --color-blue-600
|
||||
"--primary-foreground": "oklch(0.985 0.001 106.423)", // --color-blue-50
|
||||
"--ring": "oklch(0.79 0.19 153.13)", // --color-blue-400
|
||||
"--primary": "oklch(0.627 0.194 149.214)",
|
||||
"--primary-foreground": "oklch(0.985 0.001 106.423)",
|
||||
"--ring": "oklch(0.79 0.19 153.13)",
|
||||
},
|
||||
dark: {
|
||||
"--primary": "oklch(0.985 0.001 106.423)", // --color-stone-50
|
||||
"--primary-foreground": "oklch(0.216 0.006 56.043)", // --color-stone-900
|
||||
"--ring": "oklch(0.553 0.013 58.071)", // --color-stone-500
|
||||
"--primary": "oklch(0.704 0.14 182.503)",
|
||||
"--primary-foreground": "oklch(0.216 0.006 56.043)",
|
||||
"--ring": "oklch(0.704 0.14 182.503)",
|
||||
},
|
||||
},
|
||||
} as const
|
||||
@@ -109,123 +106,129 @@ export function FormsDemo() {
|
||||
}, [theme, mode])
|
||||
|
||||
return (
|
||||
<div className="flex max-w-md flex-col gap-4">
|
||||
<Card style={themeStyles as React.CSSProperties}>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">Upgrade your subscription</CardTitle>
|
||||
<CardDescription>
|
||||
You are currently on the free plan. Upgrade to the pro plan to get
|
||||
access to all features.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="flex flex-col gap-3 md:flex-row">
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor="name">Name</Label>
|
||||
<Input id="name" placeholder="Evil Rabbit" />
|
||||
<div>
|
||||
<div className="flex max-w-md flex-col gap-4">
|
||||
<Card style={themeStyles as React.CSSProperties}>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">Upgrade your subscription</CardTitle>
|
||||
<CardDescription className="text-balance">
|
||||
You are currently on the free plan. Upgrade to the pro plan to get
|
||||
access to all features.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="flex flex-col gap-3 md:flex-row">
|
||||
<div className="flex flex-1 flex-col gap-2">
|
||||
<Label htmlFor="name">Name</Label>
|
||||
<Input id="name" placeholder="Evil Rabbit" />
|
||||
</div>
|
||||
<div className="flex flex-1 flex-col gap-2">
|
||||
<Label htmlFor="email">Email</Label>
|
||||
<Input id="email" placeholder="example@acme.com" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor="email">Email</Label>
|
||||
<Input id="email" placeholder="example@acme.com" />
|
||||
<Label htmlFor="card-number">Card Number</Label>
|
||||
<div className="grid grid-cols-2 gap-3 md:grid-cols-[1fr_80px_60px]">
|
||||
<Input
|
||||
id="card-number"
|
||||
placeholder="1234 1234 1234 1234"
|
||||
className="col-span-2 md:col-span-1"
|
||||
/>
|
||||
<Input id="card-number-expiry" placeholder="MM/YY" />
|
||||
<Input id="card-number-cvc" placeholder="CVC" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor="card-number">Card Number</Label>
|
||||
<div className="grid grid-cols-2 gap-3 md:grid-cols-[1fr_80px_60px]">
|
||||
<Input
|
||||
id="card-number"
|
||||
placeholder="1234 1234 1234 1234"
|
||||
className="col-span-2 md:col-span-1"
|
||||
/>
|
||||
<Input id="card-number-expiry" placeholder="MM/YY" />
|
||||
<Input id="card-number-cvc" placeholder="CVC" />
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor="color">Color</Label>
|
||||
<Select
|
||||
onValueChange={(value) =>
|
||||
setTheme(value as keyof typeof themes)
|
||||
}
|
||||
>
|
||||
<SelectTrigger id="color" className="w-full capitalize">
|
||||
<SelectValue placeholder="Select a color" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{Object.keys(themes).map((theme) => (
|
||||
<SelectItem
|
||||
key={theme}
|
||||
value={theme}
|
||||
className="capitalize"
|
||||
>
|
||||
<div
|
||||
className="size-3.5 rounded-full border"
|
||||
style={{
|
||||
backgroundColor:
|
||||
themes[theme as keyof typeof themes][
|
||||
mode as keyof (typeof themes)[keyof typeof themes]
|
||||
]?.["--primary"],
|
||||
}}
|
||||
/>
|
||||
{theme}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor="color">Color</Label>
|
||||
<Select
|
||||
onValueChange={(value) =>
|
||||
setTheme(value as keyof typeof themes)
|
||||
}
|
||||
>
|
||||
<SelectTrigger id="color" className="w-full">
|
||||
<SelectValue placeholder="Select a color" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{Object.keys(themes).map((theme) => (
|
||||
<SelectItem key={theme} value={theme}>
|
||||
<div
|
||||
className="size-3.5 rounded-full"
|
||||
style={{
|
||||
backgroundColor:
|
||||
themes[theme as keyof typeof themes]["light"][
|
||||
"--primary"
|
||||
],
|
||||
}}
|
||||
<fieldset className="flex flex-col gap-3">
|
||||
<legend className="text-sm font-medium">Plan</legend>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
Select the plan that best fits your needs.
|
||||
</p>
|
||||
<RadioGroup
|
||||
defaultValue="starter"
|
||||
className="grid gap-3 md:grid-cols-2"
|
||||
>
|
||||
{plans.map((plan) => (
|
||||
<Label
|
||||
className="has-[[data-state=checked]]:border-ring has-[[data-state=checked]]:bg-input/30 flex items-start gap-3 rounded-lg border p-3"
|
||||
key={plan.id}
|
||||
>
|
||||
<RadioGroupItem
|
||||
value={plan.id}
|
||||
id={plan.name}
|
||||
className="data-[state=checked]:border-primary"
|
||||
/>
|
||||
{theme}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<fieldset className="flex flex-col gap-3">
|
||||
<legend className="text-sm font-medium">Plan</legend>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
Select the plan that best fits your needs.
|
||||
</p>
|
||||
<RadioGroup
|
||||
defaultValue="starter"
|
||||
className="grid gap-3 md:grid-cols-2"
|
||||
>
|
||||
{plans.map((plan) => (
|
||||
<Label
|
||||
className="has-[[data-state=checked]]:border-ring has-[[data-state=checked]]:bg-ring/10 flex items-start gap-3 rounded-lg border p-3"
|
||||
key={plan.id}
|
||||
>
|
||||
<RadioGroupItem
|
||||
value={plan.id}
|
||||
id={plan.name}
|
||||
className="data-[state=checked]:border-primary"
|
||||
/>
|
||||
<div className="grid gap-1 font-normal">
|
||||
<div className="font-medium">{plan.name}</div>
|
||||
<div className="text-muted-foreground text-xs leading-snug">
|
||||
{plan.description}
|
||||
<div className="grid gap-1 font-normal">
|
||||
<div className="font-medium">{plan.name}</div>
|
||||
<div className="text-muted-foreground pr-2 text-xs leading-snug text-balance">
|
||||
{plan.description}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Label>
|
||||
))}
|
||||
</RadioGroup>
|
||||
</fieldset>
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor="notes">Notes</Label>
|
||||
<Textarea id="notes" placeholder="Enter notes" />
|
||||
</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox id="terms" />
|
||||
<Label htmlFor="terms" className="font-normal">
|
||||
I agree to the terms and conditions
|
||||
</Label>
|
||||
))}
|
||||
</RadioGroup>
|
||||
</fieldset>
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor="notes">Notes</Label>
|
||||
<Textarea id="notes" placeholder="Enter notes" />
|
||||
</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox id="terms" />
|
||||
<Label htmlFor="terms" className="font-normal">
|
||||
I agree to the terms and conditions
|
||||
</Label>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox id="newsletter" defaultChecked />
|
||||
<Label htmlFor="newsletter" className="font-normal">
|
||||
Allow us to send you emails
|
||||
</Label>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox id="newsletter" defaultChecked />
|
||||
<Label htmlFor="newsletter" className="font-normal">
|
||||
Allow us to send you emails
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex justify-between">
|
||||
<Button variant="outline" size="sm">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button size="sm">Upgrade Plan</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</CardContent>
|
||||
<CardFooter className="flex justify-between">
|
||||
<Button variant="outline" size="sm">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button size="sm">Upgrade Plan</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -22,8 +22,9 @@ export function ModeSwitcher() {
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="group/toggle h-8 w-8 px-0"
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="group/toggle size-8"
|
||||
onClick={toggleTheme}
|
||||
>
|
||||
<SunIcon className="hidden [html.dark_&]:block" />
|
||||
|
||||
@@ -14,7 +14,7 @@ export function NavHeader() {
|
||||
const pathname = usePathname()
|
||||
|
||||
return (
|
||||
<NavigationMenu>
|
||||
<NavigationMenu className="hidden sm:flex">
|
||||
<NavigationMenuList className="gap-2 *:data-[slot=navigation-menu-item]:h-7 **:data-[slot=navigation-menu-link]:py-1 **:data-[slot=navigation-menu-link]:font-medium">
|
||||
<NavigationMenuItem>
|
||||
<NavigationMenuLink asChild data-active={pathname === "/"}>
|
||||
|
||||
@@ -1,24 +1,132 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { toast } from "sonner"
|
||||
|
||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
||||
|
||||
export function SonnerDemo() {
|
||||
return (
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() =>
|
||||
toast("Event has been created", {
|
||||
description: "Sunday, December 03, 2023 at 9:00 AM",
|
||||
action: {
|
||||
label: "Undo",
|
||||
onClick: () => console.log("Undo"),
|
||||
const promiseCode = "`${data.name} toast has been added`"
|
||||
|
||||
const allTypes = [
|
||||
{
|
||||
name: "Default",
|
||||
snippet: `toast('Event has been created')`,
|
||||
action: () => toast("Event has been created"),
|
||||
},
|
||||
{
|
||||
name: "Description",
|
||||
snippet: `toast.message('Event has been created', {
|
||||
description: 'Monday, January 3rd at 6:00pm',
|
||||
})`,
|
||||
action: () =>
|
||||
toast("Event has been created", {
|
||||
description: "Monday, January 3rd at 6:00pm",
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Success",
|
||||
snippet: `toast.success('Event has been created')`,
|
||||
action: () => toast.success("Event has been created"),
|
||||
},
|
||||
{
|
||||
name: "Info",
|
||||
snippet: `toast.info('Be at the area 10 minutes before the event time')`,
|
||||
action: () => toast.info("Be at the area 10 minutes before the event time"),
|
||||
},
|
||||
{
|
||||
name: "Warning",
|
||||
snippet: `toast.warning('Event start time cannot be earlier than 8am')`,
|
||||
action: () => toast.warning("Event start time cannot be earlier than 8am"),
|
||||
},
|
||||
{
|
||||
name: "Error",
|
||||
snippet: `toast.error('Event has not been created')`,
|
||||
action: () => toast.error("Event has not been created"),
|
||||
},
|
||||
{
|
||||
name: "Action",
|
||||
action: () =>
|
||||
toast.message("Event has been created", {
|
||||
action: {
|
||||
label: "Undo",
|
||||
onClick: () => console.log("Undo"),
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Cancel",
|
||||
action: () =>
|
||||
toast.message("Event has been created", {
|
||||
cancel: {
|
||||
label: "Cancel",
|
||||
onClick: () => console.log("Cancel"),
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Promise",
|
||||
snippet: `const promise = () => new Promise((resolve) => setTimeout(() => resolve({ name: 'Sonner' }), 2000));
|
||||
|
||||
toast.promise(promise, {
|
||||
loading: 'Loading...',
|
||||
success: (data) => {
|
||||
return ${promiseCode};
|
||||
},
|
||||
error: 'Error',
|
||||
});`,
|
||||
action: () =>
|
||||
toast.promise<{ name: string }>(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({ name: "Sonner" })
|
||||
}, 2000)
|
||||
}),
|
||||
{
|
||||
loading: "Loading...",
|
||||
success: (data) => {
|
||||
return `${data.name} toast has been added`
|
||||
},
|
||||
})
|
||||
}
|
||||
>
|
||||
Show Toast
|
||||
</Button>
|
||||
error: "Error",
|
||||
}
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
export function SonnerDemo() {
|
||||
const [activeType, setActiveType] = React.useState(allTypes[0])
|
||||
return (
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<Button onClick={() => toast("My first toast")} variant="outline">
|
||||
Give me a toast
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() =>
|
||||
toast("Event has been created", {
|
||||
description: "Sunday, December 03, 2023 at 9:00 AM",
|
||||
action: {
|
||||
label: "Undo",
|
||||
onClick: () => console.log("Undo"),
|
||||
},
|
||||
})
|
||||
}
|
||||
>
|
||||
Show Toast
|
||||
</Button>
|
||||
{allTypes.map((type) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
data-active={activeType.name === type.name}
|
||||
onClick={() => {
|
||||
type.action()
|
||||
setActiveType(type)
|
||||
}}
|
||||
key={type.name}
|
||||
>
|
||||
{type.name}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
30
apps/v4/components/theme-selector.tsx
Normal file
30
apps/v4/components/theme-selector.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
"use client"
|
||||
|
||||
import { THEMES } from "@/lib/themes"
|
||||
import { useThemeConfig } from "@/components/active-theme"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/registry/new-york-v4/ui/select"
|
||||
|
||||
export function ThemeSelector() {
|
||||
const { activeTheme, setActiveTheme } = useThemeConfig()
|
||||
|
||||
return (
|
||||
<Select value={activeTheme} onValueChange={setActiveTheme}>
|
||||
<SelectTrigger size="sm" className="w-32">
|
||||
<SelectValue placeholder="Select a theme" />
|
||||
</SelectTrigger>
|
||||
<SelectContent align="end">
|
||||
{THEMES.map((theme) => (
|
||||
<SelectItem key={theme.name} value={theme.value}>
|
||||
{theme.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
)
|
||||
}
|
||||
49
apps/v4/lib/fonts.ts
Normal file
49
apps/v4/lib/fonts.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import {
|
||||
Geist,
|
||||
Geist_Mono,
|
||||
Instrument_Sans,
|
||||
Inter,
|
||||
Mulish,
|
||||
Noto_Sans_Mono,
|
||||
} from "next/font/google"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const fontSans = Geist({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-sans",
|
||||
})
|
||||
|
||||
const fontMono = Geist_Mono({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-mono",
|
||||
})
|
||||
|
||||
const fontInstrument = Instrument_Sans({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-instrument",
|
||||
})
|
||||
|
||||
const fontNotoMono = Noto_Sans_Mono({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-noto-mono",
|
||||
})
|
||||
|
||||
const fontMullish = Mulish({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-mullish",
|
||||
})
|
||||
|
||||
const fontInter = Inter({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-inter",
|
||||
})
|
||||
|
||||
export const fontVariables = cn(
|
||||
fontSans.variable,
|
||||
fontMono.variable,
|
||||
fontInstrument.variable,
|
||||
fontNotoMono.variable,
|
||||
fontMullish.variable,
|
||||
fontInter.variable
|
||||
)
|
||||
75
apps/v4/lib/themes.ts
Normal file
75
apps/v4/lib/themes.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
export const THEMES = [
|
||||
{
|
||||
name: "Default",
|
||||
value: "default",
|
||||
colors: {
|
||||
light: "oklch(1 0 0)",
|
||||
dark: "oklch(0.145 0 0)",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Neutral",
|
||||
value: "neutral",
|
||||
colors: {
|
||||
light: "oklch(1 0 0)",
|
||||
dark: "oklch(0.145 0 0)",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Stone",
|
||||
value: "stone",
|
||||
colors: {
|
||||
light: "oklch(1 0 0)",
|
||||
dark: "oklch(0.147 0.004 49.25)",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Zinc",
|
||||
value: "zinc",
|
||||
colors: {
|
||||
light: "oklch(1 0 0)",
|
||||
dark: "oklch(0.141 0.005 285.823)",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Gray",
|
||||
value: "gray",
|
||||
colors: {
|
||||
light: "oklch(1 0 0)",
|
||||
dark: "oklch(0.13 0.028 261.692)",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Slate",
|
||||
value: "slate",
|
||||
colors: {
|
||||
light: "oklch(1 0 0)",
|
||||
dark: "oklch(0.129 0.042 264.695)",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Blue",
|
||||
value: "blue",
|
||||
colors: {
|
||||
light: "oklch(0.488 0.243 264.376)",
|
||||
dark: "oklch(0.488 0.243 264.376)",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Lime",
|
||||
value: "lime",
|
||||
colors: {
|
||||
light: "oklch(0.532 0.157 131.589)",
|
||||
dark: "oklch(0.532 0.157 131.589)",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Small",
|
||||
value: "small",
|
||||
colors: {
|
||||
light: "oklch(1 0 0)",
|
||||
dark: "oklch(0.145 0 0)",
|
||||
},
|
||||
},
|
||||
]
|
||||
export type Theme = (typeof THEMES)[number]
|
||||
@@ -121,6 +121,9 @@
|
||||
{
|
||||
"name": "badge",
|
||||
"type": "registry:ui",
|
||||
"dependencies": [
|
||||
"@radix-ui/react-slot"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/badge.tsx",
|
||||
|
||||
@@ -47,7 +47,7 @@ export function LoginForm({
|
||||
</Button>
|
||||
</div>
|
||||
<div className="after:border-border relative text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t">
|
||||
<span className="bg-background text-muted-foreground relative z-10 px-2">
|
||||
<span className="bg-card text-muted-foreground relative z-10 px-2">
|
||||
Or continue with
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -45,7 +45,7 @@ export function LoginForm({
|
||||
Login
|
||||
</Button>
|
||||
<div className="after:border-border relative text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t">
|
||||
<span className="bg-background text-muted-foreground relative z-10 px-2">
|
||||
<span className="bg-card text-muted-foreground relative z-10 px-2">
|
||||
Or continue with
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -69,8 +69,8 @@ export function TeamSwitcher({
|
||||
onClick={() => setActiveTeam(team)}
|
||||
className="gap-2 p-2"
|
||||
>
|
||||
<div className="flex size-6 items-center justify-center rounded-xs border">
|
||||
<team.logo className="size-4 shrink-0" />
|
||||
<div className="flex size-6 items-center justify-center rounded-md border">
|
||||
<team.logo className="size-3.5 shrink-0" />
|
||||
</div>
|
||||
{team.name}
|
||||
<DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>
|
||||
@@ -78,7 +78,7 @@ export function TeamSwitcher({
|
||||
))}
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem className="gap-2 p-2">
|
||||
<div className="bg-background flex size-6 items-center justify-center rounded-md border">
|
||||
<div className="flex size-6 items-center justify-center rounded-md border bg-transparent">
|
||||
<Plus className="size-4" />
|
||||
</div>
|
||||
<div className="text-muted-foreground font-medium">Add team</div>
|
||||
|
||||
@@ -36,7 +36,7 @@ function AlertDialogOverlay({
|
||||
<AlertDialogPrimitive.Overlay
|
||||
data-slot="alert-dialog-overlay"
|
||||
className={cn(
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -8,9 +8,9 @@ const alertVariants = cva(
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-background text-foreground",
|
||||
default: "bg-card text-card-foreground",
|
||||
destructive:
|
||||
"text-destructive-foreground [&>svg]:text-current *:data-[slot=alert-description]:text-destructive-foreground/80",
|
||||
"text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
||||
@@ -14,7 +14,7 @@ const badgeVariants = cva(
|
||||
secondary:
|
||||
"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
||||
destructive:
|
||||
"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
|
||||
"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/70",
|
||||
outline:
|
||||
"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
||||
},
|
||||
|
||||
@@ -5,19 +5,20 @@ import { cva, type VariantProps } from "class-variance-authority"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none 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",
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none 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",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
|
||||
destructive:
|
||||
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
|
||||
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
||||
outline:
|
||||
"border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
|
||||
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
ghost:
|
||||
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
|
||||
@@ -19,7 +19,10 @@ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-header"
|
||||
className={cn("flex flex-col gap-1.5 px-6", className)}
|
||||
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",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
@@ -45,6 +48,19 @@ function CardDescription({ 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
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
@@ -59,10 +75,18 @@ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-footer"
|
||||
className={cn("flex items-center px-6", className)}
|
||||
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
||||
export {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
CardAction,
|
||||
CardDescription,
|
||||
CardContent,
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ function Checkbox({
|
||||
<CheckboxPrimitive.Root
|
||||
data-slot="checkbox"
|
||||
className={cn(
|
||||
"peer border-input data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -126,7 +126,7 @@ function ContextMenuItem({
|
||||
data-inset={inset}
|
||||
data-variant={variant}
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive-foreground data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/40 data-[variant=destructive]:focus:text-destructive-foreground data-[variant=destructive]:*:[svg]:!text-destructive-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -38,7 +38,7 @@ function DialogOverlay({
|
||||
<DialogPrimitive.Overlay
|
||||
data-slot="dialog-overlay"
|
||||
className={cn(
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -37,7 +37,7 @@ function DrawerOverlay({
|
||||
<DrawerPrimitive.Overlay
|
||||
data-slot="drawer-overlay"
|
||||
className={cn(
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -57,10 +57,10 @@ function DrawerContent({
|
||||
data-slot="drawer-content"
|
||||
className={cn(
|
||||
"group/drawer-content bg-background fixed z-50 flex h-auto flex-col",
|
||||
"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg",
|
||||
"data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg",
|
||||
"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:sm:max-w-sm",
|
||||
"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:sm:max-w-sm",
|
||||
"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b",
|
||||
"data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t",
|
||||
"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm",
|
||||
"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -74,7 +74,7 @@ function DropdownMenuItem({
|
||||
data-inset={inset}
|
||||
data-variant={variant}
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive-foreground data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/40 data-[variant=destructive]:focus:text-destructive-foreground data-[variant=destructive]:*:[svg]:!text-destructive-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -97,7 +97,7 @@ function FormLabel({
|
||||
<Label
|
||||
data-slot="form-label"
|
||||
data-error={!!error}
|
||||
className={cn("data-[error=true]:text-destructive-foreground", className)}
|
||||
className={cn("data-[error=true]:text-destructive", className)}
|
||||
htmlFor={formItemId}
|
||||
{...props}
|
||||
/>
|
||||
@@ -147,7 +147,7 @@ function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
|
||||
<p
|
||||
data-slot="form-message"
|
||||
id={formMessageId}
|
||||
className={cn("text-destructive-foreground text-sm", className)}
|
||||
className={cn("text-destructive text-sm", className)}
|
||||
{...props}
|
||||
>
|
||||
{body}
|
||||
|
||||
@@ -26,16 +26,18 @@ function HoverCardContent({
|
||||
...props
|
||||
}: React.ComponentProps<typeof HoverCardPrimitive.Content>) {
|
||||
return (
|
||||
<HoverCardPrimitive.Content
|
||||
data-slot="hover-card-content"
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
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 z-50 w-64 rounded-md border p-4 shadow-md outline-hidden",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
<HoverCardPrimitive.Portal data-slot="hover-card-portal">
|
||||
<HoverCardPrimitive.Content
|
||||
data-slot="hover-card-content"
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
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 z-50 w-64 rounded-md border p-4 shadow-md outline-hidden",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</HoverCardPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ function InputOTPSlot({
|
||||
data-slot="input-otp-slot"
|
||||
data-active={isActive}
|
||||
className={cn(
|
||||
"border-input data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive relative flex h-9 w-9 items-center justify-center border-y border-r text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10 data-[active=true]:ring-[3px]",
|
||||
"data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive dark:bg-input/30 border-input relative flex h-9 w-9 items-center justify-center border-y border-r text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10 data-[active=true]:ring-[3px]",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -8,7 +8,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
||||
type={type}
|
||||
data-slot="input"
|
||||
className={cn(
|
||||
"border-input file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground 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",
|
||||
"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",
|
||||
className
|
||||
|
||||
@@ -103,7 +103,7 @@ function MenubarItem({
|
||||
data-inset={inset}
|
||||
data-variant={variant}
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive-foreground data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/40 data-[variant=destructive]:focus:text-destructive-foreground data-[variant=destructive]:*:[svg]:!text-destructive-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -27,7 +27,7 @@ function RadioGroupItem({
|
||||
<RadioGroupPrimitive.Item
|
||||
data-slot="radio-group-item"
|
||||
className={cn(
|
||||
"border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"border-input text-primary 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 aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -26,14 +26,18 @@ function SelectValue({
|
||||
|
||||
function SelectTrigger({
|
||||
className,
|
||||
size = "default",
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Trigger>) {
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
|
||||
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 flex h-9 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-[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 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",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -36,7 +36,7 @@ function SheetOverlay({
|
||||
<SheetPrimitive.Overlay
|
||||
data-slot="sheet-overlay"
|
||||
className={cn(
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -216,6 +216,7 @@ function Sidebar({
|
||||
>
|
||||
{/* This is what handles the sidebar gap on desktop */}
|
||||
<div
|
||||
data-slot="sidebar-gap"
|
||||
className={cn(
|
||||
"relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear",
|
||||
"group-data-[collapsible=offcanvas]:w-0",
|
||||
@@ -226,6 +227,7 @@ function Sidebar({
|
||||
)}
|
||||
/>
|
||||
<div
|
||||
data-slot="sidebar-container"
|
||||
className={cn(
|
||||
"fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
|
||||
side === "left"
|
||||
@@ -241,6 +243,7 @@ function Sidebar({
|
||||
>
|
||||
<div
|
||||
data-sidebar="sidebar"
|
||||
data-slot="sidebar-inner"
|
||||
className="bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm"
|
||||
>
|
||||
{children}
|
||||
@@ -263,7 +266,7 @@ function SidebarTrigger({
|
||||
data-slot="sidebar-trigger"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className={cn("h-7 w-7", className)}
|
||||
className={cn("size-7", className)}
|
||||
onClick={(event) => {
|
||||
onClick?.(event)
|
||||
toggleSidebar()
|
||||
|
||||
@@ -4,7 +4,7 @@ function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="skeleton"
|
||||
className={cn("bg-primary/10 animate-pulse rounded-md", className)}
|
||||
className={cn("bg-accent animate-pulse rounded-md", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -10,17 +10,13 @@ const Toaster = ({ ...props }: ToasterProps) => {
|
||||
<Sonner
|
||||
theme={theme as ToasterProps["theme"]}
|
||||
className="toaster group"
|
||||
toastOptions={{
|
||||
classNames: {
|
||||
toast:
|
||||
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
|
||||
description: "group-[.toast]:text-muted-foreground",
|
||||
actionButton:
|
||||
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground font-medium",
|
||||
cancelButton:
|
||||
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground font-medium",
|
||||
},
|
||||
}}
|
||||
style={
|
||||
{
|
||||
"--normal-bg": "var(--popover)",
|
||||
"--normal-text": "var(--popover-foreground)",
|
||||
"--normal-border": "var(--border)",
|
||||
} as React.CSSProperties
|
||||
}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -13,7 +13,7 @@ function Switch({
|
||||
<SwitchPrimitive.Root
|
||||
data-slot="switch"
|
||||
className={cn(
|
||||
"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 inline-flex h-5 w-9 shrink-0 items-center rounded-full border-2 border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -21,7 +21,7 @@ function Switch({
|
||||
<SwitchPrimitive.Thumb
|
||||
data-slot="switch-thumb"
|
||||
className={cn(
|
||||
"bg-background pointer-events-none block size-4 rounded-full ring-0 shadow-lg transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0"
|
||||
"bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0"
|
||||
)}
|
||||
/>
|
||||
</SwitchPrimitive.Root>
|
||||
|
||||
@@ -26,7 +26,7 @@ function TabsList({
|
||||
<TabsPrimitive.List
|
||||
data-slot="tabs-list"
|
||||
className={cn(
|
||||
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-1",
|
||||
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -42,7 +42,7 @@ function TabsTrigger({
|
||||
<TabsPrimitive.Trigger
|
||||
data-slot="tabs-trigger"
|
||||
className={cn(
|
||||
"data-[state=active]:bg-background data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring inline-flex flex-1 items-center justify-center gap-1.5 rounded-md px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
"data-[state=active]:bg-background data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/50 inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -7,7 +7,7 @@ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
||||
<textarea
|
||||
data-slot="textarea"
|
||||
className={cn(
|
||||
"border-input placeholder: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 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||
"border-input placeholder: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 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"dev": "next dev -p 3333",
|
||||
"build": "pnpm --filter=shadcn build && contentlayer2 build && pnpm build:registry && next build",
|
||||
"build:registry": "tsx --tsconfig ./tsconfig.scripts.json ./scripts/build-registry.mts && prettier --loglevel silent --write \"registry/**/*.{ts,tsx,mdx}\" --cache",
|
||||
"registry:build": "tsx --tsconfig ./tsconfig.scripts.json ./scripts/build-registry.mts && prettier --loglevel silent --write \"registry/**/*.{ts,tsx,mdx}\" --cache",
|
||||
"registry:capture": "tsx --tsconfig ./tsconfig.scripts.json ./scripts/capture-registry.mts",
|
||||
"build:docs": "contentlayer2 build",
|
||||
"seed:tasks": "tsx --tsconfig ./tsconfig.scripts.json ./app/(app)/examples/tasks/data/seed.ts",
|
||||
|
||||
@@ -114,7 +114,6 @@
|
||||
"accent": "oklch(0.967 0.003 264.542)",
|
||||
"accent-foreground": "oklch(0.21 0.034 264.665)",
|
||||
"destructive": "oklch(0.577 0.245 27.325)",
|
||||
"destructive-foreground": "oklch(0.577 0.245 27.325)",
|
||||
"border": "oklch(0.928 0.006 264.531)",
|
||||
"input": "oklch(0.928 0.006 264.531)",
|
||||
"ring": "oklch(0.707 0.022 261.325)",
|
||||
@@ -136,11 +135,11 @@
|
||||
"dark": {
|
||||
"background": "oklch(0.13 0.028 261.692)",
|
||||
"foreground": "oklch(0.985 0.002 247.839)",
|
||||
"card": "oklch(0.13 0.028 261.692)",
|
||||
"card": "oklch(0.21 0.034 264.665)",
|
||||
"card-foreground": "oklch(0.985 0.002 247.839)",
|
||||
"popover": "oklch(0.13 0.028 261.692)",
|
||||
"popover": "oklch(0.21 0.034 264.665)",
|
||||
"popover-foreground": "oklch(0.985 0.002 247.839)",
|
||||
"primary": "oklch(0.985 0.002 247.839)",
|
||||
"primary": "oklch(0.928 0.006 264.531)",
|
||||
"primary-foreground": "oklch(0.21 0.034 264.665)",
|
||||
"secondary": "oklch(0.278 0.033 256.848)",
|
||||
"secondary-foreground": "oklch(0.985 0.002 247.839)",
|
||||
@@ -148,11 +147,10 @@
|
||||
"muted-foreground": "oklch(0.707 0.022 261.325)",
|
||||
"accent": "oklch(0.278 0.033 256.848)",
|
||||
"accent-foreground": "oklch(0.985 0.002 247.839)",
|
||||
"destructive": "oklch(0.396 0.141 25.723)",
|
||||
"destructive-foreground": "oklch(0.637 0.237 25.331)",
|
||||
"border": "oklch(0.278 0.033 256.848)",
|
||||
"input": "oklch(0.278 0.033 256.848)",
|
||||
"ring": "oklch(0.446 0.03 256.802)",
|
||||
"destructive": "oklch(0.704 0.191 22.216)",
|
||||
"border": "oklch(1 0 0 / 10%)",
|
||||
"input": "oklch(1 0 0 / 15%)",
|
||||
"ring": "oklch(0.551 0.027 264.364)",
|
||||
"chart-1": "oklch(0.488 0.243 264.376)",
|
||||
"chart-2": "oklch(0.696 0.17 162.48)",
|
||||
"chart-3": "oklch(0.769 0.188 70.08)",
|
||||
@@ -164,8 +162,8 @@
|
||||
"sidebar-primary-foreground": "oklch(0.985 0.002 247.839)",
|
||||
"sidebar-accent": "oklch(0.278 0.033 256.848)",
|
||||
"sidebar-accent-foreground": "oklch(0.985 0.002 247.839)",
|
||||
"sidebar-border": "oklch(0.278 0.033 256.848)",
|
||||
"sidebar-ring": "oklch(0.446 0.03 256.802)"
|
||||
"sidebar-border": "oklch(1 0 0 / 10%)",
|
||||
"sidebar-ring": "oklch(0.551 0.027 264.364)"
|
||||
}
|
||||
},
|
||||
"inlineColorsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n ",
|
||||
|
||||
@@ -114,7 +114,6 @@
|
||||
"accent": "oklch(0.97 0 0)",
|
||||
"accent-foreground": "oklch(0.205 0 0)",
|
||||
"destructive": "oklch(0.577 0.245 27.325)",
|
||||
"destructive-foreground": "oklch(0.577 0.245 27.325)",
|
||||
"border": "oklch(0.922 0 0)",
|
||||
"input": "oklch(0.922 0 0)",
|
||||
"ring": "oklch(0.708 0 0)",
|
||||
@@ -136,11 +135,11 @@
|
||||
"dark": {
|
||||
"background": "oklch(0.145 0 0)",
|
||||
"foreground": "oklch(0.985 0 0)",
|
||||
"card": "oklch(0.145 0 0)",
|
||||
"card": "oklch(0.205 0 0)",
|
||||
"card-foreground": "oklch(0.985 0 0)",
|
||||
"popover": "oklch(0.145 0 0)",
|
||||
"popover": "oklch(0.205 0 0)",
|
||||
"popover-foreground": "oklch(0.985 0 0)",
|
||||
"primary": "oklch(0.985 0 0)",
|
||||
"primary": "oklch(0.922 0 0)",
|
||||
"primary-foreground": "oklch(0.205 0 0)",
|
||||
"secondary": "oklch(0.269 0 0)",
|
||||
"secondary-foreground": "oklch(0.985 0 0)",
|
||||
@@ -148,11 +147,10 @@
|
||||
"muted-foreground": "oklch(0.708 0 0)",
|
||||
"accent": "oklch(0.269 0 0)",
|
||||
"accent-foreground": "oklch(0.985 0 0)",
|
||||
"destructive": "oklch(0.396 0.141 25.723)",
|
||||
"destructive-foreground": "oklch(0.637 0.237 25.331)",
|
||||
"border": "oklch(0.269 0 0)",
|
||||
"input": "oklch(0.269 0 0)",
|
||||
"ring": "oklch(0.439 0 0)",
|
||||
"destructive": "oklch(0.704 0.191 22.216)",
|
||||
"border": "oklch(1 0 0 / 10%)",
|
||||
"input": "oklch(1 0 0 / 15%)",
|
||||
"ring": "oklch(0.556 0 0)",
|
||||
"chart-1": "oklch(0.488 0.243 264.376)",
|
||||
"chart-2": "oklch(0.696 0.17 162.48)",
|
||||
"chart-3": "oklch(0.769 0.188 70.08)",
|
||||
@@ -164,8 +162,8 @@
|
||||
"sidebar-primary-foreground": "oklch(0.985 0 0)",
|
||||
"sidebar-accent": "oklch(0.269 0 0)",
|
||||
"sidebar-accent-foreground": "oklch(0.985 0 0)",
|
||||
"sidebar-border": "oklch(0.269 0 0)",
|
||||
"sidebar-ring": "oklch(0.439 0 0)"
|
||||
"sidebar-border": "oklch(1 0 0 / 10%)",
|
||||
"sidebar-ring": "oklch(0.556 0 0)"
|
||||
}
|
||||
},
|
||||
"inlineColorsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n ",
|
||||
|
||||
@@ -114,7 +114,6 @@
|
||||
"accent": "oklch(0.968 0.007 247.896)",
|
||||
"accent-foreground": "oklch(0.208 0.042 265.755)",
|
||||
"destructive": "oklch(0.577 0.245 27.325)",
|
||||
"destructive-foreground": "oklch(0.577 0.245 27.325)",
|
||||
"border": "oklch(0.929 0.013 255.508)",
|
||||
"input": "oklch(0.929 0.013 255.508)",
|
||||
"ring": "oklch(0.704 0.04 256.788)",
|
||||
@@ -136,11 +135,11 @@
|
||||
"dark": {
|
||||
"background": "oklch(0.129 0.042 264.695)",
|
||||
"foreground": "oklch(0.984 0.003 247.858)",
|
||||
"card": "oklch(0.129 0.042 264.695)",
|
||||
"card": "oklch(0.208 0.042 265.755)",
|
||||
"card-foreground": "oklch(0.984 0.003 247.858)",
|
||||
"popover": "oklch(0.129 0.042 264.695)",
|
||||
"popover": "oklch(0.208 0.042 265.755)",
|
||||
"popover-foreground": "oklch(0.984 0.003 247.858)",
|
||||
"primary": "oklch(0.984 0.003 247.858)",
|
||||
"primary": "oklch(0.929 0.013 255.508)",
|
||||
"primary-foreground": "oklch(0.208 0.042 265.755)",
|
||||
"secondary": "oklch(0.279 0.041 260.031)",
|
||||
"secondary-foreground": "oklch(0.984 0.003 247.858)",
|
||||
@@ -148,11 +147,10 @@
|
||||
"muted-foreground": "oklch(0.704 0.04 256.788)",
|
||||
"accent": "oklch(0.279 0.041 260.031)",
|
||||
"accent-foreground": "oklch(0.984 0.003 247.858)",
|
||||
"destructive": "oklch(0.396 0.141 25.723)",
|
||||
"destructive-foreground": "oklch(0.637 0.237 25.331)",
|
||||
"border": "oklch(0.279 0.041 260.031)",
|
||||
"input": "oklch(0.279 0.041 260.031)",
|
||||
"ring": "oklch(0.446 0.043 257.281)",
|
||||
"destructive": "oklch(0.704 0.191 22.216)",
|
||||
"border": "oklch(1 0 0 / 10%)",
|
||||
"input": "oklch(1 0 0 / 15%)",
|
||||
"ring": "oklch(0.551 0.027 264.364)",
|
||||
"chart-1": "oklch(0.488 0.243 264.376)",
|
||||
"chart-2": "oklch(0.696 0.17 162.48)",
|
||||
"chart-3": "oklch(0.769 0.188 70.08)",
|
||||
@@ -164,8 +162,8 @@
|
||||
"sidebar-primary-foreground": "oklch(0.984 0.003 247.858)",
|
||||
"sidebar-accent": "oklch(0.279 0.041 260.031)",
|
||||
"sidebar-accent-foreground": "oklch(0.984 0.003 247.858)",
|
||||
"sidebar-border": "oklch(0.279 0.041 260.031)",
|
||||
"sidebar-ring": "oklch(0.446 0.043 257.281)"
|
||||
"sidebar-border": "oklch(1 0 0 / 10%)",
|
||||
"sidebar-ring": "oklch(0.551 0.027 264.364)"
|
||||
}
|
||||
},
|
||||
"inlineColorsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n ",
|
||||
|
||||
@@ -114,7 +114,6 @@
|
||||
"accent": "oklch(0.97 0.001 106.424)",
|
||||
"accent-foreground": "oklch(0.216 0.006 56.043)",
|
||||
"destructive": "oklch(0.577 0.245 27.325)",
|
||||
"destructive-foreground": "oklch(0.577 0.245 27.325)",
|
||||
"border": "oklch(0.923 0.003 48.717)",
|
||||
"input": "oklch(0.923 0.003 48.717)",
|
||||
"ring": "oklch(0.709 0.01 56.259)",
|
||||
@@ -136,11 +135,11 @@
|
||||
"dark": {
|
||||
"background": "oklch(0.147 0.004 49.25)",
|
||||
"foreground": "oklch(0.985 0.001 106.423)",
|
||||
"card": "oklch(0.147 0.004 49.25)",
|
||||
"card": "oklch(0.216 0.006 56.043)",
|
||||
"card-foreground": "oklch(0.985 0.001 106.423)",
|
||||
"popover": "oklch(0.147 0.004 49.25)",
|
||||
"popover": "oklch(0.216 0.006 56.043)",
|
||||
"popover-foreground": "oklch(0.985 0.001 106.423)",
|
||||
"primary": "oklch(0.985 0.001 106.423)",
|
||||
"primary": "oklch(0.923 0.003 48.717)",
|
||||
"primary-foreground": "oklch(0.216 0.006 56.043)",
|
||||
"secondary": "oklch(0.268 0.007 34.298)",
|
||||
"secondary-foreground": "oklch(0.985 0.001 106.423)",
|
||||
@@ -148,10 +147,9 @@
|
||||
"muted-foreground": "oklch(0.709 0.01 56.259)",
|
||||
"accent": "oklch(0.268 0.007 34.298)",
|
||||
"accent-foreground": "oklch(0.985 0.001 106.423)",
|
||||
"destructive": "oklch(0.396 0.141 25.723)",
|
||||
"destructive-foreground": "oklch(0.637 0.237 25.331)",
|
||||
"border": "oklch(0.268 0.007 34.298)",
|
||||
"input": "oklch(0.268 0.007 34.298)",
|
||||
"destructive": "oklch(0.704 0.191 22.216)",
|
||||
"border": "oklch(1 0 0 / 10%)",
|
||||
"input": "oklch(1 0 0 / 15%)",
|
||||
"ring": "oklch(0.553 0.013 58.071)",
|
||||
"chart-1": "oklch(0.488 0.243 264.376)",
|
||||
"chart-2": "oklch(0.696 0.17 162.48)",
|
||||
@@ -164,7 +162,7 @@
|
||||
"sidebar-primary-foreground": "oklch(0.985 0.001 106.423)",
|
||||
"sidebar-accent": "oklch(0.268 0.007 34.298)",
|
||||
"sidebar-accent-foreground": "oklch(0.985 0.001 106.423)",
|
||||
"sidebar-border": "oklch(0.268 0.007 34.298)",
|
||||
"sidebar-border": "oklch(1 0 0 / 10%)",
|
||||
"sidebar-ring": "oklch(0.553 0.013 58.071)"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -114,7 +114,6 @@
|
||||
"accent": "oklch(0.967 0.001 286.375)",
|
||||
"accent-foreground": "oklch(0.21 0.006 285.885)",
|
||||
"destructive": "oklch(0.577 0.245 27.325)",
|
||||
"destructive-foreground": "oklch(0.577 0.245 27.325)",
|
||||
"border": "oklch(0.92 0.004 286.32)",
|
||||
"input": "oklch(0.92 0.004 286.32)",
|
||||
"ring": "oklch(0.705 0.015 286.067)",
|
||||
@@ -136,11 +135,11 @@
|
||||
"dark": {
|
||||
"background": "oklch(0.141 0.005 285.823)",
|
||||
"foreground": "oklch(0.985 0 0)",
|
||||
"card": "oklch(0.141 0.005 285.823)",
|
||||
"card": "oklch(0.21 0.006 285.885)",
|
||||
"card-foreground": "oklch(0.985 0 0)",
|
||||
"popover": "oklch(0.141 0.005 285.823)",
|
||||
"popover": "oklch(0.21 0.006 285.885)",
|
||||
"popover-foreground": "oklch(0.985 0 0)",
|
||||
"primary": "oklch(0.985 0 0)",
|
||||
"primary": "oklch(0.92 0.004 286.32)",
|
||||
"primary-foreground": "oklch(0.21 0.006 285.885)",
|
||||
"secondary": "oklch(0.274 0.006 286.033)",
|
||||
"secondary-foreground": "oklch(0.985 0 0)",
|
||||
@@ -148,11 +147,10 @@
|
||||
"muted-foreground": "oklch(0.705 0.015 286.067)",
|
||||
"accent": "oklch(0.274 0.006 286.033)",
|
||||
"accent-foreground": "oklch(0.985 0 0)",
|
||||
"destructive": "oklch(0.396 0.141 25.723)",
|
||||
"destructive-foreground": "oklch(0.637 0.237 25.331)",
|
||||
"border": "oklch(0.274 0.006 286.033)",
|
||||
"input": "oklch(0.274 0.006 286.033)",
|
||||
"ring": "oklch(0.442 0.017 285.786)",
|
||||
"destructive": "oklch(0.704 0.191 22.216)",
|
||||
"border": "oklch(1 0 0 / 10%)",
|
||||
"input": "oklch(1 0 0 / 15%)",
|
||||
"ring": "oklch(0.552 0.016 285.938)",
|
||||
"chart-1": "oklch(0.488 0.243 264.376)",
|
||||
"chart-2": "oklch(0.696 0.17 162.48)",
|
||||
"chart-3": "oklch(0.769 0.188 70.08)",
|
||||
@@ -164,8 +162,8 @@
|
||||
"sidebar-primary-foreground": "oklch(0.985 0 0)",
|
||||
"sidebar-accent": "oklch(0.274 0.006 286.033)",
|
||||
"sidebar-accent-foreground": "oklch(0.985 0 0)",
|
||||
"sidebar-border": "oklch(0.274 0.006 286.033)",
|
||||
"sidebar-ring": "oklch(0.442 0.017 285.786)"
|
||||
"sidebar-border": "oklch(1 0 0 / 10%)",
|
||||
"sidebar-ring": "oklch(0.552 0.016 285.938)"
|
||||
}
|
||||
},
|
||||
"inlineColorsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n ",
|
||||
|
||||
@@ -97,6 +97,9 @@
|
||||
{
|
||||
"name": "badge",
|
||||
"type": "registry:ui",
|
||||
"dependencies": [
|
||||
"@radix-ui/react-slot"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"path": "ui/badge.tsx",
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
"name": "badge",
|
||||
"type": "registry:ui",
|
||||
"author": "shadcn (https://ui.shadcn.com)",
|
||||
"dependencies": [
|
||||
"@radix-ui/react-slot"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"path": "ui/badge.tsx",
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
},
|
||||
{
|
||||
"path": "blocks/sidebar-16/components/site-header.tsx",
|
||||
"content": "\"use client\"\n\nimport { SidebarIcon } from \"lucide-react\"\n\nimport { SearchForm } from \"@/registry/default/blocks/sidebar-16/components/search-form\"\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\"\nimport { Button } from \"@/registry/default/ui/button\"\nimport { Separator } from \"@/registry/default/ui/separator\"\nimport { useSidebar } from \"@/registry/default/ui/sidebar\"\n\nexport function SiteHeader() {\n const { toggleSidebar } = useSidebar()\n\n return (\n <header className=\"fle sticky top-0 z-50 w-full items-center border-b bg-background\">\n <div className=\"flex h-[--header-height] w-full items-center gap-2 px-4\">\n <Button\n className=\"h-8 w-8\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={toggleSidebar}\n >\n <SidebarIcon />\n </Button>\n <Separator orientation=\"vertical\" className=\"mr-2 h-4\" />\n <Breadcrumb className=\"hidden sm:block\">\n <BreadcrumbList>\n <BreadcrumbItem>\n <BreadcrumbLink href=\"#\">\n Building Your Application\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage>Data Fetching</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n <SearchForm className=\"w-full sm:ml-auto sm:w-auto\" />\n </div>\n </header>\n )\n}\n",
|
||||
"content": "\"use client\"\n\nimport { SidebarIcon } from \"lucide-react\"\n\nimport { SearchForm } from \"@/registry/default/blocks/sidebar-16/components/search-form\"\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\"\nimport { Button } from \"@/registry/default/ui/button\"\nimport { Separator } from \"@/registry/default/ui/separator\"\nimport { useSidebar } from \"@/registry/default/ui/sidebar\"\n\nexport function SiteHeader() {\n const { toggleSidebar } = useSidebar()\n\n return (\n <header className=\"flex sticky top-0 z-50 w-full items-center border-b bg-background\">\n <div className=\"flex h-[--header-height] w-full items-center gap-2 px-4\">\n <Button\n className=\"h-8 w-8\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={toggleSidebar}\n >\n <SidebarIcon />\n </Button>\n <Separator orientation=\"vertical\" className=\"mr-2 h-4\" />\n <Breadcrumb className=\"hidden sm:block\">\n <BreadcrumbList>\n <BreadcrumbItem>\n <BreadcrumbLink href=\"#\">\n Building Your Application\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage>Data Fetching</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n <SearchForm className=\"w-full sm:ml-auto sm:w-auto\" />\n </div>\n </header>\n )\n}\n",
|
||||
"type": "registry:component",
|
||||
"target": ""
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/alert-dialog.tsx",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\"\n\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants } from \"@/registry/new-york-v4/ui/button\"\n\nfunction AlertDialog({\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {\n return <AlertDialogPrimitive.Root data-slot=\"alert-dialog\" {...props} />\n}\n\nfunction AlertDialogTrigger({\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {\n return (\n <AlertDialogPrimitive.Trigger data-slot=\"alert-dialog-trigger\" {...props} />\n )\n}\n\nfunction AlertDialogPortal({\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {\n return (\n <AlertDialogPrimitive.Portal data-slot=\"alert-dialog-portal\" {...props} />\n )\n}\n\nfunction AlertDialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {\n return (\n <AlertDialogPrimitive.Overlay\n data-slot=\"alert-dialog-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogContent({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {\n return (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n data-slot=\"alert-dialog-content\"\n className={cn(\n \"bg-background 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 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg\",\n className\n )}\n {...props}\n />\n </AlertDialogPortal>\n )\n}\n\nfunction AlertDialogHeader({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogFooter({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {\n return (\n <AlertDialogPrimitive.Title\n data-slot=\"alert-dialog-title\"\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {\n return (\n <AlertDialogPrimitive.Description\n data-slot=\"alert-dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogAction({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {\n return (\n <AlertDialogPrimitive.Action\n className={cn(buttonVariants(), className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogCancel({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {\n return (\n <AlertDialogPrimitive.Cancel\n className={cn(buttonVariants({ variant: \"outline\" }), className)}\n {...props}\n />\n )\n}\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n}\n",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\"\n\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants } from \"@/registry/new-york-v4/ui/button\"\n\nfunction AlertDialog({\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {\n return <AlertDialogPrimitive.Root data-slot=\"alert-dialog\" {...props} />\n}\n\nfunction AlertDialogTrigger({\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {\n return (\n <AlertDialogPrimitive.Trigger data-slot=\"alert-dialog-trigger\" {...props} />\n )\n}\n\nfunction AlertDialogPortal({\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {\n return (\n <AlertDialogPrimitive.Portal data-slot=\"alert-dialog-portal\" {...props} />\n )\n}\n\nfunction AlertDialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {\n return (\n <AlertDialogPrimitive.Overlay\n data-slot=\"alert-dialog-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogContent({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {\n return (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n data-slot=\"alert-dialog-content\"\n className={cn(\n \"bg-background 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 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg\",\n className\n )}\n {...props}\n />\n </AlertDialogPortal>\n )\n}\n\nfunction AlertDialogHeader({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogFooter({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {\n return (\n <AlertDialogPrimitive.Title\n data-slot=\"alert-dialog-title\"\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {\n return (\n <AlertDialogPrimitive.Description\n data-slot=\"alert-dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogAction({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {\n return (\n <AlertDialogPrimitive.Action\n className={cn(buttonVariants(), className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogCancel({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {\n return (\n <AlertDialogPrimitive.Cancel\n className={cn(buttonVariants({ variant: \"outline\" }), className)}\n {...props}\n />\n )\n}\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/alert.tsx",
|
||||
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"text-destructive-foreground [&>svg]:text-current *:data-[slot=alert-description]:text-destructive-foreground/80\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Alert({\n className,\n variant,\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof alertVariants>) {\n return (\n <div\n data-slot=\"alert\"\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nfunction AlertTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-title\"\n className={cn(\n \"col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDescription({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-description\"\n className={cn(\n \"text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Alert, AlertTitle, AlertDescription }\n",
|
||||
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current\",\n {\n variants: {\n variant: {\n default: \"bg-card text-card-foreground\",\n destructive:\n \"text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Alert({\n className,\n variant,\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof alertVariants>) {\n return (\n <div\n data-slot=\"alert\"\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nfunction AlertTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-title\"\n className={cn(\n \"col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDescription({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-description\"\n className={cn(\n \"text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Alert, AlertTitle, AlertDescription }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "badge",
|
||||
"type": "registry:ui",
|
||||
"dependencies": [
|
||||
"@radix-ui/react-slot"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/badge.tsx",
|
||||
"content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst badgeVariants = cva(\n \"inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none 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 transition-[color,box-shadow] overflow-hidden\",\n {\n variants: {\n variant: {\n default:\n \"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90\",\n secondary:\n \"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90\",\n destructive:\n \"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40\",\n outline:\n \"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Badge({\n className,\n variant,\n asChild = false,\n ...props\n}: React.ComponentProps<\"span\"> &\n VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot : \"span\"\n\n return (\n <Comp\n data-slot=\"badge\"\n className={cn(badgeVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nexport { Badge, badgeVariants }\n",
|
||||
"content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst badgeVariants = cva(\n \"inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none 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 transition-[color,box-shadow] overflow-hidden\",\n {\n variants: {\n variant: {\n default:\n \"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90\",\n secondary:\n \"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90\",\n destructive:\n \"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/70\",\n outline:\n \"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Badge({\n className,\n variant,\n asChild = false,\n ...props\n}: React.ComponentProps<\"span\"> &\n VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot : \"span\"\n\n return (\n <Comp\n data-slot=\"badge\"\n className={cn(badgeVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nexport { Badge, badgeVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/button.tsx",
|
||||
"content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none 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\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40\",\n outline:\n \"border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none 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\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Card({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card\"\n className={cn(\n \"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\"flex flex-col gap-1.5 px-6\", className)}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-6\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\"flex items-center px-6\", className)}\n {...props}\n />\n )\n}\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Card({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card\"\n className={cn(\n \"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"@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\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-6\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\"flex items-center px-6 [.border-t]:pt-6\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/checkbox.tsx",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\"\nimport { CheckIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Checkbox({\n className,\n ...props\n}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(\n \"peer border-input data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"flex items-center justify-center text-current transition-none\"\n >\n <CheckIcon className=\"size-3.5\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n}\n\nexport { Checkbox }\n",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\"\nimport { CheckIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Checkbox({\n className,\n ...props\n}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(\n \"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"flex items-center justify-center text-current transition-none\"\n >\n <CheckIcon className=\"size-3.5\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n}\n\nexport { Checkbox }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -8,7 +8,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/dialog.tsx",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\"\nimport { XIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Dialog({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />\n}\n\nfunction DialogTrigger({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />\n}\n\nfunction DialogPortal({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />\n}\n\nfunction DialogClose({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content>) {\n return (\n <DialogPortal data-slot=\"dialog-portal\">\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n \"bg-background 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 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg\",\n className\n )}\n {...props}\n >\n {children}\n <DialogPrimitive.Close className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\">\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n </DialogPrimitive.Content>\n </DialogPortal>\n )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-lg leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\"\nimport { XIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Dialog({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />\n}\n\nfunction DialogTrigger({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />\n}\n\nfunction DialogPortal({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />\n}\n\nfunction DialogClose({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content>) {\n return (\n <DialogPortal data-slot=\"dialog-portal\">\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n \"bg-background 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 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg\",\n className\n )}\n {...props}\n >\n {children}\n <DialogPrimitive.Close className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\">\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n </DialogPrimitive.Content>\n </DialogPortal>\n )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-lg leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/drawer.tsx",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Root>) {\n return <DrawerPrimitive.Root data-slot=\"drawer\" {...props} />\n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {\n return <DrawerPrimitive.Trigger data-slot=\"drawer-trigger\" {...props} />\n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Portal>) {\n return <DrawerPrimitive.Portal data-slot=\"drawer-portal\" {...props} />\n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Close>) {\n return <DrawerPrimitive.Close data-slot=\"drawer-close\" {...props} />\n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {\n return (\n <DrawerPrimitive.Overlay\n data-slot=\"drawer-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Content>) {\n return (\n <DrawerPortal data-slot=\"drawer-portal\">\n <DrawerOverlay />\n <DrawerPrimitive.Content\n data-slot=\"drawer-content\"\n className={cn(\n \"group/drawer-content bg-background fixed z-50 flex h-auto flex-col\",\n \"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg\",\n \"data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg\",\n \"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:sm:max-w-sm\",\n \"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:sm:max-w-sm\",\n className\n )}\n {...props}\n >\n <div className=\"bg-muted mx-auto mt-4 hidden h-2 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block\" />\n {children}\n </DrawerPrimitive.Content>\n </DrawerPortal>\n )\n}\n\nfunction DrawerHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"drawer-header\"\n className={cn(\"flex flex-col gap-1.5 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"drawer-footer\"\n className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Title>) {\n return (\n <DrawerPrimitive.Title\n data-slot=\"drawer-title\"\n className={cn(\"text-foreground font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Description>) {\n return (\n <DrawerPrimitive.Description\n data-slot=\"drawer-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Drawer,\n DrawerPortal,\n DrawerOverlay,\n DrawerTrigger,\n DrawerClose,\n DrawerContent,\n DrawerHeader,\n DrawerFooter,\n DrawerTitle,\n DrawerDescription,\n}\n",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Root>) {\n return <DrawerPrimitive.Root data-slot=\"drawer\" {...props} />\n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {\n return <DrawerPrimitive.Trigger data-slot=\"drawer-trigger\" {...props} />\n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Portal>) {\n return <DrawerPrimitive.Portal data-slot=\"drawer-portal\" {...props} />\n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Close>) {\n return <DrawerPrimitive.Close data-slot=\"drawer-close\" {...props} />\n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {\n return (\n <DrawerPrimitive.Overlay\n data-slot=\"drawer-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Content>) {\n return (\n <DrawerPortal data-slot=\"drawer-portal\">\n <DrawerOverlay />\n <DrawerPrimitive.Content\n data-slot=\"drawer-content\"\n className={cn(\n \"group/drawer-content bg-background fixed z-50 flex h-auto flex-col\",\n \"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b\",\n \"data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t\",\n \"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm\",\n \"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm\",\n className\n )}\n {...props}\n >\n <div className=\"bg-muted mx-auto mt-4 hidden h-2 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block\" />\n {children}\n </DrawerPrimitive.Content>\n </DrawerPortal>\n )\n}\n\nfunction DrawerHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"drawer-header\"\n className={cn(\"flex flex-col gap-1.5 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"drawer-footer\"\n className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Title>) {\n return (\n <DrawerPrimitive.Title\n data-slot=\"drawer-title\"\n className={cn(\"text-foreground font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Description>) {\n return (\n <DrawerPrimitive.Description\n data-slot=\"drawer-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Drawer,\n DrawerPortal,\n DrawerOverlay,\n DrawerTrigger,\n DrawerClose,\n DrawerContent,\n DrawerHeader,\n DrawerFooter,\n DrawerTitle,\n DrawerDescription,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -16,7 +16,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/form.tsx",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as LabelPrimitive from \"@radix-ui/react-label\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport {\n Controller,\n FormProvider,\n useFormContext,\n useFormState,\n type ControllerProps,\n type FieldPath,\n type FieldValues,\n} from \"react-hook-form\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Label } from \"@/registry/new-york-v4/ui/label\"\n\nconst Form = FormProvider\n\ntype FormFieldContextValue<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> = {\n name: TName\n}\n\nconst FormFieldContext = React.createContext<FormFieldContextValue>(\n {} as FormFieldContextValue\n)\n\nconst FormField = <\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>({\n ...props\n}: ControllerProps<TFieldValues, TName>) => {\n return (\n <FormFieldContext.Provider value={{ name: props.name }}>\n <Controller {...props} />\n </FormFieldContext.Provider>\n )\n}\n\nconst useFormField = () => {\n const fieldContext = React.useContext(FormFieldContext)\n const itemContext = React.useContext(FormItemContext)\n const { getFieldState } = useFormContext()\n const formState = useFormState({ name: fieldContext.name })\n const fieldState = getFieldState(fieldContext.name, formState)\n\n if (!fieldContext) {\n throw new Error(\"useFormField should be used within <FormField>\")\n }\n\n const { id } = itemContext\n\n return {\n id,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n }\n}\n\ntype FormItemContextValue = {\n id: string\n}\n\nconst FormItemContext = React.createContext<FormItemContextValue>(\n {} as FormItemContextValue\n)\n\nfunction FormItem({ className, ...props }: React.ComponentProps<\"div\">) {\n const id = React.useId()\n\n return (\n <FormItemContext.Provider value={{ id }}>\n <div\n data-slot=\"form-item\"\n className={cn(\"grid gap-2\", className)}\n {...props}\n />\n </FormItemContext.Provider>\n )\n}\n\nfunction FormLabel({\n className,\n ...props\n}: React.ComponentProps<typeof LabelPrimitive.Root>) {\n const { error, formItemId } = useFormField()\n\n return (\n <Label\n data-slot=\"form-label\"\n data-error={!!error}\n className={cn(\"data-[error=true]:text-destructive-foreground\", className)}\n htmlFor={formItemId}\n {...props}\n />\n )\n}\n\nfunction FormControl({ ...props }: React.ComponentProps<typeof Slot>) {\n const { error, formItemId, formDescriptionId, formMessageId } = useFormField()\n\n return (\n <Slot\n data-slot=\"form-control\"\n id={formItemId}\n aria-describedby={\n !error\n ? `${formDescriptionId}`\n : `${formDescriptionId} ${formMessageId}`\n }\n aria-invalid={!!error}\n {...props}\n />\n )\n}\n\nfunction FormDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n const { formDescriptionId } = useFormField()\n\n return (\n <p\n data-slot=\"form-description\"\n id={formDescriptionId}\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction FormMessage({ className, ...props }: React.ComponentProps<\"p\">) {\n const { error, formMessageId } = useFormField()\n const body = error ? String(error?.message ?? \"\") : props.children\n\n if (!body) {\n return null\n }\n\n return (\n <p\n data-slot=\"form-message\"\n id={formMessageId}\n className={cn(\"text-destructive-foreground text-sm\", className)}\n {...props}\n >\n {body}\n </p>\n )\n}\n\nexport {\n useFormField,\n Form,\n FormItem,\n FormLabel,\n FormControl,\n FormDescription,\n FormMessage,\n FormField,\n}\n",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as LabelPrimitive from \"@radix-ui/react-label\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport {\n Controller,\n FormProvider,\n useFormContext,\n useFormState,\n type ControllerProps,\n type FieldPath,\n type FieldValues,\n} from \"react-hook-form\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Label } from \"@/registry/new-york-v4/ui/label\"\n\nconst Form = FormProvider\n\ntype FormFieldContextValue<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> = {\n name: TName\n}\n\nconst FormFieldContext = React.createContext<FormFieldContextValue>(\n {} as FormFieldContextValue\n)\n\nconst FormField = <\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>({\n ...props\n}: ControllerProps<TFieldValues, TName>) => {\n return (\n <FormFieldContext.Provider value={{ name: props.name }}>\n <Controller {...props} />\n </FormFieldContext.Provider>\n )\n}\n\nconst useFormField = () => {\n const fieldContext = React.useContext(FormFieldContext)\n const itemContext = React.useContext(FormItemContext)\n const { getFieldState } = useFormContext()\n const formState = useFormState({ name: fieldContext.name })\n const fieldState = getFieldState(fieldContext.name, formState)\n\n if (!fieldContext) {\n throw new Error(\"useFormField should be used within <FormField>\")\n }\n\n const { id } = itemContext\n\n return {\n id,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n }\n}\n\ntype FormItemContextValue = {\n id: string\n}\n\nconst FormItemContext = React.createContext<FormItemContextValue>(\n {} as FormItemContextValue\n)\n\nfunction FormItem({ className, ...props }: React.ComponentProps<\"div\">) {\n const id = React.useId()\n\n return (\n <FormItemContext.Provider value={{ id }}>\n <div\n data-slot=\"form-item\"\n className={cn(\"grid gap-2\", className)}\n {...props}\n />\n </FormItemContext.Provider>\n )\n}\n\nfunction FormLabel({\n className,\n ...props\n}: React.ComponentProps<typeof LabelPrimitive.Root>) {\n const { error, formItemId } = useFormField()\n\n return (\n <Label\n data-slot=\"form-label\"\n data-error={!!error}\n className={cn(\"data-[error=true]:text-destructive\", className)}\n htmlFor={formItemId}\n {...props}\n />\n )\n}\n\nfunction FormControl({ ...props }: React.ComponentProps<typeof Slot>) {\n const { error, formItemId, formDescriptionId, formMessageId } = useFormField()\n\n return (\n <Slot\n data-slot=\"form-control\"\n id={formItemId}\n aria-describedby={\n !error\n ? `${formDescriptionId}`\n : `${formDescriptionId} ${formMessageId}`\n }\n aria-invalid={!!error}\n {...props}\n />\n )\n}\n\nfunction FormDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n const { formDescriptionId } = useFormField()\n\n return (\n <p\n data-slot=\"form-description\"\n id={formDescriptionId}\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction FormMessage({ className, ...props }: React.ComponentProps<\"p\">) {\n const { error, formMessageId } = useFormField()\n const body = error ? String(error?.message ?? \"\") : props.children\n\n if (!body) {\n return null\n }\n\n return (\n <p\n data-slot=\"form-message\"\n id={formMessageId}\n className={cn(\"text-destructive text-sm\", className)}\n {...props}\n >\n {body}\n </p>\n )\n}\n\nexport {\n useFormField,\n Form,\n FormItem,\n FormLabel,\n FormControl,\n FormDescription,\n FormMessage,\n FormField,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/hover-card.tsx",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as HoverCardPrimitive from \"@radix-ui/react-hover-card\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction HoverCard({\n ...props\n}: React.ComponentProps<typeof HoverCardPrimitive.Root>) {\n return <HoverCardPrimitive.Root data-slot=\"hover-card\" {...props} />\n}\n\nfunction HoverCardTrigger({\n ...props\n}: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {\n return (\n <HoverCardPrimitive.Trigger data-slot=\"hover-card-trigger\" {...props} />\n )\n}\n\nfunction HoverCardContent({\n className,\n align = \"center\",\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof HoverCardPrimitive.Content>) {\n return (\n <HoverCardPrimitive.Content\n data-slot=\"hover-card-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"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 z-50 w-64 rounded-md border p-4 shadow-md outline-hidden\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { HoverCard, HoverCardTrigger, HoverCardContent }\n",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as HoverCardPrimitive from \"@radix-ui/react-hover-card\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction HoverCard({\n ...props\n}: React.ComponentProps<typeof HoverCardPrimitive.Root>) {\n return <HoverCardPrimitive.Root data-slot=\"hover-card\" {...props} />\n}\n\nfunction HoverCardTrigger({\n ...props\n}: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {\n return (\n <HoverCardPrimitive.Trigger data-slot=\"hover-card-trigger\" {...props} />\n )\n}\n\nfunction HoverCardContent({\n className,\n align = \"center\",\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof HoverCardPrimitive.Content>) {\n return (\n <HoverCardPrimitive.Portal data-slot=\"hover-card-portal\">\n <HoverCardPrimitive.Content\n data-slot=\"hover-card-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"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 z-50 w-64 rounded-md border p-4 shadow-md outline-hidden\",\n className\n )}\n {...props}\n />\n </HoverCardPrimitive.Portal>\n )\n}\n\nexport { HoverCard, HoverCardTrigger, HoverCardContent }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/input-otp.tsx",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport { OTPInput, OTPInputContext } from \"input-otp\"\nimport { MinusIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction InputOTP({\n className,\n containerClassName,\n ...props\n}: React.ComponentProps<typeof OTPInput> & {\n containerClassName?: string\n}) {\n return (\n <OTPInput\n data-slot=\"input-otp\"\n containerClassName={cn(\n \"flex items-center gap-2 has-disabled:opacity-50\",\n containerClassName\n )}\n className={cn(\"disabled:cursor-not-allowed\", className)}\n {...props}\n />\n )\n}\n\nfunction InputOTPGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"input-otp-group\"\n className={cn(\"flex items-center\", className)}\n {...props}\n />\n )\n}\n\nfunction InputOTPSlot({\n index,\n className,\n ...props\n}: React.ComponentProps<\"div\"> & {\n index: number\n}) {\n const inputOTPContext = React.useContext(OTPInputContext)\n const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {}\n\n return (\n <div\n data-slot=\"input-otp-slot\"\n data-active={isActive}\n className={cn(\n \"border-input data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive relative flex h-9 w-9 items-center justify-center border-y border-r text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10 data-[active=true]:ring-[3px]\",\n className\n )}\n {...props}\n >\n {char}\n {hasFakeCaret && (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"animate-caret-blink bg-foreground h-4 w-px duration-1000\" />\n </div>\n )}\n </div>\n )\n}\n\nfunction InputOTPSeparator({ ...props }: React.ComponentProps<\"div\">) {\n return (\n <div data-slot=\"input-otp-separator\" role=\"separator\" {...props}>\n <MinusIcon />\n </div>\n )\n}\n\nexport { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }\n",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport { OTPInput, OTPInputContext } from \"input-otp\"\nimport { MinusIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction InputOTP({\n className,\n containerClassName,\n ...props\n}: React.ComponentProps<typeof OTPInput> & {\n containerClassName?: string\n}) {\n return (\n <OTPInput\n data-slot=\"input-otp\"\n containerClassName={cn(\n \"flex items-center gap-2 has-disabled:opacity-50\",\n containerClassName\n )}\n className={cn(\"disabled:cursor-not-allowed\", className)}\n {...props}\n />\n )\n}\n\nfunction InputOTPGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"input-otp-group\"\n className={cn(\"flex items-center\", className)}\n {...props}\n />\n )\n}\n\nfunction InputOTPSlot({\n index,\n className,\n ...props\n}: React.ComponentProps<\"div\"> & {\n index: number\n}) {\n const inputOTPContext = React.useContext(OTPInputContext)\n const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {}\n\n return (\n <div\n data-slot=\"input-otp-slot\"\n data-active={isActive}\n className={cn(\n \"data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive dark:bg-input/30 border-input relative flex h-9 w-9 items-center justify-center border-y border-r text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10 data-[active=true]:ring-[3px]\",\n className\n )}\n {...props}\n >\n {char}\n {hasFakeCaret && (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"animate-caret-blink bg-foreground h-4 w-px duration-1000\" />\n </div>\n )}\n </div>\n )\n}\n\nfunction InputOTPSeparator({ ...props }: React.ComponentProps<\"div\">) {\n return (\n <div data-slot=\"input-otp-separator\" role=\"separator\" {...props}>\n <MinusIcon />\n </div>\n )\n}\n\nexport { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/input.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n \"border-input file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground 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\",\n \"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n \"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Input }\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n \"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\",\n \"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n \"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Input }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
},
|
||||
{
|
||||
"path": "registry/new-york-v4/blocks/login-03/components/login-form.tsx",
|
||||
"content": "import { cn } from \"@/registry/new-york-v4/lib/utils\"\nimport { Button } from \"@/registry/new-york-v4/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport { Input } from \"@/registry/new-york-v4/ui/input\"\nimport { Label } from \"@/registry/new-york-v4/ui/label\"\n\nexport function LoginForm({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div className={cn(\"flex flex-col gap-6\", className)} {...props}>\n <Card>\n <CardHeader className=\"text-center\">\n <CardTitle className=\"text-xl\">Welcome back</CardTitle>\n <CardDescription>\n Login with your Apple or Google account\n </CardDescription>\n </CardHeader>\n <CardContent>\n <form>\n <div className=\"grid gap-6\">\n <div className=\"flex flex-col gap-4\">\n <Button variant=\"outline\" className=\"w-full\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n <path\n d=\"M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701\"\n fill=\"currentColor\"\n />\n </svg>\n Login with Apple\n </Button>\n <Button variant=\"outline\" className=\"w-full\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n <path\n d=\"M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z\"\n fill=\"currentColor\"\n />\n </svg>\n Login with Google\n </Button>\n </div>\n <div className=\"after:border-border relative text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t\">\n <span className=\"bg-background text-muted-foreground relative z-10 px-2\">\n Or continue with\n </span>\n </div>\n <div className=\"grid gap-6\">\n <div className=\"grid gap-3\">\n <Label htmlFor=\"email\">Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n placeholder=\"m@example.com\"\n required\n />\n </div>\n <div className=\"grid gap-3\">\n <div className=\"flex items-center\">\n <Label htmlFor=\"password\">Password</Label>\n <a\n href=\"#\"\n className=\"ml-auto text-sm underline-offset-4 hover:underline\"\n >\n Forgot your password?\n </a>\n </div>\n <Input id=\"password\" type=\"password\" required />\n </div>\n <Button type=\"submit\" className=\"w-full\">\n Login\n </Button>\n </div>\n <div className=\"text-center text-sm\">\n Don't have an account?{\" \"}\n <a href=\"#\" className=\"underline underline-offset-4\">\n Sign up\n </a>\n </div>\n </div>\n </form>\n </CardContent>\n </Card>\n <div className=\"text-muted-foreground *:[a]:hover:text-primary text-center text-xs text-balance *:[a]:underline *:[a]:underline-offset-4\">\n By clicking continue, you agree to our <a href=\"#\">Terms of Service</a>{\" \"}\n and <a href=\"#\">Privacy Policy</a>.\n </div>\n </div>\n )\n}\n",
|
||||
"content": "import { cn } from \"@/registry/new-york-v4/lib/utils\"\nimport { Button } from \"@/registry/new-york-v4/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport { Input } from \"@/registry/new-york-v4/ui/input\"\nimport { Label } from \"@/registry/new-york-v4/ui/label\"\n\nexport function LoginForm({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div className={cn(\"flex flex-col gap-6\", className)} {...props}>\n <Card>\n <CardHeader className=\"text-center\">\n <CardTitle className=\"text-xl\">Welcome back</CardTitle>\n <CardDescription>\n Login with your Apple or Google account\n </CardDescription>\n </CardHeader>\n <CardContent>\n <form>\n <div className=\"grid gap-6\">\n <div className=\"flex flex-col gap-4\">\n <Button variant=\"outline\" className=\"w-full\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n <path\n d=\"M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701\"\n fill=\"currentColor\"\n />\n </svg>\n Login with Apple\n </Button>\n <Button variant=\"outline\" className=\"w-full\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n <path\n d=\"M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z\"\n fill=\"currentColor\"\n />\n </svg>\n Login with Google\n </Button>\n </div>\n <div className=\"after:border-border relative text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t\">\n <span className=\"bg-card text-muted-foreground relative z-10 px-2\">\n Or continue with\n </span>\n </div>\n <div className=\"grid gap-6\">\n <div className=\"grid gap-3\">\n <Label htmlFor=\"email\">Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n placeholder=\"m@example.com\"\n required\n />\n </div>\n <div className=\"grid gap-3\">\n <div className=\"flex items-center\">\n <Label htmlFor=\"password\">Password</Label>\n <a\n href=\"#\"\n className=\"ml-auto text-sm underline-offset-4 hover:underline\"\n >\n Forgot your password?\n </a>\n </div>\n <Input id=\"password\" type=\"password\" required />\n </div>\n <Button type=\"submit\" className=\"w-full\">\n Login\n </Button>\n </div>\n <div className=\"text-center text-sm\">\n Don't have an account?{\" \"}\n <a href=\"#\" className=\"underline underline-offset-4\">\n Sign up\n </a>\n </div>\n </div>\n </form>\n </CardContent>\n </Card>\n <div className=\"text-muted-foreground *:[a]:hover:text-primary text-center text-xs text-balance *:[a]:underline *:[a]:underline-offset-4\">\n By clicking continue, you agree to our <a href=\"#\">Terms of Service</a>{\" \"}\n and <a href=\"#\">Privacy Policy</a>.\n </div>\n </div>\n )\n}\n",
|
||||
"type": "registry:component"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -8,7 +8,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/radio-group.tsx",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RadioGroupPrimitive from \"@radix-ui/react-radio-group\"\nimport { CircleIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction RadioGroup({\n className,\n ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {\n return (\n <RadioGroupPrimitive.Root\n data-slot=\"radio-group\"\n className={cn(\"grid gap-3\", className)}\n {...props}\n />\n )\n}\n\nfunction RadioGroupItem({\n className,\n ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {\n return (\n <RadioGroupPrimitive.Item\n data-slot=\"radio-group-item\"\n className={cn(\n \"border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator\n data-slot=\"radio-group-indicator\"\n className=\"relative flex items-center justify-center\"\n >\n <CircleIcon className=\"fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2\" />\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n )\n}\n\nexport { RadioGroup, RadioGroupItem }\n",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RadioGroupPrimitive from \"@radix-ui/react-radio-group\"\nimport { CircleIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction RadioGroup({\n className,\n ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {\n return (\n <RadioGroupPrimitive.Root\n data-slot=\"radio-group\"\n className={cn(\"grid gap-3\", className)}\n {...props}\n />\n )\n}\n\nfunction RadioGroupItem({\n className,\n ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {\n return (\n <RadioGroupPrimitive.Item\n data-slot=\"radio-group-item\"\n className={cn(\n \"border-input text-primary 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 aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator\n data-slot=\"radio-group-indicator\"\n className=\"relative flex items-center justify-center\"\n >\n <CircleIcon className=\"fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2\" />\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n )\n}\n\nexport { RadioGroup, RadioGroupItem }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -8,7 +8,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/sheet.tsx",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as SheetPrimitive from \"@radix-ui/react-dialog\"\nimport { XIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {\n return <SheetPrimitive.Root data-slot=\"sheet\" {...props} />\n}\n\nfunction SheetTrigger({\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {\n return <SheetPrimitive.Trigger data-slot=\"sheet-trigger\" {...props} />\n}\n\nfunction SheetClose({\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Close>) {\n return <SheetPrimitive.Close data-slot=\"sheet-close\" {...props} />\n}\n\nfunction SheetPortal({\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Portal>) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />\n}\n\nfunction SheetOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Overlay>) {\n return (\n <SheetPrimitive.Overlay\n data-slot=\"sheet-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SheetContent({\n className,\n children,\n side = \"right\",\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Content> & {\n side?: \"top\" | \"right\" | \"bottom\" | \"left\"\n}) {\n return (\n <SheetPortal>\n <SheetOverlay />\n <SheetPrimitive.Content\n data-slot=\"sheet-content\"\n className={cn(\n \"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500\",\n side === \"right\" &&\n \"data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm\",\n side === \"left\" &&\n \"data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm\",\n side === \"top\" &&\n \"data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b\",\n side === \"bottom\" &&\n \"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t\",\n className\n )}\n {...props}\n >\n {children}\n <SheetPrimitive.Close className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none\">\n <XIcon className=\"size-4\" />\n <span className=\"sr-only\">Close</span>\n </SheetPrimitive.Close>\n </SheetPrimitive.Content>\n </SheetPortal>\n )\n}\n\nfunction SheetHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-header\"\n className={cn(\"flex flex-col gap-1.5 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-footer\"\n className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetTitle({\n className,\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Title>) {\n return (\n <SheetPrimitive.Title\n data-slot=\"sheet-title\"\n className={cn(\"text-foreground font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetDescription({\n className,\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Description>) {\n return (\n <SheetPrimitive.Description\n data-slot=\"sheet-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Sheet,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n}\n",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as SheetPrimitive from \"@radix-ui/react-dialog\"\nimport { XIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {\n return <SheetPrimitive.Root data-slot=\"sheet\" {...props} />\n}\n\nfunction SheetTrigger({\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {\n return <SheetPrimitive.Trigger data-slot=\"sheet-trigger\" {...props} />\n}\n\nfunction SheetClose({\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Close>) {\n return <SheetPrimitive.Close data-slot=\"sheet-close\" {...props} />\n}\n\nfunction SheetPortal({\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Portal>) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />\n}\n\nfunction SheetOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Overlay>) {\n return (\n <SheetPrimitive.Overlay\n data-slot=\"sheet-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SheetContent({\n className,\n children,\n side = \"right\",\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Content> & {\n side?: \"top\" | \"right\" | \"bottom\" | \"left\"\n}) {\n return (\n <SheetPortal>\n <SheetOverlay />\n <SheetPrimitive.Content\n data-slot=\"sheet-content\"\n className={cn(\n \"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500\",\n side === \"right\" &&\n \"data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm\",\n side === \"left\" &&\n \"data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm\",\n side === \"top\" &&\n \"data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b\",\n side === \"bottom\" &&\n \"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t\",\n className\n )}\n {...props}\n >\n {children}\n <SheetPrimitive.Close className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none\">\n <XIcon className=\"size-4\" />\n <span className=\"sr-only\">Close</span>\n </SheetPrimitive.Close>\n </SheetPrimitive.Content>\n </SheetPortal>\n )\n}\n\nfunction SheetHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-header\"\n className={cn(\"flex flex-col gap-1.5 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-footer\"\n className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetTitle({\n className,\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Title>) {\n return (\n <SheetPrimitive.Title\n data-slot=\"sheet-title\"\n className={cn(\"text-foreground font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetDescription({\n className,\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Description>) {\n return (\n <SheetPrimitive.Description\n data-slot=\"sheet-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Sheet,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
},
|
||||
{
|
||||
"path": "registry/new-york-v4/blocks/sidebar-07/components/team-switcher.tsx",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport { ChevronsUpDown, Plus } from \"lucide-react\"\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuTrigger,\n} from \"@/registry/new-york-v4/ui/dropdown-menu\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/registry/new-york-v4/ui/sidebar\"\n\nexport function TeamSwitcher({\n teams,\n}: {\n teams: {\n name: string\n logo: React.ElementType\n plan: string\n }[]\n}) {\n const { isMobile } = useSidebar()\n const [activeTeam, setActiveTeam] = React.useState(teams[0])\n\n if (!activeTeam) {\n return null\n }\n\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <SidebarMenuButton\n size=\"lg\"\n className=\"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground\"\n >\n <div className=\"bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg\">\n <activeTeam.logo className=\"size-4\" />\n </div>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">{activeTeam.name}</span>\n <span className=\"truncate text-xs\">{activeTeam.plan}</span>\n </div>\n <ChevronsUpDown className=\"ml-auto\" />\n </SidebarMenuButton>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg\"\n align=\"start\"\n side={isMobile ? \"bottom\" : \"right\"}\n sideOffset={4}\n >\n <DropdownMenuLabel className=\"text-muted-foreground text-xs\">\n Teams\n </DropdownMenuLabel>\n {teams.map((team, index) => (\n <DropdownMenuItem\n key={team.name}\n onClick={() => setActiveTeam(team)}\n className=\"gap-2 p-2\"\n >\n <div className=\"flex size-6 items-center justify-center rounded-xs border\">\n <team.logo className=\"size-4 shrink-0\" />\n </div>\n {team.name}\n <DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>\n </DropdownMenuItem>\n ))}\n <DropdownMenuSeparator />\n <DropdownMenuItem className=\"gap-2 p-2\">\n <div className=\"bg-background flex size-6 items-center justify-center rounded-md border\">\n <Plus className=\"size-4\" />\n </div>\n <div className=\"text-muted-foreground font-medium\">Add team</div>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport { ChevronsUpDown, Plus } from \"lucide-react\"\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuTrigger,\n} from \"@/registry/new-york-v4/ui/dropdown-menu\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/registry/new-york-v4/ui/sidebar\"\n\nexport function TeamSwitcher({\n teams,\n}: {\n teams: {\n name: string\n logo: React.ElementType\n plan: string\n }[]\n}) {\n const { isMobile } = useSidebar()\n const [activeTeam, setActiveTeam] = React.useState(teams[0])\n\n if (!activeTeam) {\n return null\n }\n\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <SidebarMenuButton\n size=\"lg\"\n className=\"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground\"\n >\n <div className=\"bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg\">\n <activeTeam.logo className=\"size-4\" />\n </div>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">{activeTeam.name}</span>\n <span className=\"truncate text-xs\">{activeTeam.plan}</span>\n </div>\n <ChevronsUpDown className=\"ml-auto\" />\n </SidebarMenuButton>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg\"\n align=\"start\"\n side={isMobile ? \"bottom\" : \"right\"}\n sideOffset={4}\n >\n <DropdownMenuLabel className=\"text-muted-foreground text-xs\">\n Teams\n </DropdownMenuLabel>\n {teams.map((team, index) => (\n <DropdownMenuItem\n key={team.name}\n onClick={() => setActiveTeam(team)}\n className=\"gap-2 p-2\"\n >\n <div className=\"flex size-6 items-center justify-center rounded-md border\">\n <team.logo className=\"size-3.5 shrink-0\" />\n </div>\n {team.name}\n <DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>\n </DropdownMenuItem>\n ))}\n <DropdownMenuSeparator />\n <DropdownMenuItem className=\"gap-2 p-2\">\n <div className=\"flex size-6 items-center justify-center rounded-md border bg-transparent\">\n <Plus className=\"size-4\" />\n </div>\n <div className=\"text-muted-foreground font-medium\">Add team</div>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n",
|
||||
"type": "registry:component"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -5,7 +5,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/skeleton.tsx",
|
||||
"content": "import { cn } from \"@/lib/utils\"\n\nfunction Skeleton({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"skeleton\"\n className={cn(\"bg-primary/10 animate-pulse rounded-md\", className)}\n {...props}\n />\n )\n}\n\nexport { Skeleton }\n",
|
||||
"content": "import { cn } from \"@/lib/utils\"\n\nfunction Skeleton({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"skeleton\"\n className={cn(\"bg-accent animate-pulse rounded-md\", className)}\n {...props}\n />\n )\n}\n\nexport { Skeleton }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/sonner.tsx",
|
||||
"content": "\"use client\"\n\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner, ToasterProps } from \"sonner\"\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n const { theme = \"system\" } = useTheme()\n\n return (\n <Sonner\n theme={theme as ToasterProps[\"theme\"]}\n className=\"toaster group\"\n toastOptions={{\n classNames: {\n toast:\n \"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg\",\n description: \"group-[.toast]:text-muted-foreground\",\n actionButton:\n \"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground font-medium\",\n cancelButton:\n \"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground font-medium\",\n },\n }}\n {...props}\n />\n )\n}\n\nexport { Toaster }\n",
|
||||
"content": "\"use client\"\n\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner, ToasterProps } from \"sonner\"\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n const { theme = \"system\" } = useTheme()\n\n return (\n <Sonner\n theme={theme as ToasterProps[\"theme\"]}\n className=\"toaster group\"\n style={\n {\n \"--normal-bg\": \"var(--popover)\",\n \"--normal-text\": \"var(--popover-foreground)\",\n \"--normal-border\": \"var(--border)\",\n } as React.CSSProperties\n }\n {...props}\n />\n )\n}\n\nexport { Toaster }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/switch.tsx",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as SwitchPrimitive from \"@radix-ui/react-switch\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Switch({\n className,\n ...props\n}: React.ComponentProps<typeof SwitchPrimitive.Root>) {\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n className={cn(\n \"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 inline-flex h-5 w-9 shrink-0 items-center rounded-full border-2 border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n \"bg-background pointer-events-none block size-4 rounded-full ring-0 shadow-lg transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0\"\n )}\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\n",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as SwitchPrimitive from \"@radix-ui/react-switch\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Switch({\n className,\n ...props\n}: React.ComponentProps<typeof SwitchPrimitive.Root>) {\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n className={cn(\n \"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n \"bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0\"\n )}\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/tabs.tsx",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as TabsPrimitive from \"@radix-ui/react-tabs\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Tabs({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Root>) {\n return (\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n className={cn(\"flex flex-col gap-2\", className)}\n {...props}\n />\n )\n}\n\nfunction TabsList({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.List>) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n className={cn(\n \"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-1\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TabsTrigger({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n \"data-[state=active]:bg-background data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring inline-flex flex-1 items-center justify-center gap-1.5 rounded-md px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TabsContent({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Content>) {\n return (\n <TabsPrimitive.Content\n data-slot=\"tabs-content\"\n className={cn(\"flex-1 outline-none\", className)}\n {...props}\n />\n )\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent }\n",
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as TabsPrimitive from \"@radix-ui/react-tabs\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Tabs({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Root>) {\n return (\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n className={cn(\"flex flex-col gap-2\", className)}\n {...props}\n />\n )\n}\n\nfunction TabsList({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.List>) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n className={cn(\n \"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TabsTrigger({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n \"data-[state=active]:bg-background data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/50 inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TabsContent({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Content>) {\n return (\n <TabsPrimitive.Content\n data-slot=\"tabs-content\"\n className={cn(\"flex-1 outline-none\", className)}\n {...props}\n />\n )\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/textarea.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n \"border-input placeholder: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 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Textarea }\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n \"border-input placeholder: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 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Textarea }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
"name": "badge",
|
||||
"type": "registry:ui",
|
||||
"author": "shadcn (https://ui.shadcn.com)",
|
||||
"dependencies": [
|
||||
"@radix-ui/react-slot"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"path": "ui/badge.tsx",
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
},
|
||||
{
|
||||
"path": "blocks/sidebar-16/components/site-header.tsx",
|
||||
"content": "\"use client\"\n\nimport { SidebarIcon } from \"lucide-react\"\n\nimport { SearchForm } from \"@/registry/new-york/blocks/sidebar-16/components/search-form\"\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/new-york/ui/breadcrumb\"\nimport { Button } from \"@/registry/new-york/ui/button\"\nimport { Separator } from \"@/registry/new-york/ui/separator\"\nimport { useSidebar } from \"@/registry/new-york/ui/sidebar\"\n\nexport function SiteHeader() {\n const { toggleSidebar } = useSidebar()\n\n return (\n <header className=\"fle sticky top-0 z-50 w-full items-center border-b bg-background\">\n <div className=\"flex h-[--header-height] w-full items-center gap-2 px-4\">\n <Button\n className=\"h-8 w-8\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={toggleSidebar}\n >\n <SidebarIcon />\n </Button>\n <Separator orientation=\"vertical\" className=\"mr-2 h-4\" />\n <Breadcrumb className=\"hidden sm:block\">\n <BreadcrumbList>\n <BreadcrumbItem>\n <BreadcrumbLink href=\"#\">\n Building Your Application\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage>Data Fetching</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n <SearchForm className=\"w-full sm:ml-auto sm:w-auto\" />\n </div>\n </header>\n )\n}\n",
|
||||
"content": "\"use client\"\n\nimport { SidebarIcon } from \"lucide-react\"\n\nimport { SearchForm } from \"@/registry/new-york/blocks/sidebar-16/components/search-form\"\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/new-york/ui/breadcrumb\"\nimport { Button } from \"@/registry/new-york/ui/button\"\nimport { Separator } from \"@/registry/new-york/ui/separator\"\nimport { useSidebar } from \"@/registry/new-york/ui/sidebar\"\n\nexport function SiteHeader() {\n const { toggleSidebar } = useSidebar()\n\n return (\n <header className=\"flex sticky top-0 z-50 w-full items-center border-b bg-background\">\n <div className=\"flex h-[--header-height] w-full items-center gap-2 px-4\">\n <Button\n className=\"h-8 w-8\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={toggleSidebar}\n >\n <SidebarIcon />\n </Button>\n <Separator orientation=\"vertical\" className=\"mr-2 h-4\" />\n <Breadcrumb className=\"hidden sm:block\">\n <BreadcrumbList>\n <BreadcrumbItem>\n <BreadcrumbLink href=\"#\">\n Building Your Application\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage>Data Fetching</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n <SearchForm className=\"w-full sm:ml-auto sm:w-auto\" />\n </div>\n </header>\n )\n}\n",
|
||||
"type": "registry:component",
|
||||
"target": ""
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ export function SiteHeader() {
|
||||
const { toggleSidebar } = useSidebar()
|
||||
|
||||
return (
|
||||
<header className="fle sticky top-0 z-50 w-full items-center border-b bg-background">
|
||||
<header className="flex sticky top-0 z-50 w-full items-center border-b bg-background">
|
||||
<div className="flex h-[--header-height] w-full items-center gap-2 px-4">
|
||||
<Button
|
||||
className="h-8 w-8"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user