upd: tampilan dark dan light

This commit is contained in:
2026-04-02 11:59:21 +08:00
parent 5136342877
commit ac17e059c7
6 changed files with 68 additions and 44 deletions

View File

@@ -8,34 +8,34 @@ const theme = createTheme({
primaryColor: 'brand-blue',
colors: {
'brand-blue': [
'#ebf2ff',
'#d6e4ff',
'#adc8ff',
'#85acff',
'#5c90ff',
'#2563eb', // Primary Blue
'#1e4fb8',
'#173b85',
'#102752',
'#09131f',
'#f0f9ff',
'#e0f2fe',
'#bae6fd',
'#7dd3fc',
'#38bdf8',
'#0ea5e9', // Primary Blue (Sky)
'#0284c7',
'#0369a1',
'#075985',
'#0c4a6e',
],
'brand-purple': [
'#f3ebff',
'#e7d6ff',
'#cfadff',
'#b785ff',
'#9f5cff',
'#7c3aed', // Primary Purple
'#632eb8',
'#4a2285',
'#311652',
'#180b1f',
'#faf5ff',
'#f3e8ff',
'#e9d5ff',
'#d8b4fe',
'#c084fc',
'#a855f7', // Primary Purple
'#9333ea',
'#7e22ce',
'#6b21a8',
'#581c87',
],
},
fontFamily: 'Inter, system-ui, Avenir, Helvetica, Arial, sans-serif',
headings: {
fontFamily: 'Inter, system-ui, sans-serif',
fontWeight: '600',
fontWeight: '500', // Softer headings
},
})
@@ -59,8 +59,8 @@ declare module '@tanstack/react-router' {
export function App() {
return (
<>
<ColorSchemeScript defaultColorScheme="dark" />
<MantineProvider theme={theme} defaultColorScheme="dark" forceColorScheme="dark">
<ColorSchemeScript defaultColorScheme="auto" />
<MantineProvider theme={theme} defaultColorScheme="auto">
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>

View File

@@ -1,4 +1,4 @@
import { Card, Group, Text, ThemeIcon, Badge, Avatar, Stack, Button, Progress, Box } from '@mantine/core'
import { Card, Group, Text, ThemeIcon, Badge, Avatar, Stack, Button, Progress, Box, useComputedColorScheme } from '@mantine/core'
import { Link } from '@tanstack/react-router'
import { TbDeviceMobile, TbActivity, TbAlertTriangle, TbChevronRight } from 'react-icons/tb'
@@ -13,6 +13,7 @@ interface AppCardProps {
export function AppCard({ id, name, status, users, errors, version }: AppCardProps) {
const statusColor = status === 'active' ? 'teal' : status === 'warning' ? 'orange' : 'red'
const scheme = useComputedColorScheme('light', { getInitialValueInEffect: true })
return (
<Card
@@ -22,12 +23,12 @@ export function AppCard({ id, name, status, users, errors, version }: AppCardPro
className="premium-card glass"
styles={(theme) => ({
root: {
backgroundColor: 'rgba(30, 41, 59, 0.4)',
borderColor: 'rgba(255,255,255,0.08)',
transition: 'transform 0.2s ease, box-shadow 0.2s ease',
backgroundColor: 'var(--mantine-color-body)',
borderColor: scheme === 'dark' ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.05)',
transition: 'transform 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease, border-color 0.2s ease',
'&:hover': {
transform: 'translateY(-4px)',
boxShadow: '0 12px 24px -8px rgba(0, 0, 0, 0.4)',
boxShadow: theme.shadows.md,
borderColor: 'rgba(37, 99, 235, 0.3)',
},
},

View File

@@ -1,5 +1,6 @@
import { APP_CONFIGS } from '@/frontend/config/appMenus'
import {
ActionIcon,
AppShell,
Avatar,
Box,
@@ -14,6 +15,7 @@ import {
ThemeIcon
} from '@mantine/core'
import { useDisclosure } from '@mantine/hooks'
import { useMantineColorScheme, useComputedColorScheme } from '@mantine/core'
import { Link, useLocation, useMatches, useNavigate, useParams } from '@tanstack/react-router'
import {
TbApps,
@@ -23,7 +25,9 @@ import {
TbDeviceMobile,
TbLogout,
TbSettings,
TbUserCircle
TbUserCircle,
TbSun,
TbMoon
} from 'react-icons/tb'
interface DashboardLayoutProps {
@@ -31,7 +35,10 @@ interface DashboardLayoutProps {
}
export function DashboardLayout({ children }: DashboardLayoutProps) {
const [opened, { toggle }] = useDisclosure()
const [mobileOpened, { toggle: toggleMobile }] = useDisclosure()
const [desktopOpened, { toggle: toggleDesktop }] = useDisclosure(true)
const { toggleColorScheme } = useMantineColorScheme()
const computedColorScheme = useComputedColorScheme('light', { getInitialValueInEffect: true })
const location = useLocation()
const navigate = useNavigate()
const { appId } = useParams({ strict: false }) as { appId?: string }
@@ -54,19 +61,21 @@ export function DashboardLayout({ children }: DashboardLayoutProps) {
navbar={{
width: 260,
breakpoint: 'sm',
collapsed: { mobile: !opened },
collapsed: { mobile: !mobileOpened, desktop: !desktopOpened },
}}
padding="xl"
styles={(theme) => ({
main: {
backgroundColor: theme.colors.dark[7], // Dark mode background
backgroundColor: computedColorScheme === 'dark' ? theme.colors.dark[9] : theme.colors.gray[0],
transition: 'background-color 0.2s ease',
},
})}
>
<AppShell.Header px="xl">
<Group h="100%" justify="space-between">
<Group>
<Burger opened={opened} onClick={toggle} hiddenFrom="sm" size="sm" />
<Burger opened={mobileOpened} onClick={toggleMobile} hiddenFrom="sm" size="sm" />
<Burger opened={desktopOpened} onClick={toggleDesktop} visibleFrom="sm" size="sm" />
<Group gap="xs">
<ThemeIcon
size={34}
@@ -88,6 +97,14 @@ export function DashboardLayout({ children }: DashboardLayoutProps) {
</Group>
<Group gap="md">
<ActionIcon
onClick={() => toggleColorScheme()}
variant="default"
size="lg"
aria-label="Toggle color scheme"
>
{computedColorScheme === 'dark' ? <TbSun size={18} /> : <TbMoon size={18} />}
</ActionIcon>
<Menu shadow="md" width={200} position="bottom-end">
<Menu.Target>
<Avatar

View File

@@ -22,8 +22,8 @@ export function StatsCard({ title, value, description, icon: Icon, color, trend
className="premium-card"
styles={(theme) => ({
root: {
backgroundColor: theme.colors.dark[6],
borderColor: 'rgba(255,255,255,0.05)',
backgroundColor: 'var(--mantine-color-body)',
borderColor: 'rgba(128,128,128,0.1)',
},
})}
>

View File

@@ -1,4 +1,4 @@
import { Card, Group, Text, ThemeIcon, Stack, Progress, Badge } from '@mantine/core'
import { Card, Group, Text, ThemeIcon, Stack, Progress, Badge, useComputedColorScheme } from '@mantine/core'
import { IconType } from 'react-icons'
import { TbTrendingUp, TbTrendingDown } from 'react-icons/tb'
@@ -27,6 +27,8 @@ export function SummaryCard({
progress,
isError
}: SummaryCardProps) {
const scheme = useComputedColorScheme('light', { getInitialValueInEffect: true })
return (
<Card
withBorder
@@ -35,9 +37,13 @@ export function SummaryCard({
className="glass"
styles={(theme) => ({
root: {
backgroundColor: isError && Number(value) > 0 ? 'rgba(239, 68, 68, 0.05)' : 'rgba(30, 41, 59, 0.4)',
borderColor: isError && Number(value) > 10 ? 'rgba(239, 68, 68, 0.3)' : 'rgba(255, 255, 255, 0.08)',
transition: 'transform 0.2s ease',
backgroundColor: isError && Number(value) > 0
? (scheme === 'dark' ? 'rgba(239, 68, 68, 0.1)' : 'rgba(255, 241, 242, 1)') // light pink for error in light mode
: 'var(--mantine-color-body)',
borderColor: isError && Number(value) > 10
? 'rgba(239, 68, 68, 0.3)'
: scheme === 'dark' ? 'rgba(255, 255, 255, 0.08)' : 'rgba(0, 0, 0, 0.05)',
transition: 'transform 0.2s ease, background-color 0.2s ease, border-color 0.2s ease',
'&:hover': {
transform: 'translateY(-4px)',
}

View File

@@ -27,8 +27,8 @@ html, body {
height: 100%;
width: 100%;
font-family: var(--font-inter);
background-color: var(--bg-dark); /* Default to Dark Mode as per App.tsx */
color: #F8FAFC;
/* background-color handled by Mantine */
color: var(--mantine-color-text);
}
body {
@@ -53,9 +53,9 @@ body {
/* Premium Dashboard Utilities */
.glass {
background: rgba(30, 41, 59, 0.7);
background: var(--mantine-color-default);
backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.1);
border: 1px solid rgba(128, 128, 128, 0.1);
border-radius: 24px; /* XL rounding for cards */
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}