Commit 0c806db9 by CaIon

refactor(theme): update color classes

parent 490395b2
...@@ -102,17 +102,9 @@ export function ConsumptionDistributionChart( ...@@ -102,17 +102,9 @@ export function ConsumptionDistributionChart(
props.loading ? [] : props.data, props.loading ? [] : props.data,
timeGranularity, timeGranularity,
t, t,
customization.preset,
chartRadius chartRadius
), ),
[ [props.data, props.loading, timeGranularity, t, chartRadius]
props.data,
props.loading,
timeGranularity,
t,
customization.preset,
chartRadius,
]
) )
const spec = chartType === 'bar' ? chartData.spec_line : chartData.spec_area const spec = chartType === 'bar' ? chartData.spec_line : chartData.spec_area
const specType = typeof spec?.type === 'string' ? spec.type : chartType const specType = typeof spec?.type === 'string' ? spec.type : chartType
......
...@@ -100,17 +100,9 @@ export function ModelCharts(props: ModelChartsProps) { ...@@ -100,17 +100,9 @@ export function ModelCharts(props: ModelChartsProps) {
props.loading ? [] : props.data, props.loading ? [] : props.data,
timeGranularity, timeGranularity,
t, t,
customization.preset,
chartRadius chartRadius
), ),
[ [props.data, props.loading, timeGranularity, t, chartRadius]
props.data,
props.loading,
timeGranularity,
t,
customization.preset,
chartRadius,
]
) )
const spec = chartData[CHART_SPEC_KEYS[activeTab]] const spec = chartData[CHART_SPEC_KEYS[activeTab]]
......
...@@ -30,10 +30,10 @@ import type { ...@@ -30,10 +30,10 @@ import type {
import { PanelWrapper } from '../ui/panel-wrapper' import { PanelWrapper } from '../ui/panel-wrapper'
const STATUS_COLOR_MAP: Record<number, string> = { const STATUS_COLOR_MAP: Record<number, string> = {
1: 'bg-success', 1: 'bg-emerald-500',
0: 'bg-destructive', 0: 'bg-red-500',
2: 'bg-warning', 2: 'bg-amber-500',
3: 'bg-info', 3: 'bg-blue-500',
} }
const DEFAULT_STATUS_COLOR = 'bg-muted-foreground/40' const DEFAULT_STATUS_COLOR = 'bg-muted-foreground/40'
......
...@@ -23,7 +23,6 @@ import { Users, Loader2 } from 'lucide-react' ...@@ -23,7 +23,6 @@ import { Users, Loader2 } from 'lucide-react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { getRollingDateRange, type TimeGranularity } from '@/lib/time' import { getRollingDateRange, type TimeGranularity } from '@/lib/time'
import { VCHART_OPTION } from '@/lib/vchart' import { VCHART_OPTION } from '@/lib/vchart'
import { useThemeCustomization } from '@/context/theme-customization-provider'
import { useTheme } from '@/context/theme-provider' import { useTheme } from '@/context/theme-provider'
import { Skeleton } from '@/components/ui/skeleton' import { Skeleton } from '@/components/ui/skeleton'
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs' import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'
...@@ -66,7 +65,6 @@ const TOP_USER_LIMIT_OPTIONS = [5, 10, 20, 50] ...@@ -66,7 +65,6 @@ const TOP_USER_LIMIT_OPTIONS = [5, 10, 20, 50]
export function UserCharts() { export function UserCharts() {
const { t } = useTranslation() const { t } = useTranslation()
const { resolvedTheme } = useTheme() const { resolvedTheme } = useTheme()
const { customization } = useThemeCustomization()
const [themeReady, setThemeReady] = useState(false) const [themeReady, setThemeReady] = useState(false)
const themeManagerRef = useRef< const themeManagerRef = useRef<
(typeof import('@visactor/vchart'))['ThemeManager'] | null (typeof import('@visactor/vchart'))['ThemeManager'] | null
...@@ -138,18 +136,9 @@ export function UserCharts() { ...@@ -138,18 +136,9 @@ export function UserCharts() {
isLoading ? [] : (userData ?? []), isLoading ? [] : (userData ?? []),
timeGranularity, timeGranularity,
t, t,
topUserLimit, topUserLimit
customization.preset
), ),
[ [userData, isLoading, timeGranularity, t, topUserLimit]
userData,
isLoading,
timeGranularity,
t,
topUserLimit,
customization.preset,
customization.radius,
]
) )
return ( return (
...@@ -240,7 +229,7 @@ export function UserCharts() { ...@@ -240,7 +229,7 @@ export function UserCharts() {
themeReady && themeReady &&
spec && ( spec && (
<VChart <VChart
key={`user-${chart.value}-${topUserLimit}-${resolvedTheme}-${customization.preset}`} key={`user-${chart.value}-${topUserLimit}-${resolvedTheme}`}
spec={{ spec={{
...spec, ...spec,
theme: resolvedTheme === 'dark' ? 'dark' : 'light', theme: resolvedTheme === 'dark' ? 'dark' : 'light',
......
...@@ -23,12 +23,12 @@ import type { PingStatus } from '@/features/dashboard/types' ...@@ -23,12 +23,12 @@ import type { PingStatus } from '@/features/dashboard/types'
*/ */
export function getLatencyColorClass(latency: number): string { export function getLatencyColorClass(latency: number): string {
if (latency < 200) { if (latency < 200) {
return 'text-success' return 'text-green-600 dark:text-green-400'
} }
if (latency < 500) { if (latency < 500) {
return 'text-warning' return 'text-yellow-600 dark:text-yellow-400'
} }
return 'text-destructive' return 'text-red-600 dark:text-red-400'
} }
/** /**
......
...@@ -38,37 +38,7 @@ type TooltipLineItem = { ...@@ -38,37 +38,7 @@ type TooltipLineItem = {
shapeSize?: number shapeSize?: number
} }
const THEME_CHART_COLOR_VARIABLES = [ function getVChartDefaultColors(domainLength: number) {
'--chart-1',
'--chart-2',
'--chart-3',
'--chart-4',
'--chart-5',
] as const
function getThemeChartColors(themeKey?: string): string[] {
if (typeof document === 'undefined') return []
void themeKey
const bodyStyle = window.getComputedStyle(document.body)
const rootStyle = window.getComputedStyle(document.documentElement)
return THEME_CHART_COLOR_VARIABLES.map((name) => {
return (
bodyStyle.getPropertyValue(name) || rootStyle.getPropertyValue(name)
).trim()
}).filter(Boolean)
}
function getVChartDefaultColors(domainLength: number, themeKey?: string) {
const themeColors = getThemeChartColors(themeKey)
if (themeColors.length > 0) {
return Array.from(
{ length: Math.max(domainLength, themeColors.length) },
(_, index) => themeColors[index % themeColors.length]
)
}
const scheme = const scheme =
vchartDefaultDataScheme.find( vchartDefaultDataScheme.find(
(item) => !item.maxDomainLength || domainLength <= item.maxDomainLength (item) => !item.maxDomainLength || domainLength <= item.maxDomainLength
...@@ -98,7 +68,6 @@ export function processChartData( ...@@ -98,7 +68,6 @@ export function processChartData(
data: QuotaDataItem[], data: QuotaDataItem[],
timeGranularity: TimeGranularity = 'day', timeGranularity: TimeGranularity = 'day',
t?: TFunction, t?: TFunction,
themeKey?: string,
chartCornerRadius?: number chartCornerRadius?: number
): ProcessedChartData { ): ProcessedChartData {
const tt: TFunction = t ?? ((x) => x) const tt: TFunction = t ?? ((x) => x)
...@@ -290,10 +259,7 @@ export function processChartData( ...@@ -290,10 +259,7 @@ export function processChartData(
const sortedTimes = Array.from(timeModelMap.keys()).sort() const sortedTimes = Array.from(timeModelMap.keys()).sort()
const sortedModels = [...allModels].sort() const sortedModels = [...allModels].sort()
const modelColorDomain = Array.from(new Set([...sortedModels, otherLabel])) const modelColorDomain = Array.from(new Set([...sortedModels, otherLabel]))
const modelColorRange = getVChartDefaultColors( const modelColorRange = getVChartDefaultColors(modelColorDomain.length)
modelColorDomain.length,
themeKey
)
const otherColor = modelColorRange[modelColorDomain.indexOf(otherLabel)] const otherColor = modelColorRange[modelColorDomain.indexOf(otherLabel)]
const otherTooltipColor = const otherTooltipColor =
typeof otherColor === 'string' ? otherColor : '#FF8A00' typeof otherColor === 'string' ? otherColor : '#FF8A00'
...@@ -719,7 +685,7 @@ export function processChartData( ...@@ -719,7 +685,7 @@ export function processChartData(
} }
} }
const USER_COLOR_FALLBACKS = [ const USER_COLORS = [
'#5B8FF9', '#5B8FF9',
'#5AD8A6', '#5AD8A6',
'#F6BD16', '#F6BD16',
...@@ -736,20 +702,11 @@ export function processUserChartData( ...@@ -736,20 +702,11 @@ export function processUserChartData(
data: QuotaDataItem[], data: QuotaDataItem[],
timeGranularity: TimeGranularity = 'day', timeGranularity: TimeGranularity = 'day',
t?: TFunction, t?: TFunction,
limit = 10, limit = 10
themeKey?: string
): ProcessedUserChartData { ): ProcessedUserChartData {
const tt: TFunction = t ?? ((x) => x) const tt: TFunction = t ?? ((x) => x)
const { config } = getCurrencyDisplay() const { config } = getCurrencyDisplay()
const quotaPerUnit = config.quotaPerUnit const quotaPerUnit = config.quotaPerUnit
const themeUserColors = getThemeChartColors(themeKey)
const userColorRange =
themeUserColors.length > 0
? Array.from(
{ length: Math.max(limit, themeUserColors.length) },
(_, index) => themeUserColors[index % themeUserColors.length]
)
: USER_COLOR_FALLBACKS
const formatVal = (raw: number) => renderQuotaCompat(raw, 2) const formatVal = (raw: number) => renderQuotaCompat(raw, 2)
...@@ -767,7 +724,7 @@ export function processUserChartData( ...@@ -767,7 +724,7 @@ export function processUserChartData(
subtext: tt('No data available'), subtext: tt('No data available'),
}, },
legends: { visible: false }, legends: { visible: false },
color: { type: 'ordinal', range: userColorRange }, color: { type: 'ordinal', range: USER_COLORS },
background: { fill: 'transparent' }, background: { fill: 'transparent' },
}, },
spec_user_trend: { spec_user_trend: {
...@@ -782,7 +739,7 @@ export function processUserChartData( ...@@ -782,7 +739,7 @@ export function processUserChartData(
subtext: tt('No data available'), subtext: tt('No data available'),
}, },
legends: { visible: true, selectMode: 'single' }, legends: { visible: true, selectMode: 'single' },
color: { type: 'ordinal', range: userColorRange }, color: { type: 'ordinal', range: USER_COLORS },
point: { visible: false }, point: { visible: false },
background: { fill: 'transparent' }, background: { fill: 'transparent' },
}, },
...@@ -812,7 +769,7 @@ export function processUserChartData( ...@@ -812,7 +769,7 @@ export function processUserChartData(
const userColorMap = topUsers.reduce<Record<string, string>>( const userColorMap = topUsers.reduce<Record<string, string>>(
(acc, user, i) => { (acc, user, i) => {
acc[user] = userColorRange[i % userColorRange.length] acc[user] = USER_COLORS[i % USER_COLORS.length]
return acc return acc
}, },
{} {}
......
...@@ -61,18 +61,18 @@ export function getSuccessRateLevel(rate: number): SuccessRateLevel { ...@@ -61,18 +61,18 @@ export function getSuccessRateLevel(rate: number): SuccessRateLevel {
} }
const SUCCESS_RATE_TEXT_CLASS: Record<SuccessRateLevel, string> = { const SUCCESS_RATE_TEXT_CLASS: Record<SuccessRateLevel, string> = {
excellent: 'text-success', excellent: 'text-emerald-600 dark:text-emerald-400',
good: 'text-success/70', good: 'text-emerald-500 dark:text-emerald-300',
warning: 'text-warning', warning: 'text-amber-600 dark:text-amber-400',
critical: 'text-destructive', critical: 'text-red-600 dark:text-red-400',
unknown: 'text-muted-foreground', unknown: 'text-muted-foreground',
} }
const SUCCESS_RATE_DOT_CLASS: Record<SuccessRateLevel, string> = { const SUCCESS_RATE_DOT_CLASS: Record<SuccessRateLevel, string> = {
excellent: 'bg-success', excellent: 'bg-emerald-500',
good: 'bg-success/60', good: 'bg-emerald-400',
warning: 'bg-warning', warning: 'bg-amber-500',
critical: 'bg-destructive', critical: 'bg-red-500',
unknown: 'bg-muted-foreground', unknown: 'bg-muted-foreground',
} }
......
...@@ -137,11 +137,11 @@ export function createDurationColumn<T>(config: { ...@@ -137,11 +137,11 @@ export function createDurationColumn<T>(config: {
const durationBgMap: Record<string, string> = { const durationBgMap: Record<string, string> = {
success: success:
'border border-emerald-200/40 bg-emerald-50/35 dark:border-emerald-900/40 dark:bg-emerald-950/15', 'border border-emerald-200/40 bg-emerald-50/35 !text-emerald-600 dark:border-emerald-900/40 dark:bg-emerald-950/15 dark:!text-emerald-400',
warning: warning:
'border border-amber-200/45 bg-amber-50/35 dark:border-amber-900/40 dark:bg-amber-950/15', 'border border-amber-200/45 bg-amber-50/35 !text-amber-600 dark:border-amber-900/40 dark:bg-amber-950/15 dark:!text-amber-400',
danger: danger:
'border border-rose-200/50 bg-rose-50/35 dark:border-rose-900/40 dark:bg-rose-950/15', 'border border-rose-200/50 bg-rose-50/35 !text-red-600 dark:border-rose-900/40 dark:bg-rose-950/15 dark:!text-red-400',
} }
return ( return (
......
...@@ -560,11 +560,11 @@ export function useCommonLogsColumns(isAdmin: boolean): ColumnDef<UsageLog>[] { ...@@ -560,11 +560,11 @@ export function useCommonLogsColumns(isAdmin: boolean): ColumnDef<UsageLog>[] {
const timingBgMap: Record<string, string> = { const timingBgMap: Record<string, string> = {
success: success:
'border border-emerald-200/40 bg-emerald-50/35 dark:border-emerald-900/40 dark:bg-emerald-950/15', 'border border-emerald-200/40 bg-emerald-50/35 !text-emerald-600 dark:border-emerald-900/40 dark:bg-emerald-950/15 dark:!text-emerald-400',
warning: warning:
'border border-amber-200/45 bg-amber-50/35 dark:border-amber-900/40 dark:bg-amber-950/15', 'border border-amber-200/45 bg-amber-50/35 !text-amber-600 dark:border-amber-900/40 dark:bg-amber-950/15 dark:!text-amber-400',
danger: danger:
'border border-rose-200/50 bg-rose-50/35 dark:border-rose-900/40 dark:bg-rose-950/15', 'border border-rose-200/50 bg-rose-50/35 !text-red-600 dark:border-rose-900/40 dark:bg-rose-950/15 dark:!text-red-400',
neutral: neutral:
'border border-border/60 bg-muted/30 dark:border-border/40 dark:bg-muted/20', 'border border-border/60 bg-muted/30 dark:border-border/40 dark:bg-muted/20',
} }
......
...@@ -147,9 +147,10 @@ export function useDrawingLogsColumns( ...@@ -147,9 +147,10 @@ export function useDrawingLogsColumns(
<div className='flex max-w-[160px] flex-col gap-0.5'> <div className='flex max-w-[160px] flex-col gap-0.5'>
<StatusBadge <StatusBadge
label={mjId} label={mjId}
autoColor={mjId} copyText={mjId}
variant='neutral'
size='sm' size='sm'
className='border-border/60 bg-muted/30 max-w-full truncate rounded-md border px-1.5 py-0.5 font-mono' className='border-border/60 bg-muted/30 !text-foreground max-w-full truncate rounded-md border px-1.5 py-0.5 font-mono'
/> />
</div> </div>
) )
......
...@@ -174,9 +174,10 @@ export function useTaskLogsColumns(isAdmin: boolean): ColumnDef<TaskLog>[] { ...@@ -174,9 +174,10 @@ export function useTaskLogsColumns(isAdmin: boolean): ColumnDef<TaskLog>[] {
<div className='flex max-w-[170px] flex-col gap-0.5'> <div className='flex max-w-[170px] flex-col gap-0.5'>
<StatusBadge <StatusBadge
label={taskId} label={taskId}
autoColor={taskId} copyText={taskId}
variant='neutral'
size='sm' size='sm'
className='border-border/60 bg-muted/30 max-w-full truncate rounded-md border px-1.5 py-0.5 font-mono' className='border-border/60 bg-muted/30 !text-foreground max-w-full truncate rounded-md border px-1.5 py-0.5 font-mono'
/> />
<span className='text-muted-foreground/60 truncate text-[11px]'> <span className='text-muted-foreground/60 truncate text-[11px]'>
{t(log.platform)} · {t(taskActionMapper.getLabel(log.action))} {t(log.platform)} · {t(taskActionMapper.getLabel(log.action))}
......
...@@ -145,20 +145,20 @@ For commercial licensing, please contact support@quantumnous.com ...@@ -145,20 +145,20 @@ For commercial licensing, please contact support@quantumnous.com
} }
.dark { .dark {
/* OpenAI-like dark mode: nearly black chrome, readable raised surfaces. */ /* OpenAI-like dark mode with a softer charcoal canvas. */
--background: oklch(0.185 0 0); --background: oklch(0.225 0 0);
--foreground: oklch(0.965 0 0); --foreground: oklch(0.965 0 0);
--card: oklch(0.235 0 0); --card: oklch(0.275 0 0);
--card-foreground: oklch(0.965 0 0); --card-foreground: oklch(0.965 0 0);
--popover: oklch(0.255 0 0); --popover: oklch(0.295 0 0);
--popover-foreground: oklch(0.965 0 0); --popover-foreground: oklch(0.965 0 0);
--primary: oklch(0.965 0 0); --primary: oklch(0.965 0 0);
--primary-foreground: oklch(0.145 0 0); --primary-foreground: oklch(0.145 0 0);
--secondary: oklch(0.285 0 0); --secondary: oklch(0.325 0 0);
--secondary-foreground: oklch(0.965 0 0); --secondary-foreground: oklch(0.965 0 0);
--muted: oklch(0.255 0 0); --muted: oklch(0.295 0 0);
--muted-foreground: oklch(0.76 0 0); --muted-foreground: oklch(0.76 0 0);
--accent: oklch(0.325 0 0); --accent: oklch(0.365 0 0);
--accent-foreground: oklch(0.985 0 0); --accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216); --destructive: oklch(0.704 0.191 22.216);
--destructive-foreground: oklch(0.985 0 0); --destructive-foreground: oklch(0.985 0 0);
...@@ -178,14 +178,14 @@ For commercial licensing, please contact support@quantumnous.com ...@@ -178,14 +178,14 @@ For commercial licensing, please contact support@quantumnous.com
--chart-3: oklch(0.769 0.188 70.08); --chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9); --chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439); --chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.115 0 0); --sidebar: oklch(0.195 0 0);
--sidebar-foreground: oklch(0.95 0 0); --sidebar-foreground: oklch(0.95 0 0);
--sidebar-primary: oklch(0.965 0 0); --sidebar-primary: oklch(0.965 0 0);
--sidebar-primary-foreground: oklch(0.145 0 0); --sidebar-primary-foreground: oklch(0.145 0 0);
--sidebar-accent: oklch(0.31 0 0); --sidebar-accent: oklch(0.35 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0); --sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%); --sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.68 0 0); --sidebar-ring: oklch(0.68 0 0);
--skeleton-base: oklch(0.285 0 0); --skeleton-base: oklch(0.325 0 0);
--skeleton-highlight: oklch(0.39 0 0); --skeleton-highlight: oklch(0.43 0 0);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment