diff --git a/services/frontend/src/features/analytics/index.tsx b/services/frontend/src/features/analytics/index.tsx index 4dff37a..6338edd 100644 --- a/services/frontend/src/features/analytics/index.tsx +++ b/services/frontend/src/features/analytics/index.tsx @@ -1,7 +1,7 @@ import { motion } from "framer-motion"; import { useState } from "react"; import { cardItem, cardStagger } from "../../shared/hooks/useFramerStagger"; -import { EmptyStateMascot } from "../../widgets/mascot/ChibiMascot"; +import { EmptyStateMascot } from "../../shared/ui"; import { ActivityChart } from "./components/ActivityChart"; import { ControlBar } from "./components/ControlBar"; import { Heatmap } from "./components/Heatmap"; @@ -53,12 +53,7 @@ export function AnalyticsPanel({ guildId, guildName }: AnalyticsPanelProps) { } if (!guildId) { - return ( - - ); + return ; } return ( diff --git a/services/frontend/src/features/auth/index.tsx b/services/frontend/src/features/auth/index.tsx index 9ec786f..cfadf5c 100644 --- a/services/frontend/src/features/auth/index.tsx +++ b/services/frontend/src/features/auth/index.tsx @@ -10,8 +10,8 @@ import { CardHeader, CardTitle, Input, + MascotImage, } from "../../shared/ui"; -import { ChibiMascot } from "../../widgets/mascot/ChibiMascot"; interface AuthOverlayProps { onAuthenticated: () => void; @@ -50,7 +50,7 @@ export function AuthOverlay({ onAuthenticated }: AuthOverlayProps) {
- + Admin Access Required diff --git a/services/frontend/src/features/live/components/ActiveSpeakers.tsx b/services/frontend/src/features/live/components/ActiveSpeakers.tsx index fa2b03e..3e5117c 100644 --- a/services/frontend/src/features/live/components/ActiveSpeakers.tsx +++ b/services/frontend/src/features/live/components/ActiveSpeakers.tsx @@ -7,9 +7,7 @@ interface ActiveSpeakersProps { export function ActiveSpeakers({ speakers }: ActiveSpeakersProps) { if (speakers.length === 0) { - return ( - - ); + return ; } return ( diff --git a/services/frontend/src/features/live/components/RecordingsSubPanel.tsx b/services/frontend/src/features/live/components/RecordingsSubPanel.tsx index cab8851..f07a910 100644 --- a/services/frontend/src/features/live/components/RecordingsSubPanel.tsx +++ b/services/frontend/src/features/live/components/RecordingsSubPanel.tsx @@ -92,7 +92,7 @@ export function RecordingsSubPanel() { } if (recordings.length === 0) { - return ; + return ; } return ( diff --git a/services/frontend/src/features/messages/components/ImageGrid.tsx b/services/frontend/src/features/messages/components/ImageGrid.tsx index 017e24e..fe8161b 100644 --- a/services/frontend/src/features/messages/components/ImageGrid.tsx +++ b/services/frontend/src/features/messages/components/ImageGrid.tsx @@ -1,6 +1,6 @@ import { parseMetadata } from "../../../entities/message/types"; import type { MessageRecord } from "../../../shared/api/client"; -import { EmptyStateMascot } from "../../../widgets/mascot/ChibiMascot"; +import { EmptyStateMascot } from "../../../shared/ui"; interface ImageItem { url: string; @@ -68,7 +68,7 @@ export function ImageGrid({ messages }: { messages: MessageRecord[] }) { } if (images.length === 0) { - return ; + return ; } return ( diff --git a/services/frontend/src/features/messages/components/MessageFeed.tsx b/services/frontend/src/features/messages/components/MessageFeed.tsx index 733bfe6..d24cf39 100644 --- a/services/frontend/src/features/messages/components/MessageFeed.tsx +++ b/services/frontend/src/features/messages/components/MessageFeed.tsx @@ -2,8 +2,7 @@ import { motion } from "framer-motion"; import { useEffect, useMemo, useRef } from "react"; import type { MessageRecord } from "../../../shared/api/client"; import { cardItem, cardStagger } from "../../../shared/hooks/useFramerStagger"; -import { ScrollArea } from "../../../shared/ui"; -import { EmptyStateMascot } from "../../../widgets/mascot/ChibiMascot"; +import { ScrollArea, EmptyStateMascot } from "../../../shared/ui"; import { MessageCard, MessageCardSkeleton } from "./MessageCard"; export interface MessageFeedProps { @@ -84,7 +83,7 @@ export function MessageFeed({ } if (messages.length === 0) { - return ; + return ; } return ( diff --git a/services/frontend/src/shared/ui/index.ts b/services/frontend/src/shared/ui/index.ts index c0e2504..8f72bf6 100644 --- a/services/frontend/src/shared/ui/index.ts +++ b/services/frontend/src/shared/ui/index.ts @@ -1,6 +1,6 @@ // ─── Shared UI barrel export ──────────────────────────────────────────────── -export { EmptyStateMascot } from "../../widgets/mascot/ChibiMascot"; +export { EmptyStateMascot, MascotImage } from "../../widgets/mascot/MascotImage"; export { Badge } from "./badge"; export { Button } from "./button"; export { diff --git a/services/frontend/src/widgets/Sidebar.tsx b/services/frontend/src/widgets/Sidebar.tsx index 05ea0ef..4790df8 100644 --- a/services/frontend/src/widgets/Sidebar.tsx +++ b/services/frontend/src/widgets/Sidebar.tsx @@ -2,7 +2,7 @@ import { motion } from "framer-motion"; import { BarChart3, MessageSquare, Radio } from "lucide-react"; import type { DashboardTab } from "../entities/ui/types"; import { cn } from "../shared/lib/utils"; -import { ChibiMascot } from "./mascot/ChibiMascot"; +import { MascotImage } from "./mascot/MascotImage"; const navItems: Array<{ id: DashboardTab; label: string; icon: typeof Radio }> = [ @@ -84,9 +84,9 @@ export function Sidebar({ {/* Spacer pushes mascot to bottom */}
- {/* Chibi mascot */} + {/* Mascot PNG */}
- +
); diff --git a/services/frontend/src/widgets/mascot/MascotImage.tsx b/services/frontend/src/widgets/mascot/MascotImage.tsx new file mode 100644 index 0000000..1615896 --- /dev/null +++ b/services/frontend/src/widgets/mascot/MascotImage.tsx @@ -0,0 +1,40 @@ +/** + * MascotImage — Anime mascot PNG from GitHub CDN + * Replaces ChibiMascot SVG component with external PNG asset + */ + +interface MascotImageProps { + size?: "sm" | "md" | "lg"; + className?: string; +} + +const sizeMap = { + sm: "w-16 h-auto", + md: "w-32 h-auto", + lg: "w-48 h-auto", +}; + +export function MascotImage({ size = "md", className = "" }: MascotImageProps) { + const sizeClass = sizeMap[size]; + + return ( + Mascot + ); +} + +/** + * EmptyStateMascot — Mascot for empty states + * Replaces ChibiMascot when showing empty data states + */ +export function EmptyStateMascot() { + return ( +
+ +

No data to display

+
+ ); +}