Merge pull request #1 from nexa-sol/nav-and-markets-ui
Nav and markets UI
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema.json",
|
||||||
|
"style": "new-york",
|
||||||
|
"rsc": true,
|
||||||
|
"tsx": true,
|
||||||
|
"tailwind": {
|
||||||
|
"config": "",
|
||||||
|
"css": "src/app/globals.css",
|
||||||
|
"baseColor": "neutral",
|
||||||
|
"cssVariables": true,
|
||||||
|
"prefix": ""
|
||||||
|
},
|
||||||
|
"iconLibrary": "lucide",
|
||||||
|
"rtl": false,
|
||||||
|
"aliases": {
|
||||||
|
"components": "@/components",
|
||||||
|
"utils": "@/lib/utils",
|
||||||
|
"ui": "@/components/ui",
|
||||||
|
"lib": "@/lib",
|
||||||
|
"hooks": "@/hooks"
|
||||||
|
},
|
||||||
|
"registries": {}
|
||||||
|
}
|
||||||
Generated
+6316
-4
File diff suppressed because it is too large
Load Diff
+8
-1
@@ -8,16 +8,23 @@
|
|||||||
"start": "next start"
|
"start": "next start"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"lucide-react": "^0.563.0",
|
||||||
"next": "16.1.6",
|
"next": "16.1.6",
|
||||||
|
"radix-ui": "^1.4.3",
|
||||||
"react": "19.2.3",
|
"react": "19.2.3",
|
||||||
"react-dom": "19.2.3"
|
"react-dom": "19.2.3",
|
||||||
|
"tailwind-merge": "^3.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
|
"shadcn": "^3.8.4",
|
||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
|
"tw-animate-css": "^1.4.0",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,14 @@
|
|||||||
|
<svg width="42" height="9" viewBox="0 0 42 9" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_9_13)">
|
||||||
|
<path d="M6.732 0.995999C6.732 0.843999 6.788 0.715999 6.9 0.611999C7.012 0.499999 7.148 0.443999 7.308 0.443999H7.884V9H6.708C6.588 9 6.492 8.952 6.42 8.856L0.972 1.836V4.704C0.972 4.856 0.916 4.988 0.804 5.1C0.692 5.204 0.556 5.256 0.396 5.256H-0.18V0.443999H0.984C1.104 0.443999 1.2 0.491999 1.272 0.588L6.732 7.608V0.995999ZM19.4827 8.484V9H11.0107V8.208C11.0107 8.128 11.0387 8.064 11.0947 8.016C11.1507 7.96 11.2147 7.932 11.2867 7.932H18.9067C19.0667 7.932 19.2027 7.988 19.3147 8.1C19.4267 8.204 19.4827 8.332 19.4827 8.484ZM19.3507 0.96C19.3507 1.112 19.2947 1.244 19.1827 1.356C19.0707 1.46 18.9347 1.512 18.7747 1.512H11.2987C11.2187 1.512 11.1507 1.484 11.0947 1.428C11.0387 1.372 11.0107 1.304 11.0107 1.224V0.443999H19.3507V0.96ZM11.0107 4.464C11.0107 4.392 11.0387 4.328 11.0947 4.272C11.1507 4.216 11.2147 4.188 11.2867 4.188H18.5707V4.704C18.5707 4.856 18.5147 4.988 18.4027 5.1C18.2907 5.204 18.1547 5.256 17.9947 5.256H11.0107V4.464ZM30.4834 0.443999L26.3914 4.716L30.4834 9H29.5114C29.2634 9 29.0474 8.904 28.8634 8.712L25.7194 5.424L22.5754 8.712C22.3914 8.904 22.1754 9 21.9274 9H20.8594C21.8434 7.968 24.4794 5.212 28.7674 0.732C28.9514 0.539999 29.1674 0.443999 29.4154 0.443999H30.4834ZM24.2194 3.168C24.1234 3.264 24.0114 3.312 23.8834 3.312C23.7554 3.312 23.6434 3.264 23.5474 3.168L20.9554 0.443999H21.9274C22.1754 0.443999 22.3914 0.539999 22.5754 0.732L24.5554 2.808L24.2194 3.168ZM36.3944 1.656C33.6104 6.36 32.1904 8.756 32.1344 8.844C32.0784 8.948 31.9904 9 31.8704 9H30.8024C32.9704 5.28 34.5304 2.596 35.4824 0.948C35.5624 0.796 35.6784 0.675999 35.8304 0.588C35.9904 0.491999 36.1624 0.443999 36.3464 0.443999H37.0184C37.7064 1.732 39.2304 4.584 41.5904 9H40.7144C40.4504 9 40.2544 8.884 40.1264 8.652C39.7904 8.012 39.3224 7.136 38.7224 6.024L36.3944 1.656Z" fill="url(#paint0_linear_9_13)"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_9_13" x1="-3" y1="7" x2="44" y2="7" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#6D45F9"/>
|
||||||
|
<stop offset="1" stop-color="#00C688"/>
|
||||||
|
</linearGradient>
|
||||||
|
<clipPath id="clip0_9_13">
|
||||||
|
<rect width="42" height="9" fill="white"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.2 KiB |
+113
-11
@@ -1,26 +1,128 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
|
@import "tw-animate-css";
|
||||||
|
@import "shadcn/tailwind.css";
|
||||||
|
|
||||||
:root {
|
@custom-variant dark (&:is(.dark *));
|
||||||
--background: #ffffff;
|
|
||||||
--foreground: #171717;
|
|
||||||
}
|
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
--color-background: var(--background);
|
--color-background: var(--background);
|
||||||
--color-foreground: var(--foreground);
|
--color-foreground: var(--foreground);
|
||||||
--font-sans: var(--font-geist-sans);
|
--font-sans: var(--font-geist-sans);
|
||||||
--font-mono: var(--font-geist-mono);
|
--font-mono: var(--font-geist-mono);
|
||||||
|
--color-sidebar-ring: var(--sidebar-ring);
|
||||||
|
--color-sidebar-border: var(--sidebar-border);
|
||||||
|
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||||
|
--color-sidebar-accent: var(--sidebar-accent);
|
||||||
|
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||||
|
--color-sidebar-primary: var(--sidebar-primary);
|
||||||
|
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||||
|
--color-sidebar: var(--sidebar);
|
||||||
|
--color-chart-5: var(--chart-5);
|
||||||
|
--color-chart-4: var(--chart-4);
|
||||||
|
--color-chart-3: var(--chart-3);
|
||||||
|
--color-chart-2: var(--chart-2);
|
||||||
|
--color-chart-1: var(--chart-1);
|
||||||
|
--color-ring: var(--ring);
|
||||||
|
--color-input: var(--input);
|
||||||
|
--color-border: var(--border);
|
||||||
|
--color-destructive: var(--destructive);
|
||||||
|
--color-accent-foreground: var(--accent-foreground);
|
||||||
|
--color-accent: var(--accent);
|
||||||
|
--color-muted-foreground: var(--muted-foreground);
|
||||||
|
--color-muted: var(--muted);
|
||||||
|
--color-secondary-foreground: var(--secondary-foreground);
|
||||||
|
--color-secondary: var(--secondary);
|
||||||
|
--color-primary-foreground: var(--primary-foreground);
|
||||||
|
--color-primary: var(--primary);
|
||||||
|
--color-popover-foreground: var(--popover-foreground);
|
||||||
|
--color-popover: var(--popover);
|
||||||
|
--color-card-foreground: var(--card-foreground);
|
||||||
|
--color-card: var(--card);
|
||||||
|
--radius-sm: calc(var(--radius) - 4px);
|
||||||
|
--radius-md: calc(var(--radius) - 2px);
|
||||||
|
--radius-lg: var(--radius);
|
||||||
|
--radius-xl: calc(var(--radius) + 4px);
|
||||||
|
--radius-2xl: calc(var(--radius) + 8px);
|
||||||
|
--radius-3xl: calc(var(--radius) + 12px);
|
||||||
|
--radius-4xl: calc(var(--radius) + 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
:root {
|
||||||
:root {
|
--radius: 0.425rem;
|
||||||
--background: #0a0a0a;
|
|
||||||
--foreground: #ededed;
|
/* Base surfaces */
|
||||||
|
--background: oklch(0.13 0.01 260); /* deep charcoal */
|
||||||
|
--foreground: oklch(0.98 0 0);
|
||||||
|
|
||||||
|
--card: oklch(0.18 0.015 260);
|
||||||
|
--card-foreground: oklch(0.98 0 0);
|
||||||
|
|
||||||
|
--popover: oklch(0.18 0.015 260);
|
||||||
|
--popover-foreground: oklch(0.98 0 0);
|
||||||
|
|
||||||
|
/* Primary – Solana purple */
|
||||||
|
--primary: oklch(0.55 0.25 285);
|
||||||
|
--primary-foreground: oklch(0.98 0 0);
|
||||||
|
|
||||||
|
/* Secondary – muted surface */
|
||||||
|
--secondary: oklch(0.24 0.015 260);
|
||||||
|
--secondary-foreground: oklch(0.96 0 0);
|
||||||
|
|
||||||
|
/* Muted / subtle text */
|
||||||
|
--muted: oklch(0.24 0.015 260);
|
||||||
|
--muted-foreground: oklch(0.72 0.01 260);
|
||||||
|
|
||||||
|
/* Accent – SOL mint */
|
||||||
|
--accent: oklch(0.72 0.18 165);
|
||||||
|
--accent-foreground: oklch(0.13 0.01 260);
|
||||||
|
|
||||||
|
/* Destructive */
|
||||||
|
--destructive: oklch(0.68 0.2 25);
|
||||||
|
|
||||||
|
/* Inputs / borders */
|
||||||
|
--border: oklch(1 0 0 / 10%);
|
||||||
|
--input: oklch(1 0 0 / 14%);
|
||||||
|
--ring: oklch(0.6 0.12 285);
|
||||||
|
|
||||||
|
/* Charts – crypto-native */
|
||||||
|
--chart-1: oklch(0.55 0.25 285); /* purple */
|
||||||
|
--chart-2: oklch(0.72 0.18 165); /* mint */
|
||||||
|
--chart-3: oklch(0.65 0.22 310); /* violet */
|
||||||
|
--chart-4: oklch(0.7 0.17 140); /* green */
|
||||||
|
--chart-5: oklch(0.62 0.2 30); /* orange/red */
|
||||||
|
|
||||||
|
/* Sidebar */
|
||||||
|
--sidebar: oklch(0.17 0.015 260);
|
||||||
|
--sidebar-foreground: oklch(0.96 0 0);
|
||||||
|
|
||||||
|
--sidebar-primary: oklch(0.55 0.25 285);
|
||||||
|
--sidebar-primary-foreground: oklch(0.98 0 0);
|
||||||
|
|
||||||
|
--sidebar-accent: oklch(0.24 0.015 260);
|
||||||
|
--sidebar-accent-foreground: oklch(0.98 0 0);
|
||||||
|
|
||||||
|
--sidebar-border: oklch(1 0 0 / 10%);
|
||||||
|
--sidebar-ring: oklch(0.6 0.12 285);
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
* {
|
||||||
|
@apply border-border outline-ring/50;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
@apply bg-background text-foreground;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: var(--background);
|
@apply bg-background text-foreground;
|
||||||
color: var(--foreground);
|
}
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Researcher';
|
||||||
|
src: url('/font/researcher-regular-400.ttf') format('truetype');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
}
|
}
|
||||||
+2
-2
@@ -13,8 +13,8 @@ const geistMono = Geist_Mono({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Create Next App",
|
title: "Nexa - Solana trading supercharged by AI",
|
||||||
description: "Generated by create next app",
|
description: "The solana trading terminal supercharged by AI",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { SolanaLogo } from "@/components/logos";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Card, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { Settings2Icon, ZapIcon } from "lucide-react";
|
||||||
|
|
||||||
|
export default function PairsCard({ title }: { title: string }) {
|
||||||
|
return (
|
||||||
|
<Card className="py-3">
|
||||||
|
<CardHeader className="px-4 pb-3! border-b flex justify-between items-center">
|
||||||
|
<CardTitle>{title}</CardTitle>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="border border-border animate-colors hover:bg-input/20 px-1.5 py-1.5 rounded-full flex items-center gap-1">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<ZapIcon className="w-3 h-3" />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="0.0"
|
||||||
|
className="px-1 w-10 focus:outline-0 text-xs"
|
||||||
|
/>
|
||||||
|
<SolanaLogo className="w-3 h-3" />
|
||||||
|
</div>
|
||||||
|
<div className="border-l border-border pl-1 flex items-center text-xs gap-1.5">
|
||||||
|
{["P1", "P2", "P3"].map((p) => (
|
||||||
|
<div
|
||||||
|
key={p}
|
||||||
|
className="text-foreground/90 cursor-pointer hover:text-primary"
|
||||||
|
>
|
||||||
|
{p}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
className="p-1! h-max hover:bg-accent/20 hover:text-accent"
|
||||||
|
>
|
||||||
|
<Settings2Icon />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import Navbar from "@/components/layout/Navbar";
|
||||||
|
import Statusbar from "@/components/layout/Statusbar";
|
||||||
|
import PairsCard from "./components/PairsCard";
|
||||||
|
|
||||||
|
export default function Markets() {
|
||||||
|
return (
|
||||||
|
<main className="h-svh flex flex-col">
|
||||||
|
<Navbar />
|
||||||
|
<section className="w-full h-full pt-10 pb-5 px-5">
|
||||||
|
<div className="w-full h-full grid grid-cols-3 gap-5">
|
||||||
|
<PairsCard title="New Pairs" />
|
||||||
|
<PairsCard title="Final Stretch" />
|
||||||
|
<PairsCard title="Migrated" />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<Statusbar />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import Link from "next/link";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import {
|
||||||
|
BellIcon,
|
||||||
|
ChevronDownIcon,
|
||||||
|
StarIcon,
|
||||||
|
UserIcon,
|
||||||
|
WalletIcon,
|
||||||
|
} from "lucide-react";
|
||||||
|
import { SolanaLogo } from "../logos";
|
||||||
|
|
||||||
|
const links = [
|
||||||
|
{
|
||||||
|
path: "/markets",
|
||||||
|
name: "Markets",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/trackers",
|
||||||
|
name: "Trackers",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Navbar() {
|
||||||
|
const personalItemClass =
|
||||||
|
"rounded-full bg-card p-2! aspect-square group hover:bg-accent/20 hover:text-accent";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className="border-b border-b-border py-4 px-5 flex gap-5 items-center">
|
||||||
|
<a href="/markets" className="flex gap-1 items-center">
|
||||||
|
<img src="/nexa.svg" alt="Nexa" className="h-7" />
|
||||||
|
<img src="/nexa-text.svg" alt="NEXA" className="h-5" />
|
||||||
|
</a>
|
||||||
|
<div>
|
||||||
|
<ul className="flex">
|
||||||
|
{links.map((l) => (
|
||||||
|
<li key={l.path}>
|
||||||
|
<Link
|
||||||
|
href={l.path}
|
||||||
|
className="px-3 py-2 rounded-lg hover:bg-primary/20 hover:text-primary transition-colors duration-300"
|
||||||
|
>
|
||||||
|
{l.name}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="ml-auto flex gap-4">
|
||||||
|
<Button variant="outline" className={personalItemClass}>
|
||||||
|
<StarIcon />
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline" className={personalItemClass}>
|
||||||
|
<BellIcon />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
<Button variant="outline" className={personalItemClass}>
|
||||||
|
<div className="flex gap-1 items-center h-full">
|
||||||
|
<WalletIcon />
|
||||||
|
<div className="flex items-center">
|
||||||
|
<SolanaLogo className="p-0.5" />
|
||||||
|
3.13
|
||||||
|
</div>
|
||||||
|
<span className="w-[1.5px] h-full ml-1 mr-1 bg-border group-hover:bg-accent/60 animate-colors duration-300" />
|
||||||
|
$248
|
||||||
|
<ChevronDownIcon />
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button variant="outline" className={personalItemClass}>
|
||||||
|
<UserIcon />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export default function Statusbar() {
|
||||||
|
return <footer></footer>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
import { SVGProps } from "react";
|
||||||
|
|
||||||
|
export const SolanaLogo = (props: SVGProps<SVGSVGElement>) => (
|
||||||
|
<svg
|
||||||
|
id="Layer_1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 397.7 311.7"
|
||||||
|
style={{
|
||||||
|
background: "new 0 0 397.7 311.7",
|
||||||
|
}}
|
||||||
|
xmlSpace="preserve"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<style type="text/css">
|
||||||
|
{
|
||||||
|
"\n\t.st0{fill:url(#SVGID_1_);}\n\t.st1{fill:url(#SVGID_2_);}\n\t.st2{fill:url(#SVGID_3_);}\n"
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<linearGradient
|
||||||
|
id="SVGID_1_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1={360.8791}
|
||||||
|
y1={351.4553}
|
||||||
|
x2={141.213}
|
||||||
|
y2={-69.2936}
|
||||||
|
gradientTransform="matrix(1 0 0 -1 0 314)"
|
||||||
|
>
|
||||||
|
<stop
|
||||||
|
offset={0}
|
||||||
|
style={{
|
||||||
|
stopColor: "#00FFA3",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<stop
|
||||||
|
offset={1}
|
||||||
|
style={{
|
||||||
|
stopColor: "#DC1FFF",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</linearGradient>
|
||||||
|
<path
|
||||||
|
className="st0"
|
||||||
|
d="M64.6,237.9c2.4-2.4,5.7-3.8,9.2-3.8h317.4c5.8,0,8.7,7,4.6,11.1l-62.7,62.7c-2.4,2.4-5.7,3.8-9.2,3.8H6.5 c-5.8,0-8.7-7-4.6-11.1L64.6,237.9z"
|
||||||
|
/>
|
||||||
|
<linearGradient
|
||||||
|
id="SVGID_2_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1={264.8291}
|
||||||
|
y1={401.6014}
|
||||||
|
x2={45.163}
|
||||||
|
y2={-19.1475}
|
||||||
|
gradientTransform="matrix(1 0 0 -1 0 314)"
|
||||||
|
>
|
||||||
|
<stop
|
||||||
|
offset={0}
|
||||||
|
style={{
|
||||||
|
stopColor: "#00FFA3",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<stop
|
||||||
|
offset={1}
|
||||||
|
style={{
|
||||||
|
stopColor: "#DC1FFF",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</linearGradient>
|
||||||
|
<path
|
||||||
|
className="st1"
|
||||||
|
d="M64.6,3.8C67.1,1.4,70.4,0,73.8,0h317.4c5.8,0,8.7,7,4.6,11.1l-62.7,62.7c-2.4,2.4-5.7,3.8-9.2,3.8H6.5 c-5.8,0-8.7-7-4.6-11.1L64.6,3.8z"
|
||||||
|
/>
|
||||||
|
<linearGradient
|
||||||
|
id="SVGID_3_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1={312.5484}
|
||||||
|
y1={376.688}
|
||||||
|
x2={92.8822}
|
||||||
|
y2={-44.061}
|
||||||
|
gradientTransform="matrix(1 0 0 -1 0 314)"
|
||||||
|
>
|
||||||
|
<stop
|
||||||
|
offset={0}
|
||||||
|
style={{
|
||||||
|
stopColor: "#00FFA3",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<stop
|
||||||
|
offset={1}
|
||||||
|
style={{
|
||||||
|
stopColor: "#DC1FFF",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</linearGradient>
|
||||||
|
<path
|
||||||
|
className="st2"
|
||||||
|
d="M333.1,120.1c-2.4-2.4-5.7-3.8-9.2-3.8H6.5c-5.8,0-8.7,7-4.6,11.1l62.7,62.7c2.4,2.4,5.7,3.8,9.2,3.8h317.4 c5.8,0,8.7-7,4.6-11.1L333.1,120.1z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import { cva, type VariantProps } from "class-variance-authority"
|
||||||
|
import { Slot } from "radix-ui"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const buttonVariants = cva(
|
||||||
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
||||||
|
destructive:
|
||||||
|
"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
||||||
|
outline:
|
||||||
|
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
||||||
|
secondary:
|
||||||
|
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||||
|
ghost:
|
||||||
|
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
||||||
|
link: "text-primary underline-offset-4 hover:underline",
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
||||||
|
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
||||||
|
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
||||||
|
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
||||||
|
icon: "size-9",
|
||||||
|
"icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
||||||
|
"icon-sm": "size-8",
|
||||||
|
"icon-lg": "size-10",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: "default",
|
||||||
|
size: "default",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
function Button({
|
||||||
|
className,
|
||||||
|
variant = "default",
|
||||||
|
size = "default",
|
||||||
|
asChild = false,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<"button"> &
|
||||||
|
VariantProps<typeof buttonVariants> & {
|
||||||
|
asChild?: boolean
|
||||||
|
}) {
|
||||||
|
const Comp = asChild ? Slot.Root : "button"
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Comp
|
||||||
|
data-slot="button"
|
||||||
|
data-variant={variant}
|
||||||
|
data-size={size}
|
||||||
|
className={cn(buttonVariants({ variant, size, className }))}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Button, buttonVariants }
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Card({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="card"
|
||||||
|
className={cn(
|
||||||
|
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="card-header"
|
||||||
|
className={cn(
|
||||||
|
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="card-title"
|
||||||
|
className={cn("leading-none font-semibold", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="card-description"
|
||||||
|
className={cn("text-muted-foreground text-sm", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="card-action"
|
||||||
|
className={cn(
|
||||||
|
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="card-content"
|
||||||
|
className={cn("px-6", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="card-footer"
|
||||||
|
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
Card,
|
||||||
|
CardHeader,
|
||||||
|
CardFooter,
|
||||||
|
CardTitle,
|
||||||
|
CardAction,
|
||||||
|
CardDescription,
|
||||||
|
CardContent,
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { clsx, type ClassValue } from "clsx"
|
||||||
|
import { twMerge } from "tailwind-merge"
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user