- Replace monolithic React SPA (App.tsx) with 7 Astro pages (+ routing) - Implement full design system from design/ (OKLCH tokens, Tailwind 4 @theme) - Add 12 Astro components (Button, Badge, Card, Sidebar, Header, states) - Add 11 React islands (AuthGuard, MessageFeed, VoiceControls, AudioVisualizer, etc.) - Add 3 Zustand stores (UI, voice, message state) - Add CSS architecture: dark/light themes, glassmorphism, fluid typography, animations - Add 404, login, settings, recordings pages - Remove 40+ legacy React SPA files - Add Particles background and MascotChat deferred islands - Wire WebSocket bridge for real-time messages and voice events Build: 7 pages in ~900ms Typecheck: clean (0 errors) Lint: clean (0 errors)
75 lines
1.7 KiB
Plaintext
75 lines
1.7 KiB
Plaintext
---
|
|
export interface Props {
|
|
variant?: "text" | "card" | "circle" | "rect";
|
|
width?: string;
|
|
height?: string;
|
|
class?: string;
|
|
}
|
|
|
|
const {
|
|
variant = "text",
|
|
width,
|
|
height,
|
|
class: className = "",
|
|
} = Astro.props;
|
|
|
|
const style: Record<string, string> = {};
|
|
if (width) style.width = width;
|
|
if (height) style.height = height;
|
|
---
|
|
|
|
<div
|
|
aria-hidden="true"
|
|
role="presentation"
|
|
class:list={[`skeleton skeleton--${variant}`, className]}
|
|
style={Object.keys(style).length > 0 ? style : undefined}
|
|
>
|
|
<slot />
|
|
</div>
|
|
|
|
<style is:global>
|
|
.skeleton {
|
|
background: linear-gradient(
|
|
90deg,
|
|
oklch(var(--muted)) 25%,
|
|
oklch(var(--muted-foreground) / 0.15) 50%,
|
|
oklch(var(--muted)) 75%
|
|
);
|
|
background-size: 200% 100%;
|
|
animation: shimmer 1.5s ease-in-out infinite;
|
|
border-radius: 0.5rem;
|
|
}
|
|
|
|
/* ── Variant: text (default) ───────────────────── */
|
|
|
|
.skeleton--text {
|
|
width: 100%;
|
|
height: 1rem;
|
|
border-radius: calc(var(--radius, 1rem) - 4px);
|
|
}
|
|
|
|
/* ── Variant: card ─────────────────────────────── */
|
|
|
|
.skeleton--card {
|
|
width: 100%;
|
|
height: 8rem;
|
|
border-radius: var(--radius, 1rem);
|
|
}
|
|
|
|
/* ── Variant: circle ───────────────────────────── */
|
|
|
|
.skeleton--circle {
|
|
width: 2.5rem;
|
|
height: 2.5rem;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
/* ── Variant: rect ─────────────────────────────── */
|
|
|
|
.skeleton--rect {
|
|
width: 100%;
|
|
height: 3rem;
|
|
border-radius: calc(var(--radius, 1rem) - 2px);
|
|
}
|
|
</style>
|