Token data
This commit is contained in:
+1
-1
@@ -69,7 +69,7 @@
|
|||||||
--secondary-foreground: oklch(0.96 0 0);
|
--secondary-foreground: oklch(0.96 0 0);
|
||||||
|
|
||||||
/* Muted / subtle text */
|
/* Muted / subtle text */
|
||||||
--muted: oklch(0.24 0.015 260);
|
--muted: oklch(22.068% 0.01327 258.402);
|
||||||
--muted-foreground: oklch(0.72 0.01 260);
|
--muted-foreground: oklch(0.72 0.01 260);
|
||||||
|
|
||||||
/* Accent – SOL mint */
|
/* Accent – SOL mint */
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default function PairsCard({ title }: { title: string }) {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="px-4 py-4 border-b border-border ">
|
<CardContent className="px-4 py-4 border-b border-border hover:bg-muted">
|
||||||
<TokenCard
|
<TokenCard
|
||||||
token={{ symbol: "SYM", name: "My token", mint: "myMint" }}
|
token={{ symbol: "SYM", name: "My token", mint: "myMint" }}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,23 +1,94 @@
|
|||||||
import { Token } from "@/modules/tokens/types";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { CopyIcon } from "lucide-react";
|
import { cn } from "@/lib/utils";
|
||||||
|
import { Token, TokenLiveData } from "@/modules/tokens/types";
|
||||||
|
import {
|
||||||
|
BoxesIcon,
|
||||||
|
ChefHatIcon,
|
||||||
|
CoinsIcon,
|
||||||
|
CopyIcon,
|
||||||
|
CrosshairIcon,
|
||||||
|
EyeIcon,
|
||||||
|
GhostIcon,
|
||||||
|
IconNode,
|
||||||
|
LucideIcon,
|
||||||
|
UsersIcon,
|
||||||
|
UserStarIcon,
|
||||||
|
} from "lucide-react";
|
||||||
|
|
||||||
export default function TokenCard({ token }: { token: Token }) {
|
export default function TokenCard({ token }: { token: Token }) {
|
||||||
|
const live: TokenLiveData = {
|
||||||
|
topHolder: 23,
|
||||||
|
devHold: 10,
|
||||||
|
snipersHold: 4,
|
||||||
|
insidersHold: 2,
|
||||||
|
bundleHold: 3,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
<div className="h-full overflow-hidden min-w-0">
|
<div className="h-full overflow-hidden min-w-0">
|
||||||
<img
|
{token.logoURI ? (
|
||||||
src={token.logoURI}
|
<img
|
||||||
alt="Token"
|
src={token.logoURI}
|
||||||
className="w-16 h-16 bg-amber-50 rounded-lg"
|
alt="Token"
|
||||||
/>
|
className="w-16 h-16 rounded-lg"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="w-16 h-16 bg-primary/20 rounded-lg flex items-center justify-center">
|
||||||
|
<CoinsIcon className="text-primary" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<p className="mt-1 truncate text-xs text-muted-foreground"></p>
|
<p className="mt-1 truncate text-xs text-muted-foreground"></p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-1.5">
|
<div className="flex flex-col">
|
||||||
<p className="font-semibold">{token.symbol}</p>
|
<div className="flex gap-1.5">
|
||||||
<p className="text-muted-foreground flex gap-1 items-center h-max cursor-pointer hover:text-accent">
|
<p className="font-semibold">{token.symbol}</p>
|
||||||
{token.name} <CopyIcon className="w-4 h-4" />
|
<p className="text-muted-foreground flex gap-1 items-center h-max cursor-pointer hover:text-accent">
|
||||||
</p>
|
{token.name} <CopyIcon className="w-4 h-4" />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="items-center flex gap-3">
|
||||||
|
<p className="text-green-500 text-sm">20m</p>
|
||||||
|
<p className="text-sm flex gap-1 items-center">
|
||||||
|
<UsersIcon className="w-3.5 h-3.5 text-muted-foreground" />
|
||||||
|
10
|
||||||
|
</p>
|
||||||
|
<p className="text-sm flex gap-1 items-center">
|
||||||
|
<EyeIcon className="w-3.5 h-3.5" />
|
||||||
|
10
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="items-center flex gap-2">
|
||||||
|
<TokenBadge value={live.topHolder} icon={UserStarIcon} />
|
||||||
|
<TokenBadge value={live.devHold} icon={ChefHatIcon} />
|
||||||
|
<TokenBadge value={live.snipersHold} icon={CrosshairIcon} />
|
||||||
|
<TokenBadge value={live.insidersHold} icon={GhostIcon} />
|
||||||
|
<TokenBadge value={live.bundleHold} icon={BoxesIcon} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function TokenBadge({
|
||||||
|
value,
|
||||||
|
icon: Icon,
|
||||||
|
redWhen = 10,
|
||||||
|
}: {
|
||||||
|
value: number;
|
||||||
|
icon: LucideIcon;
|
||||||
|
redWhen?: number;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Badge
|
||||||
|
variant="ghost"
|
||||||
|
className={cn(
|
||||||
|
"bg-card",
|
||||||
|
value > redWhen ? "text-red-400" : "text-green-500",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Icon />
|
||||||
|
{value}%
|
||||||
|
</Badge>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import { cva, type VariantProps } from "class-variance-authority"
|
||||||
|
import { Slot } from "radix-ui"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const badgeVariants = cva(
|
||||||
|
"inline-flex items-center justify-center rounded-full border border-transparent px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default: "bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
||||||
|
secondary:
|
||||||
|
"bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
||||||
|
destructive:
|
||||||
|
"bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
||||||
|
outline:
|
||||||
|
"border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
||||||
|
ghost: "[a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
||||||
|
link: "text-primary underline-offset-4 [a&]:hover:underline",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: "default",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
function Badge({
|
||||||
|
className,
|
||||||
|
variant = "default",
|
||||||
|
asChild = false,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<"span"> &
|
||||||
|
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
|
||||||
|
const Comp = asChild ? Slot.Root : "span"
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Comp
|
||||||
|
data-slot="badge"
|
||||||
|
data-variant={variant}
|
||||||
|
className={cn(badgeVariants({ variant }), className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Badge, badgeVariants }
|
||||||
@@ -4,3 +4,11 @@ export interface Token {
|
|||||||
name: string;
|
name: string;
|
||||||
logoURI?: string;
|
logoURI?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TokenLiveData {
|
||||||
|
topHolder: number;
|
||||||
|
devHold: number;
|
||||||
|
snipersHold: number;
|
||||||
|
insidersHold: number;
|
||||||
|
bundleHold: number;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user