feat(frontend): visual design overhaul — Inter font, softer cards/shadows, red-themed profile banner, modern typography hierarchy, and refreshed color palette

This commit is contained in:
Matthias Hochmeister
2026-04-13 11:07:28 +02:00
parent 43ce1f930c
commit f4690cf185
7 changed files with 186 additions and 86 deletions

View File

@@ -23,28 +23,34 @@ const UserProfile: React.FC<UserProfileProps> = ({ user }) => {
<Paper
elevation={0}
sx={{
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
background: 'linear-gradient(135deg, #d32f2f 0%, #9a0007 100%)',
color: 'white',
borderRadius: 2,
px: 3,
py: 1.5,
borderRadius: 3,
px: 3.5,
py: 2,
}}
>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
<Avatar
sx={{
width: 40,
height: 40,
width: 44,
height: 44,
bgcolor: 'rgba(255,255,255,0.2)',
fontSize: '1rem',
fontWeight: 'bold',
border: '2px solid rgba(255,255,255,0.3)',
}}
>
{initials.toUpperCase()}
</Avatar>
<Typography variant="h6" sx={{ fontWeight: 500 }}>
{getGreeting()}, {firstName}!
</Typography>
<Box>
<Typography variant="h6" sx={{ fontWeight: 600, lineHeight: 1.3 }}>
{getGreeting()}, {firstName}!
</Typography>
<Typography variant="body2" sx={{ opacity: 0.8, fontSize: '0.75rem' }}>
{new Date().toLocaleDateString('de-DE', { weekday: 'long', day: 'numeric', month: 'long' })}
</Typography>
</Box>
</Box>
</Paper>
);

View File

@@ -17,24 +17,28 @@ function WidgetGroup({ title, children, gridColumn }: WidgetGroupProps) {
<Box
sx={{
position: 'relative',
border: '1px solid',
borderColor: 'divider',
borderRadius: 1,
p: 2,
pt: 3,
borderRadius: 2,
p: 2.5,
pt: 3.5,
gridColumn,
bgcolor: 'rgba(0, 0, 0, 0.02)',
border: '1px solid rgba(0, 0, 0, 0.04)',
}}
>
<Typography
sx={{
position: 'absolute',
top: -10,
left: 16,
px: 1,
top: -9,
left: 20,
px: 1.5,
py: 0.25,
backgroundColor: 'background.default',
fontSize: '0.75rem',
fontSize: '0.6875rem',
color: 'text.secondary',
fontWeight: 500,
fontWeight: 600,
letterSpacing: '0.06em',
textTransform: 'uppercase',
borderRadius: 1,
}}
>
{title}

View File

@@ -129,8 +129,8 @@ export function DataTable<T>({
return (
<Paper>
{showToolbar && (
<Box sx={{ p: 2, display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 2 }}>
{title && <Typography variant="h6">{title}</Typography>}
<Box sx={{ px: 2.5, py: 2, display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 2 }}>
{title && <Typography variant="h6" fontWeight={700}>{title}</Typography>}
<Box sx={{ flex: 1 }} />
{searchEnabled && (
<TextField
@@ -138,11 +138,11 @@ export function DataTable<T>({
placeholder={searchPlaceholder}
value={search}
onChange={(e) => { setSearch(e.target.value); setPage(0); }}
sx={{ maxWidth: 300 }}
sx={{ maxWidth: 280, '& .MuiOutlinedInput-root': { bgcolor: 'rgba(0,0,0,0.02)' } }}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<SearchIcon fontSize="small" />
<SearchIcon fontSize="small" sx={{ color: 'text.disabled' }} />
</InputAdornment>
),
}}

View File

@@ -30,29 +30,32 @@ export const StatCard: React.FC<StatCardProps> = ({
) : (
<Box display="flex" alignItems="center">
<Box sx={{ flex: GOLDEN_RATIO }}>
<Typography variant="caption" textTransform="uppercase" color="text.secondary">
<Typography variant="caption" textTransform="uppercase" color="text.secondary" sx={{ letterSpacing: '0.06em', fontWeight: 600 }}>
{title}
</Typography>
<Typography variant="h4" fontWeight={700}>
<Typography variant="h3" fontWeight={800} sx={{ lineHeight: 1.1, mt: 0.5, letterSpacing: '-0.02em' }}>
{value}
</Typography>
{trend && (
<Typography
variant="caption"
color={trend.value >= 0 ? 'success.main' : 'error.main'}
>
{trend.value >= 0 ? '↑' : '↓'} {Math.abs(trend.value)}%
{trend.label && ` ${trend.label}`}
</Typography>
<Box sx={{ display: 'inline-flex', alignItems: 'center', mt: 1, px: 1, py: 0.25, borderRadius: 1, bgcolor: trend.value >= 0 ? 'rgba(34,197,94,0.1)' : 'rgba(239,68,68,0.1)' }}>
<Typography
variant="caption"
fontWeight={600}
color={trend.value >= 0 ? 'success.main' : 'error.main'}
>
{trend.value >= 0 ? '↑' : '↓'} {Math.abs(trend.value)}%
{trend.label && ` ${trend.label}`}
</Typography>
</Box>
)}
</Box>
<Box sx={{ flex: 1, display: 'flex', justifyContent: 'center' }}>
<Box
sx={{
width: 56,
height: 56,
borderRadius: '50%',
bgcolor: `${color}15`,
width: 52,
height: 52,
borderRadius: 3,
bgcolor: `${color}12`,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',

View File

@@ -4,7 +4,6 @@ import {
Card,
CardActionArea,
CardContent,
Divider,
Skeleton,
Typography,
Alert,
@@ -52,16 +51,24 @@ export const WidgetCard: React.FC<WidgetCardProps> = ({
<Box
sx={noPadding ? { px: 2.5, pt: 2.5 } : undefined}
>
<Box display="flex" alignItems="center" justifyContent="space-between" mb={2}>
<Box display="flex" alignItems="center" gap={1}>
{icon}
<Typography variant="subtitle1" fontWeight={600}>
<Box
display="flex"
alignItems="center"
justifyContent="space-between"
mb={1.5}
>
<Box display="flex" alignItems="center" gap={0.75}>
{icon && (
<Box sx={{ color: 'text.secondary', display: 'flex', alignItems: 'center', '& > *': { fontSize: '1.1rem' } }}>
{icon}
</Box>
)}
<Typography variant="subtitle2" fontWeight={600} color="text.secondary" sx={{ textTransform: 'uppercase', fontSize: '0.6875rem', letterSpacing: '0.06em' }}>
{title}
</Typography>
</Box>
{action}
</Box>
<Divider sx={{ mb: 2 }} />
</Box>
);
@@ -113,8 +120,7 @@ export const WidgetCard: React.FC<WidgetCardProps> = ({
</Box>
{footer && (
<>
<Divider sx={{ mt: 2 }} />
<Box sx={{ pt: 1.5, ...(noPadding ? { px: 2.5, pb: 2.5 } : {}) }}>
<Box sx={{ mt: 2, pt: 1.5, borderTop: '1px solid', borderColor: 'divider', ...(noPadding ? { mx: 2.5, pb: 2.5 } : {}) }}>
{footer}
</Box>
</>