feat: migrate frontend to Astro SSG with design system
- 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)
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
---
|
||||
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>
|
||||
Reference in New Issue
Block a user