Merge pull request #6 from nexa-sol/market-ui-and-landing-page-ux

Market UI and landing page ux
This commit is contained in:
2026-02-18 10:35:20 -08:00
committed by GitHub
15 changed files with 576 additions and 22 deletions
+39
View File
@@ -10,11 +10,14 @@
"dependencies": { "dependencies": {
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"lightweight-charts": "^5.1.0",
"lightweight-charts-react-components": "^1.4.0",
"lucide-react": "^0.563.0", "lucide-react": "^0.563.0",
"next": "16.1.6", "next": "16.1.6",
"radix-ui": "^1.4.3", "radix-ui": "^1.4.3",
"react": "19.2.3", "react": "19.2.3",
"react-dom": "19.2.3", "react-dom": "19.2.3",
"react-resizable-panels": "^4.6.4",
"tailwind-animations": "^1.0.1", "tailwind-animations": "^1.0.1",
"tailwind-merge": "^3.4.0", "tailwind-merge": "^3.4.0",
"tailwind-motlib": "^1.0.4" "tailwind-motlib": "^1.0.4"
@@ -4599,6 +4602,12 @@
"express": ">= 4.11" "express": ">= 4.11"
} }
}, },
"node_modules/fancy-canvas": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fancy-canvas/-/fancy-canvas-2.1.0.tgz",
"integrity": "sha512-nifxXJ95JNLFR2NgRV4/MxVP45G9909wJTEKz5fg/TZS20JJZA6hfgRVh/bC9bwl2zBtBNcYPjiBE4njQHVBwQ==",
"license": "MIT"
},
"node_modules/fast-deep-equal": { "node_modules/fast-deep-equal": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -5715,6 +5724,26 @@
"url": "https://opencollective.com/parcel" "url": "https://opencollective.com/parcel"
} }
}, },
"node_modules/lightweight-charts": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/lightweight-charts/-/lightweight-charts-5.1.0.tgz",
"integrity": "sha512-jEAYR4ODYeyNZcWUigsoLTl52rbPmgXnvd5FLIv/ZoA/2sSDw63YKnef8n4yhzum7W926yHeFwlm7ididKb7YQ==",
"license": "Apache-2.0",
"dependencies": {
"fancy-canvas": "2.1.0"
}
},
"node_modules/lightweight-charts-react-components": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/lightweight-charts-react-components/-/lightweight-charts-react-components-1.4.0.tgz",
"integrity": "sha512-FWzEiQDhQaQ04l6kV2fzsODK6jCrzbLOai+r6oEvCqC3tniXjKUAFHbTUlemII7PfiWYwyVAVgl1XRv72Q8Phw==",
"license": "MIT",
"peerDependencies": {
"lightweight-charts": ">=5 < 6",
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/lines-and-columns": { "node_modules/lines-and-columns": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@@ -6753,6 +6782,16 @@
} }
} }
}, },
"node_modules/react-resizable-panels": {
"version": "4.6.4",
"resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-4.6.4.tgz",
"integrity": "sha512-E7Szs1xyaMZ7xOI2gG4TECNz4r/gmpV1AsXyZRnER6OQnfFf9uclFmrHHZR3h/iF8vQS+nQ1LKyZv9bzwGxPSg==",
"license": "MIT",
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0"
}
},
"node_modules/react-style-singleton": { "node_modules/react-style-singleton": {
"version": "2.2.3", "version": "2.2.3",
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
+3
View File
@@ -10,11 +10,14 @@
"dependencies": { "dependencies": {
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"lightweight-charts": "^5.1.0",
"lightweight-charts-react-components": "^1.4.0",
"lucide-react": "^0.563.0", "lucide-react": "^0.563.0",
"next": "16.1.6", "next": "16.1.6",
"radix-ui": "^1.4.3", "radix-ui": "^1.4.3",
"react": "19.2.3", "react": "19.2.3",
"react-dom": "19.2.3", "react-dom": "19.2.3",
"react-resizable-panels": "^4.6.4",
"tailwind-animations": "^1.0.1", "tailwind-animations": "^1.0.1",
"tailwind-merge": "^3.4.0", "tailwind-merge": "^3.4.0",
"tailwind-motlib": "^1.0.4" "tailwind-motlib": "^1.0.4"
+10 -1
View File
@@ -48,6 +48,9 @@
--radius-2xl: calc(var(--radius) + 8px); --radius-2xl: calc(var(--radius) + 8px);
--radius-3xl: calc(var(--radius) + 12px); --radius-3xl: calc(var(--radius) + 12px);
--radius-4xl: calc(var(--radius) + 16px); --radius-4xl: calc(var(--radius) + 16px);
--color-bullish: var(--bullish);
--color-bearish: var(--bearish);
} }
:root { :root {
@@ -57,7 +60,7 @@
--background: oklch(0.13 0.01 260); /* deep charcoal */ --background: oklch(0.13 0.01 260); /* deep charcoal */
--foreground: oklch(0.98 0 0); --foreground: oklch(0.98 0 0);
--card: oklch(0.18 0.015 260); --card: oklch(15.349% 0.00726 258.438);
--card-foreground: oklch(0.98 0 0); --card-foreground: oklch(0.98 0 0);
--popover: oklch(0.18 0.015 260); --popover: oklch(0.18 0.015 260);
@@ -106,6 +109,12 @@
--sidebar-border: oklch(1 0 0 / 10%); --sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.6 0.12 285); --sidebar-ring: oklch(0.6 0.12 285);
/* Bullish - vibrant SOL mint */
--bullish: oklch(0.72 0.18 165);
/* Bearish - destructive/coral red */
--bearish: oklch(63.35% 0.2171 4.38);
} }
@layer base { @layer base {
@@ -0,0 +1,55 @@
import { Button } from "@/components/ui/button";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { ChevronDown, ChevronUp } from "lucide-react";
import { useState } from "react";
export default function BuySell() {
const [isCollapsed, setIsCollapsed] = useState(false);
return (
<Tabs defaultValue="buy" className="px-3 border-b">
<div className="flex items-center justify-between border-b bg-transparent">
<TabsList className="h-14! p-0 px-2 bg-transparent border-none flex-1">
<TabsTrigger
value="buy"
className="h-9 bg-transparent data-[state=active]:bg-bullish data-[state=active]:text-accent-foreground"
>
Buy
</TabsTrigger>
<TabsTrigger
value="sell"
className="ml-0.5 h-9 bg-transparent data-[state=active]:bg-bearish data-[state=active]:text-accent-foreground"
>
Sell
</TabsTrigger>
</TabsList>
{/* The Toggle Button */}
<Button
variant="outline"
size="xs"
className="h-6 w-6 p-0 rounded-full"
onClick={() => setIsCollapsed(!isCollapsed)}
>
{isCollapsed ? (
<ChevronUp className="h-4 w-4" />
) : (
<ChevronDown className="h-4 w-4" />
)}
</Button>
</div>
{/* Conditional Rendering or Height Hiding */}
{!isCollapsed && (
<>
<TabsContent value="buy">
<div className="h-72">buy placeholder</div>
</TabsContent>
<TabsContent value="sell">
<div className="h-72">sell placeholder</div>
</TabsContent>
</>
)}
</Tabs>
);
}
@@ -0,0 +1,96 @@
import { CandlestickSeries, Chart } from "lightweight-charts-react-components";
export default function MarketChart() {
return (
<Chart
containerProps={{
style: { width: "100%", height: "100%" },
}}
options={{
layout: {
background: { color: "#131722" }, // Dark background
textColor: "#d1d4dc", // Light text
},
grid: {
vertLines: { color: "#2B2B43" }, // Subtle dark grid lines
horzLines: { color: "#2B2B43" },
},
}}
>
<CandlestickSeries
data={[
{
time: "2018-12-22",
open: 32.5,
high: 33.0,
low: 31.8,
close: 32.51,
},
{
time: "2018-12-23",
open: 32.51,
high: 32.8,
low: 30.5,
close: 31.11,
},
{
time: "2018-12-24",
open: 31.11,
high: 31.5,
low: 26.9,
close: 27.02,
},
{
time: "2018-12-25",
open: 27.02,
high: 27.8,
low: 26.5,
close: 27.32,
},
{
time: "2018-12-26",
open: 27.32,
high: 26.0,
low: 24.8,
close: 25.17,
},
{
time: "2018-12-27",
open: 25.17,
high: 29.0,
low: 25.0,
close: 28.89,
},
{
time: "2018-12-28",
open: 28.89,
high: 26.0,
low: 25.4,
close: 25.46,
},
{
time: "2018-12-29",
open: 25.46,
high: 24.5,
low: 23.5,
close: 23.92,
},
{
time: "2018-12-30",
open: 23.92,
high: 23.0,
low: 22.5,
close: 22.68,
},
{
time: "2018-12-31",
open: 22.68,
high: 23.0,
low: 22.5,
close: 22.67,
},
]}
/>
</Chart>
);
}
@@ -0,0 +1,12 @@
import BuySell from "./BuySell";
import TokenInfo from "./TokenInfo";
export default function MarketSidebar() {
return (
<div className="h-full w-sm flex flex-col gap-4">
<div className="flex h-16 border-b px-3">placeholder</div>
<BuySell />
<TokenInfo />
</div>
);
}
@@ -0,0 +1,126 @@
import { cn } from "@/lib/utils";
import { Token, TokenLiveData } from "@/modules/tokens/types";
import {
BoxesIcon,
ChartCandlestick,
ChefHatIcon,
CrosshairIcon,
FlameIcon,
GhostIcon,
LucideIcon,
ShieldIcon,
UsersIcon,
UserStarIcon,
} from "lucide-react";
export default function TokenInfo() {
const info: Token = {
mint: "",
symbol: "",
name: "",
};
const liveData: TokenLiveData = {
topHolder: 67,
devHold: 20,
snipersHold: 30,
insidersHold: 10,
bundleHold: 3,
};
return (
<div className="px-3">
<div></div>
<div className="flex flex-col gap-4">
<div className="grid grid-cols-3 gap-3 border-b pb-4">
<DataCard
icon={UserStarIcon}
label="Top 10 H"
value={`${liveData.topHolder}%`}
className="text-bearish"
/>
<DataCard
icon={ChefHatIcon}
label="Top 10 H"
value={`${liveData.topHolder}%`}
className="text-bullish"
/>
<DataCard
icon={CrosshairIcon}
label="Snipers H"
value={`${liveData.topHolder}%`}
className="text-bearish"
/>
<DataCard
icon={GhostIcon}
label="Insiders"
value={`${liveData.insidersHold}%`}
className="text-bullish"
/>
<DataCard
icon={BoxesIcon}
label="Bundlers"
value={`${liveData.bundleHold}%`}
className="text-bullish"
/>
<DataCard
icon={FlameIcon}
label="LP Burned"
value={`${100}%`}
className="text-bullish"
/>
</div>
<div className="grid grid-cols-3 gap-3">
<DataCard
icon={UsersIcon}
label="Holders"
value={`56`}
className="text-bearish"
/>
<DataCard
icon={ChartCandlestick}
label="pro traders"
value={`19`}
className="text-bullish"
/>
<DataCard
icon={ShieldIcon}
label="Dex paid"
value={`Paid`}
className="text-bullish"
/>
</div>
<div>CA and DA placeholder</div>
</div>
</div>
);
}
function DataCard({
label,
value,
className,
icon: Icon,
}: {
icon: LucideIcon;
label: string;
value: string;
className: string;
}) {
return (
<div className="rounded-md border flex flex-col gap-1.5 justify-center pt-1 pb-2">
<div
className={cn(
"flex items-center justify-center gap-1 text-xs",
className,
)}
>
<Icon className="h-3 w-3" />
{value}
</div>
<div className="text-center text-xs text-muted-foreground">{label}</div>
</div>
);
}
+21
View File
@@ -0,0 +1,21 @@
"use client";
import Navbar from "@/components/layout/Navbar";
import Statusbar from "@/components/layout/Statusbar";
import MarketSidebar from "./components/market-sidebar/MarketSidebar";
import Chart from "./components/market-sidebar/Chart";
export default function Market() {
return (
<main className="w-full h-full">
<Navbar />
<section className="w-full h-full flex flex-row">
<div className="w-full h-svh border-r border-border">
<Chart />
</div>
<MarketSidebar />
</section>
<Statusbar />
</main>
);
}
+3 -3
View File
@@ -40,13 +40,13 @@ export default function TokenCard({ token }: { token: Token }) {
" "
onClick={(e) => { onClick={(e) => {
if (e.ctrlKey || e.metaKey) { if (e.ctrlKey || e.metaKey) {
window.open(`/token/${token.mint}`, "_blank", "noopener,noreferrer"); window.open(`/market/${token.mint}`, "_blank", "noopener,noreferrer");
} else { } else {
router.push(`/token/${token.mint}`); router.push(`/market/${token.mint}`);
} }
}} }}
onContextMenu={() => onContextMenu={() =>
window.open(`/token/${token.mint}`, "_blank", "noopener,noreferrer") window.open(`/market/${token.mint}`, "_blank", "noopener,noreferrer")
} }
> >
{/* Left: logo */} {/* Left: logo */}
+17 -17
View File
@@ -22,38 +22,38 @@ export default function Landing() {
</div> </div>
{/* Hero */} {/* Hero */}
<section className="relative z-10 px-6 pt-32 pb-24 max-w-7xl mx-auto"> <section className="pt-32 pb-24 w-full">
<div className="max-w-3xl"> <div className="w-full">
<h1 className="text-5xl md:text-6xl font-semibold leading-tight animate-fade-in-up"> <h1 className="text-center text-5xl md:text-6xl font-semibold leading-tight animate-fade-in-up">
Your copilot for <br /> Your copilot for <br />
<span className="text-transparent bg-clip-text bg-linear-to-r from-primary to-accent"> <span className="text-transparent bg-clip-text bg-linear-to-r from-primary to-accent">
memecoin trading memecoin trading
</span> </span>
</h1> </h1>
<p className="mt-6 text-lg text-muted-foreground max-w-xl animate-fade-in-up animate-delay-100"> <p className="mx-auto text-center mt-6 text-lg text-muted-foreground max-w-xl animate-fade-in-up animate-delay-100">
Catch rugs before they happen, execute trades at Solana Catch rugs before they happen, execute trades at Solana speed, and
speed, and automate the research pro traders do. automate the research pro traders do.
</p> </p>
<div className="mt-10 flex gap-4"> <div className="mt-10 flex gap-4 mx-auto w-max">
<Link <Link
href="/markets"
className="animate-fade-in-up animate-duration-500 animate-delay-200" className="animate-fade-in-up animate-duration-500 animate-delay-200"
>
<button className="px-6 py-3 rounded-lg bg-primary text-primary-foreground font-medium hover:opacity-90 transition">
Open Terminal
</button>
</Link>
<Link
className="animate-fade-in-up animate-duration-500 animate-delay-300"
href="https://github.com/nexa-sol/nexa-trade?tab=readme-ov-file#-nexa-roadmap--alpha-release" href="https://github.com/nexa-sol/nexa-trade?tab=readme-ov-file#-nexa-roadmap--alpha-release"
target="_blank" target="_blank"
> >
<button className="px-6 py-3 rounded-lg border border-border hover:bg-accent/10 transition"> <button className="px-6 py-3 rounded-lg border border-border hover:bg-accent/10 hover:text-accent transition">
View Roadmap View Roadmap
</button> </button>
</Link> </Link>
<Link
href="/markets"
className="animate-fade-in-up animate-duration-500 animate-delay-300"
>
<button className="px-6 py-3 rounded-lg font-medium transition border border-border outline-primary text-primary bg-primary/8 hover:border-primary hover:bg-primary/12">
Open Terminal
</button>
</Link>
</div> </div>
</div> </div>
</section> </section>
@@ -61,7 +61,7 @@ export default function Landing() {
{/* Features */} {/* Features */}
<section className="relative z-10 px-6 py-24 max-w-7xl mx-auto"> <section className="relative z-10 px-6 py-24 max-w-7xl mx-auto">
<div className="grid md:grid-cols-3 gap-8"> <div className="grid md:grid-cols-3 gap-8">
<Staggered stagger={100}> <Staggered stagger={150}>
{[ {[
{ {
icon: Shield, icon: Shield,
+21
View File
@@ -0,0 +1,21 @@
import * as React from "react"
import { cn } from "@/lib/utils"
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
return (
<input
type={type}
data-slot="input"
className={cn(
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
className
)}
{...props}
/>
)
}
export { Input }
+53
View File
@@ -0,0 +1,53 @@
"use client"
import { GripVerticalIcon } from "lucide-react"
import * as ResizablePrimitive from "react-resizable-panels"
import { cn } from "@/lib/utils"
function ResizablePanelGroup({
className,
...props
}: ResizablePrimitive.GroupProps) {
return (
<ResizablePrimitive.Group
data-slot="resizable-panel-group"
className={cn(
"flex h-full w-full aria-[orientation=vertical]:flex-col",
className
)}
{...props}
/>
)
}
function ResizablePanel({ ...props }: ResizablePrimitive.PanelProps) {
return <ResizablePrimitive.Panel data-slot="resizable-panel" {...props} />
}
function ResizableHandle({
withHandle,
className,
...props
}: ResizablePrimitive.SeparatorProps & {
withHandle?: boolean
}) {
return (
<ResizablePrimitive.Separator
data-slot="resizable-handle"
className={cn(
"bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden aria-[orientation=horizontal]:h-px aria-[orientation=horizontal]:w-full aria-[orientation=horizontal]:after:left-0 aria-[orientation=horizontal]:after:h-1 aria-[orientation=horizontal]:after:w-full aria-[orientation=horizontal]:after:translate-x-0 aria-[orientation=horizontal]:after:-translate-y-1/2 [&[aria-orientation=horizontal]>div]:rotate-90",
className
)}
{...props}
>
{withHandle && (
<div className="bg-border z-10 flex h-4 w-3 items-center justify-center rounded-xs border">
<GripVerticalIcon className="size-2.5" />
</div>
)}
</ResizablePrimitive.Separator>
)
}
export { ResizableHandle, ResizablePanel, ResizablePanelGroup }
+28
View File
@@ -0,0 +1,28 @@
"use client"
import * as React from "react"
import { Separator as SeparatorPrimitive } from "radix-ui"
import { cn } from "@/lib/utils"
function Separator({
className,
orientation = "horizontal",
decorative = true,
...props
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
return (
<SeparatorPrimitive.Root
data-slot="separator"
decorative={decorative}
orientation={orientation}
className={cn(
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
className
)}
{...props}
/>
)
}
export { Separator }
+91
View File
@@ -0,0 +1,91 @@
"use client"
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { Tabs as TabsPrimitive } from "radix-ui"
import { cn } from "@/lib/utils"
function Tabs({
className,
orientation = "horizontal",
...props
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
return (
<TabsPrimitive.Root
data-slot="tabs"
data-orientation={orientation}
orientation={orientation}
className={cn(
"group/tabs flex gap-2 data-[orientation=horizontal]:flex-col",
className
)}
{...props}
/>
)
}
const tabsListVariants = cva(
"rounded-lg p-[3px] group-data-[orientation=horizontal]/tabs:h-9 data-[variant=line]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col",
{
variants: {
variant: {
default: "bg-muted",
line: "gap-1 bg-transparent",
},
},
defaultVariants: {
variant: "default",
},
}
)
function TabsList({
className,
variant = "default",
...props
}: React.ComponentProps<typeof TabsPrimitive.List> &
VariantProps<typeof tabsListVariants>) {
return (
<TabsPrimitive.List
data-slot="tabs-list"
data-variant={variant}
className={cn(tabsListVariants({ variant }), className)}
{...props}
/>
)
}
function TabsTrigger({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
return (
<TabsPrimitive.Trigger
data-slot="tabs-trigger"
className={cn(
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent",
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 data-[state=active]:text-foreground",
"after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
className
)}
{...props}
/>
)
}
function TabsContent({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
return (
<TabsPrimitive.Content
data-slot="tabs-content"
className={cn("flex-1 outline-none", className)}
{...props}
/>
)
}
export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants }
+1 -1
View File
@@ -3,7 +3,7 @@ export interface Token {
symbol: string; symbol: string;
name: string; name: string;
logoURI?: string; logoURI?: string;
twitterPost: { twitterPost?: {
link: string; link: string;
author: { author: {
username: string; username: string;