Improve admin mobile dark mode contrast
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-01-22 22:02:45 +01:00
parent 6318aec3cb
commit 85f2c42fc5
5 changed files with 59 additions and 35 deletions

View File

@@ -46,14 +46,19 @@ function DashboardCard({
}: React.ComponentProps<typeof Card> & { variant?: 'default' | 'embedded' }) {
const theme = useAdminTheme();
const isEmbedded = variant === 'embedded';
const cardSurface = isEmbedded
? (theme.surfaceMuted ?? theme.glassSurface ?? theme.surface)
: (theme.glassSurfaceStrong ?? theme.surface);
const cardBorder = theme.glassBorder ?? theme.border;
const cardShadow = theme.glassShadow ?? theme.shadow;
return (
<Card
backgroundColor={theme.surface}
backgroundColor={cardSurface}
borderRadius={isEmbedded ? 16 : 20}
borderWidth={1}
borderColor={theme.border}
borderColor={cardBorder}
padding="$3.5"
shadowColor={theme.shadow}
shadowColor={cardShadow}
shadowOpacity={isEmbedded ? 0 : 0.16}
shadowRadius={isEmbedded ? 0 : 16}
shadowOffset={isEmbedded ? { width: 0, height: 0 } : { width: 0, height: 10 }}
@@ -444,7 +449,8 @@ function LifecycleHero({
alignItems="center"
justifyContent="space-between"
borderWidth={1}
borderColor={theme.border}
borderColor={theme.glassBorder ?? theme.border}
backgroundColor={theme.surfaceMuted}
borderRadius={12}
paddingHorizontal="$2.5"
paddingVertical="$2"

View File

@@ -18,9 +18,9 @@ export function BottomNav({ active, onNavigate }: { active: NavKey; onNavigate:
const theme = useAdminTheme();
// Modern Glass Background
const navSurface = 'rgba(255, 255, 255, 0.85)';
const navBorder = theme.border;
const navShadow = theme.shadow;
const navSurface = theme.glassSurfaceStrong ?? theme.surfaceMuted ?? theme.surface;
const navBorder = theme.glassBorder ?? theme.border;
const navShadow = theme.glassShadow ?? theme.shadow;
const [pressedKey, setPressedKey] = React.useState<NavKey | null>(null);
@@ -62,7 +62,7 @@ export function BottomNav({ active, onNavigate }: { active: NavKey; onNavigate:
const IconCmp = item.icon;
// Dynamic Styles
const color = activeState ? theme.primary : theme.subtle;
const color = activeState ? theme.primary : theme.muted;
const strokeWidth = activeState ? 2.5 : 2;
return (

View File

@@ -253,9 +253,13 @@ export function MobileSelect({
style,
...props
}: MobileSelectProps) {
const { border, surface, text, primary, danger, subtle } = useAdminTheme();
const borderColor = hasError ? danger : border;
const { border, surface, text, primary, danger, subtle, glassSurfaceStrong, surfaceMuted, glassBorder } = useAdminTheme();
const borderColor = hasError ? danger : (glassBorder ?? border);
const ringColor = hasError ? withAlpha(danger, 0.18) : withAlpha(primary, 0.18);
const triggerSurface = surfaceMuted ?? glassSurfaceStrong ?? surface;
const contentSurface = glassSurfaceStrong ?? surface;
const itemSurface = surface;
const itemHover = surfaceMuted ?? surface;
const hasSizing =
typeof containerStyle === 'object' &&
containerStyle !== null &&
@@ -298,7 +302,7 @@ export function MobileSelect({
borderRadius={12}
borderWidth={1}
borderColor={borderColor as any}
backgroundColor={surface as any}
backgroundColor={triggerSurface as any}
paddingVertical={compact ? 6 : 10}
paddingHorizontal="$3"
disabled={props.disabled}
@@ -320,14 +324,22 @@ export function MobileSelect({
zIndex={200000}
{...({ borderRadius: 14 } as any)}
borderWidth={1}
borderColor={border}
backgroundColor={surface as any}
borderColor={glassBorder ?? border}
backgroundColor={contentSurface as any}
>
<Select.Viewport {...({ padding: "$2" } as any)}>
<Select.Group>
{options.map((option, index) => (
<Select.Item index={index} key={`${option.value}-${index}`} value={option.value} disabled={option.disabled}>
<Select.ItemText>{option.label}</Select.ItemText>
<Select.Item
index={index}
key={`${option.value}-${index}`}
value={option.value}
disabled={option.disabled}
backgroundColor={itemSurface as any}
hoverStyle={{ backgroundColor: itemHover as any }}
pressStyle={{ backgroundColor: itemHover as any }}
>
<Select.ItemText {...({ color: text } as any)}>{option.label}</Select.ItemText>
</Select.Item>
))}
</Select.Group>

View File

@@ -44,27 +44,27 @@ export function PillBadge({
tone?: 'success' | 'warning' | 'danger' | 'muted';
children: React.ReactNode;
}) {
const { theme } = useAdminTheme();
const { successText, warningText, dangerText, muted, surfaceMuted, border } = useAdminTheme();
const palette: Record<typeof tone, { bg: string; text: string; border: string }> = {
success: {
bg: String(theme.backgroundStrong?.val ?? '#ecfdf3'),
text: String(theme.green10?.val ?? '#047857'),
border: String(theme.green6?.val ?? '#bbf7d0'),
bg: withAlpha(successText, 0.16),
text: successText,
border: withAlpha(successText, 0.35),
},
warning: {
bg: String(theme.yellow3?.val ?? '#fffbeb'),
text: String(theme.yellow11?.val ?? '#92400e'),
border: String(theme.yellow6?.val ?? '#fef3c7'),
bg: withAlpha(warningText, 0.16),
text: warningText,
border: withAlpha(warningText, 0.35),
},
danger: {
bg: String(theme.red3?.val ?? '#FEE2E2'),
text: String(theme.red11?.val ?? '#B91C1C'),
border: String(theme.red6?.val ?? '#FCA5A5'),
bg: withAlpha(dangerText, 0.16),
text: dangerText,
border: withAlpha(dangerText, 0.35),
},
muted: {
bg: String(theme.gray3?.val ?? '#f3f4f6'),
text: String(theme.gray11?.val ?? '#374151'),
border: String(theme.gray6?.val ?? '#e5e7eb'),
bg: surfaceMuted,
text: muted,
border,
},
};
const colors = palette[tone] ?? palette.muted;
@@ -210,7 +210,11 @@ export function KpiStrip({
tone?: 'accent' | 'neutral';
}>
}) {
const { glassSurface, border, textStrong, textMuted, primary, surfaceMuted, surface } = useAdminTheme();
const { glassSurface, glassSurfaceStrong, glassBorder, border, textStrong, textMuted, primary, surfaceMuted, surface } = useAdminTheme();
const cardSurface = surfaceMuted ?? glassSurfaceStrong ?? glassSurface ?? surface;
const cardBorder = glassBorder ?? border;
const separatorColor = withAlpha(textStrong, 0.12);
const innerSeparatorColor = withAlpha(textStrong, 0.08);
return (
<XStack flexWrap="wrap" gap="$2">
@@ -222,10 +226,10 @@ export function KpiStrip({
return (
<Card
key={index}
backgroundColor={glassSurface ?? surface}
backgroundColor={cardSurface}
borderRadius={14}
borderWidth={1}
borderColor={border}
borderColor={cardBorder}
padding="$2.5"
flexGrow={1}
flexBasis="48%"
@@ -242,7 +246,7 @@ export function KpiStrip({
>
{item.value}
</Text>
<Separator vertical backgroundColor={border} height={32} opacity={0.6} />
<Separator vertical backgroundColor={separatorColor} height={32} />
<YStack alignItems="center" space="$0.5">
<XStack
width={28}
@@ -264,7 +268,7 @@ export function KpiStrip({
>
{item.label}
</Text>
<Separator backgroundColor={border} opacity={0.4} width={28} alignSelf="center" />
<Separator backgroundColor={innerSeparatorColor} width={28} alignSelf="center" />
{item.note ? (
<Text fontSize={9} fontWeight="800" color={iconColor} opacity={0.9} textTransform="uppercase">
{item.note}

View File

@@ -127,6 +127,8 @@ export function useAdminTheme() {
border,
text,
textStrong: text, // Alias
textMuted: muted, // Alias for legacy usage
textSubtle: subtle, // Alias for legacy usage
muted, // Now properly derived from text color
subtle, // Now properly derived from text color
primary,
@@ -134,12 +136,12 @@ export function useAdminTheme() {
accentSoft: String(theme.blue3?.val ?? ADMIN_COLORS.accentSoft),
accentStrong: String(theme.blue11?.val ?? ADMIN_COLORS.primaryStrong),
successBg: String(theme.backgroundStrong?.val ?? '#DCFCE7'),
successText: String(theme.green10?.val ?? '#166534'),
successText: String(theme.green10?.val ?? ADMIN_COLORS.success),
dangerBg: String(theme.red3?.val ?? '#FEE2E2'),
dangerText: String(theme.red11?.val ?? ADMIN_COLORS.danger),
warningBg: String(theme.yellow3?.val ?? '#FEF3C7'),
warningBorder: String(theme.yellow6?.val ?? '#FCD34D'),
warningText: String(theme.yellow11?.val ?? '#B45309'),
warningText: String(theme.yellow11?.val ?? ADMIN_COLORS.warning),
infoBg: String(theme.blue3?.val ?? ADMIN_COLORS.accentSoft),
infoText: String(theme.blue10?.val ?? ADMIN_COLORS.primaryStrong),
danger: String(theme.danger?.val ?? ADMIN_COLORS.danger),