Template
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa74e73653 | ||
|
|
55ae7f2e42 | ||
|
|
f9550116d7 | ||
|
|
c9017c4510 | ||
|
|
6376bb3d82 | ||
|
|
d7e987cea3 | ||
|
|
a472dd5d97 | ||
|
|
8864785752 |
+1
-1
@@ -169,7 +169,7 @@
|
|||||||
background-size: 64px 100%;
|
background-size: 64px 100%;
|
||||||
}
|
}
|
||||||
html {
|
html {
|
||||||
@apply font-sans;
|
@apply scroll-pt-20 font-sans;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -11,7 +11,7 @@ import { TestimonialsSection } from "@/components/sections/testimonials-section"
|
|||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background text-foreground selection:bg-blue-600 selection:text-white">
|
<div className="min-h-screen overflow-x-clip bg-background text-foreground selection:bg-blue-600 selection:text-white">
|
||||||
<SiteHeader />
|
<SiteHeader />
|
||||||
<main id="top" className="mx-auto max-w-[1280px] border-x">
|
<main id="top" className="mx-auto max-w-[1280px] border-x">
|
||||||
<HeroSection />
|
<HeroSection />
|
||||||
@@ -22,8 +22,8 @@ export default function Home() {
|
|||||||
<PricingSection />
|
<PricingSection />
|
||||||
<TestimonialsSection />
|
<TestimonialsSection />
|
||||||
<CtaSection />
|
<CtaSection />
|
||||||
<SiteFooter />
|
|
||||||
</main>
|
</main>
|
||||||
|
<SiteFooter />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
"cssVariables": true,
|
"cssVariables": true,
|
||||||
"prefix": ""
|
"prefix": ""
|
||||||
},
|
},
|
||||||
"iconLibrary": "lucide",
|
"iconLibrary": "remixicon",
|
||||||
"rtl": false,
|
"rtl": false,
|
||||||
"menuColor": "default",
|
"menuColor": "default",
|
||||||
"menuAccent": "subtle",
|
"menuAccent": "subtle",
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { useEffect, useRef, useState } from "react"
|
||||||
|
import { RiArrowRightLine, RiCloseLine, RiMenu3Line } from "@remixicon/react"
|
||||||
|
import { Dialog as DialogPrimitive } from "radix-ui"
|
||||||
|
|
||||||
|
import { Brand } from "@/components/shared/brand"
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogClose,
|
||||||
|
DialogDescription,
|
||||||
|
DialogOverlay,
|
||||||
|
DialogPortal,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog"
|
||||||
|
|
||||||
|
type NavigationItem = {
|
||||||
|
label: string
|
||||||
|
href: string
|
||||||
|
description: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MobileNavigation({ items }: { items: NavigationItem[] }) {
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
|
const navigating = useRef(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const desktop = window.matchMedia("(min-width: 768px)")
|
||||||
|
const closeOnDesktop = () => {
|
||||||
|
if (desktop.matches) setOpen(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
desktop.addEventListener("change", closeOnDesktop)
|
||||||
|
return () => desktop.removeEventListener("change", closeOnDesktop)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
aria-label="Open navigation menu"
|
||||||
|
className="inline-flex size-11 items-center justify-center rounded-sm border bg-background/80 text-foreground transition-colors hover:border-blue-500/40 hover:bg-blue-600/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring md:hidden"
|
||||||
|
>
|
||||||
|
<RiMenu3Line className="size-5" aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
</DialogTrigger>
|
||||||
|
|
||||||
|
<DialogPortal>
|
||||||
|
<DialogOverlay className="z-[60] bg-black/45 duration-200 supports-backdrop-filter:backdrop-blur-md md:hidden" />
|
||||||
|
<DialogPrimitive.Content
|
||||||
|
className="fixed inset-x-3 top-3 z-[61] mx-auto flex max-h-[calc(100dvh-1.5rem)] max-w-lg flex-col overflow-hidden rounded-2xl border bg-background text-foreground shadow-[0_24px_100px_rgba(0,0,0,.35)] outline-none duration-200 data-open:animate-in data-open:fade-in-0 data-open:slide-in-from-top-4 data-closed:animate-out data-closed:fade-out-0 data-closed:slide-out-to-top-4 md:hidden"
|
||||||
|
onCloseAutoFocus={(event) => {
|
||||||
|
// Let the anchor move focus to its section without the trigger
|
||||||
|
// interrupting the page's smooth scroll when the dialog closes.
|
||||||
|
if (navigating.current) event.preventDefault()
|
||||||
|
navigating.current = false
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="flex shrink-0 items-center justify-between border-b bg-linear-to-r from-blue-600/10 via-blue-600/5 to-transparent px-5 py-3">
|
||||||
|
<Brand />
|
||||||
|
<DialogClose asChild>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
aria-label="Close navigation menu"
|
||||||
|
className="inline-flex size-11 items-center justify-center rounded-full border bg-background/70 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
||||||
|
>
|
||||||
|
<RiCloseLine className="size-5" aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
</DialogClose>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="min-h-0 overflow-y-auto overscroll-contain p-3">
|
||||||
|
<DialogTitle className="px-3 pb-2 pt-3 font-mono text-[10px] font-medium tracking-[0.18em] text-muted-foreground uppercase">
|
||||||
|
Explore Vertex
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogDescription className="sr-only">
|
||||||
|
Explore our products, models, features, pricing, and developer documentation.
|
||||||
|
</DialogDescription>
|
||||||
|
<nav aria-label="Mobile navigation">
|
||||||
|
<ul className="space-y-1">
|
||||||
|
{items.map(({ label, href, description }) => (
|
||||||
|
<li key={label}>
|
||||||
|
<DialogClose asChild>
|
||||||
|
<a
|
||||||
|
href={href}
|
||||||
|
onClick={() => { navigating.current = true }}
|
||||||
|
className="group flex items-center justify-between gap-4 rounded-xl px-3 py-3 transition-colors hover:bg-blue-600/8 focus-visible:bg-blue-600/8 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
|
||||||
|
>
|
||||||
|
<span className="min-w-0">
|
||||||
|
<span className="block text-xl font-medium tracking-tight">{label}</span>
|
||||||
|
<span className="mt-0.5 block text-xs leading-5 text-muted-foreground">{description}</span>
|
||||||
|
</span>
|
||||||
|
<span className="flex size-8 shrink-0 items-center justify-center rounded-full border text-muted-foreground transition-colors group-hover:border-blue-500/30 group-hover:bg-blue-600/10 group-hover:text-blue-600 dark:group-hover:text-blue-400">
|
||||||
|
<RiArrowRightLine className="size-4" aria-hidden="true" />
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</DialogClose>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="shrink-0 border-t bg-muted/35 p-5">
|
||||||
|
<p className="mb-3 text-xs text-muted-foreground">One API. Every AI model.</p>
|
||||||
|
<DialogClose asChild>
|
||||||
|
<a
|
||||||
|
href="#pricing"
|
||||||
|
onClick={() => { navigating.current = true }}
|
||||||
|
className="flex h-12 items-center justify-between rounded-lg bg-blue-600 px-4 text-sm font-medium text-white shadow-[0_6px_24px_rgba(23,61,166,.2)] transition-colors hover:bg-blue-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
|
||||||
|
>
|
||||||
|
Get started
|
||||||
|
<RiArrowRightLine className="size-4" aria-hidden="true" />
|
||||||
|
</a>
|
||||||
|
</DialogClose>
|
||||||
|
</div>
|
||||||
|
</DialogPrimitive.Content>
|
||||||
|
</DialogPortal>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
|
import { RiGithubFill, RiTwitterXFill } from "@remixicon/react"
|
||||||
|
|
||||||
import { Brand } from "@/components/shared/brand"
|
import { Brand } from "@/components/shared/brand"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
|
||||||
export function SiteFooter() {
|
export function SiteFooter() {
|
||||||
return (
|
return (
|
||||||
<footer className="px-6 py-10 sm:px-10">
|
<footer className="mx-auto max-w-[1280px] border-x px-6 py-10 sm:px-10">
|
||||||
<div className="flex flex-col gap-8 sm:flex-row sm:items-center sm:justify-between">
|
<div className="flex flex-col gap-8 sm:flex-row sm:items-center sm:justify-between">
|
||||||
<div>
|
<div>
|
||||||
<Brand />
|
<Brand />
|
||||||
@@ -18,8 +21,20 @@ export function SiteFooter() {
|
|||||||
<a className="hover:text-foreground" href="#top">Privacy</a>
|
<a className="hover:text-foreground" href="#top">Privacy</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-10 text-[11px] text-muted-foreground">
|
<div className="mt-10 flex flex-wrap items-center justify-between gap-4 text-[11px] text-muted-foreground">
|
||||||
<span>© 2026 Vertex, Inc. All rights reserved.</span>
|
<span>© 2026 Vertex, Inc. All rights reserved.</span>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Button asChild variant="ghost" size="icon">
|
||||||
|
<a href="https://github.com" aria-label="GitHub">
|
||||||
|
<RiGithubFill className="size-4" aria-hidden="true" />
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
|
<Button asChild variant="ghost" size="icon">
|
||||||
|
<a href="https://x.com" aria-label="X (Twitter)">
|
||||||
|
<RiTwitterXFill className="size-4" aria-hidden="true" />
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,30 +1,35 @@
|
|||||||
import { ChevronDown, ChevronRight } from "lucide-react"
|
import { RiArrowDownSLine, RiArrowRightSLine } from "@remixicon/react"
|
||||||
|
|
||||||
|
import { MobileNavigation } from "@/components/layout/mobile-navigation"
|
||||||
import { ThemeToggle } from "@/components/layout/theme-toggle"
|
import { ThemeToggle } from "@/components/layout/theme-toggle"
|
||||||
import { Brand } from "@/components/shared/brand"
|
import { Brand } from "@/components/shared/brand"
|
||||||
|
import { FrameCrosses } from "@/components/shared/frame-crosses"
|
||||||
|
|
||||||
|
const navigationItems = [
|
||||||
|
{ label: "Products", href: "#features", description: "One gateway for your AI stack" },
|
||||||
|
{ label: "Models", href: "#models", description: "Explore the models you can build with" },
|
||||||
|
{ label: "Features", href: "#features", description: "Routing, insights, and reliability" },
|
||||||
|
{ label: "Pricing", href: "#pricing", description: "Start free. Scale at your pace." },
|
||||||
|
{ label: "Docs", href: "#developers", description: "Your first request starts here" },
|
||||||
|
]
|
||||||
|
|
||||||
export function SiteHeader() {
|
export function SiteHeader() {
|
||||||
return (
|
return (
|
||||||
<header className="sticky top-0 z-50 w-full border-b bg-background/86 backdrop-blur-xl supports-[backdrop-filter]:bg-background/74">
|
<header className="sticky top-0 z-50 w-full border-b bg-background/86 backdrop-blur-xl supports-[backdrop-filter]:bg-background/74">
|
||||||
<div className="mx-auto flex h-16 max-w-[1280px] items-center justify-between px-5 sm:px-8">
|
<div className="relative mx-auto flex h-16 max-w-[1280px] items-center justify-between border-x px-5 sm:px-8">
|
||||||
|
<FrameCrosses edges="bottom" />
|
||||||
<a href="#top" aria-label="Vertex home">
|
<a href="#top" aria-label="Vertex home">
|
||||||
<Brand />
|
<Brand />
|
||||||
</a>
|
</a>
|
||||||
<nav aria-label="Main navigation" className="hidden items-center gap-8 md:flex lg:gap-10">
|
<nav aria-label="Main navigation" className="hidden items-center gap-8 md:flex lg:gap-10">
|
||||||
{[
|
{navigationItems.map(({ label, href }) => (
|
||||||
["Products", "#features"],
|
|
||||||
["Models", "#models"],
|
|
||||||
["Features", "#features"],
|
|
||||||
["Pricing", "#pricing"],
|
|
||||||
["Docs", "#developers"],
|
|
||||||
].map(([label, href]) => (
|
|
||||||
<a
|
<a
|
||||||
key={label}
|
key={label}
|
||||||
href={href}
|
href={href}
|
||||||
className="inline-flex items-center gap-1 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground"
|
className="inline-flex items-center gap-1 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground"
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
{label === "Products" && <ChevronDown className="size-3" />}
|
{label === "Products" && <RiArrowDownSLine className="size-3" />}
|
||||||
</a>
|
</a>
|
||||||
))}
|
))}
|
||||||
</nav>
|
</nav>
|
||||||
@@ -34,8 +39,9 @@ export function SiteHeader() {
|
|||||||
href="#pricing"
|
href="#pricing"
|
||||||
className="hidden h-9 items-center gap-1.5 rounded-sm bg-blue-600 px-4 text-xs font-medium text-white shadow-[0_6px_24px_rgba(23,61,166,.28)] transition hover:bg-blue-500 sm:inline-flex"
|
className="hidden h-9 items-center gap-1.5 rounded-sm bg-blue-600 px-4 text-xs font-medium text-white shadow-[0_6px_24px_rgba(23,61,166,.28)] transition hover:bg-blue-500 sm:inline-flex"
|
||||||
>
|
>
|
||||||
Get started <ChevronRight className="size-3.5" />
|
Get started <RiArrowRightSLine className="size-3.5" />
|
||||||
</a>
|
</a>
|
||||||
|
<MobileNavigation items={navigationItems} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { Moon, Sun } from "lucide-react"
|
import { RiMoonLine, RiSunLine } from "@remixicon/react"
|
||||||
import { useTheme } from "next-themes"
|
import { useTheme } from "next-themes"
|
||||||
import { useSyncExternalStore } from "react"
|
import { useSyncExternalStore } from "react"
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ export function ThemeToggle() {
|
|||||||
onClick={() => setTheme(isDark ? "light" : "dark")}
|
onClick={() => setTheme(isDark ? "light" : "dark")}
|
||||||
>
|
>
|
||||||
{mounted ? (
|
{mounted ? (
|
||||||
isDark ? <Sun className="size-4" /> : <Moon className="size-4" />
|
isDark ? <RiSunLine className="size-4" /> : <RiMoonLine className="size-4" />
|
||||||
) : (
|
) : (
|
||||||
<span className="size-4" aria-hidden="true" />
|
<span className="size-4" aria-hidden="true" />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Code2, Gauge, Workflow } from "lucide-react"
|
import { RiCodeSSlashLine, RiSpeedUpLine, RiFlowChart } from "@remixicon/react"
|
||||||
|
|
||||||
import { SectionHeading } from "@/components/shared/section-heading"
|
import { SectionHeading } from "@/components/shared/section-heading"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
@@ -14,17 +14,17 @@ export function DevelopersSection() {
|
|||||||
<div className="grid md:grid-cols-3">
|
<div className="grid md:grid-cols-3">
|
||||||
{[
|
{[
|
||||||
{
|
{
|
||||||
icon: Code2,
|
icon: RiCodeSSlashLine,
|
||||||
title: "Change one base URL",
|
title: "Change one base URL",
|
||||||
text: "Keep your existing OpenAI-compatible SDK, payloads, and streaming logic.",
|
text: "Keep your existing OpenAI-compatible SDK, payloads, and streaming logic.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: Workflow,
|
icon: RiFlowChart,
|
||||||
title: "Set a routing policy",
|
title: "Set a routing policy",
|
||||||
text: "Choose a model directly or let Vertex optimize for cost, quality, or latency.",
|
text: "Choose a model directly or let Vertex optimize for cost, quality, or latency.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: Gauge,
|
icon: RiSpeedUpLine,
|
||||||
title: "Observe every request",
|
title: "Observe every request",
|
||||||
text: "Trace performance and spend across models, applications, and environments.",
|
text: "Trace performance and spend across models, applications, and environments.",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ export function FeaturesSection() {
|
|||||||
description="Everything you need to move quickly across models without giving up reliability, control, or visibility."
|
description="Everything you need to move quickly across models without giving up reliability, control, or visibility."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="grid lg:grid-cols-12">
|
<div className="grid grid-cols-1 lg:grid-cols-12">
|
||||||
<article className="flex min-h-[520px] flex-col border-b lg:col-span-7 lg:border-r">
|
<article className="flex min-h-[520px] min-w-0 flex-col border-b lg:col-span-7 lg:border-r">
|
||||||
<ApiTerminal />
|
<ApiTerminal />
|
||||||
<FeatureCopy
|
<FeatureCopy
|
||||||
title="One compatible endpoint"
|
title="One compatible endpoint"
|
||||||
@@ -24,7 +24,7 @@ export function FeaturesSection() {
|
|||||||
/>
|
/>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article className="flex min-h-[520px] flex-col border-b lg:col-span-5">
|
<article className="flex min-h-[520px] min-w-0 flex-col border-b lg:col-span-5">
|
||||||
<IntegrationOrbit />
|
<IntegrationOrbit />
|
||||||
<FeatureCopy
|
<FeatureCopy
|
||||||
title="Seamless integrations"
|
title="Seamless integrations"
|
||||||
@@ -32,7 +32,7 @@ export function FeaturesSection() {
|
|||||||
/>
|
/>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article className="flex min-h-[430px] flex-col border-b lg:col-span-4 lg:border-b-0 lg:border-r">
|
<article className="flex min-h-[430px] min-w-0 flex-col border-b lg:col-span-4 lg:border-b-0 lg:border-r">
|
||||||
<RoutingActivity />
|
<RoutingActivity />
|
||||||
<FeatureCopy
|
<FeatureCopy
|
||||||
title="Automatic failover"
|
title="Automatic failover"
|
||||||
@@ -40,8 +40,8 @@ export function FeaturesSection() {
|
|||||||
/>
|
/>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article className="flex min-h-[430px] flex-col border-b lg:col-span-4 lg:border-b-0 lg:border-r">
|
<article className="flex min-h-[430px] min-w-0 flex-col border-b lg:col-span-4 lg:border-b-0 lg:border-r">
|
||||||
<div className="relative h-[360px] shrink-0 overflow-hidden bg-background">
|
<div className="relative h-[360px] w-full min-w-0 shrink-0 overflow-hidden bg-background">
|
||||||
<UsageChart />
|
<UsageChart />
|
||||||
</div>
|
</div>
|
||||||
<FeatureCopy
|
<FeatureCopy
|
||||||
@@ -50,7 +50,7 @@ export function FeaturesSection() {
|
|||||||
/>
|
/>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article className="flex min-h-[430px] flex-col lg:col-span-4">
|
<article className="flex min-h-[430px] min-w-0 flex-col lg:col-span-4">
|
||||||
<GlobalGlobe />
|
<GlobalGlobe />
|
||||||
<FeatureCopy
|
<FeatureCopy
|
||||||
title="Global inference gateway"
|
title="Global inference gateway"
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
|
import { type COBEOptions } from "cobe"
|
||||||
|
import { useTheme } from "next-themes"
|
||||||
|
|
||||||
import { Globe } from "@/components/ui/globe"
|
import { Globe } from "@/components/ui/globe"
|
||||||
|
|
||||||
const globeConfig = {
|
const darkGlobeConfig: COBEOptions = {
|
||||||
width: 800,
|
width: 800,
|
||||||
height: 800,
|
height: 800,
|
||||||
onRender: () => {},
|
onRender: () => {},
|
||||||
@@ -28,13 +31,25 @@ const globeConfig = {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lightGlobeConfig: COBEOptions = {
|
||||||
|
...darkGlobeConfig,
|
||||||
|
dark: 0,
|
||||||
|
diffuse: 0.4,
|
||||||
|
mapBrightness: 1.2,
|
||||||
|
baseColor: [0.9, 0.94, 1],
|
||||||
|
markerColor: [0.09, 0.24, 0.65],
|
||||||
|
glowColor: [0.85, 0.9, 1],
|
||||||
|
}
|
||||||
|
|
||||||
export function GlobalGlobe() {
|
export function GlobalGlobe() {
|
||||||
|
const { resolvedTheme } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative h-[360px] shrink-0 overflow-hidden bg-background">
|
<div className="relative h-[360px] shrink-0 overflow-hidden bg-background">
|
||||||
<Globe className="top-6 max-w-[360px]" config={globeConfig} />
|
<Globe
|
||||||
<div className="absolute left-5 top-5 flex items-center gap-2 rounded-full border bg-background/85 px-3 py-1.5 font-mono text-[10px] shadow-sm backdrop-blur">
|
className="top-6 max-w-[360px]"
|
||||||
<span className="size-1.5 animate-pulse rounded-full bg-emerald-500" /> 8 regions online
|
config={resolvedTheme === "light" ? lightGlobeConfig : darkGlobeConfig}
|
||||||
</div>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,37 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { Activity, CircleCheck, Route, ShieldCheck, Zap } from "lucide-react"
|
import { RiPulseLine, RiCheckboxCircleLine, RiRouteLine, RiShieldCheckLine, RiFlashlightLine } from "@remixicon/react"
|
||||||
|
|
||||||
import { AnimatedList } from "@/components/ui/animated-list"
|
import { AnimatedList } from "@/components/ui/animated-list"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
const routingEvents = [
|
const routingEvents = [
|
||||||
{
|
{
|
||||||
icon: <Route className="size-4" />,
|
icon: <RiRouteLine className="size-4" />,
|
||||||
title: "Routed to Claude Sonnet",
|
title: "Routed to Claude Sonnet",
|
||||||
meta: "342ms · 8.2k tokens",
|
meta: "342ms · 8.2k tokens",
|
||||||
accent: "bg-blue-600/15 text-blue-600 dark:text-blue-400",
|
accent: "bg-blue-600/15 text-blue-600 dark:text-blue-400",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: <Zap className="size-4" />,
|
icon: <RiFlashlightLine className="size-4" />,
|
||||||
title: "Prompt cache hit",
|
title: "Prompt cache hit",
|
||||||
meta: "Saved $0.018 · 42ms",
|
meta: "Saved $0.018 · 42ms",
|
||||||
accent: "bg-amber-500/15 text-amber-500",
|
accent: "bg-amber-500/15 text-amber-500",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: <Activity className="size-4" />,
|
icon: <RiPulseLine className="size-4" />,
|
||||||
title: "Latency policy applied",
|
title: "Latency policy applied",
|
||||||
meta: "Gemini Flash · 118ms",
|
meta: "Gemini Flash · 118ms",
|
||||||
accent: "bg-blue-500/15 text-blue-500",
|
accent: "bg-blue-500/15 text-blue-500",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: <CircleCheck className="size-4" />,
|
icon: <RiCheckboxCircleLine className="size-4" />,
|
||||||
title: "Fallback completed",
|
title: "Fallback completed",
|
||||||
meta: "OpenAI → Mistral · 621ms",
|
meta: "OpenAI → Mistral · 621ms",
|
||||||
accent: "bg-emerald-500/15 text-emerald-500",
|
accent: "bg-emerald-500/15 text-emerald-500",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: <ShieldCheck className="size-4" />,
|
icon: <RiShieldCheckLine className="size-4" />,
|
||||||
title: "Guardrail passed",
|
title: "Guardrail passed",
|
||||||
meta: "No sensitive data detected",
|
meta: "No sensitive data detected",
|
||||||
accent: "bg-cyan-500/15 text-cyan-500",
|
accent: "bg-cyan-500/15 text-cyan-500",
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export function UsageChart() {
|
|||||||
const fillId = useId()
|
const fillId = useId()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChartContainer config={chartConfig} className="h-full min-h-[270px] w-full aspect-auto">
|
<ChartContainer config={chartConfig} className="h-full min-h-[270px] w-full min-w-0 aspect-auto">
|
||||||
<AreaChart
|
<AreaChart
|
||||||
accessibilityLayer
|
accessibilityLayer
|
||||||
aria-label="Example model usage: requests increase from 2,350 to 5,680 over the day. Use the arrow keys to explore."
|
aria-label="Example model usage: requests increase from 2,350 to 5,680 over the day. Use the arrow keys to explore."
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { ArrowRight } from "lucide-react"
|
import { RiArrowRightLine } from "@remixicon/react"
|
||||||
|
|
||||||
import { FrameCrosses } from "@/components/shared/frame-crosses"
|
import { FrameCrosses } from "@/components/shared/frame-crosses"
|
||||||
|
|
||||||
export function HeroSection() {
|
export function HeroSection() {
|
||||||
return (
|
return (
|
||||||
<section className="hero-gradient relative border-b px-6 pb-14 pt-24 text-center sm:px-10 sm:pb-20 sm:pt-28 lg:pt-32">
|
<section className="hero-gradient relative border-b px-6 pb-14 pt-24 text-center sm:px-10 sm:pb-20 sm:pt-28 lg:pt-32">
|
||||||
<FrameCrosses />
|
<FrameCrosses edges="bottom" />
|
||||||
<div className="relative z-10 mx-auto max-w-4xl">
|
<div className="relative z-10 mx-auto max-w-4xl">
|
||||||
<a
|
<a
|
||||||
href="#features"
|
href="#features"
|
||||||
@@ -25,7 +25,7 @@ export function HeroSection() {
|
|||||||
href="#pricing"
|
href="#pricing"
|
||||||
className="inline-flex h-11 w-full items-center justify-center gap-2 rounded-sm bg-blue-600 px-6 text-sm font-medium text-white shadow-[0_10px_32px_rgba(23,61,166,.32)] transition hover:-translate-y-0.5 hover:bg-blue-500 sm:w-auto"
|
className="inline-flex h-11 w-full items-center justify-center gap-2 rounded-sm bg-blue-600 px-6 text-sm font-medium text-white shadow-[0_10px_32px_rgba(23,61,166,.32)] transition hover:-translate-y-0.5 hover:bg-blue-500 sm:w-auto"
|
||||||
>
|
>
|
||||||
Get your API key <ArrowRight className="size-4" />
|
Get your API key <RiArrowRightLine className="size-4" />
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="#models"
|
href="#models"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
import { Check } from "lucide-react"
|
import { RiCheckLine } from "@remixicon/react"
|
||||||
|
|
||||||
import { SectionHeading } from "@/components/shared/section-heading"
|
import { SectionHeading } from "@/components/shared/section-heading"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
@@ -94,7 +94,7 @@ export function PricingSection() {
|
|||||||
<ul className="mt-7 space-y-3">
|
<ul className="mt-7 space-y-3">
|
||||||
{plan.features.map((feature) => (
|
{plan.features.map((feature) => (
|
||||||
<li key={feature} className="flex items-start gap-2.5 text-sm text-muted-foreground">
|
<li key={feature} className="flex items-start gap-2.5 text-sm text-muted-foreground">
|
||||||
<Check className="mt-0.5 size-4 shrink-0 text-blue-600 dark:text-blue-400" />
|
<RiCheckLine className="mt-0.5 size-4 shrink-0 text-blue-600 dark:text-blue-400" />
|
||||||
{feature}
|
{feature}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LockKeyhole } from "lucide-react"
|
import { RiLock2Line } from "@remixicon/react"
|
||||||
|
|
||||||
import { Ripple } from "@/components/ui/ripple"
|
import { Ripple } from "@/components/ui/ripple"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
@@ -9,7 +9,7 @@ export function ReliabilitySection() {
|
|||||||
<Ripple className="opacity-40" mainCircleSize={180} numCircles={9} />
|
<Ripple className="opacity-40" mainCircleSize={180} numCircles={9} />
|
||||||
<div className="relative z-10 mx-auto max-w-3xl">
|
<div className="relative z-10 mx-auto max-w-3xl">
|
||||||
<div className="mx-auto flex size-12 items-center justify-center rounded-2xl border bg-background shadow-sm">
|
<div className="mx-auto flex size-12 items-center justify-center rounded-2xl border bg-background shadow-sm">
|
||||||
<LockKeyhole className="size-5 text-blue-600" />
|
<RiLock2Line className="size-5 text-blue-600" />
|
||||||
</div>
|
</div>
|
||||||
<h2 className="mt-6 text-balance text-3xl font-medium tracking-[-0.045em] sm:text-4xl">
|
<h2 className="mt-6 text-balance text-3xl font-medium tracking-[-0.045em] sm:text-4xl">
|
||||||
Reliability built into every request.
|
Reliability built into every request.
|
||||||
|
|||||||
@@ -1,10 +1,22 @@
|
|||||||
export function FrameCrosses() {
|
export function FrameCrosses({
|
||||||
|
edges = "all",
|
||||||
|
}: {
|
||||||
|
edges?: "all" | "top" | "bottom"
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
{edges !== "bottom" && (
|
||||||
<>
|
<>
|
||||||
<span className="frame-cross left-0 top-0" aria-hidden="true" />
|
<span className="frame-cross left-0 top-0" aria-hidden="true" />
|
||||||
<span className="frame-cross right-0 top-0" aria-hidden="true" />
|
<span className="frame-cross right-0 top-0" aria-hidden="true" />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{edges !== "top" && (
|
||||||
|
<>
|
||||||
<span className="frame-cross bottom-0 left-0" aria-hidden="true" />
|
<span className="frame-cross bottom-0 left-0" aria-hidden="true" />
|
||||||
<span className="frame-cross bottom-0 right-0" aria-hidden="true" />
|
<span className="frame-cross bottom-0 right-0" aria-hidden="true" />
|
||||||
</>
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import * as React from "react"
|
|||||||
import { Accordion as AccordionPrimitive } from "radix-ui"
|
import { Accordion as AccordionPrimitive } from "radix-ui"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
import { RiArrowDownSLine, RiArrowUpSLine } from "@remixicon/react"
|
||||||
|
|
||||||
function Accordion({
|
function Accordion({
|
||||||
className,
|
className,
|
||||||
@@ -48,8 +48,8 @@ function AccordionTrigger({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
<ChevronDownIcon data-slot="accordion-trigger-icon" className="pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden" />
|
<RiArrowDownSLine data-slot="accordion-trigger-icon" className="pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden" />
|
||||||
<ChevronUpIcon data-slot="accordion-trigger-icon" className="pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline" />
|
<RiArrowUpSLine data-slot="accordion-trigger-icon" className="pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline" />
|
||||||
</AccordionPrimitive.Trigger>
|
</AccordionPrimitive.Trigger>
|
||||||
</AccordionPrimitive.Header>
|
</AccordionPrimitive.Header>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import * as React from "react"
|
|||||||
import { Slot } from "radix-ui"
|
import { Slot } from "radix-ui"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react"
|
import { RiArrowRightSLine, RiMoreLine } from "@remixicon/react"
|
||||||
|
|
||||||
function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">) {
|
function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">) {
|
||||||
return (
|
return (
|
||||||
@@ -83,7 +83,7 @@ function BreadcrumbSeparator({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children ?? (
|
{children ?? (
|
||||||
<ChevronRightIcon />
|
<RiArrowRightSLine />
|
||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
@@ -104,7 +104,7 @@ function BreadcrumbEllipsis({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<MoreHorizontalIcon
|
<RiMoreLine
|
||||||
/>
|
/>
|
||||||
<span className="sr-only">More</span>
|
<span className="sr-only">More</span>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { Button, buttonVariants } from "@/components/ui/button"
|
import { Button, buttonVariants } from "@/components/ui/button"
|
||||||
import { ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon } from "lucide-react"
|
import { RiArrowLeftSLine, RiArrowRightSLine, RiArrowDownSLine } from "@remixicon/react"
|
||||||
|
|
||||||
function Calendar({
|
function Calendar({
|
||||||
className,
|
className,
|
||||||
@@ -147,18 +147,18 @@ function Calendar({
|
|||||||
Chevron: ({ className, orientation, ...props }) => {
|
Chevron: ({ className, orientation, ...props }) => {
|
||||||
if (orientation === "left") {
|
if (orientation === "left") {
|
||||||
return (
|
return (
|
||||||
<ChevronLeftIcon className={cn("size-4", className)} {...props} />
|
<RiArrowLeftSLine className={cn("size-4", className)} {...props} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (orientation === "right") {
|
if (orientation === "right") {
|
||||||
return (
|
return (
|
||||||
<ChevronRightIcon className={cn("size-4", className)} {...props} />
|
<RiArrowRightSLine className={cn("size-4", className)} {...props} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChevronDownIcon className={cn("size-4", className)} {...props} />
|
<RiArrowDownSLine className={cn("size-4", className)} {...props} />
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
DayButton: ({ ...props }) => (
|
DayButton: ({ ...props }) => (
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import useEmblaCarousel, {
|
|||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react"
|
import { RiArrowLeftSLine, RiArrowRightSLine } from "@remixicon/react"
|
||||||
|
|
||||||
type CarouselApi = UseEmblaCarouselType[1]
|
type CarouselApi = UseEmblaCarouselType[1]
|
||||||
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
|
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
|
||||||
@@ -202,7 +202,7 @@ function CarouselPrevious({
|
|||||||
onClick={scrollPrev}
|
onClick={scrollPrev}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<ChevronLeftIcon />
|
<RiArrowLeftSLine />
|
||||||
<span className="sr-only">Previous slide</span>
|
<span className="sr-only">Previous slide</span>
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
@@ -232,7 +232,7 @@ function CarouselNext({
|
|||||||
onClick={scrollNext}
|
onClick={scrollNext}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<ChevronRightIcon />
|
<RiArrowRightSLine />
|
||||||
<span className="sr-only">Next slide</span>
|
<span className="sr-only">Next slide</span>
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import * as React from "react"
|
|||||||
import { Checkbox as CheckboxPrimitive } from "radix-ui"
|
import { Checkbox as CheckboxPrimitive } from "radix-ui"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { CheckIcon } from "lucide-react"
|
import { RiCheckLine } from "@remixicon/react"
|
||||||
|
|
||||||
function Checkbox({
|
function Checkbox({
|
||||||
className,
|
className,
|
||||||
@@ -23,7 +23,7 @@ function Checkbox({
|
|||||||
data-slot="checkbox-indicator"
|
data-slot="checkbox-indicator"
|
||||||
className="grid place-content-center text-current transition-none [&>svg]:size-3.5"
|
className="grid place-content-center text-current transition-none [&>svg]:size-3.5"
|
||||||
>
|
>
|
||||||
<CheckIcon
|
<RiCheckLine
|
||||||
/>
|
/>
|
||||||
</CheckboxPrimitive.Indicator>
|
</CheckboxPrimitive.Indicator>
|
||||||
</CheckboxPrimitive.Root>
|
</CheckboxPrimitive.Root>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
InputGroupButton,
|
InputGroupButton,
|
||||||
InputGroupInput,
|
InputGroupInput,
|
||||||
} from "@/components/ui/input-group"
|
} from "@/components/ui/input-group"
|
||||||
import { ChevronDownIcon, XIcon, CheckIcon } from "lucide-react"
|
import { RiArrowDownSLine, RiCloseLine, RiCheckLine } from "@remixicon/react"
|
||||||
|
|
||||||
const Combobox = ComboboxPrimitive.Root
|
const Combobox = ComboboxPrimitive.Root
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ function ComboboxTrigger({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
<ChevronDownIcon className="pointer-events-none size-4 text-muted-foreground" />
|
<RiArrowDownSLine className="pointer-events-none size-4 text-muted-foreground" />
|
||||||
</ComboboxPrimitive.Trigger>
|
</ComboboxPrimitive.Trigger>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ function ComboboxClear({ className, ...props }: ComboboxPrimitive.Clear.Props) {
|
|||||||
className={cn(className)}
|
className={cn(className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<XIcon className="pointer-events-none" />
|
<RiCloseLine className="pointer-events-none" />
|
||||||
</ComboboxPrimitive.Clear>
|
</ComboboxPrimitive.Clear>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@ function ComboboxItem({
|
|||||||
<span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center" />
|
<span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center" />
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<CheckIcon className="pointer-events-none" />
|
<RiCheckLine className="pointer-events-none" />
|
||||||
</ComboboxPrimitive.ItemIndicator>
|
</ComboboxPrimitive.ItemIndicator>
|
||||||
</ComboboxPrimitive.Item>
|
</ComboboxPrimitive.Item>
|
||||||
)
|
)
|
||||||
@@ -255,7 +255,7 @@ function ComboboxChip({
|
|||||||
className="-ml-1 opacity-50 hover:opacity-100"
|
className="-ml-1 opacity-50 hover:opacity-100"
|
||||||
data-slot="combobox-chip-remove"
|
data-slot="combobox-chip-remove"
|
||||||
>
|
>
|
||||||
<XIcon className="pointer-events-none" />
|
<RiCloseLine className="pointer-events-none" />
|
||||||
</ComboboxPrimitive.ChipRemove>
|
</ComboboxPrimitive.ChipRemove>
|
||||||
)}
|
)}
|
||||||
</ComboboxPrimitive.Chip>
|
</ComboboxPrimitive.Chip>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
InputGroup,
|
InputGroup,
|
||||||
InputGroupAddon,
|
InputGroupAddon,
|
||||||
} from "@/components/ui/input-group"
|
} from "@/components/ui/input-group"
|
||||||
import { SearchIcon, CheckIcon } from "lucide-react"
|
import { RiSearchLine, RiCheckLine } from "@remixicon/react"
|
||||||
|
|
||||||
function Command({
|
function Command({
|
||||||
className,
|
className,
|
||||||
@@ -81,7 +81,7 @@ function CommandInput({
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
<InputGroupAddon>
|
<InputGroupAddon>
|
||||||
<SearchIcon className="size-4 shrink-0 opacity-50" />
|
<RiSearchLine className="size-4 shrink-0 opacity-50" />
|
||||||
</InputGroupAddon>
|
</InputGroupAddon>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
</div>
|
</div>
|
||||||
@@ -161,7 +161,7 @@ function CommandItem({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
<CheckIcon className="ml-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" />
|
<RiCheckLine className="ml-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" />
|
||||||
</CommandPrimitive.Item>
|
</CommandPrimitive.Item>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import * as React from "react"
|
|||||||
import { ContextMenu as ContextMenuPrimitive } from "radix-ui"
|
import { ContextMenu as ContextMenuPrimitive } from "radix-ui"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { ChevronRightIcon, CheckIcon } from "lucide-react"
|
import { RiArrowRightSLine, RiCheckLine } from "@remixicon/react"
|
||||||
|
|
||||||
function ContextMenu({
|
function ContextMenu({
|
||||||
...props
|
...props
|
||||||
@@ -117,7 +117,7 @@ function ContextMenuSubTrigger({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
<ChevronRightIcon className="ml-auto" />
|
<RiArrowRightSLine className="ml-auto" />
|
||||||
</ContextMenuPrimitive.SubTrigger>
|
</ContextMenuPrimitive.SubTrigger>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -157,7 +157,7 @@ function ContextMenuCheckboxItem({
|
|||||||
>
|
>
|
||||||
<span className="pointer-events-none absolute right-2">
|
<span className="pointer-events-none absolute right-2">
|
||||||
<ContextMenuPrimitive.ItemIndicator>
|
<ContextMenuPrimitive.ItemIndicator>
|
||||||
<CheckIcon
|
<RiCheckLine
|
||||||
/>
|
/>
|
||||||
</ContextMenuPrimitive.ItemIndicator>
|
</ContextMenuPrimitive.ItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
@@ -186,7 +186,7 @@ function ContextMenuRadioItem({
|
|||||||
>
|
>
|
||||||
<span className="pointer-events-none absolute right-2">
|
<span className="pointer-events-none absolute right-2">
|
||||||
<ContextMenuPrimitive.ItemIndicator>
|
<ContextMenuPrimitive.ItemIndicator>
|
||||||
<CheckIcon
|
<RiCheckLine
|
||||||
/>
|
/>
|
||||||
</ContextMenuPrimitive.ItemIndicator>
|
</ContextMenuPrimitive.ItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Dialog as DialogPrimitive } from "radix-ui"
|
|||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { XIcon } from "lucide-react"
|
import { RiCloseLine } from "@remixicon/react"
|
||||||
|
|
||||||
function Dialog({
|
function Dialog({
|
||||||
...props
|
...props
|
||||||
@@ -89,7 +89,7 @@ function DialogContent({
|
|||||||
className="absolute top-2 right-2"
|
className="absolute top-2 right-2"
|
||||||
size="icon-sm"
|
size="icon-sm"
|
||||||
>
|
>
|
||||||
<XIcon
|
<RiCloseLine
|
||||||
/>
|
/>
|
||||||
<span className="sr-only">Close</span>
|
<span className="sr-only">Close</span>
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import * as React from "react"
|
|||||||
import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui"
|
import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { CheckIcon, ChevronRightIcon } from "lucide-react"
|
import { RiCheckLine, RiArrowRightSLine } from "@remixicon/react"
|
||||||
|
|
||||||
function DropdownMenu({
|
function DropdownMenu({
|
||||||
...props
|
...props
|
||||||
@@ -106,7 +106,7 @@ function DropdownMenuCheckboxItem({
|
|||||||
data-slot="dropdown-menu-checkbox-item-indicator"
|
data-slot="dropdown-menu-checkbox-item-indicator"
|
||||||
>
|
>
|
||||||
<DropdownMenuPrimitive.ItemIndicator>
|
<DropdownMenuPrimitive.ItemIndicator>
|
||||||
<CheckIcon
|
<RiCheckLine
|
||||||
/>
|
/>
|
||||||
</DropdownMenuPrimitive.ItemIndicator>
|
</DropdownMenuPrimitive.ItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
@@ -149,7 +149,7 @@ function DropdownMenuRadioItem({
|
|||||||
data-slot="dropdown-menu-radio-item-indicator"
|
data-slot="dropdown-menu-radio-item-indicator"
|
||||||
>
|
>
|
||||||
<DropdownMenuPrimitive.ItemIndicator>
|
<DropdownMenuPrimitive.ItemIndicator>
|
||||||
<CheckIcon
|
<RiCheckLine
|
||||||
/>
|
/>
|
||||||
</DropdownMenuPrimitive.ItemIndicator>
|
</DropdownMenuPrimitive.ItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
@@ -232,7 +232,7 @@ function DropdownMenuSubTrigger({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
<ChevronRightIcon className="ml-auto" />
|
<RiArrowRightSLine className="ml-auto" />
|
||||||
</DropdownMenuPrimitive.SubTrigger>
|
</DropdownMenuPrimitive.SubTrigger>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import * as React from "react"
|
|||||||
import { OTPInput, OTPInputContext } from "input-otp"
|
import { OTPInput, OTPInputContext } from "input-otp"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { MinusIcon } from "lucide-react"
|
import { RiSubtractLine } from "@remixicon/react"
|
||||||
|
|
||||||
function InputOTP({
|
function InputOTP({
|
||||||
className,
|
className,
|
||||||
@@ -78,7 +78,7 @@ function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) {
|
|||||||
role="separator"
|
role="separator"
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<MinusIcon
|
<RiSubtractLine
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import * as React from "react"
|
|||||||
import { Menubar as MenubarPrimitive } from "radix-ui"
|
import { Menubar as MenubarPrimitive } from "radix-ui"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { CheckIcon, ChevronRightIcon } from "lucide-react"
|
import { RiCheckLine, RiArrowRightSLine } from "@remixicon/react"
|
||||||
|
|
||||||
function Menubar({
|
function Menubar({
|
||||||
className,
|
className,
|
||||||
@@ -130,7 +130,7 @@ function MenubarCheckboxItem({
|
|||||||
>
|
>
|
||||||
<span className="pointer-events-none absolute left-1.5 flex size-4 items-center justify-center [&_svg:not([class*='size-'])]:size-4">
|
<span className="pointer-events-none absolute left-1.5 flex size-4 items-center justify-center [&_svg:not([class*='size-'])]:size-4">
|
||||||
<MenubarPrimitive.ItemIndicator>
|
<MenubarPrimitive.ItemIndicator>
|
||||||
<CheckIcon
|
<RiCheckLine
|
||||||
/>
|
/>
|
||||||
</MenubarPrimitive.ItemIndicator>
|
</MenubarPrimitive.ItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
@@ -159,7 +159,7 @@ function MenubarRadioItem({
|
|||||||
>
|
>
|
||||||
<span className="pointer-events-none absolute left-1.5 flex size-4 items-center justify-center [&_svg:not([class*='size-'])]:size-4">
|
<span className="pointer-events-none absolute left-1.5 flex size-4 items-center justify-center [&_svg:not([class*='size-'])]:size-4">
|
||||||
<MenubarPrimitive.ItemIndicator>
|
<MenubarPrimitive.ItemIndicator>
|
||||||
<CheckIcon
|
<RiCheckLine
|
||||||
/>
|
/>
|
||||||
</MenubarPrimitive.ItemIndicator>
|
</MenubarPrimitive.ItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
@@ -242,7 +242,7 @@ function MenubarSubTrigger({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
<ChevronRightIcon className="ml-auto size-4" />
|
<RiArrowRightSLine className="ml-auto size-4" />
|
||||||
</MenubarPrimitive.SubTrigger>
|
</MenubarPrimitive.SubTrigger>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { ArrowDownIcon } from "lucide-react"
|
import { RiArrowDownLine } from "@remixicon/react"
|
||||||
|
|
||||||
function MessageScrollerProvider(
|
function MessageScrollerProvider(
|
||||||
props: React.ComponentProps<typeof MessageScrollerPrimitive.Provider>
|
props: React.ComponentProps<typeof MessageScrollerPrimitive.Provider>
|
||||||
@@ -107,7 +107,7 @@ function MessageScrollerButton({
|
|||||||
>
|
>
|
||||||
{children ?? (
|
{children ?? (
|
||||||
<>
|
<>
|
||||||
<ArrowDownIcon
|
<RiArrowDownLine
|
||||||
/>
|
/>
|
||||||
<span className="sr-only">
|
<span className="sr-only">
|
||||||
{direction === "end" ? "Scroll to end" : "Scroll to start"}
|
{direction === "end" ? "Scroll to end" : "Scroll to start"}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { ChevronDownIcon } from "lucide-react"
|
import { RiArrowDownSLine } from "@remixicon/react"
|
||||||
|
|
||||||
type NativeSelectProps = Omit<React.ComponentProps<"select">, "size"> & {
|
type NativeSelectProps = Omit<React.ComponentProps<"select">, "size"> & {
|
||||||
size?: "sm" | "default"
|
size?: "sm" | "default"
|
||||||
@@ -27,7 +27,7 @@ function NativeSelect({
|
|||||||
className="h-8 w-full min-w-0 appearance-none rounded-lg border border-input bg-transparent py-1 pr-8 pl-2.5 text-sm transition-colors outline-none select-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] data-[size=sm]:py-0.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40"
|
className="h-8 w-full min-w-0 appearance-none rounded-lg border border-input bg-transparent py-1 pr-8 pl-2.5 text-sm transition-colors outline-none select-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] data-[size=sm]:py-0.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
<ChevronDownIcon className="pointer-events-none absolute top-1/2 right-2.5 size-4 -translate-y-1/2 text-muted-foreground select-none" aria-hidden="true" data-slot="native-select-icon" />
|
<RiArrowDownSLine className="pointer-events-none absolute top-1/2 right-2.5 size-4 -translate-y-1/2 text-muted-foreground select-none" aria-hidden="true" data-slot="native-select-icon" />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { cva } from "class-variance-authority"
|
|||||||
import { NavigationMenu as NavigationMenuPrimitive } from "radix-ui"
|
import { NavigationMenu as NavigationMenuPrimitive } from "radix-ui"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { ChevronDownIcon } from "lucide-react"
|
import { RiArrowDownSLine } from "@remixicon/react"
|
||||||
|
|
||||||
function NavigationMenu({
|
function NavigationMenu({
|
||||||
className,
|
className,
|
||||||
@@ -74,7 +74,7 @@ function NavigationMenuTrigger({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}{" "}
|
{children}{" "}
|
||||||
<ChevronDownIcon className="relative top-px ml-1 size-3 transition duration-300 group-data-popup-open/navigation-menu-trigger:rotate-180 group-data-open/navigation-menu-trigger:rotate-180" aria-hidden="true" />
|
<RiArrowDownSLine className="relative top-px ml-1 size-3 transition duration-300 group-data-popup-open/navigation-menu-trigger:rotate-180 group-data-open/navigation-menu-trigger:rotate-180" aria-hidden="true" />
|
||||||
</NavigationMenuPrimitive.Trigger>
|
</NavigationMenuPrimitive.Trigger>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import * as React from "react"
|
|||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { ChevronLeftIcon, ChevronRightIcon, MoreHorizontalIcon } from "lucide-react"
|
import { RiArrowLeftSLine, RiArrowRightSLine, RiMoreLine } from "@remixicon/react"
|
||||||
|
|
||||||
function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
|
function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
|
||||||
return (
|
return (
|
||||||
@@ -73,7 +73,7 @@ function PaginationPrevious({
|
|||||||
className={cn("pl-1.5!", className)}
|
className={cn("pl-1.5!", className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<ChevronLeftIcon data-icon="inline-start" />
|
<RiArrowLeftSLine data-icon="inline-start" />
|
||||||
<span className="hidden sm:block">{text}</span>
|
<span className="hidden sm:block">{text}</span>
|
||||||
</PaginationLink>
|
</PaginationLink>
|
||||||
)
|
)
|
||||||
@@ -92,7 +92,7 @@ function PaginationNext({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<span className="hidden sm:block">{text}</span>
|
<span className="hidden sm:block">{text}</span>
|
||||||
<ChevronRightIcon data-icon="inline-end" />
|
<RiArrowRightSLine data-icon="inline-end" />
|
||||||
</PaginationLink>
|
</PaginationLink>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -111,7 +111,7 @@ function PaginationEllipsis({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<MoreHorizontalIcon
|
<RiMoreLine
|
||||||
/>
|
/>
|
||||||
<span className="sr-only">More pages</span>
|
<span className="sr-only">More pages</span>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import * as React from "react"
|
|||||||
import { Select as SelectPrimitive } from "radix-ui"
|
import { Select as SelectPrimitive } from "radix-ui"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react"
|
import { RiArrowDownSLine, RiCheckLine, RiArrowUpSLine } from "@remixicon/react"
|
||||||
|
|
||||||
function Select({
|
function Select({
|
||||||
...props
|
...props
|
||||||
@@ -51,7 +51,7 @@ function SelectTrigger({
|
|||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
<SelectPrimitive.Icon asChild>
|
<SelectPrimitive.Icon asChild>
|
||||||
<ChevronDownIcon className="pointer-events-none size-4 text-muted-foreground" />
|
<RiArrowDownSLine className="pointer-events-none size-4 text-muted-foreground" />
|
||||||
</SelectPrimitive.Icon>
|
</SelectPrimitive.Icon>
|
||||||
</SelectPrimitive.Trigger>
|
</SelectPrimitive.Trigger>
|
||||||
)
|
)
|
||||||
@@ -119,7 +119,7 @@ function SelectItem({
|
|||||||
>
|
>
|
||||||
<span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center">
|
<span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center">
|
||||||
<SelectPrimitive.ItemIndicator>
|
<SelectPrimitive.ItemIndicator>
|
||||||
<CheckIcon className="pointer-events-none" />
|
<RiCheckLine className="pointer-events-none" />
|
||||||
</SelectPrimitive.ItemIndicator>
|
</SelectPrimitive.ItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
||||||
@@ -153,7 +153,7 @@ function SelectScrollUpButton({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<ChevronUpIcon
|
<RiArrowUpSLine
|
||||||
/>
|
/>
|
||||||
</SelectPrimitive.ScrollUpButton>
|
</SelectPrimitive.ScrollUpButton>
|
||||||
)
|
)
|
||||||
@@ -172,7 +172,7 @@ function SelectScrollDownButton({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<ChevronDownIcon
|
<RiArrowDownSLine
|
||||||
/>
|
/>
|
||||||
</SelectPrimitive.ScrollDownButton>
|
</SelectPrimitive.ScrollDownButton>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Dialog as SheetPrimitive } from "radix-ui"
|
|||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { XIcon } from "lucide-react"
|
import { RiCloseLine } from "@remixicon/react"
|
||||||
|
|
||||||
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
|
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
|
||||||
return <SheetPrimitive.Root data-slot="sheet" {...props} />
|
return <SheetPrimitive.Root data-slot="sheet" {...props} />
|
||||||
@@ -75,7 +75,7 @@ function SheetContent({
|
|||||||
className="absolute top-3 right-3"
|
className="absolute top-3 right-3"
|
||||||
size="icon-sm"
|
size="icon-sm"
|
||||||
>
|
>
|
||||||
<XIcon
|
<RiCloseLine
|
||||||
/>
|
/>
|
||||||
<span className="sr-only">Close</span>
|
<span className="sr-only">Close</span>
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import {
|
|||||||
TooltipContent,
|
TooltipContent,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip"
|
} from "@/components/ui/tooltip"
|
||||||
import { PanelLeftIcon } from "lucide-react"
|
import { RiSideBarLine } from "@remixicon/react"
|
||||||
|
|
||||||
const SIDEBAR_COOKIE_NAME = "sidebar_state"
|
const SIDEBAR_COOKIE_NAME = "sidebar_state"
|
||||||
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
|
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
|
||||||
@@ -270,7 +270,7 @@ function SidebarTrigger({
|
|||||||
}}
|
}}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<PanelLeftIcon />
|
<RiSideBarLine />
|
||||||
<span className="sr-only">Toggle Sidebar</span>
|
<span className="sr-only">Toggle Sidebar</span>
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useTheme } from "next-themes"
|
import { useTheme } from "next-themes"
|
||||||
import { Toaster as Sonner, type ToasterProps } from "sonner"
|
import { Toaster as Sonner, type ToasterProps } from "sonner"
|
||||||
import { CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon } from "lucide-react"
|
import { RiCheckboxCircleLine, RiInformationLine, RiAlertLine, RiCloseCircleLine, RiLoader4Line } from "@remixicon/react"
|
||||||
|
|
||||||
const Toaster = ({ ...props }: ToasterProps) => {
|
const Toaster = ({ ...props }: ToasterProps) => {
|
||||||
const { theme = "system" } = useTheme()
|
const { theme = "system" } = useTheme()
|
||||||
@@ -13,19 +13,19 @@ const Toaster = ({ ...props }: ToasterProps) => {
|
|||||||
className="toaster group"
|
className="toaster group"
|
||||||
icons={{
|
icons={{
|
||||||
success: (
|
success: (
|
||||||
<CircleCheckIcon className="size-4" />
|
<RiCheckboxCircleLine className="size-4" />
|
||||||
),
|
),
|
||||||
info: (
|
info: (
|
||||||
<InfoIcon className="size-4" />
|
<RiInformationLine className="size-4" />
|
||||||
),
|
),
|
||||||
warning: (
|
warning: (
|
||||||
<TriangleAlertIcon className="size-4" />
|
<RiAlertLine className="size-4" />
|
||||||
),
|
),
|
||||||
error: (
|
error: (
|
||||||
<OctagonXIcon className="size-4" />
|
<RiCloseCircleLine className="size-4" />
|
||||||
),
|
),
|
||||||
loading: (
|
loading: (
|
||||||
<Loader2Icon className="size-4 animate-spin" />
|
<RiLoader4Line className="size-4 animate-spin" />
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
style={
|
style={
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { Loader2Icon } from "lucide-react"
|
import { RiLoader4Line } from "@remixicon/react"
|
||||||
|
|
||||||
function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
|
function Spinner({ className, ...props }: React.ComponentProps<typeof RiLoader4Line>) {
|
||||||
return (
|
return (
|
||||||
<Loader2Icon data-slot="spinner" role="status" aria-label="Loading" className={cn("size-4 animate-spin", className)} {...props} />
|
<RiLoader4Line data-slot="spinner" role="status" aria-label="Loading" className={cn("size-4 animate-spin", className)} {...props} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@base-ui/react": "^1.6.0",
|
"@base-ui/react": "^1.6.0",
|
||||||
"@next/swc-wasm-web": "16.2.10",
|
"@next/swc-wasm-web": "16.2.10",
|
||||||
|
"@remixicon/react": "^4.9.0",
|
||||||
"@shadcn/react": "^0.1.0",
|
"@shadcn/react": "^0.1.0",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
@@ -18,7 +19,6 @@
|
|||||||
"cobe": "^0.6.4",
|
"cobe": "^0.6.4",
|
||||||
"embla-carousel-react": "^8.6.0",
|
"embla-carousel-react": "^8.6.0",
|
||||||
"input-otp": "^1.4.2",
|
"input-otp": "^1.4.2",
|
||||||
"lucide-react": "^1.22.0",
|
|
||||||
"motion": "^13.3.0",
|
"motion": "^13.3.0",
|
||||||
"next": "16.2.10",
|
"next": "16.2.10",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
|
|||||||
@@ -2392,6 +2392,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@remixicon/react@npm:^4.9.0":
|
||||||
|
version: 4.9.0
|
||||||
|
resolution: "@remixicon/react@npm:4.9.0"
|
||||||
|
peerDependencies:
|
||||||
|
react: ">=18.2.0"
|
||||||
|
checksum: 10c0/91bbadb677f45cf8b6687fdf9d273511fddb4e862f1da6c11bc7932acb578bcb26ae5b9e1eb62143a4e916b71797739a36d689866d5b0949f0f0f22c1684cb96
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@rtsao/scc@npm:^1.1.0":
|
"@rtsao/scc@npm:^1.1.0":
|
||||||
version: 1.1.0
|
version: 1.1.0
|
||||||
resolution: "@rtsao/scc@npm:1.1.0"
|
resolution: "@rtsao/scc@npm:1.1.0"
|
||||||
@@ -6211,15 +6220,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"lucide-react@npm:^1.22.0":
|
|
||||||
version: 1.22.0
|
|
||||||
resolution: "lucide-react@npm:1.22.0"
|
|
||||||
peerDependencies:
|
|
||||||
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
checksum: 10c0/6d7066773c2d5f1a3e8f274d4544d2e6fb133f284c843ce89c041c7d2d6e265e5bed48c057724553405bdc4c943547642ceac25c2b807d5efbb1e75d0127de92
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"magic-string@npm:^0.30.21":
|
"magic-string@npm:^0.30.21":
|
||||||
version: 0.30.21
|
version: 0.30.21
|
||||||
resolution: "magic-string@npm:0.30.21"
|
resolution: "magic-string@npm:0.30.21"
|
||||||
@@ -6494,6 +6494,7 @@ __metadata:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@base-ui/react": "npm:^1.6.0"
|
"@base-ui/react": "npm:^1.6.0"
|
||||||
"@next/swc-wasm-web": "npm:16.2.10"
|
"@next/swc-wasm-web": "npm:16.2.10"
|
||||||
|
"@remixicon/react": "npm:^4.9.0"
|
||||||
"@shadcn/react": "npm:^0.1.0"
|
"@shadcn/react": "npm:^0.1.0"
|
||||||
"@tailwindcss/postcss": "npm:^4"
|
"@tailwindcss/postcss": "npm:^4"
|
||||||
"@types/node": "npm:^20"
|
"@types/node": "npm:^20"
|
||||||
@@ -6508,7 +6509,6 @@ __metadata:
|
|||||||
eslint: "npm:^9"
|
eslint: "npm:^9"
|
||||||
eslint-config-next: "npm:16.2.9"
|
eslint-config-next: "npm:16.2.9"
|
||||||
input-otp: "npm:^1.4.2"
|
input-otp: "npm:^1.4.2"
|
||||||
lucide-react: "npm:^1.22.0"
|
|
||||||
motion: "npm:^13.3.0"
|
motion: "npm:^13.3.0"
|
||||||
next: "npm:16.2.10"
|
next: "npm:16.2.10"
|
||||||
next-themes: "npm:^0.4.6"
|
next-themes: "npm:^0.4.6"
|
||||||
|
|||||||
Reference in New Issue
Block a user