Refine admin PWA layout and tamagui usage

This commit is contained in:
Codex Agent
2026-01-15 22:24:10 +01:00
parent 8941860140
commit c533d43c0f
37 changed files with 51503 additions and 21989 deletions

View File

@@ -2,27 +2,32 @@ import React from 'react';
import { YStack, XStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text';
import { Pressable } from '@tamagui/react-native-web-lite';
import { useAdminTheme } from '../theme';
import { ADMIN_GRADIENTS, useAdminTheme } from '../theme';
import { withAlpha } from './colors';
export function MobileCard({
children,
className,
style,
...rest
}: React.ComponentProps<typeof YStack>) {
const { surface, border, shadow } = useAdminTheme();
const { surface, border, shadow, glassSurface, glassBorder, glassShadow } = useAdminTheme();
return (
<YStack
className={['admin-fade-up', className].filter(Boolean).join(' ')}
backgroundColor={surface}
borderRadius={18}
borderWidth={1}
borderColor={border}
shadowColor={shadow}
shadowOpacity={0.08}
shadowRadius={14}
backgroundColor={glassSurface ?? surface}
borderRadius={20}
borderWidth={2}
borderColor={glassBorder ?? border}
shadowColor={glassShadow ?? shadow}
shadowOpacity={0.16}
shadowRadius={16}
shadowOffset={{ width: 0, height: 10 }}
padding="$3.5"
space="$2"
style={{
...style,
}}
{...rest}
>
{children}
@@ -99,13 +104,18 @@ export function CTAButton({
iconLeft?: React.ReactNode;
iconRight?: React.ReactNode;
}) {
const { primary, surface, border, text, danger } = useAdminTheme();
const { primary, surface, border, text, danger, glassSurfaceStrong } = useAdminTheme();
const isPrimary = tone === 'primary';
const isDanger = tone === 'danger';
const isDisabled = disabled || loading;
const backgroundColor = isDanger ? danger : isPrimary ? primary : surface;
const backgroundColor = isDanger ? danger : isPrimary ? primary : glassSurfaceStrong ?? surface;
const borderColor = isPrimary || isDanger ? 'transparent' : border;
const labelColor = isPrimary || isDanger ? 'white' : text;
const primaryStyle = isPrimary
? {
boxShadow: `0 18px 28px ${withAlpha(primary, 0.4)}`,
}
: undefined;
return (
<Pressable
onPress={isDisabled ? undefined : onPress}
@@ -119,13 +129,14 @@ export function CTAButton({
>
<XStack
height={52}
borderRadius={16}
borderRadius={18}
alignItems="center"
justifyContent="center"
backgroundColor={backgroundColor}
borderWidth={isPrimary || isDanger ? 0 : 1}
borderWidth={isPrimary || isDanger ? 0 : 2}
borderColor={borderColor}
space="$2"
style={primaryStyle}
>
{iconLeft}
<Text fontSize="$sm" fontWeight="800" color={labelColor}>
@@ -183,6 +194,7 @@ export function ActionTile({
color,
onPress,
disabled = false,
variant = 'grid',
delayMs = 0,
}: {
icon: React.ComponentType<{ size?: number; color?: string }>;
@@ -190,49 +202,56 @@ export function ActionTile({
color: string;
onPress?: () => void;
disabled?: boolean;
variant?: 'grid' | 'cluster';
delayMs?: number;
}) {
const { textStrong } = useAdminTheme();
const backgroundColor = `${color}18`;
const borderColor = `${color}40`;
const shadowColor = `${color}2b`;
const iconShadow = `${color}55`;
const { textStrong, glassSurface } = useAdminTheme();
const isCluster = variant === 'cluster';
const backgroundColor = withAlpha(color, 0.12);
const borderColor = withAlpha(color, 0.4);
const shadowColor = withAlpha(color, 0.35);
const iconShadow = withAlpha(color, 0.5);
const tileStyle = {
...(delayMs ? { animationDelay: `${delayMs}ms` } : {}),
backgroundImage: `linear-gradient(135deg, ${backgroundColor}, ${color}0f)`,
boxShadow: `0 10px 24px ${shadowColor}`,
backgroundImage: `linear-gradient(135deg, ${backgroundColor}, ${withAlpha(color, 0.08)})`,
boxShadow: isCluster ? `0 12px 18px ${shadowColor}` : `0 20px 30px ${shadowColor}`,
};
return (
<Pressable
onPress={disabled ? undefined : onPress}
style={{ width: '48%', marginBottom: 12, opacity: disabled ? 0.5 : 1 }}
style={{
width: isCluster ? '100%' : '48%',
flex: isCluster ? 1 : undefined,
marginBottom: isCluster ? 0 : 12,
opacity: disabled ? 0.5 : 1,
}}
disabled={disabled}
>
<YStack
className="admin-fade-up"
style={tileStyle}
borderRadius={16}
borderRadius={isCluster ? 14 : 16}
padding="$3"
space="$2.5"
backgroundColor={backgroundColor}
borderWidth={1}
backgroundColor={glassSurface ?? backgroundColor}
borderWidth={2}
borderColor={borderColor}
minHeight={110}
minHeight={120}
alignItems="center"
justifyContent="center"
>
<XStack
width={36}
height={36}
borderRadius={12}
width={44}
height={44}
borderRadius={14}
backgroundColor={color}
alignItems="center"
justifyContent="center"
style={{ boxShadow: `0 6px 14px ${iconShadow}` }}
>
<IconCmp size={16} color="white" />
<IconCmp size={18} color="white" />
</XStack>
<Text fontSize="$sm" fontWeight="700" color={textStrong} textAlign="center">
<Text fontSize="$sm" fontWeight="800" color={textStrong} textAlign="center">
{label}
</Text>
</YStack>