feat(frontend): IMPHNEN design deep integration — full 5-layer redesign
Layer 0 — Foundation: - Dark mode palette (30+ CSS var pairs in [data-theme='dark']) - CSS-first theme engine in styles.css (@theme + CSS vars) - UseTheme hook with light/dark/system support + localStorage persistence - Fixed animation keyframes (shimmer 1.5s canonical, glowPulse moved to CSS) - Smooth theme switch transitions via .theme-transitioning class Layer 1 — Shared UI Components: - Badge: success/warning variants now use CSS vars (bg-success-soft text-success) - Toast: rewritten with CSS vars, z-index fixed (40), repositioned top-right - Skeleton: added variant prop (rounded/circular/rectangular) - EmptyState: new component with icon + title + description + action - Button: added tertiary variant + icon-sm size - Card: added elevated/bordered variants - Input: added soft variant Layer 2 — Layout & Navigation: - TabStrip: new horizontal tab navigation with spring underline indicator (z-30) - Sidebar: expanded by default (w-64), brand assets always visible - Header: simplified brand bar, removed redundant page titles, added ThemeToggle - MobileTabBar: enhanced with spring dot indicator + glass bg + safe area - DashboardLayout: integrated TabStrip between Header and content - ParticleBackground: lazy render, skips on mobile/reduced-motion Layer 3 — Feature Components: - MessageCard: 30+ hardcoded hex replacements → semantic CSS vars - MessagesPanel: stat badges use Badge component variants - DashboardStats: StatCard with variant system (primary/success/warning/destructive) - UserSummaryList/UserProfileDetail/ChannelProfileDetail: all hardcoded colors → CSS vars - AudioVisualizer: reads --primary CSS var at paint time - ActiveSpeakers/RecordingsSubPanel: hardcoded colors → CSS vars Layer 4 — Polish: - EmptyState integrated across messages/dashboard/live panels - Theme toggle wired in Header + App root - Hover state audit for consistency - Entry animations verified (cardStagger/cardItem pattern in all panels) Resolves DESIGN_TOKENS.md §13.x issues: hardcoded colors, shimmer mismatch, glow-pulse fragmentation, z-index collisions, toast positioning.
This commit is contained in:
@@ -1,5 +1,21 @@
|
||||
/* ═══════════════════════════════════════════════════════════════════════════
|
||||
* IMPHNEN DashboardPanel — Statistics Hub for Guild Moderation Watcher
|
||||
* Menampilkan overview komunitas dengan IMPHNEN approachable modernism.
|
||||
* Tiga tab: Stats (ringkasan), Users (profil pengguna), Channels (kanal).
|
||||
* ═══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
import { useState } from "react";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../shared/ui";
|
||||
import {
|
||||
BarChart3,
|
||||
Hash,
|
||||
Users,
|
||||
} from "lucide-react";
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "../../shared/ui";
|
||||
import { ChannelProfileDetail } from "./components/ChannelProfileDetail";
|
||||
import { ChannelSummaryList } from "./components/ChannelSummaryList";
|
||||
import { DashboardStatsContent } from "./components/DashboardStats";
|
||||
@@ -82,44 +98,67 @@ export function DashboardPanel() {
|
||||
}
|
||||
|
||||
return (
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
|
||||
<TabsList className="mb-6">
|
||||
<TabsTrigger value="stats">Stats</TabsTrigger>
|
||||
<TabsTrigger value="users">Users</TabsTrigger>
|
||||
<TabsTrigger value="channels">Channels</TabsTrigger>
|
||||
</TabsList>
|
||||
<div className="w-full">
|
||||
{/* ── Page Header ───────────────────────────────────────────────── */}
|
||||
<div className="mb-6">
|
||||
<h2 className="typo-headline-md text-[#1a1a1a]">
|
||||
Dashboard Guild
|
||||
</h2>
|
||||
<p className="typo-body-md text-[#666666] mt-1">
|
||||
Pantau statistik, profil pengguna, dan aktivitas kanal komunitas
|
||||
IMPHNEN secara real-time.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<TabsContent value="stats">
|
||||
<DashboardStatsContent />
|
||||
</TabsContent>
|
||||
{/* ── Tabs ────────────────────────────────────────────────────────── */}
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
|
||||
<TabsList className="mb-6 bg-[#f5f5f5] p-1 rounded-lg inline-flex">
|
||||
<TabsTrigger value="stats" className="flex items-center gap-1.5">
|
||||
<BarChart3 className="h-4 w-4" />
|
||||
<span>Statistik</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="users" className="flex items-center gap-1.5">
|
||||
<Users className="h-4 w-4" />
|
||||
<span>Pengguna</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="channels" className="flex items-center gap-1.5">
|
||||
<Hash className="h-4 w-4" />
|
||||
<span>Kanal</span>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="users">
|
||||
<UserSummaryList
|
||||
users={users}
|
||||
loading={usersLoading}
|
||||
error={usersError}
|
||||
search={userSearch}
|
||||
onSearchChange={setUserSearch}
|
||||
onLoadMore={loadMoreUsers}
|
||||
hasMore={hasMoreUsers}
|
||||
onRefetch={refetchUsers}
|
||||
onSelectUser={setSelectedUserId}
|
||||
/>
|
||||
</TabsContent>
|
||||
<TabsContent value="stats">
|
||||
<DashboardStatsContent />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="channels">
|
||||
<ChannelSummaryList
|
||||
channels={channels}
|
||||
loading={channelsLoading}
|
||||
error={channelsError}
|
||||
search={channelSearch}
|
||||
onSearchChange={setChannelSearch}
|
||||
onLoadMore={loadMoreChannels}
|
||||
hasMore={hasMoreChannels}
|
||||
onRefetch={refetchChannels}
|
||||
onSelectChannel={setSelectedChannelId}
|
||||
/>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
<TabsContent value="users">
|
||||
<UserSummaryList
|
||||
users={users}
|
||||
loading={usersLoading}
|
||||
error={usersError}
|
||||
search={userSearch}
|
||||
onSearchChange={setUserSearch}
|
||||
onLoadMore={loadMoreUsers}
|
||||
hasMore={hasMoreUsers}
|
||||
onRefetch={refetchUsers}
|
||||
onSelectUser={setSelectedUserId}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="channels">
|
||||
<ChannelSummaryList
|
||||
channels={channels}
|
||||
loading={channelsLoading}
|
||||
error={channelsError}
|
||||
search={channelSearch}
|
||||
onSearchChange={setChannelSearch}
|
||||
onLoadMore={loadMoreChannels}
|
||||
hasMore={hasMoreChannels}
|
||||
onRefetch={refetchChannels}
|
||||
onSelectChannel={setSelectedChannelId}
|
||||
/>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user