feat(frontend): skeleton loading states, empty-state glow, light-mode polish

- Add shared skeleton building blocks (SkeletonHero, SkeletonMetricRow,
  SkeletonPanel, SkeletonRows) and wire them into every view's initial
  loading branch, replacing bare spinners for a cohesive shimmering shell.
- Polish EmptyState with a glow-ring icon chip instead of a flat icon.
- Harden .light theme: color-scheme, tuned scrollbar + selection for pale
  canvas. Dark/light theme toggle (next-themes) already persisted in TopBar.
This commit is contained in:
asepharyana
2026-08-18 09:21:12 +07:00
parent ff8a9c50ae
commit d78d7a0181
10 changed files with 203 additions and 26 deletions
@@ -16,8 +16,8 @@ import { Button, GlassPanel, toast } from "@/components/primitives";
import {
EmptyState,
ErrorState,
LoadingState,
SectionHeader,
SkeletonPanel,
} from "@/components/shared";
import { GuildChannelPicker } from "@/components/shared/guild-picker";
import { VoiceStage } from "@/components/voice/voice-stage";
@@ -67,7 +67,16 @@ export function VoiceView({
}, [status?.connected, ambient]);
if (error && !status) return <ErrorState error={error} />;
if (!status && isLoading) return <LoadingState label="Linking voice" />;
if (!status && isLoading)
return (
<div className="space-y-5">
<SkeletonPanel rows={2} />
<div className="grid gap-5 lg:grid-cols-3">
<SkeletonPanel className="lg:col-span-2" rows={4} />
<SkeletonPanel rows={4} />
</div>
</div>
);
const connected = status?.connected ?? false;
const listenBars = Array.from(listen.levels.values()).slice(0, 32);