refactor: update component styles to use theme-aware colors and improve UI consistency
This commit is contained in:
@@ -23,7 +23,7 @@ export function ChannelsView({
|
|||||||
CHANNEL ROSTER · SIGNAL_MAP
|
CHANNEL ROSTER · SIGNAL_MAP
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="inline-flex items-center gap-1.5 rounded-sm bg-surface px-2 py-0.5 font-mono text-[11px] text-ink-soft">
|
<div className="inline-flex items-center gap-1.5 rounded-md bg-surface px-2 py-0.5 font-mono text-[11px] text-ink-soft">
|
||||||
<span className="text-ink-faint">NODES:</span>
|
<span className="text-ink-faint">NODES:</span>
|
||||||
<span className="font-bold text-signal">{cultures?.length ?? 0}</span>
|
<span className="font-bold text-signal">{cultures?.length ?? 0}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -399,7 +399,7 @@ export function MessagesView({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={loadOlder}
|
onClick={loadOlder}
|
||||||
className="rounded-[5px] border border-hairline bg-surface-2 px-3 py-1 font-mono text-[10px] text-ink-muted transition-colors hover:bg-surface hover:text-ink"
|
className="rounded-md border border-hairline bg-surface-2 px-3 py-1 font-mono text-[10px] text-ink-muted transition-colors hover:bg-surface hover:text-ink"
|
||||||
>
|
>
|
||||||
↑ LOAD PREVIOUS BATCH
|
↑ LOAD PREVIOUS BATCH
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ export function RecordingsView({
|
|||||||
href={r.download_url}
|
href={r.download_url}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
className="inline-flex items-center gap-1 rounded-[5px] border border-hairline bg-surface-2 px-2 py-1 font-mono text-[10px] text-ink-soft transition-colors hover:bg-surface hover:text-ink"
|
className="inline-flex items-center gap-1 rounded-md border border-hairline bg-surface-2 px-2 py-1 font-mono text-[10px] text-ink-soft transition-colors hover:bg-surface hover:text-ink"
|
||||||
>
|
>
|
||||||
<Download className="size-3 text-signal" /> RAW
|
<Download className="size-3 text-signal" /> RAW
|
||||||
</a>
|
</a>
|
||||||
@@ -211,7 +211,7 @@ export function RecordingsView({
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() => onDelete(r.id)}
|
onClick={() => onDelete(r.id)}
|
||||||
disabled={del.isPending}
|
disabled={del.isPending}
|
||||||
className="inline-flex items-center gap-1 rounded-[5px] border border-vermilion/30 bg-vermilion/10 px-2 py-1 font-mono text-[10px] text-vermilion transition-colors hover:bg-vermilion/20"
|
className="inline-flex items-center gap-1 rounded-md border border-vermilion/30 bg-vermilion/10 px-2 py-1 font-mono text-[10px] text-vermilion transition-colors hover:bg-vermilion/20"
|
||||||
>
|
>
|
||||||
<Trash2 className="size-3" /> PURGE
|
<Trash2 className="size-3" /> PURGE
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -166,14 +166,7 @@
|
|||||||
border-color: var(--panel-border-hover);
|
border-color: var(--panel-border-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.glass-2 {
|
|
||||||
background: var(--panel-bg-subtle);
|
|
||||||
border: 1px solid var(--panel-border);
|
|
||||||
border-radius: var(--radius-r);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* HUD Tactical Card */
|
/* HUD Tactical Card */
|
||||||
.linear-card,
|
|
||||||
.hud-card {
|
.hud-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
background: var(--panel-bg);
|
background: var(--panel-bg);
|
||||||
@@ -184,7 +177,6 @@
|
|||||||
transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.linear-card:hover,
|
|
||||||
.hud-card:hover {
|
.hud-card:hover {
|
||||||
border-color: var(--panel-border-hover);
|
border-color: var(--panel-border-hover);
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
@@ -263,14 +255,105 @@
|
|||||||
100% { transform: scale(2.2); opacity: 0; }
|
100% { transform: scale(2.2); opacity: 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes shimmer {
|
||||||
|
0% { background-position: 200% 0; }
|
||||||
|
100% { background-position: -200% 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eq {
|
||||||
|
0%, 100% { transform: scaleY(0.35); }
|
||||||
|
50% { transform: scaleY(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-up {
|
||||||
|
from { opacity: 0; transform: translateY(6px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes toast-in {
|
||||||
|
from { opacity: 0; transform: translateY(8px) scale(0.98); }
|
||||||
|
to { opacity: 1; transform: translateY(0) scale(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes scan {
|
||||||
|
0% { transform: translateY(-100%); }
|
||||||
|
100% { transform: translateY(100%); }
|
||||||
|
}
|
||||||
|
|
||||||
.animate-breathe { animation: breathe 2.5s ease-in-out infinite; }
|
.animate-breathe { animation: breathe 2.5s ease-in-out infinite; }
|
||||||
.animate-spin-disc { animation: spin-disc 10s linear infinite; }
|
.animate-spin-disc { animation: spin-disc 10s linear infinite; }
|
||||||
.animate-pulse-ring { animation: pulse-ring 2s cubic-bezier(0.16, 1, 0.3, 1) infinite; }
|
.animate-pulse-ring { animation: pulse-ring 2s cubic-bezier(0.16, 1, 0.3, 1) infinite; }
|
||||||
|
|
||||||
|
/* Skeleton shimmer — theme-aware base + moving highlight sheen. */
|
||||||
|
.animate-shimmer {
|
||||||
|
background-color: var(--panel-bg-subtle);
|
||||||
|
background-image: linear-gradient(
|
||||||
|
105deg,
|
||||||
|
transparent 40%,
|
||||||
|
color-mix(in oklab, var(--text-primary) 6%, transparent) 50%,
|
||||||
|
transparent 60%
|
||||||
|
);
|
||||||
|
background-size: 200% 100%;
|
||||||
|
animation: shimmer 1.6s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Live equalizer bars (mini-player / recording player). */
|
||||||
|
.animate-eq {
|
||||||
|
transform-origin: bottom;
|
||||||
|
animation: eq 0.9s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Entrance for popovers, toasts, mini-player. */
|
||||||
|
.animate-fade-up { animation: fade-up 0.18s cubic-bezier(0.16, 1, 0.3, 1); }
|
||||||
|
.animate-toast-in { animation: toast-in 0.2s cubic-bezier(0.16, 1, 0.3, 1); }
|
||||||
|
|
||||||
|
/* Sweeping glow line across a hero/placeholder panel. */
|
||||||
|
.scan-line {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
transparent,
|
||||||
|
var(--accent-signal-glow),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
opacity: 0.5;
|
||||||
|
animation: scan 2.6s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile nav hover/active sweep fill. */
|
||||||
|
.game-sweep {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: inherit;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-sweep i {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: var(--accent-signal-bg);
|
||||||
|
transform: translateY(100%);
|
||||||
|
transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-nav-item.is-active .game-sweep i,
|
||||||
|
.game-nav-item:hover .game-sweep i {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.animate-breathe,
|
.animate-breathe,
|
||||||
.animate-spin-disc,
|
.animate-spin-disc,
|
||||||
.animate-pulse-ring {
|
.animate-pulse-ring,
|
||||||
|
.animate-shimmer,
|
||||||
|
.animate-eq,
|
||||||
|
.animate-fade-up,
|
||||||
|
.animate-toast-in,
|
||||||
|
.scan-line {
|
||||||
animation: none !important;
|
animation: none !important;
|
||||||
}
|
}
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export function CategoryDrilldown({
|
|||||||
<span className="w-36 shrink-0 truncate text-ink-soft">
|
<span className="w-36 shrink-0 truncate text-ink-soft">
|
||||||
{c.name}
|
{c.name}
|
||||||
</span>
|
</span>
|
||||||
<div className="h-2 flex-1 overflow-hidden rounded-full bg-white/5">
|
<div className="h-2 flex-1 overflow-hidden rounded-full bg-hairline">
|
||||||
<div
|
<div
|
||||||
className="h-full rounded-full bg-signal"
|
className="h-full rounded-full bg-signal"
|
||||||
style={{ width: `${pct}%` }}
|
style={{ width: `${pct}%` }}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import { cn } from "@/lib/utils";
|
|||||||
export function ModerationHeatmap({ hours }: { hours: HourlyModeration[] }) {
|
export function ModerationHeatmap({ hours }: { hours: HourlyModeration[] }) {
|
||||||
const max = hours.reduce((m, h) => Math.max(m, h.total), 0);
|
const max = hours.reduce((m, h) => Math.max(m, h.total), 0);
|
||||||
const intensity = (v: number) => {
|
const intensity = (v: number) => {
|
||||||
if (max <= 0) return "bg-white/5";
|
if (max <= 0) return "bg-hairline";
|
||||||
const t = Math.max(0, Math.min(1, v / max));
|
const t = Math.max(0, Math.min(1, v / max));
|
||||||
if (t < 0.25) return "bg-white/[0.06]";
|
if (t < 0.25) return "bg-surface-2";
|
||||||
if (t < 0.5) return "bg-signal/25";
|
if (t < 0.5) return "bg-signal/25";
|
||||||
if (t < 0.75) return "bg-signal/50";
|
if (t < 0.75) return "bg-signal/50";
|
||||||
return "bg-vermilion/60";
|
return "bg-vermilion/60";
|
||||||
|
|||||||
@@ -48,9 +48,9 @@ export function ScamDomains({ domains }: { domains: FlaggedDomain[] }) {
|
|||||||
<span className="w-44 shrink-0 truncate font-mono text-ink-soft">
|
<span className="w-44 shrink-0 truncate font-mono text-ink-soft">
|
||||||
{d.domain}
|
{d.domain}
|
||||||
</span>
|
</span>
|
||||||
<div className="h-2 flex-1 overflow-hidden rounded-full bg-white/5">
|
<div className="h-2 flex-1 overflow-hidden rounded-full bg-hairline">
|
||||||
<div
|
<div
|
||||||
className="h-full rounded-full bg-[#8b5cf6]"
|
className="h-full rounded-full bg-signal"
|
||||||
style={{ width: `${pct}%` }}
|
style={{ width: `${pct}%` }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -53,9 +53,9 @@ export function TopChannels({ channels }: { channels: FlaggedChannel[] }) {
|
|||||||
<span className="w-40 shrink-0 truncate text-ink-soft">
|
<span className="w-40 shrink-0 truncate text-ink-soft">
|
||||||
{c.channel_name ?? c.channel_id}
|
{c.channel_name ?? c.channel_id}
|
||||||
</span>
|
</span>
|
||||||
<div className="h-2 flex-1 overflow-hidden rounded-full bg-white/5">
|
<div className="h-2 flex-1 overflow-hidden rounded-full bg-hairline">
|
||||||
<div
|
<div
|
||||||
className="h-full rounded-full bg-[#f59e0b]"
|
className="h-full rounded-full bg-amber"
|
||||||
style={{ width: `${pct}%` }}
|
style={{ width: `${pct}%` }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ function BarRow({
|
|||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-3 text-sm">
|
<div className="flex items-center gap-3 text-sm">
|
||||||
<span className="w-32 shrink-0 truncate text-ink-soft">{label}</span>
|
<span className="w-32 shrink-0 truncate text-ink-soft">{label}</span>
|
||||||
<div className="h-2 flex-1 overflow-hidden rounded-full bg-white/5">
|
<div className="h-2 flex-1 overflow-hidden rounded-full bg-hairline">
|
||||||
<div
|
<div
|
||||||
className="h-full rounded-full"
|
className="h-full rounded-full"
|
||||||
style={{ width: `${pct}%`, background: color }}
|
style={{ width: `${pct}%`, background: color }}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export function Equalizer({
|
|||||||
{Array.from({ length: 28 }).map((_, i) => (
|
{Array.from({ length: 28 }).map((_, i) => (
|
||||||
<span
|
<span
|
||||||
key={`eq-${i}`}
|
key={`eq-${i}`}
|
||||||
className="flex-1 rounded-full bg-white/10"
|
className="flex-1 rounded-full bg-hairline"
|
||||||
style={{ height: "12%" }}
|
style={{ height: "12%" }}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ export function Chatbot() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setExpanded(!expanded)}
|
onClick={() => setExpanded(!expanded)}
|
||||||
className="rounded-[5px] p-1 text-ink-muted hover:bg-surface-2 hover:text-ink"
|
className="rounded-md p-1 text-ink-muted hover:bg-surface-2 hover:text-ink"
|
||||||
>
|
>
|
||||||
{expanded ? (
|
{expanded ? (
|
||||||
<Minimize2 className="size-3.5" />
|
<Minimize2 className="size-3.5" />
|
||||||
@@ -180,7 +180,7 @@ export function Chatbot() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setOpen(false)}
|
onClick={() => setOpen(false)}
|
||||||
className="rounded-[5px] p-1 text-ink-muted hover:bg-surface-2 hover:text-ink"
|
className="rounded-md p-1 text-ink-muted hover:bg-surface-2 hover:text-ink"
|
||||||
>
|
>
|
||||||
<X className="size-3.5" />
|
<X className="size-3.5" />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ export function CommandPalette() {
|
|||||||
placeholder="Type a command or search…"
|
placeholder="Type a command or search…"
|
||||||
className="flex-1 bg-transparent text-sm text-ink outline-none placeholder:text-ink-faint"
|
className="flex-1 bg-transparent text-sm text-ink outline-none placeholder:text-ink-faint"
|
||||||
/>
|
/>
|
||||||
<kbd className="mono rounded bg-white/8 px-1.5 py-0.5 text-[0.6rem] text-ink-faint">
|
<kbd className="mono rounded bg-surface-2 px-1.5 py-0.5 text-[0.6rem] text-ink-faint">
|
||||||
ESC
|
ESC
|
||||||
</kbd>
|
</kbd>
|
||||||
</div>
|
</div>
|
||||||
@@ -156,11 +156,11 @@ export function CommandPalette() {
|
|||||||
key={c.id}
|
key={c.id}
|
||||||
className={`flex w-full items-center gap-3 rounded-[10px] px-3 py-2.5 text-left text-sm transition-colors ${
|
className={`flex w-full items-center gap-3 rounded-[10px] px-3 py-2.5 text-left text-sm transition-colors ${
|
||||||
i === active
|
i === active
|
||||||
? "bg-signal/12 text-ink"
|
? "bg-signal/15 text-ink"
|
||||||
: "text-ink-soft hover:bg-white/5"
|
: "text-ink-soft hover:bg-surface"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<span className="flex size-7 items-center justify-center rounded-[8px] bg-white/5">
|
<span className="flex size-7 items-center justify-center rounded-[8px] bg-surface-2">
|
||||||
{c.icon}
|
{c.icon}
|
||||||
</span>
|
</span>
|
||||||
<span className="flex-1">{c.label}</span>
|
<span className="flex-1">{c.label}</span>
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export function MiniPlayer() {
|
|||||||
className="flex min-w-0 flex-1 items-center gap-3"
|
className="flex min-w-0 flex-1 items-center gap-3"
|
||||||
aria-label="Open full media player"
|
aria-label="Open full media player"
|
||||||
>
|
>
|
||||||
<span className="relative flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-full border border-hairline bg-white/5">
|
<span className="relative flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-full border border-hairline bg-surface-2">
|
||||||
{current.thumbnailUrl ? (
|
{current.thumbnailUrl ? (
|
||||||
// biome-ignore lint/performance/noImgElement: external CDN thumbnails, next/image needs remote allowlist
|
// biome-ignore lint/performance/noImgElement: external CDN thumbnails, next/image needs remote allowlist
|
||||||
<img
|
<img
|
||||||
@@ -130,7 +130,7 @@ export function MiniPlayer() {
|
|||||||
onClick={() => skip.mutate()}
|
onClick={() => skip.mutate()}
|
||||||
disabled={skip.isPending}
|
disabled={skip.isPending}
|
||||||
aria-label="Skip to next track"
|
aria-label="Skip to next track"
|
||||||
className="flex size-8 items-center justify-center rounded-full text-ink-soft transition-colors hover:bg-white/10 hover:text-signal active:scale-95"
|
className="flex size-8 items-center justify-center rounded-full text-ink-soft transition-colors hover:bg-surface hover:text-signal active:scale-95"
|
||||||
>
|
>
|
||||||
<SkipForward className="size-4" />
|
<SkipForward className="size-4" />
|
||||||
</button>
|
</button>
|
||||||
@@ -151,7 +151,7 @@ export function MiniPlayer() {
|
|||||||
className={`hidden size-8 items-center justify-center rounded-full text-xs transition-colors sm:flex ${
|
className={`hidden size-8 items-center justify-center rounded-full text-xs transition-colors sm:flex ${
|
||||||
media?.loop
|
media?.loop
|
||||||
? "bg-signal/15 text-signal"
|
? "bg-signal/15 text-signal"
|
||||||
: "text-ink-faint hover:bg-white/10 hover:text-ink"
|
: "text-ink-faint hover:bg-surface hover:text-ink"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
↻
|
↻
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export function Badge({
|
|||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
"inline-flex items-center gap-1.5 rounded-[4px] border font-mono font-medium tracking-tight",
|
"inline-flex items-center gap-1.5 rounded-[6px] border font-mono font-medium tracking-tight",
|
||||||
tones[tone],
|
tones[tone],
|
||||||
sizes[size],
|
sizes[size],
|
||||||
className,
|
className,
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ export const buttonVariants = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const sizes = {
|
const sizes = {
|
||||||
sm: "h-7 px-2.5 text-xs rounded-[5px] gap-1.5",
|
sm: "h-7 px-2.5 text-xs rounded-[8px] gap-1.5",
|
||||||
md: "h-8.5 px-3.5 text-xs rounded-[6px] gap-2",
|
md: "h-8.5 px-3.5 text-xs rounded-[8px] gap-2",
|
||||||
lg: "h-10 px-4 text-sm rounded-[7px] gap-2.5",
|
lg: "h-10 px-4 text-sm rounded-[8px] gap-2.5",
|
||||||
icon: "size-8.5 rounded-[6px] p-0",
|
icon: "size-8.5 rounded-[8px] p-0",
|
||||||
};
|
};
|
||||||
|
|
||||||
return cn(base, variants[variant], sizes[size], className);
|
return cn(base, variants[variant], sizes[size], className);
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ export function GlassPanel({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative rounded-[10px] border border-white/[0.08] bg-[#0f1011]/80 p-5 shadow-xl backdrop-blur-md transition-all duration-200",
|
"relative rounded-[10px] border border-hairline bg-surface p-5 shadow-xl backdrop-blur-md transition-all duration-200",
|
||||||
glow && "shadow-[0_0_24px_rgba(113,112,255,0.12)] border-[#7170ff]/30",
|
glow && "shadow-[0_0_24px_var(--color-signal-glow)] border-signal/30",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
style={style}
|
style={style}
|
||||||
@@ -35,7 +35,7 @@ export function GlassCard({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative rounded-[8px] border border-white/[0.06] bg-white/[0.02] p-4 transition-all duration-200 hover:border-white/[0.12] hover:bg-white/[0.04]",
|
"relative rounded-[8px] border border-hairline bg-surface-2 p-4 transition-all duration-200 hover:border-hairline-focus hover:bg-surface",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
style={style}
|
style={style}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ export function Input({
|
|||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-10 w-full rounded-[11px] bg-white/5 border border-hairline px-3.5 text-sm text-ink",
|
"h-10 w-full rounded-[8px] bg-surface-2 border border-hairline px-3.5 text-sm text-ink",
|
||||||
"placeholder:text-ink-faint transition-colors",
|
"placeholder:text-ink-faint transition-colors",
|
||||||
"focus:outline-none focus:border-signal/50 focus:bg-white/8",
|
"focus:outline-none focus:border-signal/50 focus:bg-surface",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -24,9 +24,9 @@ export function Textarea({
|
|||||||
return (
|
return (
|
||||||
<textarea
|
<textarea
|
||||||
className={cn(
|
className={cn(
|
||||||
"w-full rounded-[11px] bg-white/5 border border-hairline px-3.5 py-2.5 text-sm text-ink",
|
"w-full rounded-[8px] bg-surface-2 border border-hairline px-3.5 py-2.5 text-sm text-ink",
|
||||||
"placeholder:text-ink-faint transition-colors resize-none",
|
"placeholder:text-ink-faint transition-colors resize-none",
|
||||||
"focus:outline-none focus:border-signal/50 focus:bg-white/8",
|
"focus:outline-none focus:border-signal/50 focus:bg-surface",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export function Progress({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-1.5 w-full overflow-hidden rounded-full bg-white/8",
|
"h-1.5 w-full overflow-hidden rounded-full bg-hairline",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -39,7 +39,7 @@ export function Spinner({ className }: { className?: string }) {
|
|||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
"inline-block size-4 animate-spin rounded-full border-2 border-white/20 border-t-signal",
|
"inline-block size-4 animate-spin rounded-full border-2 border-hairline border-t-signal",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export function Select({
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() => setOpen((o) => !o)}
|
onClick={() => setOpen((o) => !o)}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex w-full items-center justify-between gap-2 rounded-[11px] border border-hairline bg-white/5 text-left text-ink transition-colors hover:border-signal/40",
|
"flex w-full items-center justify-between gap-2 rounded-[8px] border border-hairline bg-surface-2 text-left text-ink transition-colors hover:border-signal/40",
|
||||||
"focus:outline-none focus:border-signal/60",
|
"focus:outline-none focus:border-signal/60",
|
||||||
size === "sm" ? "h-9 px-3 text-xs" : "h-10 px-3.5 text-sm",
|
size === "sm" ? "h-9 px-3 text-xs" : "h-10 px-3.5 text-sm",
|
||||||
)}
|
)}
|
||||||
@@ -79,10 +79,10 @@ export function Select({
|
|||||||
setOpen(false);
|
setOpen(false);
|
||||||
}}
|
}}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex w-full items-center justify-between gap-2 rounded-[9px] px-3 py-2 text-left text-sm transition-colors",
|
"flex w-full items-center justify-between gap-2 rounded-[8px] px-3 py-2 text-left text-sm transition-colors",
|
||||||
o.value === value
|
o.value === value
|
||||||
? "bg-signal/15 text-signal"
|
? "bg-signal/15 text-signal"
|
||||||
: "text-ink hover:bg-white/6",
|
: "text-ink hover:bg-surface",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span className="truncate">{o.label}</span>
|
<span className="truncate">{o.label}</span>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export function Skeleton({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"rounded-[10px] bg-white/[0.06] animate-shimmer relative overflow-hidden",
|
"relative overflow-hidden rounded-[10px] animate-shimmer",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export function Toaster({ position = "bottom-right" }: { position?: string }) {
|
|||||||
store = store.filter((x) => x.id !== t.id);
|
store = store.filter((x) => x.id !== t.id);
|
||||||
emit();
|
emit();
|
||||||
}}
|
}}
|
||||||
className="rounded-md p-1 text-ink-faint transition-colors hover:bg-white/8 hover:text-ink"
|
className="rounded-md p-1 text-ink-faint transition-colors hover:bg-surface hover:text-ink"
|
||||||
>
|
>
|
||||||
<X className="size-3.5" />
|
<X className="size-3.5" />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ function renderInline(text: string, keyBase: string): ReactNode[] {
|
|||||||
nodes.push(
|
nodes.push(
|
||||||
<code
|
<code
|
||||||
key={`${keyBase}-c${i}`}
|
key={`${keyBase}-c${i}`}
|
||||||
className="mono rounded bg-white/10 px-1 py-0.5 text-[0.85em] text-signal"
|
className="mono rounded bg-surface-2 px-1 py-0.5 text-[0.85em] text-signal"
|
||||||
>
|
>
|
||||||
{m[4]}
|
{m[4]}
|
||||||
</code>,
|
</code>,
|
||||||
@@ -56,7 +56,7 @@ function renderBlock(content: string, keyBase: string): ReactNode[] {
|
|||||||
return (
|
return (
|
||||||
<pre
|
<pre
|
||||||
key={`${keyBase}-pre${idx}`}
|
key={`${keyBase}-pre${idx}`}
|
||||||
className="my-1.5 overflow-x-auto rounded-[10px] border border-hairline bg-black/30 p-3"
|
className="my-1.5 overflow-x-auto rounded-[10px] border border-hairline bg-surface-2 p-3"
|
||||||
>
|
>
|
||||||
<code className="mono block whitespace-pre text-xs text-ink-soft">
|
<code className="mono block whitespace-pre text-xs text-ink-soft">
|
||||||
{code.replace(/\n$/, "")}
|
{code.replace(/\n$/, "")}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export function SkeletonRows({
|
|||||||
{Array.from({ length: rows }).map((_, i) => (
|
{Array.from({ length: rows }).map((_, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className="flex items-start gap-3 rounded-[12px] border border-hairline bg-white/[0.03] p-3"
|
className="flex items-start gap-3 rounded-[12px] border border-hairline bg-surface-2 p-3"
|
||||||
>
|
>
|
||||||
<Skeleton className="size-8 shrink-0 rounded-full" />
|
<Skeleton className="size-8 shrink-0 rounded-full" />
|
||||||
<div className="flex-1 space-y-2 py-0.5">
|
<div className="flex-1 space-y-2 py-0.5">
|
||||||
@@ -111,7 +111,7 @@ export function EmptyState({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{icon && (
|
{icon && (
|
||||||
<span className="mb-1 flex size-14 items-center justify-center rounded-full border border-hairline bg-white/[0.04] text-ink-soft shadow-[0_0_30px_-12px_var(--color-signal-glow)]">
|
<span className="mb-1 flex size-14 items-center justify-center rounded-full border border-hairline bg-surface-2 text-ink-soft shadow-[0_0_30px_-12px_var(--color-signal-glow)]">
|
||||||
{icon}
|
{icon}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -26,14 +26,14 @@ export function MobileNav() {
|
|||||||
className={cn(
|
className={cn(
|
||||||
"game-nav-item relative flex min-h-[44px] flex-1 flex-col items-center justify-center rounded-t-[20px] px-2 pt-2 pb-[calc(0.4rem+env(safe-area-inset-bottom))] md:hidden",
|
"game-nav-item relative flex min-h-[44px] flex-1 flex-col items-center justify-center rounded-t-[20px] px-2 pt-2 pb-[calc(0.4rem+env(safe-area-inset-bottom))] md:hidden",
|
||||||
active
|
active
|
||||||
? "is-active text-white"
|
? "is-active text-signal"
|
||||||
: "text-ink-faint hover:text-ink-soft",
|
: "text-ink-faint hover:text-ink-soft",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{active && (
|
{active && (
|
||||||
<span
|
<span
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className="absolute inset-x-4 top-0 h-[2px] bg-white shadow-[0_0_8px_var(--color-signal-glow)]"
|
className="absolute inset-x-4 top-0 h-[2px] bg-signal shadow-[0_0_8px_var(--color-signal-glow)]"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<span className="game-sweep" aria-hidden="true">
|
<span className="game-sweep" aria-hidden="true">
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ function NavItem({
|
|||||||
aria-label={label}
|
aria-label={label}
|
||||||
aria-current={active ? "page" : undefined}
|
aria-current={active ? "page" : undefined}
|
||||||
className={cn(
|
className={cn(
|
||||||
"nav-dock-item group relative flex size-9 items-center justify-center rounded-[7px] transition-all duration-150",
|
"nav-dock-item group relative flex size-9 items-center justify-center rounded-[8px] transition-all duration-150",
|
||||||
active
|
active
|
||||||
? "is-active bg-signal/15 text-signal font-semibold shadow-xs border border-signal/30"
|
? "is-active bg-signal/15 text-signal font-semibold shadow-xs border border-signal/30"
|
||||||
: "text-ink-muted hover:bg-surface-2 hover:text-ink",
|
: "text-ink-muted hover:bg-surface-2 hover:text-ink",
|
||||||
@@ -40,7 +40,7 @@ function NavItem({
|
|||||||
<span className="absolute -left-[5px] h-3.5 w-[2px] rounded-full bg-signal shadow-[0_0_8px_var(--color-signal-glow)]" />
|
<span className="absolute -left-[5px] h-3.5 w-[2px] rounded-full bg-signal shadow-[0_0_8px_var(--color-signal-glow)]" />
|
||||||
)}
|
)}
|
||||||
{/* Tooltip on hover */}
|
{/* Tooltip on hover */}
|
||||||
<span className="pointer-events-none absolute left-full z-50 ml-2.5 hidden whitespace-nowrap rounded-[5px] border border-hairline bg-surface px-2 py-0.5 font-sans text-[11px] font-medium tracking-tight text-ink opacity-0 shadow-lg backdrop-blur-md transition-all group-hover:translate-x-0.5 group-hover:opacity-100 md:block">
|
<span className="pointer-events-none absolute left-full z-50 ml-2.5 hidden whitespace-nowrap rounded-md border border-hairline bg-surface px-2 py-0.5 font-sans text-[11px] font-medium tracking-tight text-ink opacity-0 shadow-lg backdrop-blur-md transition-all group-hover:translate-x-0.5 group-hover:opacity-100 md:block">
|
||||||
{label}
|
{label}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user