mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-11 09:51:40 +00:00
feat: rhea (#10779)
* feat: add rhea * fix: blocks * feat: build chat example * fix * fix: sidebar * fix * feat: update home * fix * fix * fix * feat: optimizine fonts * feat * fix * fix * fix * fix * fix * fix * fix: font in preview * fix
This commit is contained in:
5
.changeset/silent-crabs-bow.md
Normal file
5
.changeset/silent-crabs-bow.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"shadcn": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
add style rhea
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -43,5 +43,6 @@ tsconfig.tsbuildinfo
|
|||||||
|
|
||||||
.notes
|
.notes
|
||||||
.playwright-mcp
|
.playwright-mcp
|
||||||
|
.playwright-cli
|
||||||
shadcn-workspace
|
shadcn-workspace
|
||||||
.codex-artifacts
|
.codex-artifacts
|
||||||
|
|||||||
94
apps/v4/app/(app)/(root)/cards/account-access.tsx
Normal file
94
apps/v4/app/(app)/(root)/cards/account-access.tsx
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import {
|
||||||
|
AlertCircleIcon,
|
||||||
|
ArrowRight01Icon,
|
||||||
|
SquareLock02Icon,
|
||||||
|
} from "@hugeicons/core-free-icons"
|
||||||
|
import { HugeiconsIcon } from "@hugeicons/react"
|
||||||
|
|
||||||
|
import { Button } from "@/styles/base-rhea/ui/button"
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Field, FieldGroup, FieldLabel } from "@/styles/base-rhea/ui/field"
|
||||||
|
import { Input } from "@/styles/base-rhea/ui/input"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/item"
|
||||||
|
|
||||||
|
export function AccountAccess() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Account Access</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Update your credentials or re-authenticate.
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<FieldGroup>
|
||||||
|
<Field>
|
||||||
|
<FieldLabel htmlFor="email-address">Email Address</FieldLabel>
|
||||||
|
<Input
|
||||||
|
id="email-address"
|
||||||
|
type="email"
|
||||||
|
placeholder="artist@studio.inc"
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
<Field>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<FieldLabel htmlFor="current-password">
|
||||||
|
Current Password
|
||||||
|
</FieldLabel>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
className="text-xs font-medium tracking-wider text-muted-foreground uppercase hover:text-foreground"
|
||||||
|
>
|
||||||
|
Forgot?
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<Input
|
||||||
|
id="current-password"
|
||||||
|
type="password"
|
||||||
|
placeholder="••••••••••••••••••••••••"
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
</FieldGroup>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter className="flex-col gap-4">
|
||||||
|
<Button className="w-full">
|
||||||
|
<HugeiconsIcon icon={SquareLock02Icon} strokeWidth={2} />
|
||||||
|
Update Security
|
||||||
|
</Button>
|
||||||
|
<Item variant="muted" render={<a href="#" />}>
|
||||||
|
<ItemMedia variant="icon">
|
||||||
|
<HugeiconsIcon
|
||||||
|
icon={AlertCircleIcon}
|
||||||
|
className="text-destructive"
|
||||||
|
strokeWidth={2}
|
||||||
|
/>
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>Danger Zone</ItemTitle>
|
||||||
|
<ItemDescription className="line-clamp-1">
|
||||||
|
Archive account and remove catalog
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
<HugeiconsIcon
|
||||||
|
icon={ArrowRight01Icon}
|
||||||
|
className="size-4"
|
||||||
|
strokeWidth={2}
|
||||||
|
/>
|
||||||
|
</Item>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
46
apps/v4/app/(app)/(root)/cards/analytics-card.tsx
Normal file
46
apps/v4/app/(app)/(root)/cards/analytics-card.tsx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { Badge } from "@/styles/base-rhea/ui/badge"
|
||||||
|
import { Button } from "@/styles/base-rhea/ui/button"
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardAction,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
|
||||||
|
const areaPath = "M0 52L18 40L36 46L54 70L72 50L100 49V86H0Z"
|
||||||
|
const strokePath = "M0 52L18 40L36 46L54 70L72 50L100 49"
|
||||||
|
|
||||||
|
export function AnalyticsCard() {
|
||||||
|
return (
|
||||||
|
<Card className="mx-auto w-full max-w-sm data-[size=sm]:pb-0" size="sm">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Analytics</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
418.2K Visitors <Badge>+10%</Badge>
|
||||||
|
</CardDescription>
|
||||||
|
<CardAction>
|
||||||
|
<Button variant="outline" size="sm">
|
||||||
|
View Analytics
|
||||||
|
</Button>
|
||||||
|
</CardAction>
|
||||||
|
</CardHeader>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 100 86"
|
||||||
|
preserveAspectRatio="none"
|
||||||
|
className="aspect-[1/0.35] w-full text-chart-1"
|
||||||
|
role="img"
|
||||||
|
aria-label="Visitor trend"
|
||||||
|
>
|
||||||
|
<path d={areaPath} fill="currentColor" opacity="0.28" />
|
||||||
|
<path
|
||||||
|
d={strokePath}
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1.5"
|
||||||
|
vectorEffect="non-scaling-stroke"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
75
apps/v4/app/(app)/(root)/cards/claimable-balance.tsx
Normal file
75
apps/v4/app/(app)/(root)/cards/claimable-balance.tsx
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import { Badge } from "@/styles/base-rhea/ui/badge"
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Item, ItemContent } from "@/styles/base-rhea/ui/item"
|
||||||
|
import { Separator } from "@/styles/base-rhea/ui/separator"
|
||||||
|
|
||||||
|
const netRoyalties = 1248.75
|
||||||
|
const processingFee = 37.46
|
||||||
|
const totalClaimable = netRoyalties - processingFee
|
||||||
|
|
||||||
|
const formatCurrency = (amount: number) =>
|
||||||
|
amount.toLocaleString("en-US", {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
export function ClaimableBalance() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardDescription>Claimable Balance</CardDescription>
|
||||||
|
<CardTitle className="text-4xl tabular-nums">
|
||||||
|
${formatCurrency(totalClaimable)}
|
||||||
|
</CardTitle>
|
||||||
|
<Badge variant="outline">
|
||||||
|
<span className="size-2 rounded-full bg-yellow-500" />
|
||||||
|
Pending Setup
|
||||||
|
</Badge>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex flex-1 flex-col justify-end">
|
||||||
|
<Item variant="muted" className="flex-col items-stretch">
|
||||||
|
<ItemContent className="gap-3">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-sm text-muted-foreground">
|
||||||
|
Net Royalties
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium tabular-nums">
|
||||||
|
${formatCurrency(netRoyalties)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-sm text-muted-foreground">
|
||||||
|
Processing Fee
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium tabular-nums">
|
||||||
|
-${formatCurrency(processingFee)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<Separator />
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-sm text-muted-foreground">
|
||||||
|
Total Ready to Claim
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-semibold tabular-nums">
|
||||||
|
${formatCurrency(totalClaimable)} USD
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<CardDescription>
|
||||||
|
Once your bank is connected, balances over $10.00 are automatically
|
||||||
|
eligible for monthly distribution on the 15th of each month.
|
||||||
|
</CardDescription>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
88
apps/v4/app/(app)/(root)/cards/contribution-history.tsx
Normal file
88
apps/v4/app/(app)/(root)/cards/contribution-history.tsx
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import { Badge } from "@/styles/base-rhea/ui/badge"
|
||||||
|
import { Button } from "@/styles/base-rhea/ui/button"
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardAction,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Item, ItemContent, ItemDescription } from "@/styles/base-rhea/ui/item"
|
||||||
|
|
||||||
|
const chartData = [
|
||||||
|
{ month: "Dec", amount: 800 },
|
||||||
|
{ month: "Jan", amount: 1100 },
|
||||||
|
{ month: "Feb", amount: 900 },
|
||||||
|
{ month: "Mar", amount: 1300 },
|
||||||
|
{ month: "Apr", amount: 750 },
|
||||||
|
{ month: "May", amount: 1400 },
|
||||||
|
]
|
||||||
|
|
||||||
|
export function ContributionHistory() {
|
||||||
|
const maxAmount = Math.max(...chartData.map((item) => item.amount))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Contribution History</CardTitle>
|
||||||
|
<CardDescription>Last 6 months of activity</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div
|
||||||
|
className="flex h-[200px] w-full items-end gap-3"
|
||||||
|
role="img"
|
||||||
|
aria-label="Last 6 months of contribution activity"
|
||||||
|
>
|
||||||
|
{chartData.map((item) => (
|
||||||
|
<div
|
||||||
|
key={item.month}
|
||||||
|
className="flex h-full flex-1 flex-col justify-end gap-2"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="min-h-2 rounded-t-md bg-chart-2"
|
||||||
|
style={{ height: `${(item.amount / maxAmount) * 100}%` }}
|
||||||
|
/>
|
||||||
|
<span className="text-center text-xs text-muted-foreground">
|
||||||
|
{item.month}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardContent>
|
||||||
|
<div className="grid w-full grid-cols-1 gap-3 xl:grid-cols-2">
|
||||||
|
<Item variant="muted" className="flex-col items-stretch">
|
||||||
|
<ItemContent className="gap-1">
|
||||||
|
<ItemDescription className="text-xs font-medium tracking-wider text-muted-foreground uppercase">
|
||||||
|
Upcoming
|
||||||
|
</ItemDescription>
|
||||||
|
<span className="cn-font-heading text-base font-semibold">
|
||||||
|
May 2024
|
||||||
|
</span>
|
||||||
|
<span className="text-sm text-muted-foreground">Scheduled</span>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
<Item
|
||||||
|
variant="muted"
|
||||||
|
className="hidden flex-col items-stretch xl:flex"
|
||||||
|
>
|
||||||
|
<ItemContent className="gap-1">
|
||||||
|
<ItemDescription className="text-xs font-medium tracking-wider text-muted-foreground uppercase">
|
||||||
|
Savings Plan
|
||||||
|
</ItemDescription>
|
||||||
|
<span className="cn-font-heading text-base font-semibold">
|
||||||
|
Accelerated
|
||||||
|
</span>
|
||||||
|
<span className="text-sm text-muted-foreground">Recurring</span>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<Button className="w-full">View Full Report</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
116
apps/v4/app/(app)/(root)/cards/dividend-income.tsx
Normal file
116
apps/v4/app/(app)/(root)/cards/dividend-income.tsx
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
import { Cancel01Icon } from "@hugeicons/core-free-icons"
|
||||||
|
import { HugeiconsIcon } from "@hugeicons/react"
|
||||||
|
|
||||||
|
import { Button } from "@/styles/base-rhea/ui/button"
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardAction,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemGroup,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/item"
|
||||||
|
|
||||||
|
const HOLDINGS = [
|
||||||
|
{
|
||||||
|
name: "Vanguard",
|
||||||
|
shares: "450 Shares",
|
||||||
|
amount: "$1,842.10",
|
||||||
|
data: [
|
||||||
|
{ q: "Q1", value: 380 },
|
||||||
|
{ q: "Q2", value: 420 },
|
||||||
|
{ q: "Q3", value: 390 },
|
||||||
|
{ q: "Q4", value: 652 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "S&P 500 VOO",
|
||||||
|
shares: "112 Shares",
|
||||||
|
amount: "$928.40",
|
||||||
|
data: [
|
||||||
|
{ q: "Q1", value: 180 },
|
||||||
|
{ q: "Q2", value: 210 },
|
||||||
|
{ q: "Q3", value: 320 },
|
||||||
|
{ q: "Q4", value: 218 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Apple AAPL",
|
||||||
|
shares: "85 Shares",
|
||||||
|
amount: "$340.00",
|
||||||
|
data: [
|
||||||
|
{ q: "Q1", value: 60 },
|
||||||
|
{ q: "Q2", value: 70 },
|
||||||
|
{ q: "Q3", value: 120 },
|
||||||
|
{ q: "Q4", value: 90 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Realty Income",
|
||||||
|
shares: "320 Shares",
|
||||||
|
amount: "$1,139.50",
|
||||||
|
data: [
|
||||||
|
{ q: "Q1", value: 240 },
|
||||||
|
{ q: "Q2", value: 260 },
|
||||||
|
{ q: "Q3", value: 280 },
|
||||||
|
{ q: "Q4", value: 360 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export function DividendIncome() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Q2 Dividend Income</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Quarterly dividend payouts across your portfolio holdings.
|
||||||
|
</CardDescription>
|
||||||
|
<CardAction>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon-sm"
|
||||||
|
className="bg-muted"
|
||||||
|
aria-label="Dismiss dividend income"
|
||||||
|
>
|
||||||
|
<HugeiconsIcon icon={Cancel01Icon} strokeWidth={2} />
|
||||||
|
</Button>
|
||||||
|
</CardAction>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<ItemGroup>
|
||||||
|
{HOLDINGS.map((holding) => (
|
||||||
|
<Item key={holding.name} role="listitem" variant="muted">
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>{holding.name}</ItemTitle>
|
||||||
|
<ItemDescription>{holding.shares}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
<div
|
||||||
|
className="hidden h-8 w-24 items-end gap-1 md:flex"
|
||||||
|
role="img"
|
||||||
|
aria-label={`${holding.name} quarterly dividends`}
|
||||||
|
>
|
||||||
|
{holding.data.map((item) => (
|
||||||
|
<div
|
||||||
|
key={item.q}
|
||||||
|
className="min-h-1 flex-1 rounded-t-sm bg-chart-2"
|
||||||
|
style={{
|
||||||
|
height: `${(item.value / Math.max(...holding.data.map((point) => point.value))) * 100}%`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Item>
|
||||||
|
))}
|
||||||
|
</ItemGroup>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
37
apps/v4/app/(app)/(root)/cards/empty-distribute-track.tsx
Normal file
37
apps/v4/app/(app)/(root)/cards/empty-distribute-track.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { Add01Icon } from "@hugeicons/core-free-icons"
|
||||||
|
import { HugeiconsIcon } from "@hugeicons/react"
|
||||||
|
|
||||||
|
import { Button } from "@/styles/base-rhea/ui/button"
|
||||||
|
import { Card, CardContent } from "@/styles/base-rhea/ui/card"
|
||||||
|
import {
|
||||||
|
Empty,
|
||||||
|
EmptyContent,
|
||||||
|
EmptyDescription,
|
||||||
|
EmptyHeader,
|
||||||
|
EmptyMedia,
|
||||||
|
EmptyTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/empty"
|
||||||
|
|
||||||
|
export function EmptyDistributeTrack() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardContent>
|
||||||
|
<Empty className="p-4">
|
||||||
|
<EmptyMedia variant="icon">
|
||||||
|
<HugeiconsIcon icon={Add01Icon} strokeWidth={2} />
|
||||||
|
</EmptyMedia>
|
||||||
|
<EmptyHeader>
|
||||||
|
<EmptyTitle>Distribute Track</EmptyTitle>
|
||||||
|
<EmptyDescription>
|
||||||
|
Upload your first master to start reaching listeners on Spotify,
|
||||||
|
Apple Music, and more.
|
||||||
|
</EmptyDescription>
|
||||||
|
</EmptyHeader>
|
||||||
|
<EmptyContent>
|
||||||
|
<Button>Create Release</Button>
|
||||||
|
</EmptyContent>
|
||||||
|
</Empty>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
117
apps/v4/app/(app)/(root)/cards/index.tsx
Normal file
117
apps/v4/app/(app)/(root)/cards/index.tsx
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import { AccountAccess } from "./account-access"
|
||||||
|
import { AnalyticsCard } from "./analytics-card"
|
||||||
|
import { ClaimableBalance } from "./claimable-balance"
|
||||||
|
import { ContributionHistory } from "./contribution-history"
|
||||||
|
import { DividendIncome } from "./dividend-income"
|
||||||
|
import { EmptyDistributeTrack } from "./empty-distribute-track"
|
||||||
|
import { NewMilestone } from "./new-milestone"
|
||||||
|
import { NotificationSettings } from "./notification-settings"
|
||||||
|
import { Payments } from "./payments"
|
||||||
|
import { PayoutThreshold } from "./payout-threshold"
|
||||||
|
import { PowerUsage } from "./power-usage"
|
||||||
|
import { QrConnect } from "./qr-connect"
|
||||||
|
import { SavingsTargets } from "./savings-targets"
|
||||||
|
import { SidebarNav } from "./sidebar-nav"
|
||||||
|
import { AccountAccess as SkeletonAccountAccess } from "./skeleton/account-access"
|
||||||
|
import { AnalyticsCard as SkeletonAnalyticsCard } from "./skeleton/analytics-card"
|
||||||
|
import { ClaimableBalance as SkeletonClaimableBalance } from "./skeleton/claimable-balance"
|
||||||
|
import { ContributionHistory as SkeletonContributionHistory } from "./skeleton/contribution-history"
|
||||||
|
import { DividendIncome as SkeletonDividendIncome } from "./skeleton/dividend-income"
|
||||||
|
import { EmptyDistributeTrack as SkeletonEmptyDistributeTrack } from "./skeleton/empty-distribute-track"
|
||||||
|
import { NewMilestone as SkeletonNewMilestone } from "./skeleton/new-milestone"
|
||||||
|
import { NotificationSettings as SkeletonNotificationSettings } from "./skeleton/notification-settings"
|
||||||
|
import { Payments as SkeletonPayments } from "./skeleton/payments"
|
||||||
|
import { PayoutThreshold as SkeletonPayoutThreshold } from "./skeleton/payout-threshold"
|
||||||
|
import { PowerUsage as SkeletonPowerUsage } from "./skeleton/power-usage"
|
||||||
|
import { QrConnect as SkeletonQrConnect } from "./skeleton/qr-connect"
|
||||||
|
import { SavingsTargets as SkeletonSavingsTargets } from "./skeleton/savings-targets"
|
||||||
|
import { TransferFunds as SkeletonTransferFunds } from "./skeleton/transfer-funds"
|
||||||
|
import { UIElements as SkeletonUIElements } from "./skeleton/ui-elements"
|
||||||
|
import { TransferFunds } from "./transfer-funds"
|
||||||
|
import { UIElements } from "./ui-elements"
|
||||||
|
|
||||||
|
function CardsSkeletonRails() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
className="pointer-events-none absolute inset-x-0 top-12 z-10 hidden min-[2200px]:block [&_[data-slot=skeleton]:nth-child(even)]:hidden"
|
||||||
|
>
|
||||||
|
<div className="absolute top-0 left-[calc(50%-950px-var(--rail-width)-var(--gap))] grid w-(--rail-width) grid-cols-[repeat(2,var(--rail-column))] gap-(--gap) opacity-50 [--rail-column:20rem] [--rail-width:calc(var(--rail-column)*2+var(--gap))]">
|
||||||
|
<div className="flex flex-col gap-(--gap)">
|
||||||
|
<SkeletonContributionHistory />
|
||||||
|
<SkeletonClaimableBalance />
|
||||||
|
<SkeletonDividendIncome />
|
||||||
|
<SkeletonPayoutThreshold />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-(--gap)">
|
||||||
|
<SkeletonUIElements />
|
||||||
|
<SkeletonSavingsTargets />
|
||||||
|
<SkeletonNewMilestone />
|
||||||
|
<SkeletonPayoutThreshold />
|
||||||
|
<SkeletonAccountAccess />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="absolute top-0 right-[calc(50%-950px-var(--rail-width)-var(--gap))] grid w-(--rail-width) grid-cols-[repeat(2,var(--rail-column))] gap-(--gap) opacity-50 [--rail-column:20rem] [--rail-width:calc(var(--rail-column)*2+var(--gap))]">
|
||||||
|
<div className="flex flex-col gap-(--gap)">
|
||||||
|
<SkeletonNewMilestone />
|
||||||
|
<SkeletonPayoutThreshold />
|
||||||
|
<SkeletonAccountAccess />
|
||||||
|
<SkeletonQrConnect />
|
||||||
|
<SkeletonTransferFunds />
|
||||||
|
<SkeletonPayments />
|
||||||
|
<SkeletonEmptyDistributeTrack />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-(--gap)">
|
||||||
|
<SkeletonQrConnect />
|
||||||
|
<SkeletonTransferFunds />
|
||||||
|
<SkeletonPayments />
|
||||||
|
<SkeletonEmptyDistributeTrack />
|
||||||
|
<SkeletonAnalyticsCard />
|
||||||
|
<SkeletonNotificationSettings />
|
||||||
|
<SkeletonPowerUsage />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CardsDemo() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="demo"
|
||||||
|
className="theme-neutral relative flex w-full max-w-none flex-col gap-(--gap) overflow-hidden bg-muted p-12 pb-0! [--gap:--spacing(8)] 3xl:[--gap:--spacing(8)] min-[1900px]:[--gap:--spacing(10)]! lg:p-8 lg:[--gap:--spacing(6)] xl:p-12 dark:bg-background"
|
||||||
|
>
|
||||||
|
<CardsSkeletonRails />
|
||||||
|
<div className="relative z-10 mx-auto grid gap-(--gap) **:data-[slot=card]:w-full min-[1400px]:grid-cols-4! min-[1900px]:grid-cols-5! md:max-w-3xl md:grid-cols-2 lg:max-w-none lg:grid-cols-3 xl:max-w-[1600px] 2xl:max-w-[1900px]">
|
||||||
|
<div className="flex flex-col items-start gap-(--gap)">
|
||||||
|
<UIElements />
|
||||||
|
<SidebarNav />
|
||||||
|
<SavingsTargets />
|
||||||
|
</div>
|
||||||
|
<div className="hidden flex-col gap-(--gap) lg:flex">
|
||||||
|
<ContributionHistory />
|
||||||
|
<ClaimableBalance />
|
||||||
|
<DividendIncome />
|
||||||
|
</div>
|
||||||
|
<div className="hidden flex-col gap-(--gap) 3xl:flex!">
|
||||||
|
<NewMilestone />
|
||||||
|
<PayoutThreshold />
|
||||||
|
<AccountAccess />
|
||||||
|
</div>
|
||||||
|
<div className="hidden flex-col gap-(--gap) md:flex">
|
||||||
|
<QrConnect />
|
||||||
|
<TransferFunds />
|
||||||
|
<Payments />
|
||||||
|
</div>
|
||||||
|
<div className="hidden flex-col gap-(--gap) min-[1400px]:flex">
|
||||||
|
<EmptyDistributeTrack />
|
||||||
|
<AnalyticsCard />
|
||||||
|
<NotificationSettings />
|
||||||
|
<PowerUsage />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="absolute inset-x-0 top-0 z-1 h-120 bg-linear-to-b from-background via-muted to-transparent dark:hidden" />
|
||||||
|
<div className="absolute inset-x-0 bottom-0 z-20 h-48 bg-linear-to-t from-background via-muted/80 to-transparent lg:h-80 xl:h-64 dark:via-background/80" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
52
apps/v4/app/(app)/(root)/cards/new-milestone.tsx
Normal file
52
apps/v4/app/(app)/(root)/cards/new-milestone.tsx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { Button } from "@/styles/base-rhea/ui/button"
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Field, FieldGroup, FieldLabel } from "@/styles/base-rhea/ui/field"
|
||||||
|
import { Input } from "@/styles/base-rhea/ui/input"
|
||||||
|
|
||||||
|
export function NewMilestone() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Set a new milestone</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Define your financial target and we'll help you pace your
|
||||||
|
savings.
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<FieldGroup>
|
||||||
|
<Field>
|
||||||
|
<FieldLabel htmlFor="goal-name">Goal Name</FieldLabel>
|
||||||
|
<Input
|
||||||
|
id="goal-name"
|
||||||
|
placeholder="e.g. New Car, Home Downpayment"
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
<div className="grid grid-cols-2 gap-3">
|
||||||
|
<Field>
|
||||||
|
<FieldLabel htmlFor="target-amount">Target Amount</FieldLabel>
|
||||||
|
<Input id="target-amount" defaultValue="$15,000" />
|
||||||
|
</Field>
|
||||||
|
<Field>
|
||||||
|
<FieldLabel htmlFor="target-date">Target Date</FieldLabel>
|
||||||
|
<Input id="target-date" defaultValue="Dec 2025" />
|
||||||
|
</Field>
|
||||||
|
</div>
|
||||||
|
</FieldGroup>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter className="flex-col gap-2">
|
||||||
|
<Button className="w-full">Create Goal</Button>
|
||||||
|
<Button variant="outline" className="w-full">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
76
apps/v4/app/(app)/(root)/cards/notification-settings.tsx
Normal file
76
apps/v4/app/(app)/(root)/cards/notification-settings.tsx
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import { Button } from "@/styles/base-rhea/ui/button"
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Checkbox } from "@/styles/base-rhea/ui/checkbox"
|
||||||
|
import {
|
||||||
|
Field,
|
||||||
|
FieldContent,
|
||||||
|
FieldDescription,
|
||||||
|
FieldGroup,
|
||||||
|
FieldLabel,
|
||||||
|
} from "@/styles/base-rhea/ui/field"
|
||||||
|
|
||||||
|
const NOTIFICATIONS = [
|
||||||
|
{
|
||||||
|
id: "transactions",
|
||||||
|
label: "Transaction alerts",
|
||||||
|
description: "Deposits, withdrawals, and transfers.",
|
||||||
|
defaultChecked: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "security",
|
||||||
|
label: "Security alerts",
|
||||||
|
description: "Login attempts and account changes.",
|
||||||
|
defaultChecked: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "goals",
|
||||||
|
label: "Goal milestones",
|
||||||
|
description: "Updates at 25%, 50%, 75%, and 100%.",
|
||||||
|
defaultChecked: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "market",
|
||||||
|
label: "Market updates",
|
||||||
|
description: "Daily portfolio summary and price alerts.",
|
||||||
|
defaultChecked: false,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export function NotificationSettings() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Notifications</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Choose which email and push alerts you want to receive.
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<FieldGroup>
|
||||||
|
{NOTIFICATIONS.map((n) => (
|
||||||
|
<Field key={n.id} orientation="horizontal">
|
||||||
|
<Checkbox
|
||||||
|
id={`notify-${n.id}`}
|
||||||
|
defaultChecked={n.defaultChecked}
|
||||||
|
/>
|
||||||
|
<FieldContent>
|
||||||
|
<FieldLabel htmlFor={`notify-${n.id}`}>{n.label}</FieldLabel>
|
||||||
|
<FieldDescription>{n.description}</FieldDescription>
|
||||||
|
</FieldContent>
|
||||||
|
</Field>
|
||||||
|
))}
|
||||||
|
</FieldGroup>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<Button className="w-full">Save Preferences</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
139
apps/v4/app/(app)/(root)/cards/payments.tsx
Normal file
139
apps/v4/app/(app)/(root)/cards/payments.tsx
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
import {
|
||||||
|
ArrowRight01Icon,
|
||||||
|
Calendar03Icon,
|
||||||
|
MoreHorizontalCircle01Icon,
|
||||||
|
RefreshIcon,
|
||||||
|
Settings01Icon,
|
||||||
|
} from "@hugeicons/core-free-icons"
|
||||||
|
import { HugeiconsIcon } from "@hugeicons/react"
|
||||||
|
|
||||||
|
import {
|
||||||
|
Breadcrumb,
|
||||||
|
BreadcrumbItem,
|
||||||
|
BreadcrumbLink,
|
||||||
|
BreadcrumbList,
|
||||||
|
BreadcrumbPage,
|
||||||
|
BreadcrumbSeparator,
|
||||||
|
} from "@/styles/base-rhea/ui/breadcrumb"
|
||||||
|
import { Button } from "@/styles/base-rhea/ui/button"
|
||||||
|
import { Card, CardContent, CardHeader } from "@/styles/base-rhea/ui/card"
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuGroup,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from "@/styles/base-rhea/ui/dropdown-menu"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemGroup,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/item"
|
||||||
|
|
||||||
|
export function Payments() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="flex flex-col gap-3">
|
||||||
|
<Breadcrumb>
|
||||||
|
<BreadcrumbList>
|
||||||
|
<BreadcrumbItem>
|
||||||
|
<BreadcrumbLink href="#">Home</BreadcrumbLink>
|
||||||
|
</BreadcrumbItem>
|
||||||
|
<BreadcrumbSeparator />
|
||||||
|
<BreadcrumbItem>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger
|
||||||
|
render={
|
||||||
|
<Button
|
||||||
|
size="icon-sm"
|
||||||
|
variant="ghost"
|
||||||
|
aria-label="Account options"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<HugeiconsIcon
|
||||||
|
icon={MoreHorizontalCircle01Icon}
|
||||||
|
strokeWidth={2}
|
||||||
|
/>
|
||||||
|
<span className="sr-only">Account options</span>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="start">
|
||||||
|
<DropdownMenuGroup>
|
||||||
|
<DropdownMenuItem>Profile</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem>Statements</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem>Documents</DropdownMenuItem>
|
||||||
|
</DropdownMenuGroup>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</BreadcrumbItem>
|
||||||
|
<BreadcrumbSeparator />
|
||||||
|
<BreadcrumbItem>
|
||||||
|
<BreadcrumbPage>Payments</BreadcrumbPage>
|
||||||
|
</BreadcrumbItem>
|
||||||
|
</BreadcrumbList>
|
||||||
|
</Breadcrumb>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<ItemGroup>
|
||||||
|
<div role="listitem" className="w-full">
|
||||||
|
<Item variant="muted" render={<a href="#" />}>
|
||||||
|
<ItemMedia variant="icon">
|
||||||
|
<HugeiconsIcon icon={Settings01Icon} strokeWidth={2} />
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>Change transfer limit</ItemTitle>
|
||||||
|
<ItemDescription>
|
||||||
|
Adjust how much you can send from your balance.
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
<HugeiconsIcon
|
||||||
|
icon={ArrowRight01Icon}
|
||||||
|
className="size-4 shrink-0 text-muted-foreground"
|
||||||
|
strokeWidth={2}
|
||||||
|
/>
|
||||||
|
</Item>
|
||||||
|
</div>
|
||||||
|
<div role="listitem" className="w-full">
|
||||||
|
<Item variant="muted" render={<a href="#" />}>
|
||||||
|
<ItemMedia variant="icon">
|
||||||
|
<HugeiconsIcon icon={Calendar03Icon} strokeWidth={2} />
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>Scheduled transfers</ItemTitle>
|
||||||
|
<ItemDescription>
|
||||||
|
Set up a transfer to send at a later date.
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
<HugeiconsIcon
|
||||||
|
icon={ArrowRight01Icon}
|
||||||
|
className="size-4 shrink-0 text-muted-foreground"
|
||||||
|
strokeWidth={2}
|
||||||
|
/>
|
||||||
|
</Item>
|
||||||
|
</div>
|
||||||
|
<div role="listitem" className="w-full">
|
||||||
|
<Item variant="muted" render={<a href="#" />}>
|
||||||
|
<ItemMedia variant="icon">
|
||||||
|
<HugeiconsIcon icon={RefreshIcon} strokeWidth={2} />
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>Recurring card payments</ItemTitle>
|
||||||
|
<ItemDescription>
|
||||||
|
Manage your repeated card transactions.
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
<HugeiconsIcon
|
||||||
|
icon={ArrowRight01Icon}
|
||||||
|
className="size-4 shrink-0 text-muted-foreground"
|
||||||
|
strokeWidth={2}
|
||||||
|
/>
|
||||||
|
</Item>
|
||||||
|
</div>
|
||||||
|
</ItemGroup>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
112
apps/v4/app/(app)/(root)/cards/payout-threshold.tsx
Normal file
112
apps/v4/app/(app)/(root)/cards/payout-threshold.tsx
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
import { Cancel01Icon } from "@hugeicons/core-free-icons"
|
||||||
|
import { HugeiconsIcon } from "@hugeicons/react"
|
||||||
|
|
||||||
|
import { Button } from "@/styles/base-rhea/ui/button"
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardAction,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import {
|
||||||
|
Field,
|
||||||
|
FieldDescription,
|
||||||
|
FieldGroup,
|
||||||
|
FieldLabel,
|
||||||
|
} from "@/styles/base-rhea/ui/field"
|
||||||
|
import { Progress } from "@/styles/base-rhea/ui/progress"
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/styles/base-rhea/ui/select"
|
||||||
|
import { Textarea } from "@/styles/base-rhea/ui/textarea"
|
||||||
|
|
||||||
|
const CURRENCIES = [
|
||||||
|
{ label: "USD — United States Dollar", value: "usd" },
|
||||||
|
{ label: "EUR — Euro", value: "eur" },
|
||||||
|
{ label: "GBP — British Pound", value: "gbp" },
|
||||||
|
{ label: "JPY — Japanese Yen", value: "jpy" },
|
||||||
|
]
|
||||||
|
|
||||||
|
export function PayoutThreshold() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Payout Threshold</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Set the minimum balance required before a payout is triggered.
|
||||||
|
</CardDescription>
|
||||||
|
<CardAction>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon-sm"
|
||||||
|
className="bg-muted"
|
||||||
|
aria-label="Dismiss payout threshold"
|
||||||
|
>
|
||||||
|
<HugeiconsIcon icon={Cancel01Icon} strokeWidth={2} />
|
||||||
|
</Button>
|
||||||
|
</CardAction>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<FieldGroup>
|
||||||
|
<Field>
|
||||||
|
<FieldLabel htmlFor="preferred-currency">
|
||||||
|
Preferred Currency
|
||||||
|
</FieldLabel>
|
||||||
|
<Select items={CURRENCIES} defaultValue="usd">
|
||||||
|
<SelectTrigger id="preferred-currency" className="w-full">
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
{CURRENCIES.map((item) => (
|
||||||
|
<SelectItem key={item.value} value={item.value}>
|
||||||
|
{item.label}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</Field>
|
||||||
|
<Field>
|
||||||
|
<div className="flex items-baseline justify-between">
|
||||||
|
<FieldLabel id="min-payout-label">
|
||||||
|
Minimum Payout Amount
|
||||||
|
</FieldLabel>
|
||||||
|
<span className="text-2xl font-semibold tabular-nums">
|
||||||
|
$2500.00
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<Progress
|
||||||
|
value={25}
|
||||||
|
aria-labelledby="min-payout-label"
|
||||||
|
aria-valuetext="$2,500 of $10,000"
|
||||||
|
/>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<FieldDescription>$50 (MIN)</FieldDescription>
|
||||||
|
<FieldDescription>$10,000 (MAX)</FieldDescription>
|
||||||
|
</div>
|
||||||
|
</Field>
|
||||||
|
<Field>
|
||||||
|
<FieldLabel htmlFor="payout-notes">Notes</FieldLabel>
|
||||||
|
<Textarea
|
||||||
|
id="payout-notes"
|
||||||
|
placeholder="Add any notes for this payout configuration..."
|
||||||
|
className="min-h-[100px]"
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
</FieldGroup>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<Button className="w-full">Save Threshold</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
67
apps/v4/app/(app)/(root)/cards/power-usage.tsx
Normal file
67
apps/v4/app/(app)/(root)/cards/power-usage.tsx
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Separator } from "@/styles/base-rhea/ui/separator"
|
||||||
|
|
||||||
|
const chartData = [
|
||||||
|
{ hour: "6a", usage: 1.2 },
|
||||||
|
{ hour: "8a", usage: 2.8 },
|
||||||
|
{ hour: "10a", usage: 3.1 },
|
||||||
|
{ hour: "12p", usage: 2.4 },
|
||||||
|
{ hour: "2p", usage: 3.4 },
|
||||||
|
{ hour: "4p", usage: 2.9 },
|
||||||
|
{ hour: "6p", usage: 3.8 },
|
||||||
|
{ hour: "8p", usage: 3.2 },
|
||||||
|
]
|
||||||
|
|
||||||
|
export function PowerUsage() {
|
||||||
|
const maxUsage = Math.max(...chartData.map((item) => item.usage))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Power Usage</CardTitle>
|
||||||
|
<CardDescription>Whole Home</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex flex-col gap-4">
|
||||||
|
<div
|
||||||
|
className="flex h-[140px] w-full items-end gap-2"
|
||||||
|
role="img"
|
||||||
|
aria-label="Power usage by hour"
|
||||||
|
>
|
||||||
|
{chartData.map((item) => (
|
||||||
|
<div
|
||||||
|
key={item.hour}
|
||||||
|
className="flex h-full flex-1 flex-col justify-end gap-1.5"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="min-h-2 rounded-t bg-chart-2"
|
||||||
|
style={{ height: `${(item.usage / maxUsage) * 100}%` }}
|
||||||
|
/>
|
||||||
|
<span className="text-center text-xs text-muted-foreground">
|
||||||
|
{item.hour}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<Separator />
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div className="flex flex-col gap-0.5">
|
||||||
|
<span className="text-sm text-muted-foreground">
|
||||||
|
Currently Using
|
||||||
|
</span>
|
||||||
|
<span className="text-lg font-semibold tabular-nums">3.4 kW</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-0.5">
|
||||||
|
<span className="text-sm text-muted-foreground">Solar Gen</span>
|
||||||
|
<span className="text-lg font-semibold tabular-nums">+1.2 kW</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
64
apps/v4/app/(app)/(root)/cards/qr-connect.tsx
Normal file
64
apps/v4/app/(app)/(root)/cards/qr-connect.tsx
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
|
||||||
|
const qrCells = [
|
||||||
|
"111111100101101111111",
|
||||||
|
"100000101001001000001",
|
||||||
|
"101110101111101011101",
|
||||||
|
"101110100100001011101",
|
||||||
|
"101110101010101011101",
|
||||||
|
"100000100111001000001",
|
||||||
|
"111111101010101111111",
|
||||||
|
"000000001101000000000",
|
||||||
|
"101011111001111010110",
|
||||||
|
"010100001110010101001",
|
||||||
|
"111010111011101111010",
|
||||||
|
"001101000101000010101",
|
||||||
|
"110111101111010111011",
|
||||||
|
"000000001001010001010",
|
||||||
|
"111111101101111101001",
|
||||||
|
"100000100010001001111",
|
||||||
|
"101110101011101110100",
|
||||||
|
"101110100110100010011",
|
||||||
|
"101110101000111101110",
|
||||||
|
"100000101101000011001",
|
||||||
|
"111111101011101101111",
|
||||||
|
]
|
||||||
|
|
||||||
|
export function QrConnect() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardContent className="flex justify-center pt-6">
|
||||||
|
<div className="rounded-xl border bg-white p-4">
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 21 21"
|
||||||
|
className="size-40 text-black"
|
||||||
|
role="img"
|
||||||
|
aria-label="Connect device QR code"
|
||||||
|
shapeRendering="crispEdges"
|
||||||
|
>
|
||||||
|
<rect width="21" height="21" fill="white" />
|
||||||
|
{qrCells.map((row, y) =>
|
||||||
|
[...row].map((cell, x) =>
|
||||||
|
cell === "1" ? (
|
||||||
|
<rect key={`${x}-${y}`} x={x} y={y} width="1" height="1" />
|
||||||
|
) : null
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardHeader className="text-center">
|
||||||
|
<CardTitle>Scan to connect your mobile device</CardTitle>
|
||||||
|
<CardDescription className="text-balance">
|
||||||
|
Open the Ledger mobile app and scan this code to link your device.
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
81
apps/v4/app/(app)/(root)/cards/savings-targets.tsx
Normal file
81
apps/v4/app/(app)/(root)/cards/savings-targets.tsx
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemFooter,
|
||||||
|
ItemGroup,
|
||||||
|
} from "@/styles/base-rhea/ui/item"
|
||||||
|
import { Progress } from "@/styles/base-rhea/ui/progress"
|
||||||
|
|
||||||
|
export function SavingsTargets() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Savings Targets</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Active milestones for 2024 across your portfolio. Monitor how close
|
||||||
|
you are to each savings goal.
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<ItemGroup className="gap-3">
|
||||||
|
<Item
|
||||||
|
role="listitem"
|
||||||
|
variant="muted"
|
||||||
|
className="flex-col items-stretch"
|
||||||
|
>
|
||||||
|
<ItemContent className="gap-3">
|
||||||
|
<ItemDescription className="cn-font-heading text-xs font-medium tracking-wider text-muted-foreground uppercase">
|
||||||
|
Retirement
|
||||||
|
</ItemDescription>
|
||||||
|
<span className="text-3xl font-semibold tabular-nums">
|
||||||
|
$420,000
|
||||||
|
</span>
|
||||||
|
<Progress value={65} aria-label="Retirement savings progress" />
|
||||||
|
</ItemContent>
|
||||||
|
<ItemFooter>
|
||||||
|
<span className="text-sm text-muted-foreground">
|
||||||
|
65% achieved
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium tabular-nums">$273,000</span>
|
||||||
|
</ItemFooter>
|
||||||
|
</Item>
|
||||||
|
<Item
|
||||||
|
role="listitem"
|
||||||
|
variant="muted"
|
||||||
|
className="flex-col items-stretch"
|
||||||
|
>
|
||||||
|
<ItemContent className="gap-3">
|
||||||
|
<ItemDescription className="cn-font-heading text-xs font-medium tracking-wider text-muted-foreground uppercase">
|
||||||
|
Real Estate
|
||||||
|
</ItemDescription>
|
||||||
|
<span className="text-3xl font-semibold tabular-nums">
|
||||||
|
$85,000
|
||||||
|
</span>
|
||||||
|
<Progress value={32} aria-label="Real estate savings progress" />
|
||||||
|
</ItemContent>
|
||||||
|
<ItemFooter>
|
||||||
|
<span className="text-sm text-muted-foreground">
|
||||||
|
32% achieved
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium tabular-nums">$27,200</span>
|
||||||
|
</ItemFooter>
|
||||||
|
</Item>
|
||||||
|
</ItemGroup>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<CardDescription className="text-center">
|
||||||
|
You have not met your targets for this year.
|
||||||
|
</CardDescription>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
218
apps/v4/app/(app)/(root)/cards/sidebar-nav.tsx
Normal file
218
apps/v4/app/(app)/(root)/cards/sidebar-nav.tsx
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import {
|
||||||
|
ActivityIcon,
|
||||||
|
Analytics01Icon,
|
||||||
|
AnalyticsUpIcon,
|
||||||
|
ArrowDataTransferHorizontalIcon,
|
||||||
|
BankIcon,
|
||||||
|
BookOpen02Icon,
|
||||||
|
Calendar03Icon,
|
||||||
|
ChartBarLineIcon,
|
||||||
|
CreditCardIcon,
|
||||||
|
File02Icon,
|
||||||
|
Globe02Icon,
|
||||||
|
HelpCircleIcon,
|
||||||
|
Message01Icon,
|
||||||
|
Notification03Icon,
|
||||||
|
PaintBoardIcon,
|
||||||
|
PieChartIcon,
|
||||||
|
ShieldIcon,
|
||||||
|
Target02Icon,
|
||||||
|
UserIcon,
|
||||||
|
Wallet01Icon,
|
||||||
|
} from "@hugeicons/core-free-icons"
|
||||||
|
import { HugeiconsIcon } from "@hugeicons/react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Card } from "@/styles/base-rhea/ui/card"
|
||||||
|
import {
|
||||||
|
Sidebar,
|
||||||
|
SidebarContent,
|
||||||
|
SidebarGroup,
|
||||||
|
SidebarGroupContent,
|
||||||
|
SidebarGroupLabel,
|
||||||
|
SidebarMenu,
|
||||||
|
SidebarMenuButton,
|
||||||
|
SidebarMenuItem,
|
||||||
|
SidebarProvider,
|
||||||
|
} from "@/styles/base-rhea/ui/sidebar"
|
||||||
|
|
||||||
|
function SidebarSection({
|
||||||
|
label,
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
label: string
|
||||||
|
children: React.ReactNode
|
||||||
|
className?: string
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Card className={cn("w-full overflow-hidden rounded-3xl py-0", className)}>
|
||||||
|
<SidebarProvider className="min-h-0">
|
||||||
|
<Sidebar collapsible="none" className="w-full bg-transparent">
|
||||||
|
<SidebarContent className="gap-0 overflow-hidden">
|
||||||
|
<SidebarGroup>
|
||||||
|
<SidebarGroupLabel>{label}</SidebarGroupLabel>
|
||||||
|
<SidebarGroupContent>
|
||||||
|
<SidebarMenu className="gap-1">{children}</SidebarMenu>
|
||||||
|
</SidebarGroupContent>
|
||||||
|
</SidebarGroup>
|
||||||
|
</SidebarContent>
|
||||||
|
</Sidebar>
|
||||||
|
</SidebarProvider>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SidebarNav() {
|
||||||
|
return (
|
||||||
|
<div className="grid w-full grid-cols-2 gap-4 xl:gap-6">
|
||||||
|
<SidebarSection
|
||||||
|
label="Overview"
|
||||||
|
className="xl:col-start-1 xl:row-start-2"
|
||||||
|
>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton isActive>
|
||||||
|
<HugeiconsIcon icon={Analytics01Icon} strokeWidth={2} />
|
||||||
|
Analytics
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon
|
||||||
|
icon={ArrowDataTransferHorizontalIcon}
|
||||||
|
strokeWidth={2}
|
||||||
|
/>
|
||||||
|
Transactions
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={AnalyticsUpIcon} strokeWidth={2} />
|
||||||
|
Investments
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={BankIcon} strokeWidth={2} />
|
||||||
|
Accounts
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={PieChartIcon} strokeWidth={2} />
|
||||||
|
Spending
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
</SidebarSection>
|
||||||
|
|
||||||
|
<SidebarSection
|
||||||
|
label="Planning"
|
||||||
|
className="xl:col-start-1 xl:row-start-1"
|
||||||
|
>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={File02Icon} strokeWidth={2} />
|
||||||
|
Documents
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={Wallet01Icon} strokeWidth={2} />
|
||||||
|
Budget
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={ChartBarLineIcon} strokeWidth={2} />
|
||||||
|
Reports
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={Target02Icon} strokeWidth={2} />
|
||||||
|
Goals
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={Calendar03Icon} strokeWidth={2} />
|
||||||
|
Calendar
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
</SidebarSection>
|
||||||
|
|
||||||
|
<SidebarSection
|
||||||
|
label="Support"
|
||||||
|
className="hidden xl:col-start-2 xl:row-start-1 xl:flex"
|
||||||
|
>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={HelpCircleIcon} strokeWidth={2} />
|
||||||
|
Help Center
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={BookOpen02Icon} strokeWidth={2} />
|
||||||
|
Docs
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={Message01Icon} strokeWidth={2} />
|
||||||
|
Contact Us
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={ActivityIcon} strokeWidth={2} />
|
||||||
|
Status
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={Globe02Icon} strokeWidth={2} />
|
||||||
|
Community
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
</SidebarSection>
|
||||||
|
|
||||||
|
<SidebarSection
|
||||||
|
label="Account"
|
||||||
|
className="hidden xl:col-start-2 xl:row-start-2 xl:flex"
|
||||||
|
>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={UserIcon} strokeWidth={2} />
|
||||||
|
Profile
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton isActive>
|
||||||
|
<HugeiconsIcon icon={CreditCardIcon} strokeWidth={2} />
|
||||||
|
Billing
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={Notification03Icon} strokeWidth={2} />
|
||||||
|
Notifications
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={ShieldIcon} strokeWidth={2} />
|
||||||
|
Security
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<HugeiconsIcon icon={PaintBoardIcon} strokeWidth={2} />
|
||||||
|
Appearance
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
</SidebarSection>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
35
apps/v4/app/(app)/(root)/cards/skeleton/account-access.tsx
Normal file
35
apps/v4/app/(app)/(root)/cards/skeleton/account-access.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
export function AccountAccess() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="gap-2">
|
||||||
|
<Skeleton className="h-5 w-36 rounded-md" />
|
||||||
|
<Skeleton className="h-4 w-64 rounded-md" />
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex flex-col gap-6">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<Skeleton className="h-3 w-24 rounded-md" />
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Skeleton className="h-3 w-32 rounded-md" />
|
||||||
|
<Skeleton className="h-3 w-12 rounded-md" />
|
||||||
|
</div>
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter className="flex-col gap-4">
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
<Skeleton className="h-14 w-full rounded-xl" />
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
17
apps/v4/app/(app)/(root)/cards/skeleton/analytics-card.tsx
Normal file
17
apps/v4/app/(app)/(root)/cards/skeleton/analytics-card.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Card, CardAction, CardHeader } from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
export function AnalyticsCard() {
|
||||||
|
return (
|
||||||
|
<Card className="mx-auto w-full max-w-sm data-[size=sm]:pb-0" size="sm">
|
||||||
|
<CardHeader className="gap-2">
|
||||||
|
<Skeleton className="h-5 w-24 rounded-md" />
|
||||||
|
<Skeleton className="h-4 w-40 rounded-md" />
|
||||||
|
<CardAction>
|
||||||
|
<Skeleton className="h-7 w-28 rounded-lg" />
|
||||||
|
</CardAction>
|
||||||
|
</CardHeader>
|
||||||
|
<Skeleton className="mx-6 mb-6 aspect-[1/0.35] w-auto rounded-lg" />
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
export function ClaimableBalance() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="gap-3">
|
||||||
|
<Skeleton className="h-4 w-36 rounded-md" />
|
||||||
|
<Skeleton className="h-12 w-56 rounded-lg" />
|
||||||
|
<Skeleton className="h-6 w-32 rounded-full" />
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex flex-1 flex-col justify-end">
|
||||||
|
<div className="flex flex-col gap-3 rounded-xl bg-muted p-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Skeleton className="h-4 w-28 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-4 w-20 rounded-md bg-muted-foreground/15" />
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Skeleton className="h-4 w-32 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-4 w-16 rounded-md bg-muted-foreground/15" />
|
||||||
|
</div>
|
||||||
|
<Skeleton className="h-px w-full rounded-none bg-muted-foreground/15" />
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Skeleton className="h-4 w-36 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-4 w-24 rounded-md bg-muted-foreground/15" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter className="flex-col gap-2">
|
||||||
|
<Skeleton className="h-3 w-full rounded-md" />
|
||||||
|
<Skeleton className="h-3 w-11/12 rounded-md" />
|
||||||
|
<Skeleton className="h-3 w-3/4 rounded-md" />
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
const bars = [60, 80, 65, 95, 50, 100]
|
||||||
|
|
||||||
|
export function ContributionHistory() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="gap-2">
|
||||||
|
<Skeleton className="h-5 w-44 rounded-md" />
|
||||||
|
<Skeleton className="h-4 w-52 rounded-md" />
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="flex h-[200px] w-full items-end gap-3">
|
||||||
|
{bars.map((height, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="flex h-full flex-1 flex-col justify-end gap-2"
|
||||||
|
>
|
||||||
|
<Skeleton
|
||||||
|
className="w-full rounded-t-md rounded-b-none"
|
||||||
|
style={{ height: `${height}%` }}
|
||||||
|
/>
|
||||||
|
<Skeleton className="mx-auto h-3 w-6 rounded-md" />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardContent>
|
||||||
|
<div className="grid w-full grid-cols-1 gap-3 xl:grid-cols-2">
|
||||||
|
<div className="flex flex-col gap-2 rounded-xl bg-muted p-4">
|
||||||
|
<Skeleton className="h-3 w-20 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-5 w-28 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-3 w-24 rounded-md bg-muted-foreground/15" />
|
||||||
|
</div>
|
||||||
|
<div className="hidden flex-col gap-2 rounded-xl bg-muted p-4 xl:flex">
|
||||||
|
<Skeleton className="h-3 w-24 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-5 w-32 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-3 w-28 rounded-md bg-muted-foreground/15" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
49
apps/v4/app/(app)/(root)/cards/skeleton/dividend-income.tsx
Normal file
49
apps/v4/app/(app)/(root)/cards/skeleton/dividend-income.tsx
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardAction,
|
||||||
|
CardContent,
|
||||||
|
CardHeader,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
const rows = [0, 1, 2, 3]
|
||||||
|
const miniBars = [40, 60, 80, 50]
|
||||||
|
|
||||||
|
export function DividendIncome() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="gap-2">
|
||||||
|
<Skeleton className="h-5 w-48 rounded-md" />
|
||||||
|
<Skeleton className="h-4 w-64 rounded-md" />
|
||||||
|
<CardAction>
|
||||||
|
<Skeleton className="size-8 rounded-md" />
|
||||||
|
</CardAction>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
{rows.map((row) => (
|
||||||
|
<div
|
||||||
|
key={row}
|
||||||
|
className="flex items-center gap-3 rounded-xl bg-muted p-3"
|
||||||
|
>
|
||||||
|
<div className="flex flex-1 flex-col gap-2">
|
||||||
|
<Skeleton className="h-4 w-28 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-3 w-20 rounded-md bg-muted-foreground/15" />
|
||||||
|
</div>
|
||||||
|
<div className="hidden h-8 w-24 items-end gap-1 md:flex">
|
||||||
|
{miniBars.map((h, i) => (
|
||||||
|
<Skeleton
|
||||||
|
key={i}
|
||||||
|
className="flex-1 rounded-t-sm rounded-b-none bg-muted-foreground/15"
|
||||||
|
style={{ height: `${h}%` }}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<Skeleton className="hidden h-4 w-16 rounded-md bg-muted-foreground/15 md:block" />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { Card, CardContent } from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
export function EmptyDistributeTrack() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardContent>
|
||||||
|
<div className="flex flex-col items-center gap-4 p-4">
|
||||||
|
<Skeleton className="size-12 rounded-xl" />
|
||||||
|
<div className="flex flex-col items-center gap-2">
|
||||||
|
<Skeleton className="h-5 w-40 rounded-md" />
|
||||||
|
<Skeleton className="h-3 w-64 rounded-md" />
|
||||||
|
<Skeleton className="h-3 w-48 rounded-md" />
|
||||||
|
</div>
|
||||||
|
<Skeleton className="h-9 w-32 rounded-lg" />
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
56
apps/v4/app/(app)/(root)/cards/skeleton/index.tsx
Normal file
56
apps/v4/app/(app)/(root)/cards/skeleton/index.tsx
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import { AccountAccess } from "./account-access"
|
||||||
|
import { AnalyticsCard } from "./analytics-card"
|
||||||
|
import { ClaimableBalance } from "./claimable-balance"
|
||||||
|
import { ContributionHistory } from "./contribution-history"
|
||||||
|
import { DividendIncome } from "./dividend-income"
|
||||||
|
import { EmptyDistributeTrack } from "./empty-distribute-track"
|
||||||
|
import { NewMilestone } from "./new-milestone"
|
||||||
|
import { NotificationSettings } from "./notification-settings"
|
||||||
|
import { Payments } from "./payments"
|
||||||
|
import { PayoutThreshold } from "./payout-threshold"
|
||||||
|
import { PowerUsage } from "./power-usage"
|
||||||
|
import { QrConnect } from "./qr-connect"
|
||||||
|
import { SavingsTargets } from "./savings-targets"
|
||||||
|
import { SidebarNav } from "./sidebar-nav"
|
||||||
|
import { TransferFunds } from "./transfer-funds"
|
||||||
|
import { UIElements } from "./ui-elements"
|
||||||
|
|
||||||
|
export function CardsSkeletonDemo() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="demo"
|
||||||
|
className="theme-neutral relative flex w-full max-w-none flex-col gap-(--gap) bg-muted p-12 pb-0! [--gap:--spacing(8)] 3xl:[--gap:--spacing(8)] min-[1900px]:[--gap:--spacing(10)]! lg:p-8 lg:[--gap:--spacing(6)] xl:p-12 dark:bg-muted/30"
|
||||||
|
>
|
||||||
|
<div className="relative z-10 mx-auto grid gap-(--gap) **:data-[slot=card]:w-full min-[1900px]:grid-cols-5! md:max-w-3xl md:grid-cols-2 lg:max-w-none lg:grid-cols-3 xl:max-w-[1600px] xl:grid-cols-4 2xl:max-w-[1900px]">
|
||||||
|
<div className="flex flex-col items-start gap-(--gap)">
|
||||||
|
<UIElements />
|
||||||
|
<SidebarNav />
|
||||||
|
<SavingsTargets />
|
||||||
|
</div>
|
||||||
|
<div className="hidden flex-col gap-(--gap) lg:flex">
|
||||||
|
<ContributionHistory />
|
||||||
|
<ClaimableBalance />
|
||||||
|
<DividendIncome />
|
||||||
|
</div>
|
||||||
|
<div className="hidden flex-col gap-(--gap) 3xl:flex!">
|
||||||
|
<NewMilestone />
|
||||||
|
<PayoutThreshold />
|
||||||
|
<AccountAccess />
|
||||||
|
</div>
|
||||||
|
<div className="hidden flex-col gap-(--gap) md:flex">
|
||||||
|
<QrConnect />
|
||||||
|
<TransferFunds />
|
||||||
|
<Payments />
|
||||||
|
</div>
|
||||||
|
<div className="hidden flex-col gap-(--gap) xl:flex">
|
||||||
|
<EmptyDistributeTrack />
|
||||||
|
<AnalyticsCard />
|
||||||
|
<NotificationSettings />
|
||||||
|
<PowerUsage />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="absolute inset-x-0 top-0 z-1 h-80 bg-linear-to-b from-background via-muted to-transparent dark:via-muted/30" />
|
||||||
|
<div className="absolute inset-x-0 bottom-0 z-20 h-80 bg-linear-to-t from-background via-muted to-transparent dark:via-muted/30" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
38
apps/v4/app/(app)/(root)/cards/skeleton/new-milestone.tsx
Normal file
38
apps/v4/app/(app)/(root)/cards/skeleton/new-milestone.tsx
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
export function NewMilestone() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="gap-2">
|
||||||
|
<Skeleton className="h-5 w-44 rounded-md" />
|
||||||
|
<Skeleton className="h-4 w-72 rounded-md" />
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex flex-col gap-4">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<Skeleton className="h-3 w-20 rounded-md" />
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-2 gap-3">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<Skeleton className="h-3 w-24 rounded-md" />
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<Skeleton className="h-3 w-20 rounded-md" />
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter className="flex-col gap-2">
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
const rows = [0, 1, 2, 3]
|
||||||
|
|
||||||
|
export function NotificationSettings() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="gap-2">
|
||||||
|
<Skeleton className="h-5 w-32 rounded-md" />
|
||||||
|
<Skeleton className="h-4 w-64 rounded-md" />
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex flex-col gap-4">
|
||||||
|
{rows.map((row) => (
|
||||||
|
<div key={row} className="flex items-start gap-3">
|
||||||
|
<Skeleton className="size-4 rounded-sm" />
|
||||||
|
<div className="flex flex-1 flex-col gap-2">
|
||||||
|
<Skeleton className="h-4 w-40 rounded-md" />
|
||||||
|
<Skeleton className="h-3 w-56 rounded-md" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
37
apps/v4/app/(app)/(root)/cards/skeleton/payments.tsx
Normal file
37
apps/v4/app/(app)/(root)/cards/skeleton/payments.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { Card, CardContent, CardHeader } from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
const rows = [0, 1, 2]
|
||||||
|
|
||||||
|
export function Payments() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="flex flex-col gap-3">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Skeleton className="h-4 w-12 rounded-md" />
|
||||||
|
<Skeleton className="size-1.5 rounded-full" />
|
||||||
|
<Skeleton className="size-7 rounded-md" />
|
||||||
|
<Skeleton className="size-1.5 rounded-full" />
|
||||||
|
<Skeleton className="h-4 w-20 rounded-md" />
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
{rows.map((row) => (
|
||||||
|
<div
|
||||||
|
key={row}
|
||||||
|
className="flex items-center gap-3 rounded-xl bg-muted p-3"
|
||||||
|
>
|
||||||
|
<Skeleton className="size-9 rounded-lg bg-muted-foreground/15" />
|
||||||
|
<div className="flex flex-1 flex-col gap-2">
|
||||||
|
<Skeleton className="h-4 w-40 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-3 w-56 rounded-md bg-muted-foreground/15" />
|
||||||
|
</div>
|
||||||
|
<Skeleton className="size-4 rounded-md bg-muted-foreground/15" />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
43
apps/v4/app/(app)/(root)/cards/skeleton/payout-threshold.tsx
Normal file
43
apps/v4/app/(app)/(root)/cards/skeleton/payout-threshold.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardAction,
|
||||||
|
CardContent,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
export function PayoutThreshold() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="gap-2">
|
||||||
|
<Skeleton className="h-5 w-44 rounded-md" />
|
||||||
|
<Skeleton className="h-4 w-72 rounded-md" />
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex flex-col gap-4">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<Skeleton className="h-3 w-32 rounded-md" />
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-3">
|
||||||
|
<div className="flex items-baseline justify-between">
|
||||||
|
<Skeleton className="h-3 w-40 rounded-md" />
|
||||||
|
<Skeleton className="h-7 w-24 rounded-md" />
|
||||||
|
</div>
|
||||||
|
<Skeleton className="h-2 w-full rounded-full" />
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Skeleton className="h-3 w-16 rounded-md" />
|
||||||
|
<Skeleton className="h-3 w-20 rounded-md" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<Skeleton className="h-3 w-16 rounded-md" />
|
||||||
|
<Skeleton className="h-[100px] w-full rounded-lg" />
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
54
apps/v4/app/(app)/(root)/cards/skeleton/power-usage.tsx
Normal file
54
apps/v4/app/(app)/(root)/cards/skeleton/power-usage.tsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
const bars = [30, 70, 80, 60, 90, 75, 100, 85]
|
||||||
|
|
||||||
|
export function PowerUsage() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="gap-2">
|
||||||
|
<Skeleton className="h-5 w-32 rounded-md" />
|
||||||
|
<Skeleton className="h-4 w-24 rounded-md" />
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex flex-col gap-4">
|
||||||
|
<div className="flex h-[140px] w-full items-end gap-2">
|
||||||
|
{bars.map((height, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="flex h-full flex-1 flex-col justify-end gap-1.5"
|
||||||
|
>
|
||||||
|
<Skeleton
|
||||||
|
className="w-full rounded-t rounded-b-none"
|
||||||
|
style={{ height: `${height}%` }}
|
||||||
|
/>
|
||||||
|
<Skeleton className="mx-auto h-3 w-5 rounded-md" />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<Skeleton className="h-px w-full rounded-none" />
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div className="flex flex-col gap-1.5">
|
||||||
|
<Skeleton className="h-3 w-28 rounded-md" />
|
||||||
|
<Skeleton className="h-5 w-20 rounded-md" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-1.5">
|
||||||
|
<Skeleton className="h-3 w-20 rounded-md" />
|
||||||
|
<Skeleton className="h-5 w-24 rounded-md" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter className="flex-col items-start gap-2">
|
||||||
|
<Skeleton className="h-3 w-24 rounded-md" />
|
||||||
|
<div className="flex w-full items-center gap-2">
|
||||||
|
<Skeleton className="h-2 flex-1 rounded-full" />
|
||||||
|
<Skeleton className="h-3 w-10 rounded-md" />
|
||||||
|
</div>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
17
apps/v4/app/(app)/(root)/cards/skeleton/qr-connect.tsx
Normal file
17
apps/v4/app/(app)/(root)/cards/skeleton/qr-connect.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Card, CardContent, CardHeader } from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
export function QrConnect() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardContent className="flex justify-center pt-6">
|
||||||
|
<Skeleton className="size-44 rounded-xl" />
|
||||||
|
</CardContent>
|
||||||
|
<CardHeader className="items-center gap-2 text-center">
|
||||||
|
<Skeleton className="h-5 w-56 rounded-md" />
|
||||||
|
<Skeleton className="h-4 w-64 rounded-md" />
|
||||||
|
<Skeleton className="h-4 w-48 rounded-md" />
|
||||||
|
</CardHeader>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
44
apps/v4/app/(app)/(root)/cards/skeleton/savings-targets.tsx
Normal file
44
apps/v4/app/(app)/(root)/cards/skeleton/savings-targets.tsx
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
const rows = [0, 1]
|
||||||
|
|
||||||
|
export function SavingsTargets() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="gap-2">
|
||||||
|
<Skeleton className="h-5 w-36 rounded-md" />
|
||||||
|
<div className="flex flex-col gap-1.5">
|
||||||
|
<Skeleton className="h-4 w-full max-w-64 rounded-md" />
|
||||||
|
<Skeleton className="h-4 w-48 rounded-md" />
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="flex flex-col gap-3">
|
||||||
|
{rows.map((row) => (
|
||||||
|
<div
|
||||||
|
key={row}
|
||||||
|
className="flex flex-col gap-3 rounded-xl bg-muted p-4"
|
||||||
|
>
|
||||||
|
<Skeleton className="h-3 w-24 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-8 w-36 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-2 w-full rounded-full bg-muted-foreground/15" />
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Skeleton className="h-3 w-24 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-3 w-20 rounded-md bg-muted-foreground/15" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter className="justify-center">
|
||||||
|
<Skeleton className="h-3 w-56 rounded-md" />
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
39
apps/v4/app/(app)/(root)/cards/skeleton/sidebar-nav.tsx
Normal file
39
apps/v4/app/(app)/(root)/cards/skeleton/sidebar-nav.tsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { Card } from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
const groupA = [0, 1, 2, 3, 4]
|
||||||
|
const groupB = [0, 1, 2, 3, 4]
|
||||||
|
|
||||||
|
function NavSkeleton({ groups }: { groups: number[][] }) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-1 p-2">
|
||||||
|
{groups.map((items, gi) => (
|
||||||
|
<div key={gi} className="flex flex-col gap-1 px-2 py-1.5">
|
||||||
|
<Skeleton className="mb-1 h-3 w-20 rounded-md" />
|
||||||
|
{items.map((item) => (
|
||||||
|
<div key={item} className="flex items-center gap-2 px-2 py-2">
|
||||||
|
<Skeleton className="size-4 rounded-md" />
|
||||||
|
<Skeleton className="h-3 w-24 rounded-md" />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{gi < groups.length - 1 && (
|
||||||
|
<Skeleton className="my-1 h-px w-full rounded-none" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SidebarNav() {
|
||||||
|
return (
|
||||||
|
<div className="grid w-full items-start gap-4 xl:grid-cols-2 xl:gap-6">
|
||||||
|
<Card className="w-full overflow-hidden rounded-3xl py-0">
|
||||||
|
<NavSkeleton groups={[groupA, groupB]} />
|
||||||
|
</Card>
|
||||||
|
<Card className="hidden w-full overflow-hidden rounded-3xl py-0 xl:flex">
|
||||||
|
<NavSkeleton groups={[groupA, groupB]} />
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
55
apps/v4/app/(app)/(root)/cards/skeleton/transfer-funds.tsx
Normal file
55
apps/v4/app/(app)/(root)/cards/skeleton/transfer-funds.tsx
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardAction,
|
||||||
|
CardContent,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
export function TransferFunds() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="gap-2">
|
||||||
|
<Skeleton className="h-5 w-36 rounded-md" />
|
||||||
|
<Skeleton className="h-4 w-64 rounded-md" />
|
||||||
|
<CardAction>
|
||||||
|
<Skeleton className="size-8 rounded-md" />
|
||||||
|
</CardAction>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex flex-col gap-4">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<Skeleton className="h-3 w-32 rounded-md" />
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<Skeleton className="h-3 w-24 rounded-md" />
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<Skeleton className="h-3 w-20 rounded-md" />
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-3 rounded-xl bg-muted p-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Skeleton className="h-4 w-28 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-4 w-24 rounded-md bg-muted-foreground/15" />
|
||||||
|
</div>
|
||||||
|
<Skeleton className="h-px w-full rounded-none bg-muted-foreground/15" />
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Skeleton className="h-4 w-28 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-4 w-12 rounded-md bg-muted-foreground/15" />
|
||||||
|
</div>
|
||||||
|
<Skeleton className="h-px w-full rounded-none bg-muted-foreground/15" />
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Skeleton className="h-4 w-24 rounded-md bg-muted-foreground/15" />
|
||||||
|
<Skeleton className="h-4 w-20 rounded-md bg-muted-foreground/15" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
45
apps/v4/app/(app)/(root)/cards/skeleton/ui-elements.tsx
Normal file
45
apps/v4/app/(app)/(root)/cards/skeleton/ui-elements.tsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { Card, CardContent } from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Skeleton } from "@/styles/base-rhea/ui/skeleton"
|
||||||
|
|
||||||
|
export function UIElements() {
|
||||||
|
return (
|
||||||
|
<Card className="w-full">
|
||||||
|
<CardContent className="flex flex-col gap-6">
|
||||||
|
<Skeleton className="h-8 w-full rounded-2xl" />
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<Skeleton className="h-9 w-20 rounded-lg" />
|
||||||
|
<Skeleton className="h-9 w-24 rounded-lg" />
|
||||||
|
<Skeleton className="h-9 w-20 rounded-lg" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-3">
|
||||||
|
<Skeleton className="h-9 w-full rounded-lg" />
|
||||||
|
<Skeleton className="h-20 w-full rounded-lg" />
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Skeleton className="h-5 w-12 rounded-full" />
|
||||||
|
<Skeleton className="h-5 w-16 rounded-full" />
|
||||||
|
<Skeleton className="hidden h-5 w-14 rounded-full 4xl:block" />
|
||||||
|
</div>
|
||||||
|
<div className="ml-auto flex gap-3">
|
||||||
|
<Skeleton className="size-4 rounded-full" />
|
||||||
|
<Skeleton className="size-4 rounded-full" />
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-3">
|
||||||
|
<Skeleton className="size-4 rounded-sm" />
|
||||||
|
<Skeleton className="hidden size-4 rounded-sm 4xl:block" />
|
||||||
|
</div>
|
||||||
|
<Skeleton className="ml-auto h-5 w-9 rounded-full 4xl:hidden" />
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<Skeleton className="h-9 w-24 rounded-lg" />
|
||||||
|
<div className="flex">
|
||||||
|
<Skeleton className="h-9 w-28 rounded-l-lg rounded-r-none" />
|
||||||
|
<Skeleton className="ml-px h-9 w-9 rounded-l-none rounded-r-lg" />
|
||||||
|
</div>
|
||||||
|
<Skeleton className="ml-auto hidden h-5 w-9 rounded-full 4xl:block" />
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
139
apps/v4/app/(app)/(root)/cards/transfer-funds.tsx
Normal file
139
apps/v4/app/(app)/(root)/cards/transfer-funds.tsx
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
import { Cancel01Icon } from "@hugeicons/core-free-icons"
|
||||||
|
import { HugeiconsIcon } from "@hugeicons/react"
|
||||||
|
|
||||||
|
import { Button } from "@/styles/base-rhea/ui/button"
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardAction,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Field, FieldGroup, FieldLabel } from "@/styles/base-rhea/ui/field"
|
||||||
|
import {
|
||||||
|
InputGroup,
|
||||||
|
InputGroupAddon,
|
||||||
|
InputGroupInput,
|
||||||
|
InputGroupText,
|
||||||
|
} from "@/styles/base-rhea/ui/input-group"
|
||||||
|
import { Item, ItemContent } from "@/styles/base-rhea/ui/item"
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/styles/base-rhea/ui/select"
|
||||||
|
import { Separator } from "@/styles/base-rhea/ui/separator"
|
||||||
|
|
||||||
|
const FROM_ACCOUNTS = [
|
||||||
|
{ label: "Main Checking (··8402) — $12,450.00", value: "checking" },
|
||||||
|
{ label: "Business (··7731) — $8,920.00", value: "business" },
|
||||||
|
]
|
||||||
|
|
||||||
|
const TO_ACCOUNTS = [
|
||||||
|
{ label: "High Yield Savings (··1192) — $42,100.00", value: "savings" },
|
||||||
|
{ label: "Investment (··3349) — $18,200.00", value: "investment" },
|
||||||
|
]
|
||||||
|
|
||||||
|
export function TransferFunds() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Transfer Funds</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Move money between your connected accounts.
|
||||||
|
</CardDescription>
|
||||||
|
<CardAction>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon-sm"
|
||||||
|
className="bg-muted"
|
||||||
|
aria-label="Dismiss transfer funds"
|
||||||
|
>
|
||||||
|
<HugeiconsIcon icon={Cancel01Icon} strokeWidth={2} />
|
||||||
|
</Button>
|
||||||
|
</CardAction>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<FieldGroup>
|
||||||
|
<Field>
|
||||||
|
<FieldLabel htmlFor="transfer-amount">
|
||||||
|
Amount to Transfer
|
||||||
|
</FieldLabel>
|
||||||
|
<InputGroup>
|
||||||
|
<InputGroupAddon>
|
||||||
|
<InputGroupText>$</InputGroupText>
|
||||||
|
</InputGroupAddon>
|
||||||
|
<InputGroupInput id="transfer-amount" defaultValue="1,200.00" />
|
||||||
|
</InputGroup>
|
||||||
|
</Field>
|
||||||
|
<Field>
|
||||||
|
<FieldLabel htmlFor="from-account">From Account</FieldLabel>
|
||||||
|
<Select items={FROM_ACCOUNTS} defaultValue="checking">
|
||||||
|
<SelectTrigger id="from-account" className="w-full">
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
{FROM_ACCOUNTS.map((item) => (
|
||||||
|
<SelectItem key={item.value} value={item.value}>
|
||||||
|
{item.label}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</Field>
|
||||||
|
<Field>
|
||||||
|
<FieldLabel htmlFor="to-account">To Account</FieldLabel>
|
||||||
|
<Select items={TO_ACCOUNTS} defaultValue="savings">
|
||||||
|
<SelectTrigger id="to-account" className="w-full">
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
{TO_ACCOUNTS.map((item) => (
|
||||||
|
<SelectItem key={item.value} value={item.value}>
|
||||||
|
{item.label}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</Field>
|
||||||
|
<Item variant="muted" className="flex-col items-stretch">
|
||||||
|
<ItemContent className="gap-3">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-sm text-muted-foreground">
|
||||||
|
Estimated arrival
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">Today, Apr 14</span>
|
||||||
|
</div>
|
||||||
|
<Separator />
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-sm text-muted-foreground">
|
||||||
|
Transaction fee
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium tabular-nums">$0.00</span>
|
||||||
|
</div>
|
||||||
|
<Separator />
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-sm font-medium">Total amount</span>
|
||||||
|
<span className="text-sm font-semibold tabular-nums">
|
||||||
|
$1,200.00
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</FieldGroup>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<Button className="w-full">Confirm Transfer</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
176
apps/v4/app/(app)/(root)/cards/ui-elements.tsx
Normal file
176
apps/v4/app/(app)/(root)/cards/ui-elements.tsx
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import {
|
||||||
|
ArrowRight02Icon,
|
||||||
|
ArrowUp01Icon,
|
||||||
|
Search01Icon,
|
||||||
|
} from "@hugeicons/core-free-icons"
|
||||||
|
import { HugeiconsIcon } from "@hugeicons/react"
|
||||||
|
|
||||||
|
import {
|
||||||
|
AlertDialog,
|
||||||
|
AlertDialogAction,
|
||||||
|
AlertDialogCancel,
|
||||||
|
AlertDialogContent,
|
||||||
|
AlertDialogDescription,
|
||||||
|
AlertDialogFooter,
|
||||||
|
AlertDialogHeader,
|
||||||
|
AlertDialogTitle,
|
||||||
|
AlertDialogTrigger,
|
||||||
|
} from "@/styles/base-rhea/ui/alert-dialog"
|
||||||
|
import { Badge } from "@/styles/base-rhea/ui/badge"
|
||||||
|
import { Button } from "@/styles/base-rhea/ui/button"
|
||||||
|
import { ButtonGroup } from "@/styles/base-rhea/ui/button-group"
|
||||||
|
import { Card, CardContent } from "@/styles/base-rhea/ui/card"
|
||||||
|
import { Checkbox } from "@/styles/base-rhea/ui/checkbox"
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuGroup,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuLabel,
|
||||||
|
DropdownMenuSeparator,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from "@/styles/base-rhea/ui/dropdown-menu"
|
||||||
|
import { Field, FieldGroup } from "@/styles/base-rhea/ui/field"
|
||||||
|
import {
|
||||||
|
InputGroup,
|
||||||
|
InputGroupAddon,
|
||||||
|
InputGroupInput,
|
||||||
|
InputGroupText,
|
||||||
|
} from "@/styles/base-rhea/ui/input-group"
|
||||||
|
import { RadioGroup, RadioGroupItem } from "@/styles/base-rhea/ui/radio-group"
|
||||||
|
import { Switch } from "@/styles/base-rhea/ui/switch"
|
||||||
|
import {
|
||||||
|
Tabs,
|
||||||
|
TabsContent,
|
||||||
|
TabsList,
|
||||||
|
TabsTrigger,
|
||||||
|
} from "@/styles/base-rhea/ui/tabs"
|
||||||
|
import { Textarea } from "@/styles/base-rhea/ui/textarea"
|
||||||
|
|
||||||
|
export function UIElements() {
|
||||||
|
return (
|
||||||
|
<Card className="w-full">
|
||||||
|
<CardContent className="flex flex-col gap-6">
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Button>
|
||||||
|
Button{" "}
|
||||||
|
<HugeiconsIcon
|
||||||
|
icon={ArrowRight02Icon}
|
||||||
|
strokeWidth={2}
|
||||||
|
data-icon="inline-end"
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
<Button variant="secondary">Secondary</Button>
|
||||||
|
<Button variant="outline">Outline</Button>
|
||||||
|
</div>
|
||||||
|
<FieldGroup>
|
||||||
|
<Field>
|
||||||
|
<InputGroup>
|
||||||
|
<InputGroupInput placeholder="Name" />
|
||||||
|
<InputGroupAddon align="inline-end">
|
||||||
|
<InputGroupText>
|
||||||
|
<HugeiconsIcon icon={Search01Icon} strokeWidth={2} />
|
||||||
|
</InputGroupText>
|
||||||
|
</InputGroupAddon>
|
||||||
|
</InputGroup>
|
||||||
|
</Field>
|
||||||
|
<Field className="flex-1">
|
||||||
|
<Textarea placeholder="Message" className="resize-none" />
|
||||||
|
</Field>
|
||||||
|
</FieldGroup>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Badge>Badge</Badge>
|
||||||
|
<Badge variant="secondary">Secondary</Badge>
|
||||||
|
<Badge variant="outline" className="hidden 4xl:flex">
|
||||||
|
Outline
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<RadioGroup
|
||||||
|
defaultValue="apple"
|
||||||
|
className="ml-auto flex w-fit gap-3"
|
||||||
|
aria-label="Fruit preference"
|
||||||
|
>
|
||||||
|
<RadioGroupItem value="apple" aria-label="Apple" />
|
||||||
|
<RadioGroupItem value="banana" aria-label="Banana" />
|
||||||
|
</RadioGroup>
|
||||||
|
<div className="flex gap-3">
|
||||||
|
<Checkbox defaultChecked aria-label="Enable email alerts" />
|
||||||
|
<Checkbox
|
||||||
|
className="hidden 4xl:flex"
|
||||||
|
aria-label="Enable push alerts"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Switch
|
||||||
|
defaultChecked
|
||||||
|
className="flex 4xl:hidden"
|
||||||
|
aria-label="Enable compact notifications"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<AlertDialog>
|
||||||
|
<AlertDialogTrigger render={<Button variant="outline" />}>
|
||||||
|
<span className="hidden md:flex style-sera:md:hidden">
|
||||||
|
Alert Dialog
|
||||||
|
</span>
|
||||||
|
<span className="flex md:hidden style-sera:md:flex">Dialog</span>
|
||||||
|
</AlertDialogTrigger>
|
||||||
|
<AlertDialogContent size="sm">
|
||||||
|
<AlertDialogHeader>
|
||||||
|
<AlertDialogTitle>Allow accessory to connect?</AlertDialogTitle>
|
||||||
|
<AlertDialogDescription>
|
||||||
|
Do you want to allow the USB accessory to connect to this
|
||||||
|
device and your data?
|
||||||
|
</AlertDialogDescription>
|
||||||
|
</AlertDialogHeader>
|
||||||
|
<AlertDialogFooter>
|
||||||
|
<AlertDialogCancel>Don't allow</AlertDialogCancel>
|
||||||
|
<AlertDialogAction>Allow</AlertDialogAction>
|
||||||
|
</AlertDialogFooter>
|
||||||
|
</AlertDialogContent>
|
||||||
|
</AlertDialog>
|
||||||
|
<ButtonGroup className="ml-auto">
|
||||||
|
<Button variant="outline">
|
||||||
|
<span className="style-sera:hidden">Button Group</span>
|
||||||
|
<span className="hidden style-sera:block">Group</span>
|
||||||
|
</Button>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger
|
||||||
|
render={
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="icon"
|
||||||
|
aria-label="Open quick actions"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<HugeiconsIcon icon={ArrowUp01Icon} strokeWidth={2} />
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end" side="top" className="w-40">
|
||||||
|
<DropdownMenuGroup>
|
||||||
|
<DropdownMenuLabel>Quick Actions</DropdownMenuLabel>
|
||||||
|
<DropdownMenuItem>Mute Conversation</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem>Mark as Read</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem>Block User</DropdownMenuItem>
|
||||||
|
</DropdownMenuGroup>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuGroup>
|
||||||
|
<DropdownMenuItem variant="destructive">
|
||||||
|
Delete Conversation
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuGroup>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</ButtonGroup>
|
||||||
|
<Switch
|
||||||
|
defaultChecked
|
||||||
|
className="hidden 4xl:flex"
|
||||||
|
aria-label="Enable advanced setting"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import * as React from "react"
|
|
||||||
import { IconMinus, IconPlus } from "@tabler/icons-react"
|
|
||||||
|
|
||||||
import { Button } from "@/styles/radix-nova/ui/button"
|
|
||||||
import { ButtonGroup } from "@/styles/radix-nova/ui/button-group"
|
|
||||||
import {
|
|
||||||
Field,
|
|
||||||
FieldContent,
|
|
||||||
FieldDescription,
|
|
||||||
FieldGroup,
|
|
||||||
FieldLabel,
|
|
||||||
FieldLegend,
|
|
||||||
FieldSeparator,
|
|
||||||
FieldSet,
|
|
||||||
FieldTitle,
|
|
||||||
} from "@/styles/radix-nova/ui/field"
|
|
||||||
import { Input } from "@/styles/radix-nova/ui/input"
|
|
||||||
import { RadioGroup, RadioGroupItem } from "@/styles/radix-nova/ui/radio-group"
|
|
||||||
import { Switch } from "@/styles/radix-nova/ui/switch"
|
|
||||||
|
|
||||||
export function AppearanceSettings() {
|
|
||||||
const [gpuCount, setGpuCount] = React.useState(8)
|
|
||||||
|
|
||||||
const handleGpuAdjustment = React.useCallback((adjustment: number) => {
|
|
||||||
setGpuCount((prevCount) =>
|
|
||||||
Math.max(1, Math.min(99, prevCount + adjustment))
|
|
||||||
)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const handleGpuInputChange = React.useCallback(
|
|
||||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
const value = parseInt(e.target.value, 10)
|
|
||||||
if (!isNaN(value) && value >= 1 && value <= 99) {
|
|
||||||
setGpuCount(value)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[]
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FieldSet>
|
|
||||||
<FieldGroup>
|
|
||||||
<FieldSet>
|
|
||||||
<FieldLegend>Compute Environment</FieldLegend>
|
|
||||||
<FieldDescription>
|
|
||||||
Select the compute environment for your cluster.
|
|
||||||
</FieldDescription>
|
|
||||||
<RadioGroup defaultValue="kubernetes">
|
|
||||||
<FieldLabel htmlFor="kubernetes-r2h">
|
|
||||||
<Field orientation="horizontal">
|
|
||||||
<FieldContent>
|
|
||||||
<FieldTitle>Kubernetes</FieldTitle>
|
|
||||||
<FieldDescription>
|
|
||||||
Run GPU workloads on a K8s configured cluster. This is the
|
|
||||||
default.
|
|
||||||
</FieldDescription>
|
|
||||||
</FieldContent>
|
|
||||||
<RadioGroupItem
|
|
||||||
value="kubernetes"
|
|
||||||
id="kubernetes-r2h"
|
|
||||||
aria-label="Kubernetes"
|
|
||||||
/>
|
|
||||||
</Field>
|
|
||||||
</FieldLabel>
|
|
||||||
<FieldLabel htmlFor="vm-z4k">
|
|
||||||
<Field orientation="horizontal">
|
|
||||||
<FieldContent>
|
|
||||||
<FieldTitle>Virtual Machine</FieldTitle>
|
|
||||||
<FieldDescription>
|
|
||||||
Access a VM configured cluster to run workloads. (Coming
|
|
||||||
soon)
|
|
||||||
</FieldDescription>
|
|
||||||
</FieldContent>
|
|
||||||
<RadioGroupItem
|
|
||||||
value="vm"
|
|
||||||
id="vm-z4k"
|
|
||||||
aria-label="Virtual Machine"
|
|
||||||
/>
|
|
||||||
</Field>
|
|
||||||
</FieldLabel>
|
|
||||||
</RadioGroup>
|
|
||||||
</FieldSet>
|
|
||||||
<FieldSeparator />
|
|
||||||
<Field orientation="horizontal">
|
|
||||||
<FieldContent>
|
|
||||||
<FieldLabel htmlFor="number-of-gpus-f6l">Number of GPUs</FieldLabel>
|
|
||||||
<FieldDescription>You can add more later.</FieldDescription>
|
|
||||||
</FieldContent>
|
|
||||||
<ButtonGroup>
|
|
||||||
<Input
|
|
||||||
id="number-of-gpus-f6l"
|
|
||||||
value={gpuCount}
|
|
||||||
onChange={handleGpuInputChange}
|
|
||||||
size={3}
|
|
||||||
className="h-7 w-14! font-mono"
|
|
||||||
maxLength={3}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="icon-sm"
|
|
||||||
type="button"
|
|
||||||
aria-label="Decrement"
|
|
||||||
onClick={() => handleGpuAdjustment(-1)}
|
|
||||||
disabled={gpuCount <= 1}
|
|
||||||
>
|
|
||||||
<IconMinus />
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="icon-sm"
|
|
||||||
type="button"
|
|
||||||
aria-label="Increment"
|
|
||||||
onClick={() => handleGpuAdjustment(1)}
|
|
||||||
disabled={gpuCount >= 99}
|
|
||||||
>
|
|
||||||
<IconPlus />
|
|
||||||
</Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
</Field>
|
|
||||||
<FieldSeparator />
|
|
||||||
<Field orientation="horizontal">
|
|
||||||
<FieldContent>
|
|
||||||
<FieldLabel htmlFor="tinting">Wallpaper Tinting</FieldLabel>
|
|
||||||
<FieldDescription>
|
|
||||||
Allow the wallpaper to be tinted.
|
|
||||||
</FieldDescription>
|
|
||||||
</FieldContent>
|
|
||||||
<Switch id="tinting" defaultChecked />
|
|
||||||
</Field>
|
|
||||||
</FieldGroup>
|
|
||||||
</FieldSet>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import * as React from "react"
|
|
||||||
import {
|
|
||||||
ArchiveIcon,
|
|
||||||
ArrowLeftIcon,
|
|
||||||
CalendarPlusIcon,
|
|
||||||
ClockIcon,
|
|
||||||
ListFilterIcon,
|
|
||||||
MailCheckIcon,
|
|
||||||
MoreHorizontalIcon,
|
|
||||||
TagIcon,
|
|
||||||
Trash2Icon,
|
|
||||||
} from "lucide-react"
|
|
||||||
|
|
||||||
import { Button } from "@/styles/radix-nova/ui/button"
|
|
||||||
import { ButtonGroup } from "@/styles/radix-nova/ui/button-group"
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuGroup,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuRadioGroup,
|
|
||||||
DropdownMenuRadioItem,
|
|
||||||
DropdownMenuSeparator,
|
|
||||||
DropdownMenuSub,
|
|
||||||
DropdownMenuSubContent,
|
|
||||||
DropdownMenuSubTrigger,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from "@/styles/radix-nova/ui/dropdown-menu"
|
|
||||||
|
|
||||||
export function ButtonGroupDemo() {
|
|
||||||
const [label, setLabel] = React.useState("personal")
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ButtonGroup>
|
|
||||||
<ButtonGroup className="hidden sm:flex">
|
|
||||||
<Button variant="outline" size="icon-sm" aria-label="Go Back">
|
|
||||||
<ArrowLeftIcon />
|
|
||||||
</Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
<ButtonGroup>
|
|
||||||
<Button variant="outline" size="sm">
|
|
||||||
Archive
|
|
||||||
</Button>
|
|
||||||
<Button variant="outline" size="sm">
|
|
||||||
Report
|
|
||||||
</Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
<ButtonGroup>
|
|
||||||
<Button variant="outline" size="sm">
|
|
||||||
Snooze
|
|
||||||
</Button>
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownMenuTrigger asChild>
|
|
||||||
<Button variant="outline" size="icon-sm" aria-label="More Options">
|
|
||||||
<MoreHorizontalIcon />
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent align="end" className="w-48">
|
|
||||||
<DropdownMenuGroup>
|
|
||||||
<DropdownMenuItem>
|
|
||||||
<MailCheckIcon />
|
|
||||||
Mark as Read
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem>
|
|
||||||
<ArchiveIcon />
|
|
||||||
Archive
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DropdownMenuGroup>
|
|
||||||
<DropdownMenuSeparator />
|
|
||||||
<DropdownMenuGroup>
|
|
||||||
<DropdownMenuItem>
|
|
||||||
<ClockIcon />
|
|
||||||
Snooze
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem>
|
|
||||||
<CalendarPlusIcon />
|
|
||||||
Add to Calendar
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem>
|
|
||||||
<ListFilterIcon />
|
|
||||||
Add to List
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuSub>
|
|
||||||
<DropdownMenuSubTrigger>
|
|
||||||
<TagIcon />
|
|
||||||
Label As...
|
|
||||||
</DropdownMenuSubTrigger>
|
|
||||||
<DropdownMenuSubContent>
|
|
||||||
<DropdownMenuRadioGroup
|
|
||||||
value={label}
|
|
||||||
onValueChange={setLabel}
|
|
||||||
>
|
|
||||||
<DropdownMenuRadioItem value="personal">
|
|
||||||
Personal
|
|
||||||
</DropdownMenuRadioItem>
|
|
||||||
<DropdownMenuRadioItem value="work">
|
|
||||||
Work
|
|
||||||
</DropdownMenuRadioItem>
|
|
||||||
<DropdownMenuRadioItem value="other">
|
|
||||||
Other
|
|
||||||
</DropdownMenuRadioItem>
|
|
||||||
</DropdownMenuRadioGroup>
|
|
||||||
</DropdownMenuSubContent>
|
|
||||||
</DropdownMenuSub>
|
|
||||||
</DropdownMenuGroup>
|
|
||||||
<DropdownMenuSeparator />
|
|
||||||
<DropdownMenuGroup>
|
|
||||||
<DropdownMenuItem variant="destructive">
|
|
||||||
<Trash2Icon />
|
|
||||||
Trash
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DropdownMenuGroup>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
</ButtonGroup>
|
|
||||||
</ButtonGroup>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import * as React from "react"
|
|
||||||
import { AudioLinesIcon, PlusIcon } from "lucide-react"
|
|
||||||
|
|
||||||
import { Button } from "@/styles/radix-nova/ui/button"
|
|
||||||
import { ButtonGroup } from "@/styles/radix-nova/ui/button-group"
|
|
||||||
import {
|
|
||||||
InputGroup,
|
|
||||||
InputGroupAddon,
|
|
||||||
InputGroupButton,
|
|
||||||
InputGroupInput,
|
|
||||||
} from "@/styles/radix-nova/ui/input-group"
|
|
||||||
import {
|
|
||||||
Tooltip,
|
|
||||||
TooltipContent,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from "@/styles/radix-nova/ui/tooltip"
|
|
||||||
|
|
||||||
export function ButtonGroupInputGroup() {
|
|
||||||
const [voiceEnabled, setVoiceEnabled] = React.useState(false)
|
|
||||||
return (
|
|
||||||
<ButtonGroup className="[--radius:9999rem]">
|
|
||||||
<ButtonGroup>
|
|
||||||
<Button variant="outline" size="icon" aria-label="Add">
|
|
||||||
<PlusIcon />
|
|
||||||
</Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
<ButtonGroup className="flex-1">
|
|
||||||
<InputGroup>
|
|
||||||
<InputGroupInput
|
|
||||||
placeholder={
|
|
||||||
voiceEnabled ? "Record and send audio..." : "Send a message..."
|
|
||||||
}
|
|
||||||
disabled={voiceEnabled}
|
|
||||||
/>
|
|
||||||
<InputGroupAddon align="inline-end">
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<InputGroupButton
|
|
||||||
onClick={() => setVoiceEnabled(!voiceEnabled)}
|
|
||||||
data-active={voiceEnabled}
|
|
||||||
className="data-[active=true]:bg-primary data-[active=true]:text-primary-foreground"
|
|
||||||
aria-pressed={voiceEnabled}
|
|
||||||
size="icon-xs"
|
|
||||||
aria-label="Voice Mode"
|
|
||||||
>
|
|
||||||
<AudioLinesIcon />
|
|
||||||
</InputGroupButton>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>Voice Mode</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</InputGroupAddon>
|
|
||||||
</InputGroup>
|
|
||||||
</ButtonGroup>
|
|
||||||
</ButtonGroup>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react"
|
|
||||||
|
|
||||||
import { Button } from "@/styles/radix-nova/ui/button"
|
|
||||||
import { ButtonGroup } from "@/styles/radix-nova/ui/button-group"
|
|
||||||
|
|
||||||
export function ButtonGroupNested() {
|
|
||||||
return (
|
|
||||||
<ButtonGroup>
|
|
||||||
<ButtonGroup>
|
|
||||||
<Button variant="outline" size="sm">
|
|
||||||
1
|
|
||||||
</Button>
|
|
||||||
<Button variant="outline" size="sm">
|
|
||||||
2
|
|
||||||
</Button>
|
|
||||||
<Button variant="outline" size="sm">
|
|
||||||
3
|
|
||||||
</Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
<ButtonGroup>
|
|
||||||
<Button variant="outline" size="icon-sm" aria-label="Previous">
|
|
||||||
<ArrowLeftIcon />
|
|
||||||
</Button>
|
|
||||||
<Button variant="outline" size="icon-sm" aria-label="Next">
|
|
||||||
<ArrowRightIcon />
|
|
||||||
</Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
</ButtonGroup>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import { BotIcon, ChevronDownIcon } from "lucide-react"
|
|
||||||
|
|
||||||
import { Button } from "@/styles/radix-nova/ui/button"
|
|
||||||
import { ButtonGroup } from "@/styles/radix-nova/ui/button-group"
|
|
||||||
import {
|
|
||||||
Popover,
|
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
|
||||||
} from "@/styles/radix-nova/ui/popover"
|
|
||||||
import { Separator } from "@/styles/radix-nova/ui/separator"
|
|
||||||
import { Textarea } from "@/styles/radix-nova/ui/textarea"
|
|
||||||
|
|
||||||
export function ButtonGroupPopover() {
|
|
||||||
return (
|
|
||||||
<ButtonGroup>
|
|
||||||
<Button variant="outline" size="sm">
|
|
||||||
<BotIcon /> Copilot
|
|
||||||
</Button>
|
|
||||||
<Popover>
|
|
||||||
<PopoverTrigger asChild>
|
|
||||||
<Button variant="outline" size="icon-sm" aria-label="Open Popover">
|
|
||||||
<ChevronDownIcon />
|
|
||||||
</Button>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent align="end" className="gap-0 rounded-xl p-0 text-sm">
|
|
||||||
<div className="px-4 py-3">
|
|
||||||
<div className="text-sm font-medium">Agent Tasks</div>
|
|
||||||
</div>
|
|
||||||
<Separator />
|
|
||||||
<div className="p-4 text-sm *:[p:not(:last-child)]:mb-2">
|
|
||||||
<Textarea
|
|
||||||
placeholder="Describe your task in natural language."
|
|
||||||
className="mb-4 resize-none"
|
|
||||||
/>
|
|
||||||
<p className="font-medium">Start a new task with Copilot</p>
|
|
||||||
<p className="text-muted-foreground">
|
|
||||||
Describe your task in natural language. Copilot will work in the
|
|
||||||
background and open a pull request for your review.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
</ButtonGroup>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
import { PlusIcon } from "lucide-react"
|
|
||||||
|
|
||||||
import {
|
|
||||||
Avatar,
|
|
||||||
AvatarFallback,
|
|
||||||
AvatarGroup,
|
|
||||||
AvatarImage,
|
|
||||||
} from "@/styles/radix-nova/ui/avatar"
|
|
||||||
import { Button } from "@/styles/radix-nova/ui/button"
|
|
||||||
import {
|
|
||||||
Empty,
|
|
||||||
EmptyContent,
|
|
||||||
EmptyDescription,
|
|
||||||
EmptyHeader,
|
|
||||||
EmptyMedia,
|
|
||||||
EmptyTitle,
|
|
||||||
} from "@/styles/radix-nova/ui/empty"
|
|
||||||
|
|
||||||
export function EmptyAvatarGroup() {
|
|
||||||
return (
|
|
||||||
<Empty className="flex-none border py-10">
|
|
||||||
<EmptyHeader>
|
|
||||||
<EmptyMedia>
|
|
||||||
<AvatarGroup className="grayscale">
|
|
||||||
<Avatar>
|
|
||||||
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
|
|
||||||
<AvatarFallback>CN</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
<Avatar>
|
|
||||||
<AvatarImage
|
|
||||||
src="https://github.com/maxleiter.png"
|
|
||||||
alt="@maxleiter"
|
|
||||||
/>
|
|
||||||
<AvatarFallback>LR</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
<Avatar>
|
|
||||||
<AvatarImage
|
|
||||||
src="https://github.com/evilrabbit.png"
|
|
||||||
alt="@evilrabbit"
|
|
||||||
/>
|
|
||||||
<AvatarFallback>ER</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
</AvatarGroup>
|
|
||||||
</EmptyMedia>
|
|
||||||
<EmptyTitle>No Team Members</EmptyTitle>
|
|
||||||
<EmptyDescription>
|
|
||||||
Invite your team to collaborate on this project.
|
|
||||||
</EmptyDescription>
|
|
||||||
</EmptyHeader>
|
|
||||||
<EmptyContent>
|
|
||||||
<Button size="sm">
|
|
||||||
<PlusIcon />
|
|
||||||
Invite Members
|
|
||||||
</Button>
|
|
||||||
</EmptyContent>
|
|
||||||
</Empty>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
import { SearchIcon } from "lucide-react"
|
|
||||||
|
|
||||||
import {
|
|
||||||
Empty,
|
|
||||||
EmptyContent,
|
|
||||||
EmptyDescription,
|
|
||||||
EmptyHeader,
|
|
||||||
EmptyTitle,
|
|
||||||
} from "@/registry/new-york-v4/ui/empty"
|
|
||||||
import {
|
|
||||||
InputGroup,
|
|
||||||
InputGroupAddon,
|
|
||||||
InputGroupInput,
|
|
||||||
} from "@/registry/new-york-v4/ui/input-group"
|
|
||||||
import { Kbd } from "@/registry/new-york-v4/ui/kbd"
|
|
||||||
|
|
||||||
export function EmptyInputGroup() {
|
|
||||||
return (
|
|
||||||
<Empty>
|
|
||||||
<EmptyHeader>
|
|
||||||
<EmptyTitle>404 - Not Found</EmptyTitle>
|
|
||||||
<EmptyDescription>
|
|
||||||
The page you're looking for doesn't exist. Try searching for
|
|
||||||
what you need below.
|
|
||||||
</EmptyDescription>
|
|
||||||
</EmptyHeader>
|
|
||||||
<EmptyContent>
|
|
||||||
<InputGroup className="w-3/4">
|
|
||||||
<InputGroupInput placeholder="Try searching for pages..." />
|
|
||||||
<InputGroupAddon>
|
|
||||||
<SearchIcon />
|
|
||||||
</InputGroupAddon>
|
|
||||||
<InputGroupAddon align="inline-end">
|
|
||||||
<Kbd>/</Kbd>
|
|
||||||
</InputGroupAddon>
|
|
||||||
</InputGroup>
|
|
||||||
<EmptyDescription>
|
|
||||||
Need help? <a href="#">Contact support</a>
|
|
||||||
</EmptyDescription>
|
|
||||||
</EmptyContent>
|
|
||||||
</Empty>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import { Checkbox } from "@/styles/radix-nova/ui/checkbox"
|
|
||||||
import { Field, FieldLabel } from "@/styles/radix-nova/ui/field"
|
|
||||||
|
|
||||||
export function FieldCheckbox() {
|
|
||||||
return (
|
|
||||||
<FieldLabel htmlFor="checkbox-demo">
|
|
||||||
<Field orientation="horizontal">
|
|
||||||
<Checkbox id="checkbox-demo" defaultChecked />
|
|
||||||
<FieldLabel htmlFor="checkbox-demo" className="line-clamp-1">
|
|
||||||
I agree to the terms and conditions
|
|
||||||
</FieldLabel>
|
|
||||||
</Field>
|
|
||||||
</FieldLabel>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
import {
|
|
||||||
Field,
|
|
||||||
FieldContent,
|
|
||||||
FieldDescription,
|
|
||||||
FieldGroup,
|
|
||||||
FieldLabel,
|
|
||||||
FieldSet,
|
|
||||||
FieldTitle,
|
|
||||||
} from "@/registry/new-york-v4/ui/field"
|
|
||||||
import {
|
|
||||||
RadioGroup,
|
|
||||||
RadioGroupItem,
|
|
||||||
} from "@/registry/new-york-v4/ui/radio-group"
|
|
||||||
|
|
||||||
export function FieldChoiceCard() {
|
|
||||||
return (
|
|
||||||
<div className="w-full max-w-md">
|
|
||||||
<FieldGroup>
|
|
||||||
<FieldSet>
|
|
||||||
<FieldLabel htmlFor="compute-environment-p8w">
|
|
||||||
Compute Environment
|
|
||||||
</FieldLabel>
|
|
||||||
<FieldDescription>
|
|
||||||
Select the compute environment for your cluster.
|
|
||||||
</FieldDescription>
|
|
||||||
<RadioGroup defaultValue="kubernetes">
|
|
||||||
<FieldLabel htmlFor="kubernetes-r2h">
|
|
||||||
<Field orientation="horizontal">
|
|
||||||
<RadioGroupItem
|
|
||||||
value="kubernetes"
|
|
||||||
id="kubernetes-r2h"
|
|
||||||
aria-label="Kubernetes"
|
|
||||||
/>
|
|
||||||
<FieldContent>
|
|
||||||
<FieldTitle>Kubernetes</FieldTitle>
|
|
||||||
<FieldDescription>
|
|
||||||
Run GPU workloads on a K8s configured cluster.
|
|
||||||
</FieldDescription>
|
|
||||||
</FieldContent>
|
|
||||||
</Field>
|
|
||||||
</FieldLabel>
|
|
||||||
<FieldLabel htmlFor="vm-z4k">
|
|
||||||
<Field orientation="horizontal">
|
|
||||||
<RadioGroupItem
|
|
||||||
value="vm"
|
|
||||||
id="vm-z4k"
|
|
||||||
aria-label="Virtual Machine"
|
|
||||||
/>
|
|
||||||
<FieldContent>
|
|
||||||
<FieldTitle>Virtual Machine</FieldTitle>
|
|
||||||
<FieldDescription>
|
|
||||||
Access a VM configured cluster to run workloads.
|
|
||||||
</FieldDescription>
|
|
||||||
</FieldContent>
|
|
||||||
</Field>
|
|
||||||
</FieldLabel>
|
|
||||||
</RadioGroup>
|
|
||||||
</FieldSet>
|
|
||||||
</FieldGroup>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
import { Button } from "@/styles/radix-nova/ui/button"
|
|
||||||
import { Checkbox } from "@/styles/radix-nova/ui/checkbox"
|
|
||||||
import {
|
|
||||||
Field,
|
|
||||||
FieldDescription,
|
|
||||||
FieldGroup,
|
|
||||||
FieldLabel,
|
|
||||||
FieldLegend,
|
|
||||||
FieldSeparator,
|
|
||||||
FieldSet,
|
|
||||||
} from "@/styles/radix-nova/ui/field"
|
|
||||||
import { Input } from "@/styles/radix-nova/ui/input"
|
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectGroup,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue,
|
|
||||||
} from "@/styles/radix-nova/ui/select"
|
|
||||||
import { Textarea } from "@/styles/radix-nova/ui/textarea"
|
|
||||||
|
|
||||||
export function FieldDemo() {
|
|
||||||
return (
|
|
||||||
<div className="w-full max-w-md rounded-xl border p-6">
|
|
||||||
<form>
|
|
||||||
<FieldGroup>
|
|
||||||
<FieldSet>
|
|
||||||
<FieldLegend>Payment Method</FieldLegend>
|
|
||||||
<FieldDescription>
|
|
||||||
All transactions are secure and encrypted
|
|
||||||
</FieldDescription>
|
|
||||||
<FieldGroup>
|
|
||||||
<Field>
|
|
||||||
<FieldLabel htmlFor="checkout-7j9-card-name-43j">
|
|
||||||
Name on Card
|
|
||||||
</FieldLabel>
|
|
||||||
<Input
|
|
||||||
id="checkout-7j9-card-name-43j"
|
|
||||||
placeholder="John Doe"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</Field>
|
|
||||||
<div className="grid grid-cols-3 gap-4">
|
|
||||||
<Field className="col-span-2">
|
|
||||||
<FieldLabel htmlFor="checkout-7j9-card-number-uw1">
|
|
||||||
Card Number
|
|
||||||
</FieldLabel>
|
|
||||||
<Input
|
|
||||||
id="checkout-7j9-card-number-uw1"
|
|
||||||
placeholder="1234 5678 9012 3456"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<FieldDescription>
|
|
||||||
Enter your 16-digit number.
|
|
||||||
</FieldDescription>
|
|
||||||
</Field>
|
|
||||||
<Field className="col-span-1">
|
|
||||||
<FieldLabel htmlFor="checkout-7j9-cvv">CVV</FieldLabel>
|
|
||||||
<Input id="checkout-7j9-cvv" placeholder="123" required />
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
|
||||||
<Field>
|
|
||||||
<FieldLabel htmlFor="checkout-7j9-exp-month-ts6">
|
|
||||||
Month
|
|
||||||
</FieldLabel>
|
|
||||||
<Select defaultValue="">
|
|
||||||
<SelectTrigger id="checkout-7j9-exp-month-ts6">
|
|
||||||
<SelectValue placeholder="MM" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectGroup>
|
|
||||||
<SelectItem value="01">01</SelectItem>
|
|
||||||
<SelectItem value="02">02</SelectItem>
|
|
||||||
<SelectItem value="03">03</SelectItem>
|
|
||||||
<SelectItem value="04">04</SelectItem>
|
|
||||||
<SelectItem value="05">05</SelectItem>
|
|
||||||
<SelectItem value="06">06</SelectItem>
|
|
||||||
<SelectItem value="07">07</SelectItem>
|
|
||||||
<SelectItem value="08">08</SelectItem>
|
|
||||||
<SelectItem value="09">09</SelectItem>
|
|
||||||
<SelectItem value="10">10</SelectItem>
|
|
||||||
<SelectItem value="11">11</SelectItem>
|
|
||||||
<SelectItem value="12">12</SelectItem>
|
|
||||||
</SelectGroup>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</Field>
|
|
||||||
<Field>
|
|
||||||
<FieldLabel htmlFor="checkout-7j9-exp-year-f59">
|
|
||||||
Year
|
|
||||||
</FieldLabel>
|
|
||||||
<Select defaultValue="">
|
|
||||||
<SelectTrigger id="checkout-7j9-exp-year-f59">
|
|
||||||
<SelectValue placeholder="YYYY" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectGroup>
|
|
||||||
<SelectItem value="2024">2024</SelectItem>
|
|
||||||
<SelectItem value="2025">2025</SelectItem>
|
|
||||||
<SelectItem value="2026">2026</SelectItem>
|
|
||||||
<SelectItem value="2027">2027</SelectItem>
|
|
||||||
<SelectItem value="2028">2028</SelectItem>
|
|
||||||
<SelectItem value="2029">2029</SelectItem>
|
|
||||||
</SelectGroup>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
</FieldGroup>
|
|
||||||
</FieldSet>
|
|
||||||
<FieldSeparator />
|
|
||||||
<FieldSet>
|
|
||||||
<FieldLegend>Billing Address</FieldLegend>
|
|
||||||
<FieldDescription>
|
|
||||||
The billing address associated with your payment method
|
|
||||||
</FieldDescription>
|
|
||||||
<FieldGroup>
|
|
||||||
<Field orientation="horizontal">
|
|
||||||
<Checkbox
|
|
||||||
id="checkout-7j9-same-as-shipping-wgm"
|
|
||||||
defaultChecked
|
|
||||||
/>
|
|
||||||
<FieldLabel
|
|
||||||
htmlFor="checkout-7j9-same-as-shipping-wgm"
|
|
||||||
className="font-normal"
|
|
||||||
>
|
|
||||||
Same as shipping address
|
|
||||||
</FieldLabel>
|
|
||||||
</Field>
|
|
||||||
</FieldGroup>
|
|
||||||
</FieldSet>
|
|
||||||
<FieldSeparator />
|
|
||||||
<FieldSet>
|
|
||||||
<FieldGroup>
|
|
||||||
<Field>
|
|
||||||
<FieldLabel htmlFor="checkout-7j9-optional-comments">
|
|
||||||
Comments
|
|
||||||
</FieldLabel>
|
|
||||||
<Textarea
|
|
||||||
id="checkout-7j9-optional-comments"
|
|
||||||
placeholder="Add any additional comments"
|
|
||||||
/>
|
|
||||||
</Field>
|
|
||||||
</FieldGroup>
|
|
||||||
</FieldSet>
|
|
||||||
<Field orientation="horizontal">
|
|
||||||
<Button type="submit">Submit</Button>
|
|
||||||
<Button variant="outline" type="button">
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</Field>
|
|
||||||
</FieldGroup>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
import { Card, CardContent } from "@/styles/radix-nova/ui/card"
|
|
||||||
import { Checkbox } from "@/styles/radix-nova/ui/checkbox"
|
|
||||||
import {
|
|
||||||
Field,
|
|
||||||
FieldDescription,
|
|
||||||
FieldGroup,
|
|
||||||
FieldLabel,
|
|
||||||
FieldLegend,
|
|
||||||
FieldSet,
|
|
||||||
FieldTitle,
|
|
||||||
} from "@/styles/radix-nova/ui/field"
|
|
||||||
|
|
||||||
const options = [
|
|
||||||
{
|
|
||||||
label: "Social Media",
|
|
||||||
value: "social-media",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
label: "Search Engine",
|
|
||||||
value: "search-engine",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Referral",
|
|
||||||
value: "referral",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Other",
|
|
||||||
value: "other",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
export function FieldHear() {
|
|
||||||
return (
|
|
||||||
<Card className="py-4 shadow-none">
|
|
||||||
<CardContent className="px-4">
|
|
||||||
<form>
|
|
||||||
<FieldGroup>
|
|
||||||
<FieldSet className="gap-4">
|
|
||||||
<FieldLegend>How did you hear about us?</FieldLegend>
|
|
||||||
<FieldDescription className="line-clamp-1">
|
|
||||||
Select the option that best describes how you heard about us.
|
|
||||||
</FieldDescription>
|
|
||||||
<FieldGroup className="flex flex-row flex-wrap gap-2 [--radius:9999rem]">
|
|
||||||
{options.map((option) => (
|
|
||||||
<FieldLabel
|
|
||||||
htmlFor={option.value}
|
|
||||||
key={option.value}
|
|
||||||
className="w-fit!"
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
orientation="horizontal"
|
|
||||||
className="gap-1.5 overflow-hidden px-3! py-1.5! transition-all duration-100 ease-linear group-has-data-[state=checked]/field-label:px-2!"
|
|
||||||
>
|
|
||||||
<Checkbox
|
|
||||||
value={option.value}
|
|
||||||
id={option.value}
|
|
||||||
defaultChecked={option.value === "social-media"}
|
|
||||||
className="-ml-6 -translate-x-1 rounded-full transition-all duration-100 ease-linear data-[state=checked]:ml-0 data-[state=checked]:translate-x-0"
|
|
||||||
/>
|
|
||||||
<FieldTitle>{option.label}</FieldTitle>
|
|
||||||
</Field>
|
|
||||||
</FieldLabel>
|
|
||||||
))}
|
|
||||||
</FieldGroup>
|
|
||||||
</FieldSet>
|
|
||||||
</FieldGroup>
|
|
||||||
</form>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import { useState } from "react"
|
|
||||||
|
|
||||||
import {
|
|
||||||
Field,
|
|
||||||
FieldDescription,
|
|
||||||
FieldTitle,
|
|
||||||
} from "@/styles/radix-nova/ui/field"
|
|
||||||
import { Slider } from "@/styles/radix-nova/ui/slider"
|
|
||||||
|
|
||||||
export function FieldSlider() {
|
|
||||||
const [value, setValue] = useState([200, 800])
|
|
||||||
return (
|
|
||||||
<div className="w-full max-w-md">
|
|
||||||
<Field>
|
|
||||||
<FieldTitle>Price Range</FieldTitle>
|
|
||||||
<FieldDescription>
|
|
||||||
Set your budget range ($
|
|
||||||
<span className="font-medium tabular-nums">{value[0]}</span> -{" "}
|
|
||||||
<span className="font-medium tabular-nums">{value[1]}</span>).
|
|
||||||
</FieldDescription>
|
|
||||||
<Slider
|
|
||||||
value={value}
|
|
||||||
onValueChange={setValue}
|
|
||||||
max={1000}
|
|
||||||
min={0}
|
|
||||||
step={10}
|
|
||||||
className="mt-2 w-full"
|
|
||||||
aria-label="Price Range"
|
|
||||||
/>
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import { FieldSeparator } from "@/styles/radix-nova/ui/field"
|
|
||||||
|
|
||||||
import { AppearanceSettings } from "./appearance-settings"
|
|
||||||
import { ButtonGroupDemo } from "./button-group-demo"
|
|
||||||
import { ButtonGroupInputGroup } from "./button-group-input-group"
|
|
||||||
import { ButtonGroupNested } from "./button-group-nested"
|
|
||||||
import { ButtonGroupPopover } from "./button-group-popover"
|
|
||||||
import { EmptyAvatarGroup } from "./empty-avatar-group"
|
|
||||||
import { FieldCheckbox } from "./field-checkbox"
|
|
||||||
import { FieldDemo } from "./field-demo"
|
|
||||||
import { FieldHear } from "./field-hear"
|
|
||||||
import { FieldSlider } from "./field-slider"
|
|
||||||
import { InputGroupButtonExample } from "./input-group-button"
|
|
||||||
import { InputGroupDemo } from "./input-group-demo"
|
|
||||||
import { ItemDemo } from "./item-demo"
|
|
||||||
import { NotionPromptForm } from "./notion-prompt-form"
|
|
||||||
import { SpinnerBadge } from "./spinner-badge"
|
|
||||||
import { SpinnerEmpty } from "./spinner-empty"
|
|
||||||
|
|
||||||
export function RootComponents() {
|
|
||||||
return (
|
|
||||||
<div className="mx-auto grid gap-8 py-1 theme-container md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 xl:gap-6 2xl:gap-8">
|
|
||||||
<div className="flex flex-col gap-6 *:[div]:w-full *:[div]:max-w-full">
|
|
||||||
<FieldDemo />
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col gap-6 *:[div]:w-full *:[div]:max-w-full">
|
|
||||||
<EmptyAvatarGroup />
|
|
||||||
<SpinnerBadge />
|
|
||||||
<ButtonGroupInputGroup />
|
|
||||||
<FieldSlider />
|
|
||||||
<InputGroupDemo />
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col gap-6 *:[div]:w-full *:[div]:max-w-full">
|
|
||||||
<InputGroupButtonExample />
|
|
||||||
<ItemDemo />
|
|
||||||
<FieldSeparator className="my-4">Appearance Settings</FieldSeparator>
|
|
||||||
<AppearanceSettings />
|
|
||||||
</div>
|
|
||||||
<div className="order-first flex flex-col gap-6 lg:hidden xl:order-last xl:flex *:[div]:w-full *:[div]:max-w-full">
|
|
||||||
<NotionPromptForm />
|
|
||||||
<ButtonGroupDemo />
|
|
||||||
<FieldCheckbox />
|
|
||||||
<div className="flex justify-between gap-4">
|
|
||||||
<ButtonGroupNested />
|
|
||||||
<ButtonGroupPopover />
|
|
||||||
</div>
|
|
||||||
<FieldHear />
|
|
||||||
<SpinnerEmpty />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import * as React from "react"
|
|
||||||
import { IconInfoCircle, IconStar } from "@tabler/icons-react"
|
|
||||||
|
|
||||||
import {
|
|
||||||
InputGroup,
|
|
||||||
InputGroupAddon,
|
|
||||||
InputGroupButton,
|
|
||||||
InputGroupInput,
|
|
||||||
} from "@/styles/radix-nova/ui/input-group"
|
|
||||||
import { Label } from "@/styles/radix-nova/ui/label"
|
|
||||||
import {
|
|
||||||
Popover,
|
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
|
||||||
} from "@/styles/radix-nova/ui/popover"
|
|
||||||
|
|
||||||
export function InputGroupButtonExample() {
|
|
||||||
const [isFavorite, setIsFavorite] = React.useState(false)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="grid w-full max-w-sm gap-6">
|
|
||||||
<Label htmlFor="input-secure-19" className="sr-only">
|
|
||||||
Input Secure
|
|
||||||
</Label>
|
|
||||||
<InputGroup className="[--radius:9999px]">
|
|
||||||
<InputGroupInput id="input-secure-19" className="pl-0.5!" />
|
|
||||||
<Popover>
|
|
||||||
<PopoverTrigger asChild>
|
|
||||||
<InputGroupAddon>
|
|
||||||
<InputGroupButton
|
|
||||||
variant="secondary"
|
|
||||||
size="icon-xs"
|
|
||||||
aria-label="Info"
|
|
||||||
>
|
|
||||||
<IconInfoCircle />
|
|
||||||
</InputGroupButton>
|
|
||||||
</InputGroupAddon>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent
|
|
||||||
align="start"
|
|
||||||
alignOffset={10}
|
|
||||||
className="flex flex-col gap-1 rounded-xl text-sm"
|
|
||||||
>
|
|
||||||
<p className="font-medium">Your connection is not secure.</p>
|
|
||||||
<p>You should not enter any sensitive information on this site.</p>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
<InputGroupAddon className="pl-1! text-muted-foreground">
|
|
||||||
https://
|
|
||||||
</InputGroupAddon>
|
|
||||||
<InputGroupAddon align="inline-end">
|
|
||||||
<InputGroupButton
|
|
||||||
onClick={() => setIsFavorite(!isFavorite)}
|
|
||||||
size="icon-xs"
|
|
||||||
aria-label="Favorite"
|
|
||||||
>
|
|
||||||
<IconStar
|
|
||||||
data-favorite={isFavorite}
|
|
||||||
className="data-[favorite=true]:fill-primary data-[favorite=true]:stroke-primary"
|
|
||||||
/>
|
|
||||||
</InputGroupButton>
|
|
||||||
</InputGroupAddon>
|
|
||||||
</InputGroup>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
import { IconCheck, IconInfoCircle, IconPlus } from "@tabler/icons-react"
|
|
||||||
import { ArrowUpIcon, Search } from "lucide-react"
|
|
||||||
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from "@/styles/radix-nova/ui/dropdown-menu"
|
|
||||||
import {
|
|
||||||
InputGroup,
|
|
||||||
InputGroupAddon,
|
|
||||||
InputGroupButton,
|
|
||||||
InputGroupInput,
|
|
||||||
InputGroupText,
|
|
||||||
InputGroupTextarea,
|
|
||||||
} from "@/styles/radix-nova/ui/input-group"
|
|
||||||
import { Separator } from "@/styles/radix-nova/ui/separator"
|
|
||||||
import {
|
|
||||||
Tooltip,
|
|
||||||
TooltipContent,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from "@/styles/radix-nova/ui/tooltip"
|
|
||||||
|
|
||||||
export function InputGroupDemo() {
|
|
||||||
return (
|
|
||||||
<div className="grid w-full max-w-sm gap-6">
|
|
||||||
<InputGroup>
|
|
||||||
<InputGroupInput placeholder="Search..." />
|
|
||||||
<InputGroupAddon>
|
|
||||||
<Search />
|
|
||||||
</InputGroupAddon>
|
|
||||||
<InputGroupAddon align="inline-end">12 results</InputGroupAddon>
|
|
||||||
</InputGroup>
|
|
||||||
<InputGroup>
|
|
||||||
<InputGroupInput placeholder="example.com" className="pl-1!" />
|
|
||||||
<InputGroupAddon>
|
|
||||||
<InputGroupText>https://</InputGroupText>
|
|
||||||
</InputGroupAddon>
|
|
||||||
<InputGroupAddon align="inline-end">
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<InputGroupButton
|
|
||||||
className="rounded-full"
|
|
||||||
size="icon-xs"
|
|
||||||
aria-label="Info"
|
|
||||||
>
|
|
||||||
<IconInfoCircle />
|
|
||||||
</InputGroupButton>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>This is content in a tooltip.</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</InputGroupAddon>
|
|
||||||
</InputGroup>
|
|
||||||
<InputGroup>
|
|
||||||
<InputGroupTextarea placeholder="Ask, Search or Chat..." />
|
|
||||||
<InputGroupAddon align="block-end">
|
|
||||||
<InputGroupButton
|
|
||||||
variant="outline"
|
|
||||||
className="rounded-full"
|
|
||||||
size="icon-xs"
|
|
||||||
aria-label="Add"
|
|
||||||
>
|
|
||||||
<IconPlus />
|
|
||||||
</InputGroupButton>
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownMenuTrigger asChild>
|
|
||||||
<InputGroupButton variant="ghost">Auto</InputGroupButton>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent side="top" align="start">
|
|
||||||
<DropdownMenuItem>Auto</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem>Agent</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem>Manual</DropdownMenuItem>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
<InputGroupText className="ml-auto">52% used</InputGroupText>
|
|
||||||
<Separator orientation="vertical" className="h-4!" />
|
|
||||||
<InputGroupButton
|
|
||||||
variant="default"
|
|
||||||
className="rounded-full"
|
|
||||||
size="icon-xs"
|
|
||||||
>
|
|
||||||
<ArrowUpIcon />
|
|
||||||
<span className="sr-only">Send</span>
|
|
||||||
</InputGroupButton>
|
|
||||||
</InputGroupAddon>
|
|
||||||
</InputGroup>
|
|
||||||
<InputGroup>
|
|
||||||
<InputGroupInput placeholder="@shadcn" />
|
|
||||||
<InputGroupAddon align="inline-end">
|
|
||||||
<div className="flex size-4 items-center justify-center rounded-full bg-primary text-foreground">
|
|
||||||
<IconCheck className="size-3 text-background" />
|
|
||||||
</div>
|
|
||||||
</InputGroupAddon>
|
|
||||||
</InputGroup>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
import {
|
|
||||||
IconBrandJavascript,
|
|
||||||
IconCopy,
|
|
||||||
IconCornerDownLeft,
|
|
||||||
IconRefresh,
|
|
||||||
} from "@tabler/icons-react"
|
|
||||||
|
|
||||||
import {
|
|
||||||
InputGroup,
|
|
||||||
InputGroupAddon,
|
|
||||||
InputGroupButton,
|
|
||||||
InputGroupText,
|
|
||||||
InputGroupTextarea,
|
|
||||||
} from "@/registry/new-york-v4/ui/input-group"
|
|
||||||
|
|
||||||
export function InputGroupTextareaExample() {
|
|
||||||
return (
|
|
||||||
<div className="grid w-full max-w-md gap-4">
|
|
||||||
<InputGroup>
|
|
||||||
<InputGroupTextarea
|
|
||||||
id="textarea-code-32"
|
|
||||||
placeholder="console.log('Hello, world!');"
|
|
||||||
className="min-h-[180px]"
|
|
||||||
/>
|
|
||||||
<InputGroupAddon align="block-end" className="border-t">
|
|
||||||
<InputGroupText>Line 1, Column 1</InputGroupText>
|
|
||||||
<InputGroupButton size="sm" className="ml-auto" variant="default">
|
|
||||||
Run <IconCornerDownLeft />
|
|
||||||
</InputGroupButton>
|
|
||||||
</InputGroupAddon>
|
|
||||||
<InputGroupAddon align="block-start" className="border-b">
|
|
||||||
<InputGroupText className="font-mono font-medium">
|
|
||||||
<IconBrandJavascript />
|
|
||||||
script.js
|
|
||||||
</InputGroupText>
|
|
||||||
<InputGroupButton className="ml-auto">
|
|
||||||
<IconRefresh />
|
|
||||||
</InputGroupButton>
|
|
||||||
<InputGroupButton variant="ghost">
|
|
||||||
<IconCopy />
|
|
||||||
</InputGroupButton>
|
|
||||||
</InputGroupAddon>
|
|
||||||
</InputGroup>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
import { Plus } from "lucide-react"
|
|
||||||
|
|
||||||
import {
|
|
||||||
Avatar,
|
|
||||||
AvatarFallback,
|
|
||||||
AvatarImage,
|
|
||||||
} from "@/registry/new-york-v4/ui/avatar"
|
|
||||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
|
||||||
import {
|
|
||||||
Item,
|
|
||||||
ItemActions,
|
|
||||||
ItemContent,
|
|
||||||
ItemDescription,
|
|
||||||
ItemMedia,
|
|
||||||
ItemTitle,
|
|
||||||
} from "@/registry/new-york-v4/ui/item"
|
|
||||||
|
|
||||||
export function ItemAvatar() {
|
|
||||||
return (
|
|
||||||
<div className="flex w-full max-w-lg flex-col gap-6">
|
|
||||||
<Item variant="outline" className="hidden">
|
|
||||||
<ItemMedia>
|
|
||||||
<Avatar className="size-10">
|
|
||||||
<AvatarImage src="https://github.com/maxleiter.png" />
|
|
||||||
<AvatarFallback>LR</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
</ItemMedia>
|
|
||||||
<ItemContent>
|
|
||||||
<ItemTitle>Max Leiter</ItemTitle>
|
|
||||||
<ItemDescription>Last seen 5 months ago</ItemDescription>
|
|
||||||
</ItemContent>
|
|
||||||
<ItemActions>
|
|
||||||
<Button
|
|
||||||
size="icon-sm"
|
|
||||||
variant="outline"
|
|
||||||
className="rounded-full"
|
|
||||||
aria-label="Invite"
|
|
||||||
>
|
|
||||||
<Plus />
|
|
||||||
</Button>
|
|
||||||
</ItemActions>
|
|
||||||
</Item>
|
|
||||||
<Item variant="outline">
|
|
||||||
<ItemMedia>
|
|
||||||
<div className="flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background *:data-[slot=avatar]:grayscale">
|
|
||||||
<Avatar className="hidden sm:flex">
|
|
||||||
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
|
|
||||||
<AvatarFallback>CN</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
<Avatar className="hidden sm:flex">
|
|
||||||
<AvatarImage
|
|
||||||
src="https://github.com/maxleiter.png"
|
|
||||||
alt="@maxleiter"
|
|
||||||
/>
|
|
||||||
<AvatarFallback>LR</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
<Avatar>
|
|
||||||
<AvatarImage
|
|
||||||
src="https://github.com/evilrabbit.png"
|
|
||||||
alt="@evilrabbit"
|
|
||||||
/>
|
|
||||||
<AvatarFallback>ER</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
</div>
|
|
||||||
</ItemMedia>
|
|
||||||
<ItemContent>
|
|
||||||
<ItemTitle>No Team Members</ItemTitle>
|
|
||||||
<ItemDescription>Invite your team to collaborate.</ItemDescription>
|
|
||||||
</ItemContent>
|
|
||||||
<ItemActions>
|
|
||||||
<Button size="sm" variant="outline">
|
|
||||||
Invite
|
|
||||||
</Button>
|
|
||||||
</ItemActions>
|
|
||||||
</Item>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
import { BadgeCheckIcon, ChevronRightIcon } from "lucide-react"
|
|
||||||
|
|
||||||
import { Button } from "@/styles/radix-nova/ui/button"
|
|
||||||
import {
|
|
||||||
Item,
|
|
||||||
ItemActions,
|
|
||||||
ItemContent,
|
|
||||||
ItemDescription,
|
|
||||||
ItemMedia,
|
|
||||||
ItemTitle,
|
|
||||||
} from "@/styles/radix-nova/ui/item"
|
|
||||||
|
|
||||||
export function ItemDemo() {
|
|
||||||
return (
|
|
||||||
<div className="flex w-full max-w-md flex-col gap-6">
|
|
||||||
<Item variant="outline">
|
|
||||||
<ItemContent>
|
|
||||||
<ItemTitle>Two-factor authentication</ItemTitle>
|
|
||||||
<ItemDescription className="text-pretty xl:hidden 2xl:block">
|
|
||||||
Verify via email or phone number.
|
|
||||||
</ItemDescription>
|
|
||||||
</ItemContent>
|
|
||||||
<ItemActions>
|
|
||||||
<Button size="sm">Enable</Button>
|
|
||||||
</ItemActions>
|
|
||||||
</Item>
|
|
||||||
<Item variant="outline" size="sm" asChild>
|
|
||||||
<a href="#">
|
|
||||||
<ItemMedia>
|
|
||||||
<BadgeCheckIcon className="size-5" />
|
|
||||||
</ItemMedia>
|
|
||||||
<ItemContent>
|
|
||||||
<ItemTitle>Your profile has been verified.</ItemTitle>
|
|
||||||
</ItemContent>
|
|
||||||
<ItemActions>
|
|
||||||
<ChevronRightIcon className="size-4" />
|
|
||||||
</ItemActions>
|
|
||||||
</a>
|
|
||||||
</Item>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,453 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import { useMemo, useState } from "react"
|
|
||||||
import {
|
|
||||||
IconApps,
|
|
||||||
IconArrowUp,
|
|
||||||
IconAt,
|
|
||||||
IconBook,
|
|
||||||
IconCircleDashedPlus,
|
|
||||||
IconPaperclip,
|
|
||||||
IconPlus,
|
|
||||||
IconWorld,
|
|
||||||
IconX,
|
|
||||||
} from "@tabler/icons-react"
|
|
||||||
|
|
||||||
import {
|
|
||||||
Avatar,
|
|
||||||
AvatarFallback,
|
|
||||||
AvatarImage,
|
|
||||||
} from "@/styles/radix-nova/ui/avatar"
|
|
||||||
import { Badge } from "@/styles/radix-nova/ui/badge"
|
|
||||||
import {
|
|
||||||
Command,
|
|
||||||
CommandEmpty,
|
|
||||||
CommandGroup,
|
|
||||||
CommandInput,
|
|
||||||
CommandItem,
|
|
||||||
CommandList,
|
|
||||||
} from "@/styles/radix-nova/ui/command"
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuCheckboxItem,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuGroup,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuLabel,
|
|
||||||
DropdownMenuSeparator,
|
|
||||||
DropdownMenuSub,
|
|
||||||
DropdownMenuSubContent,
|
|
||||||
DropdownMenuSubTrigger,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from "@/styles/radix-nova/ui/dropdown-menu"
|
|
||||||
import { Field, FieldLabel } from "@/styles/radix-nova/ui/field"
|
|
||||||
import {
|
|
||||||
InputGroup,
|
|
||||||
InputGroupAddon,
|
|
||||||
InputGroupButton,
|
|
||||||
InputGroupTextarea,
|
|
||||||
} from "@/styles/radix-nova/ui/input-group"
|
|
||||||
import {
|
|
||||||
Popover,
|
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
|
||||||
} from "@/styles/radix-nova/ui/popover"
|
|
||||||
import { Switch } from "@/styles/radix-nova/ui/switch"
|
|
||||||
import {
|
|
||||||
Tooltip,
|
|
||||||
TooltipContent,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from "@/styles/radix-nova/ui/tooltip"
|
|
||||||
|
|
||||||
const SAMPLE_DATA = {
|
|
||||||
mentionable: [
|
|
||||||
{
|
|
||||||
type: "page",
|
|
||||||
title: "Meeting Notes",
|
|
||||||
image: "📝",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "page",
|
|
||||||
title: "Project Dashboard",
|
|
||||||
image: "📊",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "page",
|
|
||||||
title: "Ideas & Brainstorming",
|
|
||||||
image: "💡",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "page",
|
|
||||||
title: "Calendar & Events",
|
|
||||||
image: "📅",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "page",
|
|
||||||
title: "Documentation",
|
|
||||||
image: "📚",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "page",
|
|
||||||
title: "Goals & Objectives",
|
|
||||||
image: "🎯",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "page",
|
|
||||||
title: "Budget Planning",
|
|
||||||
image: "💰",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "page",
|
|
||||||
title: "Team Directory",
|
|
||||||
image: "👥",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "page",
|
|
||||||
title: "Technical Specs",
|
|
||||||
image: "🔧",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "page",
|
|
||||||
title: "Analytics Report",
|
|
||||||
image: "📈",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "user",
|
|
||||||
title: "shadcn",
|
|
||||||
image: "https://github.com/shadcn.png",
|
|
||||||
workspace: "Workspace",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "user",
|
|
||||||
title: "maxleiter",
|
|
||||||
image: "https://github.com/maxleiter.png",
|
|
||||||
workspace: "Workspace",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "user",
|
|
||||||
title: "evilrabbit",
|
|
||||||
image: "https://github.com/evilrabbit.png",
|
|
||||||
workspace: "Workspace",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
models: [
|
|
||||||
{
|
|
||||||
name: "Auto",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Agent Mode",
|
|
||||||
badge: "Beta",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Plan Mode",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
function MentionableIcon({
|
|
||||||
item,
|
|
||||||
}: {
|
|
||||||
item: (typeof SAMPLE_DATA.mentionable)[0]
|
|
||||||
}) {
|
|
||||||
return item.type === "page" ? (
|
|
||||||
<span className="flex size-4 items-center justify-center">
|
|
||||||
{item.image}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<Avatar className="size-4">
|
|
||||||
<AvatarImage src={item.image} />
|
|
||||||
<AvatarFallback>{item.title[0]}</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function NotionPromptForm() {
|
|
||||||
const [mentions, setMentions] = useState<string[]>([])
|
|
||||||
const [mentionPopoverOpen, setMentionPopoverOpen] = useState(false)
|
|
||||||
const [modelPopoverOpen, setModelPopoverOpen] = useState(false)
|
|
||||||
const [selectedModel, setSelectedModel] = useState<
|
|
||||||
(typeof SAMPLE_DATA.models)[0]
|
|
||||||
>(SAMPLE_DATA.models[0])
|
|
||||||
const [scopeMenuOpen, setScopeMenuOpen] = useState(false)
|
|
||||||
|
|
||||||
const grouped = useMemo(() => {
|
|
||||||
return SAMPLE_DATA.mentionable.reduce(
|
|
||||||
(acc, item) => {
|
|
||||||
const isAvailable = !mentions.includes(item.title)
|
|
||||||
|
|
||||||
if (isAvailable) {
|
|
||||||
if (!acc[item.type]) {
|
|
||||||
acc[item.type] = []
|
|
||||||
}
|
|
||||||
acc[item.type].push(item)
|
|
||||||
}
|
|
||||||
return acc
|
|
||||||
},
|
|
||||||
{} as Record<string, typeof SAMPLE_DATA.mentionable>
|
|
||||||
)
|
|
||||||
}, [mentions])
|
|
||||||
|
|
||||||
const hasMentions = mentions.length > 0
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form>
|
|
||||||
<Field>
|
|
||||||
<FieldLabel htmlFor="notion-prompt" className="sr-only">
|
|
||||||
Prompt
|
|
||||||
</FieldLabel>
|
|
||||||
<InputGroup className="rounded-xl">
|
|
||||||
<InputGroupTextarea
|
|
||||||
id="notion-prompt"
|
|
||||||
placeholder="Ask, search, or make anything..."
|
|
||||||
/>
|
|
||||||
<InputGroupAddon align="block-start" className="pt-3">
|
|
||||||
<Popover
|
|
||||||
open={mentionPopoverOpen}
|
|
||||||
onOpenChange={setMentionPopoverOpen}
|
|
||||||
>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger
|
|
||||||
asChild
|
|
||||||
onFocusCapture={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
<PopoverTrigger asChild>
|
|
||||||
<InputGroupButton
|
|
||||||
variant="outline"
|
|
||||||
size={!hasMentions ? "sm" : "icon-sm"}
|
|
||||||
className="transition-transform"
|
|
||||||
>
|
|
||||||
<IconAt /> {!hasMentions && "Add context"}
|
|
||||||
</InputGroupButton>
|
|
||||||
</PopoverTrigger>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>Mention a person, page, or date</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
<PopoverContent className="p-0" align="start">
|
|
||||||
<Command>
|
|
||||||
<CommandInput placeholder="Search pages..." />
|
|
||||||
<CommandList>
|
|
||||||
<CommandEmpty>No pages found</CommandEmpty>
|
|
||||||
{Object.entries(grouped).map(([type, items]) => (
|
|
||||||
<CommandGroup
|
|
||||||
key={type}
|
|
||||||
heading={type === "page" ? "Pages" : "Users"}
|
|
||||||
>
|
|
||||||
{items.map((item) => (
|
|
||||||
<CommandItem
|
|
||||||
key={item.title}
|
|
||||||
value={item.title}
|
|
||||||
onSelect={(currentValue) => {
|
|
||||||
setMentions((prev) => [...prev, currentValue])
|
|
||||||
setMentionPopoverOpen(false)
|
|
||||||
}}
|
|
||||||
className="rounded-lg"
|
|
||||||
>
|
|
||||||
<MentionableIcon item={item} />
|
|
||||||
{item.title}
|
|
||||||
</CommandItem>
|
|
||||||
))}
|
|
||||||
</CommandGroup>
|
|
||||||
))}
|
|
||||||
</CommandList>
|
|
||||||
</Command>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
<div className="-m-1.5 no-scrollbar flex gap-1 overflow-y-auto p-1.5">
|
|
||||||
{mentions.map((mention) => {
|
|
||||||
const item = SAMPLE_DATA.mentionable.find(
|
|
||||||
(item) => item.title === mention
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!item) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<InputGroupButton
|
|
||||||
key={mention}
|
|
||||||
size="sm"
|
|
||||||
variant="secondary"
|
|
||||||
className="rounded-full pl-2!"
|
|
||||||
onClick={() => {
|
|
||||||
setMentions((prev) => prev.filter((m) => m !== mention))
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MentionableIcon item={item} />
|
|
||||||
{item.title}
|
|
||||||
<IconX />
|
|
||||||
</InputGroupButton>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</InputGroupAddon>
|
|
||||||
<InputGroupAddon align="block-end" className="gap-1">
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<InputGroupButton
|
|
||||||
size="icon-sm"
|
|
||||||
className="rounded-full"
|
|
||||||
aria-label="Attach file"
|
|
||||||
>
|
|
||||||
<IconPaperclip />
|
|
||||||
</InputGroupButton>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>Attach file</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
<DropdownMenu
|
|
||||||
open={modelPopoverOpen}
|
|
||||||
onOpenChange={setModelPopoverOpen}
|
|
||||||
>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<DropdownMenuTrigger asChild>
|
|
||||||
<InputGroupButton size="sm" className="rounded-full">
|
|
||||||
{selectedModel.name}
|
|
||||||
</InputGroupButton>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>Select AI model</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
<DropdownMenuContent
|
|
||||||
side="top"
|
|
||||||
align="start"
|
|
||||||
className="min-w-48"
|
|
||||||
>
|
|
||||||
<DropdownMenuGroup>
|
|
||||||
<DropdownMenuLabel className="text-xs text-muted-foreground">
|
|
||||||
Select Agent Mode
|
|
||||||
</DropdownMenuLabel>
|
|
||||||
{SAMPLE_DATA.models.map((model) => (
|
|
||||||
<DropdownMenuCheckboxItem
|
|
||||||
key={model.name}
|
|
||||||
checked={model.name === selectedModel.name}
|
|
||||||
onCheckedChange={(checked) => {
|
|
||||||
if (checked) {
|
|
||||||
setSelectedModel(model)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className="pl-2 *:[span:first-child]:right-2 *:[span:first-child]:left-auto"
|
|
||||||
>
|
|
||||||
{model.name}
|
|
||||||
{model.badge && (
|
|
||||||
<Badge
|
|
||||||
variant="secondary"
|
|
||||||
className="h-5 rounded-sm bg-blue-100 px-1 text-xs text-blue-800 dark:bg-blue-900 dark:text-blue-100"
|
|
||||||
>
|
|
||||||
{model.badge}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</DropdownMenuCheckboxItem>
|
|
||||||
))}
|
|
||||||
</DropdownMenuGroup>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
<DropdownMenu open={scopeMenuOpen} onOpenChange={setScopeMenuOpen}>
|
|
||||||
<DropdownMenuTrigger asChild>
|
|
||||||
<InputGroupButton size="sm" className="rounded-full">
|
|
||||||
<IconWorld /> All Sources
|
|
||||||
</InputGroupButton>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent side="top" align="end" className="w-72">
|
|
||||||
<DropdownMenuGroup>
|
|
||||||
<DropdownMenuItem
|
|
||||||
asChild
|
|
||||||
onSelect={(e) => e.preventDefault()}
|
|
||||||
>
|
|
||||||
<label htmlFor="web-search">
|
|
||||||
<IconWorld /> Web Search{" "}
|
|
||||||
<Switch
|
|
||||||
id="web-search"
|
|
||||||
className="ml-auto"
|
|
||||||
defaultChecked
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DropdownMenuGroup>
|
|
||||||
<DropdownMenuSeparator />
|
|
||||||
<DropdownMenuGroup>
|
|
||||||
<DropdownMenuItem
|
|
||||||
asChild
|
|
||||||
onSelect={(e) => e.preventDefault()}
|
|
||||||
>
|
|
||||||
<label htmlFor="apps">
|
|
||||||
<IconApps /> Apps and Integrations
|
|
||||||
<Switch id="apps" className="ml-auto" defaultChecked />
|
|
||||||
</label>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem>
|
|
||||||
<IconCircleDashedPlus /> All Sources I can access
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuSub>
|
|
||||||
<DropdownMenuSubTrigger>
|
|
||||||
<Avatar className="size-4">
|
|
||||||
<AvatarImage src="https://github.com/shadcn.png" />
|
|
||||||
<AvatarFallback>CN</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
shadcn
|
|
||||||
</DropdownMenuSubTrigger>
|
|
||||||
<DropdownMenuSubContent className="w-72 p-0 [--radius:1rem]">
|
|
||||||
<Command>
|
|
||||||
<CommandInput
|
|
||||||
placeholder="Find or use knowledge in..."
|
|
||||||
autoFocus
|
|
||||||
/>
|
|
||||||
<CommandList>
|
|
||||||
<CommandEmpty>No knowledge found</CommandEmpty>
|
|
||||||
<CommandGroup>
|
|
||||||
{SAMPLE_DATA.mentionable
|
|
||||||
.filter((item) => item.type === "user")
|
|
||||||
.map((user) => (
|
|
||||||
<CommandItem
|
|
||||||
key={user.title}
|
|
||||||
value={user.title}
|
|
||||||
onSelect={() => {
|
|
||||||
// Handle user selection here
|
|
||||||
console.log("Selected user:", user.title)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Avatar className="size-4">
|
|
||||||
<AvatarImage src={user.image} />
|
|
||||||
<AvatarFallback>
|
|
||||||
{user.title[0]}
|
|
||||||
</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
{user.title}{" "}
|
|
||||||
<span className="text-muted-foreground">
|
|
||||||
- {user.workspace}
|
|
||||||
</span>
|
|
||||||
</CommandItem>
|
|
||||||
))}
|
|
||||||
</CommandGroup>
|
|
||||||
</CommandList>
|
|
||||||
</Command>
|
|
||||||
</DropdownMenuSubContent>
|
|
||||||
</DropdownMenuSub>
|
|
||||||
<DropdownMenuItem>
|
|
||||||
<IconBook /> Help Center
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DropdownMenuGroup>
|
|
||||||
<DropdownMenuSeparator />
|
|
||||||
<DropdownMenuGroup>
|
|
||||||
<DropdownMenuItem>
|
|
||||||
<IconPlus /> Connect Apps
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuLabel className="text-xs text-muted-foreground">
|
|
||||||
We'll only search in the sources selected here.
|
|
||||||
</DropdownMenuLabel>
|
|
||||||
</DropdownMenuGroup>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
<InputGroupButton
|
|
||||||
aria-label="Send"
|
|
||||||
className="ml-auto rounded-full"
|
|
||||||
variant="default"
|
|
||||||
size="icon-sm"
|
|
||||||
>
|
|
||||||
<IconArrowUp />
|
|
||||||
</InputGroupButton>
|
|
||||||
</InputGroupAddon>
|
|
||||||
</InputGroup>
|
|
||||||
</Field>
|
|
||||||
</form>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import { Badge } from "@/styles/radix-nova/ui/badge"
|
|
||||||
import { Spinner } from "@/styles/radix-nova/ui/spinner"
|
|
||||||
|
|
||||||
export function SpinnerBadge() {
|
|
||||||
return (
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Badge>
|
|
||||||
<Spinner />
|
|
||||||
Syncing
|
|
||||||
</Badge>
|
|
||||||
<Badge variant="secondary">
|
|
||||||
<Spinner />
|
|
||||||
Updating
|
|
||||||
</Badge>
|
|
||||||
<Badge variant="outline">
|
|
||||||
<Spinner />
|
|
||||||
Loading
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
import { Button } from "@/styles/radix-nova/ui/button"
|
|
||||||
import {
|
|
||||||
Empty,
|
|
||||||
EmptyContent,
|
|
||||||
EmptyDescription,
|
|
||||||
EmptyHeader,
|
|
||||||
EmptyMedia,
|
|
||||||
EmptyTitle,
|
|
||||||
} from "@/styles/radix-nova/ui/empty"
|
|
||||||
import { Spinner } from "@/styles/radix-nova/ui/spinner"
|
|
||||||
|
|
||||||
export function SpinnerEmpty() {
|
|
||||||
return (
|
|
||||||
<Empty className="w-full border md:p-6">
|
|
||||||
<EmptyHeader>
|
|
||||||
<EmptyMedia variant="icon">
|
|
||||||
<Spinner />
|
|
||||||
</EmptyMedia>
|
|
||||||
<EmptyTitle>Processing your request</EmptyTitle>
|
|
||||||
<EmptyDescription>
|
|
||||||
Please wait while we process your request. Do not refresh the page.
|
|
||||||
</EmptyDescription>
|
|
||||||
</EmptyHeader>
|
|
||||||
<EmptyContent>
|
|
||||||
<Button variant="outline" size="sm">
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</EmptyContent>
|
|
||||||
</Empty>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { type Metadata } from "next"
|
import { type Metadata } from "next"
|
||||||
import Image from "next/image"
|
import Image from "next/image"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
|
import { IconArrowRight } from "@tabler/icons-react"
|
||||||
|
|
||||||
import { Announcement } from "@/components/announcement"
|
import { Announcement } from "@/components/announcement"
|
||||||
import {
|
import {
|
||||||
@@ -9,9 +10,9 @@ import {
|
|||||||
PageHeaderDescription,
|
PageHeaderDescription,
|
||||||
PageHeaderHeading,
|
PageHeaderHeading,
|
||||||
} from "@/components/page-header"
|
} from "@/components/page-header"
|
||||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
import { Button } from "@/styles/radix-nova/ui/button"
|
||||||
|
|
||||||
import { RootComponents } from "./components"
|
import { CardsDemo } from "./cards"
|
||||||
|
|
||||||
const title = "The Foundation for your Design System"
|
const title = "The Foundation for your Design System"
|
||||||
const description =
|
const description =
|
||||||
@@ -47,21 +48,20 @@ export const metadata: Metadata = {
|
|||||||
export default function IndexPage() {
|
export default function IndexPage() {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-1 flex-col">
|
<div className="flex flex-1 flex-col">
|
||||||
<PageHeader>
|
<PageHeader className="md:**:[.container]:pb-8 lg:**:[.container]:pb-12">
|
||||||
<Announcement />
|
<Announcement />
|
||||||
<PageHeaderHeading className="max-w-4xl">{title}</PageHeaderHeading>
|
<PageHeaderHeading className="max-w-4xl">{title}</PageHeaderHeading>
|
||||||
<PageHeaderDescription>{description}</PageHeaderDescription>
|
<PageHeaderDescription>{description}</PageHeaderDescription>
|
||||||
<PageActions>
|
<PageActions>
|
||||||
<Button asChild size="sm" className="h-[31px] rounded-lg">
|
<Button asChild className="h-[31px] rounded-lg">
|
||||||
<Link href="/create">New Project</Link>
|
<Link href="/create?preset=b27GcrRo">
|
||||||
</Button>
|
Build Your Own <IconArrowRight data-icon="inline-end" />
|
||||||
<Button asChild size="sm" variant="ghost" className="rounded-lg">
|
</Link>
|
||||||
<Link href="/docs/components">View Components</Link>
|
|
||||||
</Button>
|
</Button>
|
||||||
</PageActions>
|
</PageActions>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
<div className="container-wrapper flex-1 pb-6">
|
<div className="container-wrapper flex-1 pb-6 md:px-0">
|
||||||
<div className="container overflow-hidden">
|
<div className="container overflow-hidden md:px-0 lg:max-w-none">
|
||||||
<section className="-mx-4 w-[160vw] overflow-hidden rounded-lg border border-border/50 md:hidden md:w-[150vw]">
|
<section className="-mx-4 w-[160vw] overflow-hidden rounded-lg border border-border/50 md:hidden md:w-[150vw]">
|
||||||
<Image
|
<Image
|
||||||
src="/r/styles/new-york-v4/dashboard-01-light.png"
|
src="/r/styles/new-york-v4/dashboard-01-light.png"
|
||||||
@@ -80,8 +80,8 @@ export default function IndexPage() {
|
|||||||
priority
|
priority
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
<section className="hidden theme-container md:block">
|
<section className="hidden md:block">
|
||||||
<RootComponents />
|
<CardsDemo />
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export function Customizer({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
className="dark top-24 right-12 isolate z-10 max-h-full min-h-0 w-full self-start rounded-2xl bg-card/90 shadow-xl backdrop-blur-xl md:w-(--customizer-width)"
|
className="dark top-24 right-12 isolate z-10 max-h-full min-h-0 w-full self-start rounded-2xl bg-card/90 backdrop-blur-xl md:w-(--customizer-width)"
|
||||||
ref={anchorRef}
|
ref={anchorRef}
|
||||||
size="sm"
|
size="sm"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -143,6 +143,11 @@ export function DesignSystemProvider({
|
|||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (style === "lyra" || (style === "sera" && radius !== "none")) {
|
if (style === "lyra" || (style === "sera" && radius !== "none")) {
|
||||||
setSearchParams({ radius: "none" })
|
setSearchParams({ radius: "none" })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (style === "rhea" && radius === "large") {
|
||||||
|
setSearchParams({ radius: "default" })
|
||||||
}
|
}
|
||||||
}, [style, radius, setSearchParams])
|
}, [style, radius, setSearchParams])
|
||||||
|
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ export function RadiusPicker({
|
|||||||
key={radius.name}
|
key={radius.name}
|
||||||
value={radius.name}
|
value={radius.name}
|
||||||
closeOnClick={isMobile}
|
closeOnClick={isMobile}
|
||||||
|
disabled={params.style === "rhea" && radius.name === "large"}
|
||||||
>
|
>
|
||||||
{radius.label}
|
{radius.label}
|
||||||
</PickerRadioItem>
|
</PickerRadioItem>
|
||||||
|
|||||||
@@ -1,195 +1,14 @@
|
|||||||
import {
|
|
||||||
DM_Sans,
|
|
||||||
EB_Garamond,
|
|
||||||
Figtree,
|
|
||||||
Geist,
|
|
||||||
Geist_Mono,
|
|
||||||
IBM_Plex_Sans,
|
|
||||||
Instrument_Sans,
|
|
||||||
Instrument_Serif,
|
|
||||||
Inter,
|
|
||||||
JetBrains_Mono,
|
|
||||||
Lora,
|
|
||||||
Manrope,
|
|
||||||
Merriweather,
|
|
||||||
Montserrat,
|
|
||||||
Noto_Sans,
|
|
||||||
Noto_Serif,
|
|
||||||
Nunito_Sans,
|
|
||||||
Outfit,
|
|
||||||
Oxanium,
|
|
||||||
Playfair_Display,
|
|
||||||
Public_Sans,
|
|
||||||
Raleway,
|
|
||||||
Roboto,
|
|
||||||
Roboto_Slab,
|
|
||||||
Source_Sans_3,
|
|
||||||
Space_Grotesk,
|
|
||||||
} from "next/font/google"
|
|
||||||
|
|
||||||
import { FONT_DEFINITIONS, type FontName } from "@/lib/font-definitions"
|
import { FONT_DEFINITIONS, type FontName } from "@/lib/font-definitions"
|
||||||
|
|
||||||
type PreviewFont = ReturnType<typeof Inter>
|
type CreateFont = {
|
||||||
|
family: string
|
||||||
const geistSans = Geist({
|
import: string
|
||||||
subsets: ["latin"],
|
previewVariable: string
|
||||||
variable: "--font-geist-sans",
|
style: {
|
||||||
})
|
fontFamily: string
|
||||||
|
}
|
||||||
const inter = Inter({
|
variable: string
|
||||||
subsets: ["latin"],
|
}
|
||||||
variable: "--font-inter",
|
|
||||||
})
|
|
||||||
|
|
||||||
const notoSans = Noto_Sans({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-noto-sans",
|
|
||||||
})
|
|
||||||
|
|
||||||
const nunitoSans = Nunito_Sans({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-nunito-sans",
|
|
||||||
})
|
|
||||||
|
|
||||||
const figtree = Figtree({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-figtree",
|
|
||||||
})
|
|
||||||
|
|
||||||
const roboto = Roboto({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-roboto",
|
|
||||||
})
|
|
||||||
|
|
||||||
const raleway = Raleway({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-raleway",
|
|
||||||
})
|
|
||||||
|
|
||||||
const dmSans = DM_Sans({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-dm-sans",
|
|
||||||
})
|
|
||||||
|
|
||||||
const publicSans = Public_Sans({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-public-sans",
|
|
||||||
})
|
|
||||||
|
|
||||||
const outfit = Outfit({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-outfit",
|
|
||||||
})
|
|
||||||
|
|
||||||
const oxanium = Oxanium({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-oxanium",
|
|
||||||
})
|
|
||||||
|
|
||||||
const manrope = Manrope({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-manrope",
|
|
||||||
})
|
|
||||||
|
|
||||||
const spaceGrotesk = Space_Grotesk({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-space-grotesk",
|
|
||||||
})
|
|
||||||
|
|
||||||
const montserrat = Montserrat({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-montserrat",
|
|
||||||
})
|
|
||||||
|
|
||||||
const ibmPlexSans = IBM_Plex_Sans({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-ibm-plex-sans",
|
|
||||||
})
|
|
||||||
|
|
||||||
const sourceSans3 = Source_Sans_3({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-source-sans-3",
|
|
||||||
})
|
|
||||||
|
|
||||||
const instrumentSans = Instrument_Sans({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-instrument-sans",
|
|
||||||
})
|
|
||||||
|
|
||||||
const jetbrainsMono = JetBrains_Mono({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-jetbrains-mono",
|
|
||||||
})
|
|
||||||
|
|
||||||
const geistMono = Geist_Mono({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-geist-mono",
|
|
||||||
})
|
|
||||||
|
|
||||||
const notoSerif = Noto_Serif({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-noto-serif",
|
|
||||||
})
|
|
||||||
|
|
||||||
const robotoSlab = Roboto_Slab({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-roboto-slab",
|
|
||||||
})
|
|
||||||
|
|
||||||
const merriweather = Merriweather({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-merriweather",
|
|
||||||
})
|
|
||||||
|
|
||||||
const lora = Lora({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-lora",
|
|
||||||
})
|
|
||||||
|
|
||||||
const playfairDisplay = Playfair_Display({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-playfair-display",
|
|
||||||
})
|
|
||||||
|
|
||||||
const ebGaramond = EB_Garamond({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-eb-garamond",
|
|
||||||
})
|
|
||||||
|
|
||||||
const instrumentSerif = Instrument_Serif({
|
|
||||||
subsets: ["latin"],
|
|
||||||
weight: "400",
|
|
||||||
variable: "--font-instrument-serif",
|
|
||||||
})
|
|
||||||
|
|
||||||
const PREVIEW_FONTS = {
|
|
||||||
geist: geistSans,
|
|
||||||
inter,
|
|
||||||
"noto-sans": notoSans,
|
|
||||||
"nunito-sans": nunitoSans,
|
|
||||||
figtree,
|
|
||||||
roboto,
|
|
||||||
raleway,
|
|
||||||
"dm-sans": dmSans,
|
|
||||||
"public-sans": publicSans,
|
|
||||||
outfit,
|
|
||||||
oxanium,
|
|
||||||
manrope,
|
|
||||||
"space-grotesk": spaceGrotesk,
|
|
||||||
montserrat,
|
|
||||||
"ibm-plex-sans": ibmPlexSans,
|
|
||||||
"source-sans-3": sourceSans3,
|
|
||||||
"instrument-sans": instrumentSans,
|
|
||||||
"jetbrains-mono": jetbrainsMono,
|
|
||||||
"geist-mono": geistMono,
|
|
||||||
"noto-serif": notoSerif,
|
|
||||||
"roboto-slab": robotoSlab,
|
|
||||||
merriweather,
|
|
||||||
lora,
|
|
||||||
"playfair-display": playfairDisplay,
|
|
||||||
"eb-garamond": ebGaramond,
|
|
||||||
"instrument-serif": instrumentSerif,
|
|
||||||
} satisfies Record<FontName, PreviewFont>
|
|
||||||
|
|
||||||
function createFontOption(name: FontName) {
|
function createFontOption(name: FontName) {
|
||||||
const definition = FONT_DEFINITIONS.find((font) => font.name === name)
|
const definition = FONT_DEFINITIONS.find((font) => font.name === name)
|
||||||
@@ -201,7 +20,15 @@ function createFontOption(name: FontName) {
|
|||||||
return {
|
return {
|
||||||
name: definition.title,
|
name: definition.title,
|
||||||
value: definition.name,
|
value: definition.name,
|
||||||
font: PREVIEW_FONTS[name],
|
font: {
|
||||||
|
family: definition.family,
|
||||||
|
import: definition.import,
|
||||||
|
previewVariable: definition.previewVariable,
|
||||||
|
style: {
|
||||||
|
fontFamily: `var(${definition.previewVariable}), ${definition.family}`,
|
||||||
|
},
|
||||||
|
variable: definition.registryVariable,
|
||||||
|
} satisfies CreateFont,
|
||||||
type: definition.type,
|
type: definition.type,
|
||||||
} as const
|
} as const
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,11 @@ export const RANDOMIZE_BIASES: RandomizeBiases = {
|
|||||||
return radii.filter((radius) => radius.name === "none")
|
return radii.filter((radius) => radius.name === "none")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rhea does not support the "large" radius.
|
||||||
|
if (context.style === "rhea") {
|
||||||
|
return radii.filter((radius) => radius.name !== "large")
|
||||||
|
}
|
||||||
|
|
||||||
return radii
|
return radii
|
||||||
},
|
},
|
||||||
chartColors: (chartColors, context) => {
|
chartColors: (chartColors, context) => {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ export default async function Page(props: {
|
|||||||
>
|
>
|
||||||
<div className="flex min-w-0 flex-1 flex-col">
|
<div className="flex min-w-0 flex-1 flex-col">
|
||||||
<div className="h-(--top-spacing) shrink-0" />
|
<div className="h-(--top-spacing) shrink-0" />
|
||||||
<div className="mx-auto flex w-full max-w-[40rem] min-w-0 flex-1 flex-col gap-6 px-4 py-6 text-neutral-800 md:px-0 lg:py-8 dark:text-neutral-300">
|
<div className="mx-auto flex w-full max-w-160 min-w-0 flex-1 flex-col gap-6 px-4 py-6 text-foreground md:px-0 lg:py-8 dark:text-foreground">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<div className="flex items-center justify-between md:items-start">
|
<div className="flex items-center justify-between md:items-start">
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export default function ChangelogPage() {
|
|||||||
>
|
>
|
||||||
<div className="flex min-w-0 flex-1 flex-col">
|
<div className="flex min-w-0 flex-1 flex-col">
|
||||||
<div className="h-(--top-spacing) shrink-0" />
|
<div className="h-(--top-spacing) shrink-0" />
|
||||||
<div className="mx-auto flex w-full max-w-160 min-w-0 flex-1 flex-col gap-6 px-4 py-6 text-neutral-800 md:px-0 lg:py-8 dark:text-neutral-300">
|
<div className="mx-auto flex w-full max-w-160 min-w-0 flex-1 flex-col gap-6 px-4 py-6 text-foreground md:px-0 lg:py-8 dark:text-foreground">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h1 className="scroll-m-24 text-4xl font-semibold tracking-tight sm:text-3xl">
|
<h1 className="scroll-m-24 text-4xl font-semibold tracking-tight sm:text-3xl">
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import { PreviewStyle } from "@/app/(app)/create/components/preview-style"
|
|||||||
import { RandomizeScript } from "@/app/(app)/create/components/random-button"
|
import { RandomizeScript } from "@/app/(app)/create/components/random-button"
|
||||||
import { getBaseComponent, getBaseItem } from "@/app/(app)/create/lib/api"
|
import { getBaseComponent, getBaseItem } from "@/app/(app)/create/lib/api"
|
||||||
|
|
||||||
|
import "@/app/style-registry.css"
|
||||||
|
|
||||||
export const revalidate = false
|
export const revalidate = false
|
||||||
export const dynamic = "force-static"
|
export const dynamic = "force-static"
|
||||||
export const dynamicParams = true
|
export const dynamicParams = true
|
||||||
|
|||||||
21
apps/v4/app/(create)/preview/font-variables.tsx
Normal file
21
apps/v4/app/(create)/preview/font-variables.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
export function PreviewFontVariables({ className }: { className: string }) {
|
||||||
|
React.useLayoutEffect(() => {
|
||||||
|
const classNames = className.split(/\s+/).filter(Boolean)
|
||||||
|
|
||||||
|
if (!classNames.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
document.documentElement.classList.add(...classNames)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.documentElement.classList.remove(...classNames)
|
||||||
|
}
|
||||||
|
}, [className])
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
190
apps/v4/app/(create)/preview/fonts.ts
Normal file
190
apps/v4/app/(create)/preview/fonts.ts
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
import {
|
||||||
|
DM_Sans,
|
||||||
|
EB_Garamond,
|
||||||
|
Figtree,
|
||||||
|
Geist,
|
||||||
|
Geist_Mono,
|
||||||
|
IBM_Plex_Sans,
|
||||||
|
Instrument_Sans,
|
||||||
|
Instrument_Serif,
|
||||||
|
Inter,
|
||||||
|
JetBrains_Mono,
|
||||||
|
Lora,
|
||||||
|
Manrope,
|
||||||
|
Merriweather,
|
||||||
|
Montserrat,
|
||||||
|
Noto_Sans,
|
||||||
|
Noto_Serif,
|
||||||
|
Nunito_Sans,
|
||||||
|
Outfit,
|
||||||
|
Oxanium,
|
||||||
|
Playfair_Display,
|
||||||
|
Public_Sans,
|
||||||
|
Raleway,
|
||||||
|
Roboto,
|
||||||
|
Roboto_Slab,
|
||||||
|
Source_Sans_3,
|
||||||
|
Space_Grotesk,
|
||||||
|
} from "next/font/google"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const geistSans = Geist({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-geist-sans",
|
||||||
|
})
|
||||||
|
|
||||||
|
const inter = Inter({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-inter",
|
||||||
|
})
|
||||||
|
|
||||||
|
const notoSans = Noto_Sans({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-noto-sans",
|
||||||
|
})
|
||||||
|
|
||||||
|
const nunitoSans = Nunito_Sans({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-nunito-sans",
|
||||||
|
})
|
||||||
|
|
||||||
|
const figtree = Figtree({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-figtree",
|
||||||
|
})
|
||||||
|
|
||||||
|
const roboto = Roboto({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-roboto",
|
||||||
|
})
|
||||||
|
|
||||||
|
const raleway = Raleway({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-raleway",
|
||||||
|
})
|
||||||
|
|
||||||
|
const dmSans = DM_Sans({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-dm-sans",
|
||||||
|
})
|
||||||
|
|
||||||
|
const publicSans = Public_Sans({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-public-sans",
|
||||||
|
})
|
||||||
|
|
||||||
|
const outfit = Outfit({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-outfit",
|
||||||
|
})
|
||||||
|
|
||||||
|
const oxanium = Oxanium({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-oxanium",
|
||||||
|
})
|
||||||
|
|
||||||
|
const manrope = Manrope({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-manrope",
|
||||||
|
})
|
||||||
|
|
||||||
|
const spaceGrotesk = Space_Grotesk({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-space-grotesk",
|
||||||
|
})
|
||||||
|
|
||||||
|
const montserrat = Montserrat({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-montserrat",
|
||||||
|
})
|
||||||
|
|
||||||
|
const ibmPlexSans = IBM_Plex_Sans({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-ibm-plex-sans",
|
||||||
|
})
|
||||||
|
|
||||||
|
const sourceSans3 = Source_Sans_3({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-source-sans-3",
|
||||||
|
})
|
||||||
|
|
||||||
|
const instrumentSans = Instrument_Sans({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-instrument-sans",
|
||||||
|
})
|
||||||
|
|
||||||
|
const jetbrainsMono = JetBrains_Mono({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-jetbrains-mono",
|
||||||
|
})
|
||||||
|
|
||||||
|
const geistMono = Geist_Mono({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-geist-mono",
|
||||||
|
})
|
||||||
|
|
||||||
|
const notoSerif = Noto_Serif({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-noto-serif",
|
||||||
|
})
|
||||||
|
|
||||||
|
const robotoSlab = Roboto_Slab({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-roboto-slab",
|
||||||
|
})
|
||||||
|
|
||||||
|
const merriweather = Merriweather({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-merriweather",
|
||||||
|
})
|
||||||
|
|
||||||
|
const lora = Lora({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-lora",
|
||||||
|
})
|
||||||
|
|
||||||
|
const playfairDisplay = Playfair_Display({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-playfair-display",
|
||||||
|
})
|
||||||
|
|
||||||
|
const ebGaramond = EB_Garamond({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-eb-garamond",
|
||||||
|
})
|
||||||
|
|
||||||
|
const instrumentSerif = Instrument_Serif({
|
||||||
|
subsets: ["latin"],
|
||||||
|
weight: "400",
|
||||||
|
variable: "--font-instrument-serif",
|
||||||
|
})
|
||||||
|
|
||||||
|
export const previewFontVariables = cn(
|
||||||
|
geistSans.variable,
|
||||||
|
inter.variable,
|
||||||
|
notoSans.variable,
|
||||||
|
nunitoSans.variable,
|
||||||
|
figtree.variable,
|
||||||
|
roboto.variable,
|
||||||
|
raleway.variable,
|
||||||
|
dmSans.variable,
|
||||||
|
publicSans.variable,
|
||||||
|
outfit.variable,
|
||||||
|
oxanium.variable,
|
||||||
|
manrope.variable,
|
||||||
|
spaceGrotesk.variable,
|
||||||
|
montserrat.variable,
|
||||||
|
ibmPlexSans.variable,
|
||||||
|
sourceSans3.variable,
|
||||||
|
instrumentSans.variable,
|
||||||
|
geistMono.variable,
|
||||||
|
jetbrainsMono.variable,
|
||||||
|
notoSerif.variable,
|
||||||
|
robotoSlab.variable,
|
||||||
|
merriweather.variable,
|
||||||
|
lora.variable,
|
||||||
|
playfairDisplay.variable,
|
||||||
|
ebGaramond.variable,
|
||||||
|
instrumentSerif.variable
|
||||||
|
)
|
||||||
15
apps/v4/app/(create)/preview/layout.tsx
Normal file
15
apps/v4/app/(create)/preview/layout.tsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { PreviewFontVariables } from "@/app/(create)/preview/font-variables"
|
||||||
|
import { previewFontVariables } from "@/app/(create)/preview/fonts"
|
||||||
|
|
||||||
|
export default function PreviewLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className={previewFontVariables}>
|
||||||
|
<PreviewFontVariables className={previewFontVariables} />
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -3,14 +3,6 @@
|
|||||||
@import "shadcn/tailwind.css";
|
@import "shadcn/tailwind.css";
|
||||||
@import "./legacy-themes.css";
|
@import "./legacy-themes.css";
|
||||||
|
|
||||||
@import "../registry/styles/style-vega.css" layer(base);
|
|
||||||
@import "../registry/styles/style-nova.css" layer(base);
|
|
||||||
@import "../registry/styles/style-lyra.css" layer(base);
|
|
||||||
@import "../registry/styles/style-maia.css" layer(base);
|
|
||||||
@import "../registry/styles/style-mira.css" layer(base);
|
|
||||||
@import "../registry/styles/style-luma.css" layer(base);
|
|
||||||
@import "../registry/styles/style-sera.css" layer(base);
|
|
||||||
|
|
||||||
@custom-variant style-vega (&:where(.style-vega *));
|
@custom-variant style-vega (&:where(.style-vega *));
|
||||||
@custom-variant style-nova (&:where(.style-nova *));
|
@custom-variant style-nova (&:where(.style-nova *));
|
||||||
@custom-variant style-lyra (&:where(.style-lyra *));
|
@custom-variant style-lyra (&:where(.style-lyra *));
|
||||||
@@ -18,6 +10,7 @@
|
|||||||
@custom-variant style-mira (&:where(.style-mira *));
|
@custom-variant style-mira (&:where(.style-mira *));
|
||||||
@custom-variant style-luma (&:where(.style-luma *));
|
@custom-variant style-luma (&:where(.style-luma *));
|
||||||
@custom-variant style-sera (&:where(.style-sera *));
|
@custom-variant style-sera (&:where(.style-sera *));
|
||||||
|
@custom-variant style-rhea (&:where(.style-rhea *));
|
||||||
|
|
||||||
@custom-variant dark (&:is(.dark *));
|
@custom-variant dark (&:is(.dark *));
|
||||||
@custom-variant fixed (&:is(.layout-fixed *));
|
@custom-variant fixed (&:is(.layout-fixed *));
|
||||||
@@ -80,12 +73,12 @@
|
|||||||
:root {
|
:root {
|
||||||
--radius: 0.625rem;
|
--radius: 0.625rem;
|
||||||
--background: oklch(1 0 0);
|
--background: oklch(1 0 0);
|
||||||
--foreground: oklch(0.145 0 0);
|
--foreground: oklch(0% 0 0);
|
||||||
--card: oklch(1 0 0);
|
--card: oklch(1 0 0);
|
||||||
--card-foreground: oklch(0.145 0 0);
|
--card-foreground: oklch(0% 0 0);
|
||||||
--popover: oklch(1 0 0);
|
--popover: oklch(1 0 0);
|
||||||
--popover-foreground: oklch(0.145 0 0);
|
--popover-foreground: oklch(0% 0 0);
|
||||||
--primary: oklch(0.205 0 0);
|
--primary: oklch(0% 0 0);
|
||||||
--primary-foreground: oklch(0.985 0 0);
|
--primary-foreground: oklch(0.985 0 0);
|
||||||
--secondary: oklch(0.97 0 0);
|
--secondary: oklch(0.97 0 0);
|
||||||
--secondary-foreground: oklch(0.205 0 0);
|
--secondary-foreground: oklch(0.205 0 0);
|
||||||
@@ -104,7 +97,7 @@
|
|||||||
--chart-4: var(--color-blue-700);
|
--chart-4: var(--color-blue-700);
|
||||||
--chart-5: var(--color-blue-800);
|
--chart-5: var(--color-blue-800);
|
||||||
--sidebar: oklch(0.985 0 0);
|
--sidebar: oklch(0.985 0 0);
|
||||||
--sidebar-foreground: oklch(0.145 0 0);
|
--sidebar-foreground: oklch(0% 0 0);
|
||||||
--sidebar-primary: oklch(0.205 0 0);
|
--sidebar-primary: oklch(0.205 0 0);
|
||||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||||
--sidebar-accent: oklch(0.97 0 0);
|
--sidebar-accent: oklch(0.97 0 0);
|
||||||
@@ -117,7 +110,7 @@
|
|||||||
--code-foreground: var(--surface-foreground);
|
--code-foreground: var(--surface-foreground);
|
||||||
--code-highlight: oklch(0.96 0 0);
|
--code-highlight: oklch(0.96 0 0);
|
||||||
--code-number: oklch(0.56 0 0);
|
--code-number: oklch(0.56 0 0);
|
||||||
--selection: oklch(0.145 0 0);
|
--selection: oklch(0% 0 0);
|
||||||
--selection-foreground: oklch(1 0 0);
|
--selection-foreground: oklch(1 0 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,7 +204,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@utility section-soft {
|
@utility section-soft {
|
||||||
@apply from-background to-surface/40 dark:bg-background 3xl:fixed:bg-none bg-linear-to-b;
|
@apply bg-linear-to-b from-background to-surface/40 dark:bg-background 3xl:fixed:bg-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility theme-container {
|
@utility theme-container {
|
||||||
@@ -219,11 +212,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@utility container-wrapper {
|
@utility container-wrapper {
|
||||||
@apply 3xl:fixed:max-w-[calc(var(--breakpoint-2xl)+2rem)] mx-auto w-full px-2;
|
@apply mx-auto w-full px-2 3xl:fixed:max-w-[calc(var(--breakpoint-2xl)+2rem)];
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility container {
|
@utility container {
|
||||||
@apply 3xl:max-w-screen-2xl mx-auto max-w-[1400px] px-4 lg:px-8;
|
@apply mx-auto max-w-[1400px] px-4 3xl:max-w-screen-2xl lg:px-8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility no-scrollbar {
|
@utility no-scrollbar {
|
||||||
@@ -236,14 +229,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@utility border-ghost {
|
@utility border-ghost {
|
||||||
@apply after:border-border relative after:absolute after:inset-0 after:border after:mix-blend-darken dark:after:mix-blend-lighten;
|
@apply relative after:absolute after:inset-0 after:border after:border-border after:mix-blend-darken dark:after:mix-blend-lighten;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility step {
|
@utility step {
|
||||||
counter-increment: step;
|
counter-increment: step;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
@apply border-background bg-muted mr-2 inline-flex size-6 items-center justify-center rounded-full text-center -indent-px font-mono text-sm font-medium md:absolute md:mt-[-4px] md:ml-[-50px] md:size-9 md:border-4;
|
@apply mr-2 inline-flex size-6 items-center justify-center rounded-full border-background bg-muted text-center -indent-px font-mono text-sm font-medium md:absolute md:mt-[-4px] md:ml-[-50px] md:size-9 md:border-4;
|
||||||
content: counter(step);
|
content: counter(step);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -353,14 +346,8 @@
|
|||||||
white-space: pre;
|
white-space: pre;
|
||||||
line-height: 0.95;
|
line-height: 0.95;
|
||||||
font-family:
|
font-family:
|
||||||
ui-monospace,
|
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
|
||||||
SFMono-Regular,
|
"Courier New", monospace;
|
||||||
Menlo,
|
|
||||||
Monaco,
|
|
||||||
Consolas,
|
|
||||||
"Liberation Mono",
|
|
||||||
"Courier New",
|
|
||||||
monospace;
|
|
||||||
font-variant-ligatures: none;
|
font-variant-ligatures: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { NuqsAdapter } from "nuqs/adapters/next/app"
|
|||||||
import { META_THEME_COLORS, siteConfig } from "@/lib/config"
|
import { META_THEME_COLORS, siteConfig } from "@/lib/config"
|
||||||
import { fontVariables } from "@/lib/fonts"
|
import { fontVariables } from "@/lib/fonts"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { LayoutProvider } from "@/hooks/use-layout"
|
|
||||||
import { ActiveThemeProvider } from "@/components/active-theme"
|
import { ActiveThemeProvider } from "@/components/active-theme"
|
||||||
import { Analytics } from "@/components/analytics"
|
import { Analytics } from "@/components/analytics"
|
||||||
import { TailwindIndicator } from "@/components/tailwind-indicator"
|
import { TailwindIndicator } from "@/components/tailwind-indicator"
|
||||||
@@ -81,9 +80,6 @@ export default function RootLayout({
|
|||||||
if (localStorage.theme === 'dark' || ((!('theme' in localStorage) || localStorage.theme === 'system') && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
if (localStorage.theme === 'dark' || ((!('theme' in localStorage) || localStorage.theme === 'system') && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||||
document.querySelector('meta[name="theme-color"]').setAttribute('content', '${META_THEME_COLORS.dark}')
|
document.querySelector('meta[name="theme-color"]').setAttribute('content', '${META_THEME_COLORS.dark}')
|
||||||
}
|
}
|
||||||
if (localStorage.layout) {
|
|
||||||
document.documentElement.classList.add('layout-' + localStorage.layout)
|
|
||||||
}
|
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
`,
|
`,
|
||||||
}}
|
}}
|
||||||
@@ -92,24 +88,22 @@ export default function RootLayout({
|
|||||||
</head>
|
</head>
|
||||||
<body
|
<body
|
||||||
className={cn(
|
className={cn(
|
||||||
"group/body overscroll-none antialiased [--footer-height:calc(var(--spacing)*14)] [--header-height:calc(var(--spacing)*14)] xl:[--footer-height:calc(var(--spacing)*24)]"
|
"group/body overscroll-none antialiased [--footer-height:calc(var(--spacing)*14)] [--header-height:calc(var(--spacing)*14)] lg:[--header-height:calc(var(--spacing)*16)] xl:[--footer-height:calc(var(--spacing)*24)]"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<LayoutProvider>
|
<ActiveThemeProvider>
|
||||||
<ActiveThemeProvider>
|
<NuqsAdapter>
|
||||||
<NuqsAdapter>
|
<BaseTooltipProvider delay={0}>
|
||||||
<BaseTooltipProvider delay={0}>
|
<RadixTooltipProvider delayDuration={0}>
|
||||||
<RadixTooltipProvider delayDuration={0}>
|
{children}
|
||||||
{children}
|
<Toaster position="top-center" />
|
||||||
<Toaster position="top-center" />
|
</RadixTooltipProvider>
|
||||||
</RadixTooltipProvider>
|
</BaseTooltipProvider>
|
||||||
</BaseTooltipProvider>
|
</NuqsAdapter>
|
||||||
</NuqsAdapter>
|
<TailwindIndicator />
|
||||||
<TailwindIndicator />
|
<Analytics />
|
||||||
<Analytics />
|
</ActiveThemeProvider>
|
||||||
</ActiveThemeProvider>
|
|
||||||
</LayoutProvider>
|
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -394,3 +394,172 @@
|
|||||||
--sidebar-ring: var(--color-violet-900);
|
--sidebar-ring: var(--color-violet-900);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme-sketch {
|
||||||
|
--background: oklch(0.9721 0.0158 110.5501);
|
||||||
|
--foreground: oklch(0.5066 0.2501 271.8903);
|
||||||
|
--card: oklch(0.9721 0.0158 110.5501);
|
||||||
|
--card-foreground: oklch(0.5066 0.2501 271.8903);
|
||||||
|
--popover: oklch(0.9721 0.0158 110.5501);
|
||||||
|
--popover-foreground: oklch(0.5066 0.2501 271.8903);
|
||||||
|
--primary: oklch(0.5066 0.2501 271.8903);
|
||||||
|
--primary-foreground: oklch(1 0 0);
|
||||||
|
--secondary: oklch(1 0 0);
|
||||||
|
--secondary-foreground: oklch(0.5066 0.2501 271.8903);
|
||||||
|
--muted: oklch(0.9189 0.0147 106.6853);
|
||||||
|
--muted-foreground: oklch(0.5066 0.2501 271.8903);
|
||||||
|
--accent: oklch(0.9168 0.0214 109.7161);
|
||||||
|
--accent-foreground: oklch(0.4486 0.2266 271.5512);
|
||||||
|
--destructive: oklch(0.63 0.19 23.03);
|
||||||
|
--destructive-foreground: oklch(1 0 0);
|
||||||
|
--border: oklch(0.5066 0.2501 271.8903);
|
||||||
|
--input: oklch(0.5066 0.2501 271.8903);
|
||||||
|
--ring: oklch(0.468 0.2721 279.6007);
|
||||||
|
--chart-1: oklch(0.5066 0.2501 271.8903);
|
||||||
|
--chart-2: oklch(0.7 0.19 48);
|
||||||
|
--chart-3: oklch(0.77 0.2 131);
|
||||||
|
--chart-4: oklch(0.68 0.15 237);
|
||||||
|
--chart-5: oklch(0.66 0.21 354);
|
||||||
|
--sidebar: oklch(0.9721 0.0158 110.5501);
|
||||||
|
--sidebar-foreground: oklch(0.5066 0.2501 271.8903);
|
||||||
|
--sidebar-primary: oklch(0.5066 0.2501 271.8903);
|
||||||
|
--sidebar-primary-foreground: oklch(1 0 0);
|
||||||
|
--sidebar-accent: oklch(0.9168 0.0214 109.7161);
|
||||||
|
--sidebar-accent-foreground: oklch(0.4486 0.2266 271.5512);
|
||||||
|
--sidebar-border: oklch(0.4486 0.2266 271.5512);
|
||||||
|
--sidebar-ring: oklch(0.4486 0.2266 271.5512);
|
||||||
|
--font-sans: Geist Mono;
|
||||||
|
--shadow-2xs: 4px 4px 0px 0px hsl(238.3146 85.5769% 59.2157% / 0.07);
|
||||||
|
--shadow-xs: 4px 4px 0px 0px hsl(238.3146 85.5769% 59.2157% / 0.07);
|
||||||
|
--shadow-sm:
|
||||||
|
4px 4px 0px 0px hsl(238.3146 85.5769% 59.2157% / 0.15),
|
||||||
|
4px 1px 2px -1px hsl(238.3146 85.5769% 59.2157% / 0.15);
|
||||||
|
--shadow:
|
||||||
|
4px 4px 0px 0px hsl(238.3146 85.5769% 59.2157% / 0.15),
|
||||||
|
4px 1px 2px -1px hsl(238.3146 85.5769% 59.2157% / 0.15);
|
||||||
|
--shadow-md:
|
||||||
|
4px 4px 0px 0px hsl(238.3146 85.5769% 59.2157% / 0.15),
|
||||||
|
4px 2px 4px -1px hsl(238.3146 85.5769% 59.2157% / 0.15);
|
||||||
|
--shadow-lg:
|
||||||
|
4px 4px 0px 0px hsl(238.3146 85.5769% 59.2157% / 0.15),
|
||||||
|
4px 4px 6px -1px hsl(238.3146 85.5769% 59.2157% / 0.15);
|
||||||
|
--shadow-xl:
|
||||||
|
4px 4px 0px 0px hsl(238.3146 85.5769% 59.2157% / 0.15),
|
||||||
|
4px 8px 10px -1px hsl(238.3146 85.5769% 59.2157% / 0.15);
|
||||||
|
--shadow-2xl: 4px 4px 0px 0px hsl(238.3146 85.5769% 59.2157% / 0.38);
|
||||||
|
--radius: 0rem;
|
||||||
|
|
||||||
|
@variant dark {
|
||||||
|
--background: oklch(0.256 0.151 268.343);
|
||||||
|
--foreground: oklch(0.972 0.016 110.55);
|
||||||
|
--card: oklch(0.256 0.151 268.343);
|
||||||
|
--card-foreground: oklch(0.972 0.016 110.55);
|
||||||
|
--popover: oklch(0.507 0.25 271.89);
|
||||||
|
--popover-foreground: oklch(0.972 0.016 110.55);
|
||||||
|
--primary: oklch(0.972 0.016 110.55);
|
||||||
|
--primary-foreground: oklch(0.253 0.094 275.725);
|
||||||
|
--secondary: oklch(1 0 0 / 0.2);
|
||||||
|
--secondary-foreground: oklch(1 0 0);
|
||||||
|
--muted: oklch(0.228 0.127 269.556);
|
||||||
|
--muted-foreground: oklch(0.972 0.016 110.55);
|
||||||
|
--accent: oklch(0.228 0.127 269.556);
|
||||||
|
--accent-foreground: oklch(0.972 0.016 110.55);
|
||||||
|
--destructive: oklch(0.711 0.166 22.216);
|
||||||
|
--destructive-foreground: oklch(0 0 0);
|
||||||
|
--border: oklch(0.427 0.149 277.089);
|
||||||
|
--input: oklch(0.427 0.149 277.089);
|
||||||
|
--ring: oklch(1 0 0);
|
||||||
|
--chart-1: oklch(0.972 0.016 110.55);
|
||||||
|
--chart-2: oklch(0.7 0.19 48);
|
||||||
|
--chart-3: oklch(0.77 0.2 131);
|
||||||
|
--chart-4: oklch(0.68 0.15 237);
|
||||||
|
--chart-5: oklch(0.66 0.21 354);
|
||||||
|
--sidebar: oklch(0.256 0.151 268.343);
|
||||||
|
--sidebar-foreground: oklch(0.972 0.016 110.55);
|
||||||
|
--sidebar-primary: oklch(0.507 0.25 271.89);
|
||||||
|
--sidebar-primary-foreground: oklch(1 0 0);
|
||||||
|
--sidebar-accent: oklch(0.416 0.203 272.082);
|
||||||
|
--sidebar-accent-foreground: oklch(0.972 0.016 110.55);
|
||||||
|
--sidebar-border: oklch(0.972 0.016 110.55);
|
||||||
|
--sidebar-ring: oklch(0.972 0.016 110.55);
|
||||||
|
--sidebar-background: oklch(0.253 0.094 275.725);
|
||||||
|
--font-sans: Geist Mono;
|
||||||
|
--shadow-2xs: 4px 4px 0px 0px oklch(0.427 0.149 277.089 / 0.5);
|
||||||
|
--shadow-xs: 4px 4px 0px 0px oklch(0.427 0.149 277.089 / 0.5);
|
||||||
|
--shadow-sm: 4px 4px 0px 0px oklch(0.427 0.149 277.089 / 0.5);
|
||||||
|
--shadow: 4px 4px 0px 0px oklch(0.427 0.149 277.089 / 0.5);
|
||||||
|
--shadow-md: 4px 4px 0px 0px oklch(0.427 0.149 277.089 / 0.5);
|
||||||
|
--shadow-lg: 4px 4px 0px 0px oklch(0.427 0.149 277.089 / 0.5);
|
||||||
|
--shadow-xl: 4px 4px 0px 0px oklch(0.427 0.149 277.089 / 0.5);
|
||||||
|
--shadow-2xl: 4px 4px 0px 0px oklch(0.427 0.149 277.089 / 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-neutral {
|
||||||
|
--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.87 0 0);
|
||||||
|
--chart-2: oklch(0.556 0 0);
|
||||||
|
--chart-3: oklch(0.439 0 0);
|
||||||
|
--chart-4: oklch(0.371 0 0);
|
||||||
|
--chart-5: oklch(0.269 0 0);
|
||||||
|
--radius: 0.625rem;
|
||||||
|
--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.87 0 0);
|
||||||
|
--chart-2: oklch(0.556 0 0);
|
||||||
|
--chart-3: oklch(0.439 0 0);
|
||||||
|
--chart-4: oklch(0.371 0 0);
|
||||||
|
--chart-5: oklch(0.269 0 0);
|
||||||
|
--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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
10
apps/v4/app/style-registry.css
Normal file
10
apps/v4/app/style-registry.css
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
@reference "./globals.css";
|
||||||
|
|
||||||
|
@import "../registry/styles/style-vega.css" layer(base);
|
||||||
|
@import "../registry/styles/style-nova.css" layer(base);
|
||||||
|
@import "../registry/styles/style-lyra.css" layer(base);
|
||||||
|
@import "../registry/styles/style-maia.css" layer(base);
|
||||||
|
@import "../registry/styles/style-mira.css" layer(base);
|
||||||
|
@import "../registry/styles/style-luma.css" layer(base);
|
||||||
|
@import "../registry/styles/style-sera.css" layer(base);
|
||||||
|
@import "../registry/styles/style-rhea.css" layer(base);
|
||||||
@@ -7,7 +7,7 @@ export function Announcement() {
|
|||||||
return (
|
return (
|
||||||
<Badge asChild variant="secondary" className="bg-muted">
|
<Badge asChild variant="secondary" className="bg-muted">
|
||||||
<Link href="/docs/changelog">
|
<Link href="/docs/changelog">
|
||||||
New preset commands <ArrowRightIcon />
|
Introducing Rhea <ArrowRightIcon />
|
||||||
</Link>
|
</Link>
|
||||||
</Badge>
|
</Badge>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -391,7 +391,7 @@ export function CommandMenu({
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative h-8 w-full justify-start rounded-lg pl-3 font-normal text-foreground shadow-none hover:bg-muted/50 sm:pr-12 md:w-48 lg:w-40 xl:w-64 dark:bg-card"
|
"relative h-8 w-full justify-start rounded-lg border-none bg-muted pl-3 text-foreground shadow-none transition-colors hover:bg-muted/50 md:w-48 lg:w-40 xl:w-64 dark:bg-card"
|
||||||
)}
|
)}
|
||||||
onClick={() => setOpen(true)}
|
onClick={() => setOpen(true)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -79,8 +79,7 @@ export function DocsSidebar({
|
|||||||
>
|
>
|
||||||
<div className="h-9" />
|
<div className="h-9" />
|
||||||
<div className="absolute top-8 z-10 h-8 w-(--sidebar-menu-width) shrink-0 bg-linear-to-b from-background via-background/80 to-background/50 blur-xs" />
|
<div className="absolute top-8 z-10 h-8 w-(--sidebar-menu-width) shrink-0 bg-linear-to-b from-background via-background/80 to-background/50 blur-xs" />
|
||||||
<div className="absolute top-12 right-2 bottom-0 hidden h-full w-px bg-linear-to-b from-transparent via-border to-transparent lg:flex" />
|
<SidebarContent className="no-scrollbar w-(--sidebar-menu-width) overflow-x-hidden px-2.5">
|
||||||
<SidebarContent className="mx-auto no-scrollbar w-(--sidebar-menu-width) overflow-x-hidden px-2">
|
|
||||||
<SidebarGroup className="pt-6">
|
<SidebarGroup className="pt-6">
|
||||||
<SidebarGroupLabel className="font-medium text-muted-foreground">
|
<SidebarGroupLabel className="font-medium text-muted-foreground">
|
||||||
Sections
|
Sections
|
||||||
|
|||||||
@@ -118,9 +118,6 @@ export function MobileNav({
|
|||||||
Menu
|
Menu
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
<MobileLink href="/" onOpenChange={setOpen}>
|
|
||||||
Home
|
|
||||||
</MobileLink>
|
|
||||||
{items.map((item, index) => (
|
{items.map((item, index) => (
|
||||||
<MobileLink key={index} href={item.href} onOpenChange={setOpen}>
|
<MobileLink key={index} href={item.href} onOpenChange={setOpen}>
|
||||||
{item.label}
|
{item.label}
|
||||||
|
|||||||
@@ -8,11 +8,9 @@ import { siteConfig } from "@/lib/config"
|
|||||||
import { source } from "@/lib/source"
|
import { source } from "@/lib/source"
|
||||||
import { CommandMenu } from "@/components/command-menu"
|
import { CommandMenu } from "@/components/command-menu"
|
||||||
import { GitHubLink } from "@/components/github-link"
|
import { GitHubLink } from "@/components/github-link"
|
||||||
import { Icons } from "@/components/icons"
|
|
||||||
import { MainNav } from "@/components/main-nav"
|
import { MainNav } from "@/components/main-nav"
|
||||||
import { MobileNav } from "@/components/mobile-nav"
|
import { MobileNav } from "@/components/mobile-nav"
|
||||||
import { ModeSwitcher } from "@/components/mode-switcher"
|
import { ModeSwitcher } from "@/components/mode-switcher"
|
||||||
import { SiteConfig } from "@/components/site-config"
|
|
||||||
import { Separator } from "@/registry/new-york-v4/ui/separator"
|
import { Separator } from "@/registry/new-york-v4/ui/separator"
|
||||||
import { Button } from "@/styles/radix-nova/ui/button"
|
import { Button } from "@/styles/radix-nova/ui/button"
|
||||||
import { ProjectForm } from "@/app/(app)/create/components/project-form"
|
import { ProjectForm } from "@/app/(app)/create/components/project-form"
|
||||||
@@ -31,17 +29,6 @@ export function SiteHeader() {
|
|||||||
items={siteConfig.navItems}
|
items={siteConfig.navItems}
|
||||||
className="flex lg:hidden"
|
className="flex lg:hidden"
|
||||||
/>
|
/>
|
||||||
<Button
|
|
||||||
asChild
|
|
||||||
variant="ghost"
|
|
||||||
size="icon"
|
|
||||||
className="hidden size-8 lg:flex"
|
|
||||||
>
|
|
||||||
<Link href="/">
|
|
||||||
<Icons.logo className="size-5" />
|
|
||||||
<span className="sr-only">{siteConfig.name}</span>
|
|
||||||
</Link>
|
|
||||||
</Button>
|
|
||||||
<MainNav items={siteConfig.navItems} className="hidden lg:flex" />
|
<MainNav items={siteConfig.navItems} className="hidden lg:flex" />
|
||||||
<div className="ml-auto flex items-center gap-2 md:flex-1 md:justify-end">
|
<div className="ml-auto flex items-center gap-2 md:flex-1 md:justify-end">
|
||||||
<div className="hidden w-full flex-1 md:flex md:w-auto md:flex-none">
|
<div className="hidden w-full flex-1 md:flex md:w-auto md:flex-none">
|
||||||
@@ -56,11 +43,6 @@ export function SiteHeader() {
|
|||||||
className="ml-2 hidden lg:block"
|
className="ml-2 hidden lg:block"
|
||||||
/>
|
/>
|
||||||
<GitHubLink />
|
<GitHubLink />
|
||||||
<Separator
|
|
||||||
orientation="vertical"
|
|
||||||
className="hidden group-has-data-[slot=designer]/layout:hidden 3xl:flex"
|
|
||||||
/>
|
|
||||||
<SiteConfig className="hidden 3xl:flex 3xl:group-has-data-[slot=designer]/layout:hidden" />
|
|
||||||
<Separator orientation="vertical" />
|
<Separator orientation="vertical" />
|
||||||
<ModeSwitcher />
|
<ModeSwitcher />
|
||||||
<div className="hidden items-center gap-2 group-has-data-[slot=designer]/layout:md:flex">
|
<div className="hidden items-center gap-2 group-has-data-[slot=designer]/layout:md:flex">
|
||||||
|
|||||||
45
apps/v4/content/docs/changelog/2026-05-rhea.mdx
Normal file
45
apps/v4/content/docs/changelog/2026-05-rhea.mdx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
title: May 2026 - Introducing Rhea
|
||||||
|
description: A more compact Luma. Smaller spacing. Denser surfaces. Built for focused product interfaces.
|
||||||
|
date: 2026-05-26
|
||||||
|
---
|
||||||
|
|
||||||
|
Introducing Rhea, a new shadcn/ui style. A more compact Luma. Smaller spacing. Denser surfaces. Built for focused product interfaces.
|
||||||
|
|
||||||
|
<a href="/create?preset=b27GcrRo">
|
||||||
|
<Image
|
||||||
|
src="/images/rhea-light.png"
|
||||||
|
width="3840"
|
||||||
|
height="2160"
|
||||||
|
alt="Rhea style preview"
|
||||||
|
className="mt-6 w-full overflow-hidden rounded-lg border dark:hidden"
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="/images/rhea-dark.png"
|
||||||
|
width="3840"
|
||||||
|
height="2160"
|
||||||
|
alt="Rhea style preview"
|
||||||
|
className="mt-6 hidden w-full overflow-hidden rounded-lg border shadow-sm dark:block"
|
||||||
|
/>
|
||||||
|
<span className="sr-only">Try Rhea in shadcn/create</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
Rhea started from a simple request we've heard a lot: Luma, but more compact. We looked at how people were using the new styles and what they were asking for, and the pattern was clear. A lot of teams wanted the softness and shape of Luma with tighter spacing, smaller controls, and more information density.
|
||||||
|
|
||||||
|
Rhea keeps the same rounded foundation, but makes it more compact for product interfaces where space matters. Buttons, inputs, menus, cards, and lists all sit a little tighter so the UI can carry more without feeling crowded.
|
||||||
|
|
||||||
|
## Why a new style?
|
||||||
|
|
||||||
|
We considered making this a spacing tweak for Luma, but `--spacing` is a multiplier. Changing it would change what familiar utilities mean across your app. `p-2`, `w-4`, and `m-16` would no longer mean the same size.
|
||||||
|
|
||||||
|
That tradeoff felt wrong. Compactness should not force you to relearn Tailwind's spacing scale or wonder whether a utility means something different in one style than another.
|
||||||
|
|
||||||
|
So Rhea is a new style instead. It lets us adjust component sizes, gaps, and density directly while keeping the underlying utility scale predictable.
|
||||||
|
|
||||||
|
Available now in [shadcn/create](/create) for both Radix and Base UI.
|
||||||
|
|
||||||
|
<Button asChild size="sm">
|
||||||
|
<Link href="/create?preset=b27GcrRo" className="mt-6 no-underline!">
|
||||||
|
Try Rhea
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
@@ -9,6 +9,10 @@ export const siteConfig = {
|
|||||||
github: "https://github.com/shadcn-ui/ui",
|
github: "https://github.com/shadcn-ui/ui",
|
||||||
},
|
},
|
||||||
navItems: [
|
navItems: [
|
||||||
|
{
|
||||||
|
href: "/",
|
||||||
|
label: "Home",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
href: "/docs/installation",
|
href: "/docs/installation",
|
||||||
label: "Docs",
|
label: "Docs",
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
Lora as FontLora,
|
|
||||||
Geist_Mono as FontMono,
|
Geist_Mono as FontMono,
|
||||||
Noto_Sans as FontNotoSans,
|
|
||||||
Noto_Sans_Arabic as FontNotoSansArabic,
|
Noto_Sans_Arabic as FontNotoSansArabic,
|
||||||
Noto_Sans_Hebrew as FontNotoSansHebrew,
|
Noto_Sans_Hebrew as FontNotoSansHebrew,
|
||||||
Noto_Serif as FontNotoSerif,
|
|
||||||
Geist as FontSans,
|
Geist as FontSans,
|
||||||
Inter,
|
|
||||||
Playfair_Display,
|
|
||||||
} from "next/font/google"
|
} from "next/font/google"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
@@ -17,27 +12,17 @@ const fontSans = FontSans({
|
|||||||
variable: "--font-sans",
|
variable: "--font-sans",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const fontHeading = FontSans({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-heading",
|
||||||
|
})
|
||||||
|
|
||||||
const fontMono = FontMono({
|
const fontMono = FontMono({
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
variable: "--font-mono",
|
variable: "--font-mono",
|
||||||
weight: ["400"],
|
weight: ["400"],
|
||||||
})
|
})
|
||||||
|
|
||||||
const fontInter = Inter({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-inter",
|
|
||||||
})
|
|
||||||
|
|
||||||
const fontNotoSans = FontNotoSans({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-noto-sans",
|
|
||||||
})
|
|
||||||
|
|
||||||
const fontNotoSerif = FontNotoSerif({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-noto-serif",
|
|
||||||
})
|
|
||||||
|
|
||||||
const fontNotoSansArabic = FontNotoSansArabic({
|
const fontNotoSansArabic = FontNotoSansArabic({
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
variable: "--font-ar",
|
variable: "--font-ar",
|
||||||
@@ -48,24 +33,10 @@ const fontNotoSansHebrew = FontNotoSansHebrew({
|
|||||||
variable: "--font-he",
|
variable: "--font-he",
|
||||||
})
|
})
|
||||||
|
|
||||||
const fontLora = FontLora({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-lora",
|
|
||||||
})
|
|
||||||
|
|
||||||
const fontPlayfairDisplay = Playfair_Display({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-playfair-display",
|
|
||||||
})
|
|
||||||
|
|
||||||
export const fontVariables = cn(
|
export const fontVariables = cn(
|
||||||
fontSans.variable,
|
fontSans.variable,
|
||||||
|
fontHeading.variable,
|
||||||
fontMono.variable,
|
fontMono.variable,
|
||||||
fontInter.variable,
|
|
||||||
fontNotoSans.variable,
|
|
||||||
fontNotoSerif.variable,
|
|
||||||
fontNotoSansArabic.variable,
|
fontNotoSansArabic.variable,
|
||||||
fontNotoSansHebrew.variable,
|
fontNotoSansHebrew.variable
|
||||||
fontPlayfairDisplay.variable,
|
|
||||||
fontLora.variable
|
|
||||||
)
|
)
|
||||||
|
|||||||
BIN
apps/v4/public/images/rhea-dark.png
Normal file
BIN
apps/v4/public/images/rhea-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 205 KiB |
BIN
apps/v4/public/images/rhea-light.png
Normal file
BIN
apps/v4/public/images/rhea-light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 252 KiB |
@@ -216,6 +216,42 @@
|
|||||||
"menuColor": "default",
|
"menuColor": "default",
|
||||||
"radius": "default"
|
"radius": "default"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "radix-rhea",
|
||||||
|
"title": "Rhea (Radix)",
|
||||||
|
"description": "Rhea / Lucide / Inter",
|
||||||
|
"base": "radix",
|
||||||
|
"style": "rhea",
|
||||||
|
"baseColor": "neutral",
|
||||||
|
"theme": "neutral",
|
||||||
|
"chartColor": "neutral",
|
||||||
|
"iconLibrary": "lucide",
|
||||||
|
"font": "inter",
|
||||||
|
"fontHeading": "inherit",
|
||||||
|
"item": "Item",
|
||||||
|
"rtl": false,
|
||||||
|
"menuAccent": "subtle",
|
||||||
|
"menuColor": "default",
|
||||||
|
"radius": "default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "base-rhea",
|
||||||
|
"title": "Rhea (Base)",
|
||||||
|
"description": "Rhea / Lucide / Inter",
|
||||||
|
"base": "base",
|
||||||
|
"style": "rhea",
|
||||||
|
"baseColor": "neutral",
|
||||||
|
"theme": "neutral",
|
||||||
|
"chartColor": "neutral",
|
||||||
|
"iconLibrary": "lucide",
|
||||||
|
"font": "inter",
|
||||||
|
"fontHeading": "inherit",
|
||||||
|
"item": "Item",
|
||||||
|
"rtl": false,
|
||||||
|
"menuAccent": "subtle",
|
||||||
|
"menuColor": "default",
|
||||||
|
"radius": "default"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "radix-sera",
|
"name": "radix-sera",
|
||||||
"title": "Sera (Radix)",
|
"title": "Sera (Radix)",
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,11 +1,12 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||||
"name": "preview-03",
|
"name": "preview-03",
|
||||||
"title": "E-commerce",
|
"title": "Preview 03",
|
||||||
|
"registryDependencies": [],
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "registry/base-luma/blocks/preview-03/index.tsx",
|
"path": "registry/base-luma/blocks/preview-03/index.tsx",
|
||||||
"content": "export default function Preview02Example() {\n return (\n <div className=\"overflow-x-auto overflow-y-hidden bg-muted contain-[paint] [--gap:--spacing(4)] 3xl:[--gap:--spacing(12)] md:[--gap:--spacing(10)] dark:bg-background style-lyra:md:[--gap:--spacing(6)] style-mira:md:[--gap:--spacing(6)]\">\n <div className=\"flex w-full min-w-max justify-center\">\n <div\n className=\"grid w-[2400px] grid-cols-7 items-start gap-(--gap) bg-muted p-(--gap) md:w-[3000px] dark:bg-background style-lyra:md:w-[2600px] style-mira:md:w-[2600px] *:[div]:gap-(--gap)\"\n data-slot=\"capture-target\"\n >\n <div className=\"flex flex-col p-1 [contain-intrinsic-size:380px_1200px] [content-visibility:auto]\">\n <p>foo</p>\n </div>\n </div>\n </div>\n </div>\n )\n}\n",
|
"content": "export default function Preview03Example() {\n return (\n <div className=\"overflow-x-auto overflow-y-hidden bg-muted contain-[paint] [--gap:--spacing(4)] 3xl:[--gap:--spacing(12)] md:[--gap:--spacing(10)] dark:bg-background\">\n <div className=\"flex w-full min-w-max justify-center\">\n <div\n className=\"grid w-[2400px] grid-cols-7 items-start gap-(--gap) bg-muted p-(--gap) md:w-[3000px] dark:bg-background\"\n data-slot=\"capture-target\"\n />\n </div>\n </div>\n )\n}\n",
|
||||||
"type": "registry:block"
|
"type": "registry:block"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "registry/base-luma/examples/scroll-area-example.tsx",
|
"path": "registry/base-luma/examples/scroll-area-example.tsx",
|
||||||
"content": "import * as React from \"react\"\nimport Image from \"next/image\"\n\nimport {\n Example,\n ExampleWrapper,\n} from \"@/registry/base-luma/components/example\"\nimport { ScrollArea, ScrollBar } from \"@/registry/base-luma/ui/scroll-area\"\nimport { Separator } from \"@/registry/base-luma/ui/separator\"\n\nconst tags = Array.from({ length: 50 }).map(\n (_, i, a) => `v1.2.0-beta.${a.length - i}`\n)\n\nconst works = [\n {\n artist: \"Ornella Binni\",\n art: \"https://images.unsplash.com/photo-1465869185982-5a1a7522cbcb?auto=format&fit=crop&w=300&q=80\",\n },\n {\n artist: \"Tom Byrom\",\n art: \"https://images.unsplash.com/photo-1548516173-3cabfa4607e9?auto=format&fit=crop&w=300&q=80\",\n },\n {\n artist: \"Vladimir Malyav\",\n art: \"https://images.unsplash.com/photo-1494337480532-3725c85fd2ab?auto=format&fit=crop&w=300&q=80\",\n },\n] as const\n\nexport default function ScrollAreaExample() {\n return (\n <ExampleWrapper>\n <ScrollAreaVertical />\n <ScrollAreaHorizontal />\n </ExampleWrapper>\n )\n}\n\nfunction ScrollAreaVertical() {\n return (\n <Example title=\"Vertical\">\n <ScrollArea className=\"mx-auto h-72 w-48 rounded-md border style-luma:rounded-2xl\">\n <div className=\"p-4\">\n <h4 className=\"mb-4 text-sm leading-none font-medium\">Tags</h4>\n {tags.map((tag) => (\n <React.Fragment key={tag}>\n <div className=\"text-sm\">{tag}</div>\n <Separator className=\"my-2\" />\n </React.Fragment>\n ))}\n </div>\n </ScrollArea>\n </Example>\n )\n}\n\nfunction ScrollAreaHorizontal() {\n return (\n <Example title=\"Horizontal\">\n <ScrollArea className=\"mx-auto w-full max-w-96 rounded-md border p-4 style-luma:rounded-2xl\">\n <div className=\"flex gap-4\">\n {works.map((artwork) => (\n <figure key={artwork.artist} className=\"shrink-0\">\n <div className=\"overflow-hidden rounded-md\">\n <Image\n src={artwork.art}\n alt={`Photo by ${artwork.artist}`}\n className=\"aspect-[3/4] h-fit w-fit object-cover\"\n width={300}\n height={400}\n />\n </div>\n <figcaption className=\"pt-2 text-xs text-muted-foreground\">\n Photo by{\" \"}\n <span className=\"font-semibold text-foreground\">\n {artwork.artist}\n </span>\n </figcaption>\n </figure>\n ))}\n </div>\n <ScrollBar orientation=\"horizontal\" />\n </ScrollArea>\n </Example>\n )\n}\n",
|
"content": "import * as React from \"react\"\nimport Image from \"next/image\"\n\nimport {\n Example,\n ExampleWrapper,\n} from \"@/registry/base-luma/components/example\"\nimport { ScrollArea, ScrollBar } from \"@/registry/base-luma/ui/scroll-area\"\nimport { Separator } from \"@/registry/base-luma/ui/separator\"\n\nconst tags = Array.from({ length: 50 }).map(\n (_, i, a) => `v1.2.0-beta.${a.length - i}`\n)\n\nconst works = [\n {\n artist: \"Ornella Binni\",\n art: \"https://images.unsplash.com/photo-1465869185982-5a1a7522cbcb?auto=format&fit=crop&w=300&q=80\",\n },\n {\n artist: \"Tom Byrom\",\n art: \"https://images.unsplash.com/photo-1548516173-3cabfa4607e9?auto=format&fit=crop&w=300&q=80\",\n },\n {\n artist: \"Vladimir Malyav\",\n art: \"https://images.unsplash.com/photo-1494337480532-3725c85fd2ab?auto=format&fit=crop&w=300&q=80\",\n },\n] as const\n\nexport default function ScrollAreaExample() {\n return (\n <ExampleWrapper>\n <ScrollAreaVertical />\n <ScrollAreaHorizontal />\n </ExampleWrapper>\n )\n}\n\nfunction ScrollAreaVertical() {\n return (\n <Example title=\"Vertical\">\n <ScrollArea className=\"mx-auto h-72 w-48 rounded-md border style-luma:rounded-2xl style-rhea:rounded-2xl\">\n <div className=\"p-4\">\n <h4 className=\"mb-4 text-sm leading-none font-medium\">Tags</h4>\n {tags.map((tag) => (\n <React.Fragment key={tag}>\n <div className=\"text-sm\">{tag}</div>\n <Separator className=\"my-2\" />\n </React.Fragment>\n ))}\n </div>\n </ScrollArea>\n </Example>\n )\n}\n\nfunction ScrollAreaHorizontal() {\n return (\n <Example title=\"Horizontal\">\n <ScrollArea className=\"mx-auto w-full max-w-96 rounded-md border p-4 style-luma:rounded-2xl style-rhea:rounded-2xl\">\n <div className=\"flex gap-4\">\n {works.map((artwork) => (\n <figure key={artwork.artist} className=\"shrink-0\">\n <div className=\"overflow-hidden rounded-md\">\n <Image\n src={artwork.art}\n alt={`Photo by ${artwork.artist}`}\n className=\"aspect-[3/4] h-fit w-fit object-cover\"\n width={300}\n height={400}\n />\n </div>\n <figcaption className=\"pt-2 text-xs text-muted-foreground\">\n Photo by{\" \"}\n <span className=\"font-semibold text-foreground\">\n {artwork.artist}\n </span>\n </figcaption>\n </figure>\n ))}\n </div>\n <ScrollBar orientation=\"horizontal\" />\n </ScrollArea>\n </Example>\n )\n}\n",
|
||||||
"type": "registry:example"
|
"type": "registry:example"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -30,17 +30,17 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "registry/base-luma/blocks/sidebar-07/components/nav-projects.tsx",
|
"path": "registry/base-luma/blocks/sidebar-07/components/nav-projects.tsx",
|
||||||
"content": "\"use client\"\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/base-luma/ui/dropdown-menu\"\nimport {\n SidebarGroup,\n SidebarGroupLabel,\n SidebarMenu,\n SidebarMenuAction,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/registry/base-luma/ui/sidebar\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nexport function NavProjects({\n projects,\n}: {\n projects: {\n name: string\n url: string\n icon: React.ReactNode\n }[]\n}) {\n const { isMobile } = useSidebar()\n return (\n <SidebarGroup className=\"group-data-[collapsible=icon]:hidden\">\n <SidebarGroupLabel>Projects</SidebarGroupLabel>\n <SidebarMenu>\n {projects.map((item) => (\n <SidebarMenuItem key={item.name}>\n <SidebarMenuButton render={<a href={item.url} />}>\n {item.icon}\n <span>{item.name}</span>\n </SidebarMenuButton>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <SidebarMenuAction\n showOnHover\n className=\"aria-expanded:bg-muted\"\n />\n }\n >\n <IconPlaceholder\n lucide=\"MoreHorizontalIcon\"\n tabler=\"IconDots\"\n hugeicons=\"MoreHorizontalCircle01Icon\"\n phosphor=\"DotsThreeOutlineIcon\"\n remixicon=\"RiMoreLine\"\n />\n <span className=\"sr-only\">More</span>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-48 rounded-lg\"\n side={isMobile ? \"bottom\" : \"right\"}\n align={isMobile ? \"end\" : \"start\"}\n >\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"FolderIcon\"\n tabler=\"IconFolder\"\n hugeicons=\"FolderIcon\"\n phosphor=\"FolderIcon\"\n remixicon=\"RiFolderLine\"\n className=\"text-muted-foreground\"\n />\n <span>View Project</span>\n </DropdownMenuItem>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"ArrowRightIcon\"\n tabler=\"IconArrowForward\"\n hugeicons=\"ArrowRightIcon\"\n phosphor=\"ShareFatIcon\"\n remixicon=\"RiShareForwardLine\"\n className=\"text-muted-foreground\"\n />\n <span>Share Project</span>\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"Trash2Icon\"\n tabler=\"IconTrash\"\n hugeicons=\"Delete02Icon\"\n phosphor=\"TrashIcon\"\n remixicon=\"RiDeleteBinLine\"\n className=\"text-muted-foreground\"\n />\n <span>Delete Project</span>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n ))}\n <SidebarMenuItem>\n <SidebarMenuButton className=\"text-sidebar-foreground/70\">\n <IconPlaceholder\n lucide=\"MoreHorizontalIcon\"\n tabler=\"IconDots\"\n hugeicons=\"MoreHorizontalCircle01Icon\"\n phosphor=\"DotsThreeOutlineIcon\"\n remixicon=\"RiMoreLine\"\n className=\"text-sidebar-foreground/70\"\n />\n <span>More</span>\n </SidebarMenuButton>\n </SidebarMenuItem>\n </SidebarMenu>\n </SidebarGroup>\n )\n}\n",
|
"content": "\"use client\"\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/base-luma/ui/dropdown-menu\"\nimport {\n SidebarGroup,\n SidebarGroupLabel,\n SidebarMenu,\n SidebarMenuAction,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/registry/base-luma/ui/sidebar\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nexport function NavProjects({\n projects,\n}: {\n projects: {\n name: string\n url: string\n icon: React.ReactNode\n }[]\n}) {\n const { isMobile } = useSidebar()\n return (\n <SidebarGroup className=\"group-data-[collapsible=icon]:hidden\">\n <SidebarGroupLabel>Projects</SidebarGroupLabel>\n <SidebarMenu>\n {projects.map((item) => (\n <SidebarMenuItem key={item.name}>\n <SidebarMenuButton render={<a href={item.url} />}>\n {item.icon}\n <span>{item.name}</span>\n </SidebarMenuButton>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <SidebarMenuAction\n showOnHover\n className=\"aria-expanded:bg-muted\"\n />\n }\n >\n <IconPlaceholder\n lucide=\"MoreHorizontalIcon\"\n tabler=\"IconDots\"\n hugeicons=\"MoreHorizontalCircle01Icon\"\n phosphor=\"DotsThreeOutlineIcon\"\n remixicon=\"RiMoreLine\"\n />\n <span className=\"sr-only\">More</span>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-fit\"\n side={isMobile ? \"bottom\" : \"right\"}\n align={isMobile ? \"end\" : \"start\"}\n >\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"FolderIcon\"\n tabler=\"IconFolder\"\n hugeicons=\"FolderIcon\"\n phosphor=\"FolderIcon\"\n remixicon=\"RiFolderLine\"\n />\n <span>View Project</span>\n </DropdownMenuItem>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"ArrowRightIcon\"\n tabler=\"IconArrowForward\"\n hugeicons=\"ArrowRightIcon\"\n phosphor=\"ShareFatIcon\"\n remixicon=\"RiShareForwardLine\"\n />\n <span>Share Project</span>\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem variant=\"destructive\">\n <IconPlaceholder\n lucide=\"Trash2Icon\"\n tabler=\"IconTrash\"\n hugeicons=\"Delete02Icon\"\n phosphor=\"TrashIcon\"\n remixicon=\"RiDeleteBinLine\"\n />\n <span>Delete Project</span>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n ))}\n <SidebarMenuItem>\n <SidebarMenuButton className=\"text-sidebar-foreground/70\">\n <IconPlaceholder\n lucide=\"MoreHorizontalIcon\"\n tabler=\"IconDots\"\n hugeicons=\"MoreHorizontalCircle01Icon\"\n phosphor=\"DotsThreeOutlineIcon\"\n remixicon=\"RiMoreLine\"\n className=\"text-sidebar-foreground/70\"\n />\n <span>More</span>\n </SidebarMenuButton>\n </SidebarMenuItem>\n </SidebarMenu>\n </SidebarGroup>\n )\n}\n",
|
||||||
"type": "registry:component"
|
"type": "registry:component"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "registry/base-luma/blocks/sidebar-07/components/nav-user.tsx",
|
"path": "registry/base-luma/blocks/sidebar-07/components/nav-user.tsx",
|
||||||
"content": "\"use client\"\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/base-luma/ui/avatar\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/base-luma/ui/dropdown-menu\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/registry/base-luma/ui/sidebar\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nexport function NavUser({\n user,\n}: {\n user: {\n name: string\n email: string\n avatar: string\n }\n}) {\n const { isMobile } = useSidebar()\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <SidebarMenuButton size=\"lg\" className=\"aria-expanded:bg-muted\" />\n }\n >\n <Avatar>\n <AvatarImage src={user.avatar} alt={user.name} />\n <AvatarFallback>CN</AvatarFallback>\n </Avatar>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">{user.name}</span>\n <span className=\"truncate text-xs\">{user.email}</span>\n </div>\n <IconPlaceholder\n lucide=\"ChevronsUpDownIcon\"\n tabler=\"IconSelector\"\n hugeicons=\"UnfoldMoreIcon\"\n phosphor=\"CaretUpDownIcon\"\n remixicon=\"RiArrowUpDownLine\"\n className=\"ml-auto size-4\"\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"min-w-56 rounded-lg\"\n side={isMobile ? \"bottom\" : \"right\"}\n align=\"end\"\n sideOffset={4}\n >\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"p-0 font-normal\">\n <div className=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n <Avatar>\n <AvatarImage src={user.avatar} alt={user.name} />\n <AvatarFallback>CN</AvatarFallback>\n </Avatar>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">{user.name}</span>\n <span className=\"truncate text-xs\">{user.email}</span>\n </div>\n </div>\n </DropdownMenuLabel>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"SparklesIcon\"\n tabler=\"IconSparkles\"\n hugeicons=\"SparklesIcon\"\n phosphor=\"SparkleIcon\"\n remixicon=\"RiSparklingLine\"\n />\n Upgrade to Pro\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"BadgeCheckIcon\"\n tabler=\"IconRosetteDiscountCheck\"\n hugeicons=\"CheckmarkBadgeIcon\"\n phosphor=\"CheckCircleIcon\"\n remixicon=\"RiCheckboxCircleLine\"\n />\n Account\n </DropdownMenuItem>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"CreditCardIcon\"\n tabler=\"IconCreditCard\"\n hugeicons=\"CreditCardIcon\"\n phosphor=\"CreditCardIcon\"\n remixicon=\"RiBankCardLine\"\n />\n Billing\n </DropdownMenuItem>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"BellIcon\"\n tabler=\"IconBell\"\n hugeicons=\"NotificationIcon\"\n phosphor=\"BellIcon\"\n remixicon=\"RiNotificationLine\"\n />\n Notifications\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"LogOutIcon\"\n tabler=\"IconLogout\"\n hugeicons=\"LogoutIcon\"\n phosphor=\"SignOutIcon\"\n remixicon=\"RiLogoutBoxLine\"\n />\n Log out\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n",
|
"content": "\"use client\"\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/base-luma/ui/avatar\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/base-luma/ui/dropdown-menu\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/registry/base-luma/ui/sidebar\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nexport function NavUser({\n user,\n}: {\n user: {\n name: string\n email: string\n avatar: string\n }\n}) {\n const { isMobile } = useSidebar()\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <SidebarMenuButton size=\"lg\" className=\"aria-expanded:bg-muted\" />\n }\n >\n <Avatar>\n <AvatarImage src={user.avatar} alt={user.name} />\n <AvatarFallback>CN</AvatarFallback>\n </Avatar>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">{user.name}</span>\n <span className=\"truncate text-xs\">{user.email}</span>\n </div>\n <IconPlaceholder\n lucide=\"ChevronsUpDownIcon\"\n tabler=\"IconSelector\"\n hugeicons=\"UnfoldMoreIcon\"\n phosphor=\"CaretUpDownIcon\"\n remixicon=\"RiArrowUpDownLine\"\n className=\"ml-auto size-4\"\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-fit\"\n side={isMobile ? \"bottom\" : \"right\"}\n align=\"end\"\n sideOffset={4}\n >\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"p-0 font-normal\">\n <div className=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n <Avatar>\n <AvatarImage src={user.avatar} alt={user.name} />\n <AvatarFallback>CN</AvatarFallback>\n </Avatar>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">{user.name}</span>\n <span className=\"truncate text-xs\">{user.email}</span>\n </div>\n </div>\n </DropdownMenuLabel>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"SparklesIcon\"\n tabler=\"IconSparkles\"\n hugeicons=\"SparklesIcon\"\n phosphor=\"SparkleIcon\"\n remixicon=\"RiSparklingLine\"\n />\n Upgrade to Pro\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"BadgeCheckIcon\"\n tabler=\"IconRosetteDiscountCheck\"\n hugeicons=\"CheckmarkBadgeIcon\"\n phosphor=\"CheckCircleIcon\"\n remixicon=\"RiCheckboxCircleLine\"\n />\n Account\n </DropdownMenuItem>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"CreditCardIcon\"\n tabler=\"IconCreditCard\"\n hugeicons=\"CreditCardIcon\"\n phosphor=\"CreditCardIcon\"\n remixicon=\"RiBankCardLine\"\n />\n Billing\n </DropdownMenuItem>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"BellIcon\"\n tabler=\"IconBell\"\n hugeicons=\"NotificationIcon\"\n phosphor=\"BellIcon\"\n remixicon=\"RiNotificationLine\"\n />\n Notifications\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"LogOutIcon\"\n tabler=\"IconLogout\"\n hugeicons=\"LogoutIcon\"\n phosphor=\"SignOutIcon\"\n remixicon=\"RiLogoutBoxLine\"\n />\n Log out\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n",
|
||||||
"type": "registry:component"
|
"type": "registry:component"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "registry/base-luma/blocks/sidebar-07/components/team-switcher.tsx",
|
"path": "registry/base-luma/blocks/sidebar-07/components/team-switcher.tsx",
|
||||||
"content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuTrigger,\n} from \"@/registry/base-luma/ui/dropdown-menu\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/registry/base-luma/ui/sidebar\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nexport function TeamSwitcher({\n teams,\n}: {\n teams: {\n name: string\n logo: React.ReactNode\n plan: string\n }[]\n}) {\n const { isMobile } = useSidebar()\n const [activeTeam, setActiveTeam] = React.useState(teams[0])\n if (!activeTeam) {\n return null\n }\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <SidebarMenuButton\n size=\"lg\"\n className=\"data-open:bg-sidebar-accent data-open:text-sidebar-accent-foreground\"\n />\n }\n >\n <div className=\"flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground\">\n {activeTeam.logo}\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 <IconPlaceholder\n lucide=\"ChevronsUpDownIcon\"\n tabler=\"IconSelector\"\n hugeicons=\"UnfoldMoreIcon\"\n phosphor=\"CaretUpDownIcon\"\n remixicon=\"RiArrowUpDownLine\"\n className=\"ml-auto\"\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"min-w-56 rounded-lg\"\n align=\"start\"\n side={isMobile ? \"bottom\" : \"right\"}\n sideOffset={4}\n >\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"text-xs text-muted-foreground\">\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}\n </div>\n {team.name}\n <DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>\n </DropdownMenuItem>\n ))}\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem className=\"gap-2 p-2\">\n <div className=\"flex size-6 items-center justify-center rounded-md border bg-transparent\">\n <IconPlaceholder\n lucide=\"PlusIcon\"\n tabler=\"IconPlus\"\n hugeicons=\"PlusSignIcon\"\n phosphor=\"PlusIcon\"\n remixicon=\"RiAddLine\"\n className=\"size-4\"\n />\n </div>\n <div className=\"font-medium text-muted-foreground\">\n Add team\n </div>\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n",
|
"content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuTrigger,\n} from \"@/registry/base-luma/ui/dropdown-menu\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/registry/base-luma/ui/sidebar\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nexport function TeamSwitcher({\n teams,\n}: {\n teams: {\n name: string\n logo: React.ReactNode\n plan: string\n }[]\n}) {\n const { isMobile } = useSidebar()\n const [activeTeam, setActiveTeam] = React.useState(teams[0])\n if (!activeTeam) {\n return null\n }\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <SidebarMenuButton\n size=\"lg\"\n className=\"data-open:bg-sidebar-accent data-open:text-sidebar-accent-foreground\"\n />\n }\n >\n <div className=\"flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground\">\n {activeTeam.logo}\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 <IconPlaceholder\n lucide=\"ChevronsUpDownIcon\"\n tabler=\"IconSelector\"\n hugeicons=\"UnfoldMoreIcon\"\n phosphor=\"CaretUpDownIcon\"\n remixicon=\"RiArrowUpDownLine\"\n className=\"ml-auto\"\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-fit\"\n align=\"start\"\n side={isMobile ? \"bottom\" : \"right\"}\n sideOffset={4}\n >\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"text-xs text-muted-foreground\">\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}\n </div>\n {team.name}\n <DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>\n </DropdownMenuItem>\n ))}\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem className=\"gap-2 p-2\">\n <div className=\"flex size-6 items-center justify-center rounded-md border bg-transparent\">\n <IconPlaceholder\n lucide=\"PlusIcon\"\n tabler=\"IconPlus\"\n hugeicons=\"PlusSignIcon\"\n phosphor=\"PlusIcon\"\n remixicon=\"RiAddLine\"\n className=\"size-4\"\n />\n </div>\n <div className=\"font-medium text-muted-foreground\">\n Add team\n </div>\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n",
|
||||||
"type": "registry:component"
|
"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
File diff suppressed because one or more lines are too long
@@ -1,11 +1,12 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||||
"name": "preview-03",
|
"name": "preview-03",
|
||||||
"title": "E-commerce",
|
"title": "Preview 03",
|
||||||
|
"registryDependencies": [],
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "registry/base-lyra/blocks/preview-03/index.tsx",
|
"path": "registry/base-lyra/blocks/preview-03/index.tsx",
|
||||||
"content": "export default function Preview02Example() {\n return (\n <div className=\"overflow-x-auto overflow-y-hidden bg-muted contain-[paint] [--gap:--spacing(4)] 3xl:[--gap:--spacing(12)] md:[--gap:--spacing(10)] dark:bg-background style-lyra:md:[--gap:--spacing(6)] style-mira:md:[--gap:--spacing(6)]\">\n <div className=\"flex w-full min-w-max justify-center\">\n <div\n className=\"grid w-[2400px] grid-cols-7 items-start gap-(--gap) bg-muted p-(--gap) md:w-[3000px] dark:bg-background style-lyra:md:w-[2600px] style-mira:md:w-[2600px] *:[div]:gap-(--gap)\"\n data-slot=\"capture-target\"\n >\n <div className=\"flex flex-col p-1 [contain-intrinsic-size:380px_1200px] [content-visibility:auto]\">\n <p>foo</p>\n </div>\n </div>\n </div>\n </div>\n )\n}\n",
|
"content": "export default function Preview03Example() {\n return (\n <div className=\"overflow-x-auto overflow-y-hidden bg-muted contain-[paint] [--gap:--spacing(4)] 3xl:[--gap:--spacing(12)] md:[--gap:--spacing(10)] dark:bg-background\">\n <div className=\"flex w-full min-w-max justify-center\">\n <div\n className=\"grid w-[2400px] grid-cols-7 items-start gap-(--gap) bg-muted p-(--gap) md:w-[3000px] dark:bg-background\"\n data-slot=\"capture-target\"\n />\n </div>\n </div>\n )\n}\n",
|
||||||
"type": "registry:block"
|
"type": "registry:block"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "registry/base-lyra/examples/scroll-area-example.tsx",
|
"path": "registry/base-lyra/examples/scroll-area-example.tsx",
|
||||||
"content": "import * as React from \"react\"\nimport Image from \"next/image\"\n\nimport {\n Example,\n ExampleWrapper,\n} from \"@/registry/base-lyra/components/example\"\nimport { ScrollArea, ScrollBar } from \"@/registry/base-lyra/ui/scroll-area\"\nimport { Separator } from \"@/registry/base-lyra/ui/separator\"\n\nconst tags = Array.from({ length: 50 }).map(\n (_, i, a) => `v1.2.0-beta.${a.length - i}`\n)\n\nconst works = [\n {\n artist: \"Ornella Binni\",\n art: \"https://images.unsplash.com/photo-1465869185982-5a1a7522cbcb?auto=format&fit=crop&w=300&q=80\",\n },\n {\n artist: \"Tom Byrom\",\n art: \"https://images.unsplash.com/photo-1548516173-3cabfa4607e9?auto=format&fit=crop&w=300&q=80\",\n },\n {\n artist: \"Vladimir Malyav\",\n art: \"https://images.unsplash.com/photo-1494337480532-3725c85fd2ab?auto=format&fit=crop&w=300&q=80\",\n },\n] as const\n\nexport default function ScrollAreaExample() {\n return (\n <ExampleWrapper>\n <ScrollAreaVertical />\n <ScrollAreaHorizontal />\n </ExampleWrapper>\n )\n}\n\nfunction ScrollAreaVertical() {\n return (\n <Example title=\"Vertical\">\n <ScrollArea className=\"mx-auto h-72 w-48 rounded-md border style-luma:rounded-2xl\">\n <div className=\"p-4\">\n <h4 className=\"mb-4 text-sm leading-none font-medium\">Tags</h4>\n {tags.map((tag) => (\n <React.Fragment key={tag}>\n <div className=\"text-sm\">{tag}</div>\n <Separator className=\"my-2\" />\n </React.Fragment>\n ))}\n </div>\n </ScrollArea>\n </Example>\n )\n}\n\nfunction ScrollAreaHorizontal() {\n return (\n <Example title=\"Horizontal\">\n <ScrollArea className=\"mx-auto w-full max-w-96 rounded-md border p-4 style-luma:rounded-2xl\">\n <div className=\"flex gap-4\">\n {works.map((artwork) => (\n <figure key={artwork.artist} className=\"shrink-0\">\n <div className=\"overflow-hidden rounded-md\">\n <Image\n src={artwork.art}\n alt={`Photo by ${artwork.artist}`}\n className=\"aspect-[3/4] h-fit w-fit object-cover\"\n width={300}\n height={400}\n />\n </div>\n <figcaption className=\"pt-2 text-xs text-muted-foreground\">\n Photo by{\" \"}\n <span className=\"font-semibold text-foreground\">\n {artwork.artist}\n </span>\n </figcaption>\n </figure>\n ))}\n </div>\n <ScrollBar orientation=\"horizontal\" />\n </ScrollArea>\n </Example>\n )\n}\n",
|
"content": "import * as React from \"react\"\nimport Image from \"next/image\"\n\nimport {\n Example,\n ExampleWrapper,\n} from \"@/registry/base-lyra/components/example\"\nimport { ScrollArea, ScrollBar } from \"@/registry/base-lyra/ui/scroll-area\"\nimport { Separator } from \"@/registry/base-lyra/ui/separator\"\n\nconst tags = Array.from({ length: 50 }).map(\n (_, i, a) => `v1.2.0-beta.${a.length - i}`\n)\n\nconst works = [\n {\n artist: \"Ornella Binni\",\n art: \"https://images.unsplash.com/photo-1465869185982-5a1a7522cbcb?auto=format&fit=crop&w=300&q=80\",\n },\n {\n artist: \"Tom Byrom\",\n art: \"https://images.unsplash.com/photo-1548516173-3cabfa4607e9?auto=format&fit=crop&w=300&q=80\",\n },\n {\n artist: \"Vladimir Malyav\",\n art: \"https://images.unsplash.com/photo-1494337480532-3725c85fd2ab?auto=format&fit=crop&w=300&q=80\",\n },\n] as const\n\nexport default function ScrollAreaExample() {\n return (\n <ExampleWrapper>\n <ScrollAreaVertical />\n <ScrollAreaHorizontal />\n </ExampleWrapper>\n )\n}\n\nfunction ScrollAreaVertical() {\n return (\n <Example title=\"Vertical\">\n <ScrollArea className=\"mx-auto h-72 w-48 rounded-md border style-luma:rounded-2xl style-rhea:rounded-2xl\">\n <div className=\"p-4\">\n <h4 className=\"mb-4 text-sm leading-none font-medium\">Tags</h4>\n {tags.map((tag) => (\n <React.Fragment key={tag}>\n <div className=\"text-sm\">{tag}</div>\n <Separator className=\"my-2\" />\n </React.Fragment>\n ))}\n </div>\n </ScrollArea>\n </Example>\n )\n}\n\nfunction ScrollAreaHorizontal() {\n return (\n <Example title=\"Horizontal\">\n <ScrollArea className=\"mx-auto w-full max-w-96 rounded-md border p-4 style-luma:rounded-2xl style-rhea:rounded-2xl\">\n <div className=\"flex gap-4\">\n {works.map((artwork) => (\n <figure key={artwork.artist} className=\"shrink-0\">\n <div className=\"overflow-hidden rounded-md\">\n <Image\n src={artwork.art}\n alt={`Photo by ${artwork.artist}`}\n className=\"aspect-[3/4] h-fit w-fit object-cover\"\n width={300}\n height={400}\n />\n </div>\n <figcaption className=\"pt-2 text-xs text-muted-foreground\">\n Photo by{\" \"}\n <span className=\"font-semibold text-foreground\">\n {artwork.artist}\n </span>\n </figcaption>\n </figure>\n ))}\n </div>\n <ScrollBar orientation=\"horizontal\" />\n </ScrollArea>\n </Example>\n )\n}\n",
|
||||||
"type": "registry:example"
|
"type": "registry:example"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -30,17 +30,17 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "registry/base-lyra/blocks/sidebar-07/components/nav-projects.tsx",
|
"path": "registry/base-lyra/blocks/sidebar-07/components/nav-projects.tsx",
|
||||||
"content": "\"use client\"\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/base-lyra/ui/dropdown-menu\"\nimport {\n SidebarGroup,\n SidebarGroupLabel,\n SidebarMenu,\n SidebarMenuAction,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/registry/base-lyra/ui/sidebar\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nexport function NavProjects({\n projects,\n}: {\n projects: {\n name: string\n url: string\n icon: React.ReactNode\n }[]\n}) {\n const { isMobile } = useSidebar()\n return (\n <SidebarGroup className=\"group-data-[collapsible=icon]:hidden\">\n <SidebarGroupLabel>Projects</SidebarGroupLabel>\n <SidebarMenu>\n {projects.map((item) => (\n <SidebarMenuItem key={item.name}>\n <SidebarMenuButton render={<a href={item.url} />}>\n {item.icon}\n <span>{item.name}</span>\n </SidebarMenuButton>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <SidebarMenuAction\n showOnHover\n className=\"aria-expanded:bg-muted\"\n />\n }\n >\n <IconPlaceholder\n lucide=\"MoreHorizontalIcon\"\n tabler=\"IconDots\"\n hugeicons=\"MoreHorizontalCircle01Icon\"\n phosphor=\"DotsThreeOutlineIcon\"\n remixicon=\"RiMoreLine\"\n />\n <span className=\"sr-only\">More</span>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-48 rounded-lg\"\n side={isMobile ? \"bottom\" : \"right\"}\n align={isMobile ? \"end\" : \"start\"}\n >\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"FolderIcon\"\n tabler=\"IconFolder\"\n hugeicons=\"FolderIcon\"\n phosphor=\"FolderIcon\"\n remixicon=\"RiFolderLine\"\n className=\"text-muted-foreground\"\n />\n <span>View Project</span>\n </DropdownMenuItem>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"ArrowRightIcon\"\n tabler=\"IconArrowForward\"\n hugeicons=\"ArrowRightIcon\"\n phosphor=\"ShareFatIcon\"\n remixicon=\"RiShareForwardLine\"\n className=\"text-muted-foreground\"\n />\n <span>Share Project</span>\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"Trash2Icon\"\n tabler=\"IconTrash\"\n hugeicons=\"Delete02Icon\"\n phosphor=\"TrashIcon\"\n remixicon=\"RiDeleteBinLine\"\n className=\"text-muted-foreground\"\n />\n <span>Delete Project</span>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n ))}\n <SidebarMenuItem>\n <SidebarMenuButton className=\"text-sidebar-foreground/70\">\n <IconPlaceholder\n lucide=\"MoreHorizontalIcon\"\n tabler=\"IconDots\"\n hugeicons=\"MoreHorizontalCircle01Icon\"\n phosphor=\"DotsThreeOutlineIcon\"\n remixicon=\"RiMoreLine\"\n className=\"text-sidebar-foreground/70\"\n />\n <span>More</span>\n </SidebarMenuButton>\n </SidebarMenuItem>\n </SidebarMenu>\n </SidebarGroup>\n )\n}\n",
|
"content": "\"use client\"\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/base-lyra/ui/dropdown-menu\"\nimport {\n SidebarGroup,\n SidebarGroupLabel,\n SidebarMenu,\n SidebarMenuAction,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/registry/base-lyra/ui/sidebar\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nexport function NavProjects({\n projects,\n}: {\n projects: {\n name: string\n url: string\n icon: React.ReactNode\n }[]\n}) {\n const { isMobile } = useSidebar()\n return (\n <SidebarGroup className=\"group-data-[collapsible=icon]:hidden\">\n <SidebarGroupLabel>Projects</SidebarGroupLabel>\n <SidebarMenu>\n {projects.map((item) => (\n <SidebarMenuItem key={item.name}>\n <SidebarMenuButton render={<a href={item.url} />}>\n {item.icon}\n <span>{item.name}</span>\n </SidebarMenuButton>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <SidebarMenuAction\n showOnHover\n className=\"aria-expanded:bg-muted\"\n />\n }\n >\n <IconPlaceholder\n lucide=\"MoreHorizontalIcon\"\n tabler=\"IconDots\"\n hugeicons=\"MoreHorizontalCircle01Icon\"\n phosphor=\"DotsThreeOutlineIcon\"\n remixicon=\"RiMoreLine\"\n />\n <span className=\"sr-only\">More</span>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-fit\"\n side={isMobile ? \"bottom\" : \"right\"}\n align={isMobile ? \"end\" : \"start\"}\n >\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"FolderIcon\"\n tabler=\"IconFolder\"\n hugeicons=\"FolderIcon\"\n phosphor=\"FolderIcon\"\n remixicon=\"RiFolderLine\"\n />\n <span>View Project</span>\n </DropdownMenuItem>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"ArrowRightIcon\"\n tabler=\"IconArrowForward\"\n hugeicons=\"ArrowRightIcon\"\n phosphor=\"ShareFatIcon\"\n remixicon=\"RiShareForwardLine\"\n />\n <span>Share Project</span>\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem variant=\"destructive\">\n <IconPlaceholder\n lucide=\"Trash2Icon\"\n tabler=\"IconTrash\"\n hugeicons=\"Delete02Icon\"\n phosphor=\"TrashIcon\"\n remixicon=\"RiDeleteBinLine\"\n />\n <span>Delete Project</span>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n ))}\n <SidebarMenuItem>\n <SidebarMenuButton className=\"text-sidebar-foreground/70\">\n <IconPlaceholder\n lucide=\"MoreHorizontalIcon\"\n tabler=\"IconDots\"\n hugeicons=\"MoreHorizontalCircle01Icon\"\n phosphor=\"DotsThreeOutlineIcon\"\n remixicon=\"RiMoreLine\"\n className=\"text-sidebar-foreground/70\"\n />\n <span>More</span>\n </SidebarMenuButton>\n </SidebarMenuItem>\n </SidebarMenu>\n </SidebarGroup>\n )\n}\n",
|
||||||
"type": "registry:component"
|
"type": "registry:component"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "registry/base-lyra/blocks/sidebar-07/components/nav-user.tsx",
|
"path": "registry/base-lyra/blocks/sidebar-07/components/nav-user.tsx",
|
||||||
"content": "\"use client\"\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/base-lyra/ui/avatar\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/base-lyra/ui/dropdown-menu\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/registry/base-lyra/ui/sidebar\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nexport function NavUser({\n user,\n}: {\n user: {\n name: string\n email: string\n avatar: string\n }\n}) {\n const { isMobile } = useSidebar()\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <SidebarMenuButton size=\"lg\" className=\"aria-expanded:bg-muted\" />\n }\n >\n <Avatar>\n <AvatarImage src={user.avatar} alt={user.name} />\n <AvatarFallback>CN</AvatarFallback>\n </Avatar>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">{user.name}</span>\n <span className=\"truncate text-xs\">{user.email}</span>\n </div>\n <IconPlaceholder\n lucide=\"ChevronsUpDownIcon\"\n tabler=\"IconSelector\"\n hugeicons=\"UnfoldMoreIcon\"\n phosphor=\"CaretUpDownIcon\"\n remixicon=\"RiArrowUpDownLine\"\n className=\"ml-auto size-4\"\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"min-w-56 rounded-lg\"\n side={isMobile ? \"bottom\" : \"right\"}\n align=\"end\"\n sideOffset={4}\n >\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"p-0 font-normal\">\n <div className=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n <Avatar>\n <AvatarImage src={user.avatar} alt={user.name} />\n <AvatarFallback>CN</AvatarFallback>\n </Avatar>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">{user.name}</span>\n <span className=\"truncate text-xs\">{user.email}</span>\n </div>\n </div>\n </DropdownMenuLabel>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"SparklesIcon\"\n tabler=\"IconSparkles\"\n hugeicons=\"SparklesIcon\"\n phosphor=\"SparkleIcon\"\n remixicon=\"RiSparklingLine\"\n />\n Upgrade to Pro\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"BadgeCheckIcon\"\n tabler=\"IconRosetteDiscountCheck\"\n hugeicons=\"CheckmarkBadgeIcon\"\n phosphor=\"CheckCircleIcon\"\n remixicon=\"RiCheckboxCircleLine\"\n />\n Account\n </DropdownMenuItem>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"CreditCardIcon\"\n tabler=\"IconCreditCard\"\n hugeicons=\"CreditCardIcon\"\n phosphor=\"CreditCardIcon\"\n remixicon=\"RiBankCardLine\"\n />\n Billing\n </DropdownMenuItem>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"BellIcon\"\n tabler=\"IconBell\"\n hugeicons=\"NotificationIcon\"\n phosphor=\"BellIcon\"\n remixicon=\"RiNotificationLine\"\n />\n Notifications\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"LogOutIcon\"\n tabler=\"IconLogout\"\n hugeicons=\"LogoutIcon\"\n phosphor=\"SignOutIcon\"\n remixicon=\"RiLogoutBoxLine\"\n />\n Log out\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n",
|
"content": "\"use client\"\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/base-lyra/ui/avatar\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/base-lyra/ui/dropdown-menu\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/registry/base-lyra/ui/sidebar\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nexport function NavUser({\n user,\n}: {\n user: {\n name: string\n email: string\n avatar: string\n }\n}) {\n const { isMobile } = useSidebar()\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <SidebarMenuButton size=\"lg\" className=\"aria-expanded:bg-muted\" />\n }\n >\n <Avatar>\n <AvatarImage src={user.avatar} alt={user.name} />\n <AvatarFallback>CN</AvatarFallback>\n </Avatar>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">{user.name}</span>\n <span className=\"truncate text-xs\">{user.email}</span>\n </div>\n <IconPlaceholder\n lucide=\"ChevronsUpDownIcon\"\n tabler=\"IconSelector\"\n hugeicons=\"UnfoldMoreIcon\"\n phosphor=\"CaretUpDownIcon\"\n remixicon=\"RiArrowUpDownLine\"\n className=\"ml-auto size-4\"\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-fit\"\n side={isMobile ? \"bottom\" : \"right\"}\n align=\"end\"\n sideOffset={4}\n >\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"p-0 font-normal\">\n <div className=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n <Avatar>\n <AvatarImage src={user.avatar} alt={user.name} />\n <AvatarFallback>CN</AvatarFallback>\n </Avatar>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">{user.name}</span>\n <span className=\"truncate text-xs\">{user.email}</span>\n </div>\n </div>\n </DropdownMenuLabel>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"SparklesIcon\"\n tabler=\"IconSparkles\"\n hugeicons=\"SparklesIcon\"\n phosphor=\"SparkleIcon\"\n remixicon=\"RiSparklingLine\"\n />\n Upgrade to Pro\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"BadgeCheckIcon\"\n tabler=\"IconRosetteDiscountCheck\"\n hugeicons=\"CheckmarkBadgeIcon\"\n phosphor=\"CheckCircleIcon\"\n remixicon=\"RiCheckboxCircleLine\"\n />\n Account\n </DropdownMenuItem>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"CreditCardIcon\"\n tabler=\"IconCreditCard\"\n hugeicons=\"CreditCardIcon\"\n phosphor=\"CreditCardIcon\"\n remixicon=\"RiBankCardLine\"\n />\n Billing\n </DropdownMenuItem>\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"BellIcon\"\n tabler=\"IconBell\"\n hugeicons=\"NotificationIcon\"\n phosphor=\"BellIcon\"\n remixicon=\"RiNotificationLine\"\n />\n Notifications\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuItem>\n <IconPlaceholder\n lucide=\"LogOutIcon\"\n tabler=\"IconLogout\"\n hugeicons=\"LogoutIcon\"\n phosphor=\"SignOutIcon\"\n remixicon=\"RiLogoutBoxLine\"\n />\n Log out\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n",
|
||||||
"type": "registry:component"
|
"type": "registry:component"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "registry/base-lyra/blocks/sidebar-07/components/team-switcher.tsx",
|
"path": "registry/base-lyra/blocks/sidebar-07/components/team-switcher.tsx",
|
||||||
"content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuTrigger,\n} from \"@/registry/base-lyra/ui/dropdown-menu\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/registry/base-lyra/ui/sidebar\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nexport function TeamSwitcher({\n teams,\n}: {\n teams: {\n name: string\n logo: React.ReactNode\n plan: string\n }[]\n}) {\n const { isMobile } = useSidebar()\n const [activeTeam, setActiveTeam] = React.useState(teams[0])\n if (!activeTeam) {\n return null\n }\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <SidebarMenuButton\n size=\"lg\"\n className=\"data-open:bg-sidebar-accent data-open:text-sidebar-accent-foreground\"\n />\n }\n >\n <div className=\"flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground\">\n {activeTeam.logo}\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 <IconPlaceholder\n lucide=\"ChevronsUpDownIcon\"\n tabler=\"IconSelector\"\n hugeicons=\"UnfoldMoreIcon\"\n phosphor=\"CaretUpDownIcon\"\n remixicon=\"RiArrowUpDownLine\"\n className=\"ml-auto\"\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"min-w-56 rounded-lg\"\n align=\"start\"\n side={isMobile ? \"bottom\" : \"right\"}\n sideOffset={4}\n >\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"text-xs text-muted-foreground\">\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}\n </div>\n {team.name}\n <DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>\n </DropdownMenuItem>\n ))}\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem className=\"gap-2 p-2\">\n <div className=\"flex size-6 items-center justify-center rounded-md border bg-transparent\">\n <IconPlaceholder\n lucide=\"PlusIcon\"\n tabler=\"IconPlus\"\n hugeicons=\"PlusSignIcon\"\n phosphor=\"PlusIcon\"\n remixicon=\"RiAddLine\"\n className=\"size-4\"\n />\n </div>\n <div className=\"font-medium text-muted-foreground\">\n Add team\n </div>\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n",
|
"content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuTrigger,\n} from \"@/registry/base-lyra/ui/dropdown-menu\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/registry/base-lyra/ui/sidebar\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nexport function TeamSwitcher({\n teams,\n}: {\n teams: {\n name: string\n logo: React.ReactNode\n plan: string\n }[]\n}) {\n const { isMobile } = useSidebar()\n const [activeTeam, setActiveTeam] = React.useState(teams[0])\n if (!activeTeam) {\n return null\n }\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <SidebarMenuButton\n size=\"lg\"\n className=\"data-open:bg-sidebar-accent data-open:text-sidebar-accent-foreground\"\n />\n }\n >\n <div className=\"flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground\">\n {activeTeam.logo}\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 <IconPlaceholder\n lucide=\"ChevronsUpDownIcon\"\n tabler=\"IconSelector\"\n hugeicons=\"UnfoldMoreIcon\"\n phosphor=\"CaretUpDownIcon\"\n remixicon=\"RiArrowUpDownLine\"\n className=\"ml-auto\"\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-fit\"\n align=\"start\"\n side={isMobile ? \"bottom\" : \"right\"}\n sideOffset={4}\n >\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"text-xs text-muted-foreground\">\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}\n </div>\n {team.name}\n <DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>\n </DropdownMenuItem>\n ))}\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem className=\"gap-2 p-2\">\n <div className=\"flex size-6 items-center justify-center rounded-md border bg-transparent\">\n <IconPlaceholder\n lucide=\"PlusIcon\"\n tabler=\"IconPlus\"\n hugeicons=\"PlusSignIcon\"\n phosphor=\"PlusIcon\"\n remixicon=\"RiAddLine\"\n className=\"size-4\"\n />\n </div>\n <div className=\"font-medium text-muted-foreground\">\n Add team\n </div>\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n",
|
||||||
"type": "registry:component"
|
"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
File diff suppressed because one or more lines are too long
@@ -1,11 +1,12 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||||
"name": "preview-03",
|
"name": "preview-03",
|
||||||
"title": "E-commerce",
|
"title": "Preview 03",
|
||||||
|
"registryDependencies": [],
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "registry/base-maia/blocks/preview-03/index.tsx",
|
"path": "registry/base-maia/blocks/preview-03/index.tsx",
|
||||||
"content": "export default function Preview02Example() {\n return (\n <div className=\"overflow-x-auto overflow-y-hidden bg-muted contain-[paint] [--gap:--spacing(4)] 3xl:[--gap:--spacing(12)] md:[--gap:--spacing(10)] dark:bg-background style-lyra:md:[--gap:--spacing(6)] style-mira:md:[--gap:--spacing(6)]\">\n <div className=\"flex w-full min-w-max justify-center\">\n <div\n className=\"grid w-[2400px] grid-cols-7 items-start gap-(--gap) bg-muted p-(--gap) md:w-[3000px] dark:bg-background style-lyra:md:w-[2600px] style-mira:md:w-[2600px] *:[div]:gap-(--gap)\"\n data-slot=\"capture-target\"\n >\n <div className=\"flex flex-col p-1 [contain-intrinsic-size:380px_1200px] [content-visibility:auto]\">\n <p>foo</p>\n </div>\n </div>\n </div>\n </div>\n )\n}\n",
|
"content": "export default function Preview03Example() {\n return (\n <div className=\"overflow-x-auto overflow-y-hidden bg-muted contain-[paint] [--gap:--spacing(4)] 3xl:[--gap:--spacing(12)] md:[--gap:--spacing(10)] dark:bg-background\">\n <div className=\"flex w-full min-w-max justify-center\">\n <div\n className=\"grid w-[2400px] grid-cols-7 items-start gap-(--gap) bg-muted p-(--gap) md:w-[3000px] dark:bg-background\"\n data-slot=\"capture-target\"\n />\n </div>\n </div>\n )\n}\n",
|
||||||
"type": "registry:block"
|
"type": "registry:block"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user