feat: Fredy UI redesign

* New design :)
This commit is contained in:
Christian Kellner
2026-04-22 21:11:18 +02:00
committed by GitHub
parent c78472bd19
commit f30ec4645c
43 changed files with 4004 additions and 794 deletions

View File

@@ -18,6 +18,7 @@
display: grid;
place-items: center;
height: 14rem;
opacity: .7;
color: #94a3b8;
font-size: 0.9rem;
}
}

View File

@@ -1,45 +1,34 @@
@import './DashboardCardColors.less';
@keyframes card-glow-rotate {
0% { box-shadow: 3px 3px 14px -4px var(--card-glow); }
25% { box-shadow: -3px 3px 14px -4px var(--card-glow); }
50% { box-shadow: -3px -3px 14px -4px var(--card-glow); }
75% { box-shadow: 3px -3px 14px -4px var(--card-glow); }
100% { box-shadow: 3px 3px 14px -4px var(--card-glow); }
}
.dashboard-card {
width: 100%;
height: 140px;
margin-bottom: 16px;
transition: transform 0.2s, box-shadow 0.2s;
background-color: #181b26;
border: 1px solid #232735;
border-radius: 10px;
--pulse-color: rgba(255, 255, 255, 0.08);
height: 112px;
border-radius: @radius-card !important;
border: 1px solid @color-border !important;
background-color: @color-surface !important;
transition: box-shadow @transition-card;
position: relative;
z-index: 1;
overflow: visible;
&::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: inherit;
box-shadow: 0 4px 25px -2px var(--pulse-color);
opacity: 0;
animation: pulse 5s infinite ease-in-out;
pointer-events: none;
z-index: -1;
will-change: opacity;
}
&__icon {
font-size: 20px;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
color: var(--card-accent, #94a3b8);
color: var(--card-accent, @color-gray-text);
}
&__title {
color: var(--semi-color-text-2) !important;
font-size: 12px !important;
color: rgba(148, 163, 184, 0.7) !important;
font-size: @text-xs !important;
text-transform: uppercase;
letter-spacing: 0.05em;
}
@@ -49,61 +38,50 @@
}
&__value {
font-size: 1.2rem;
font-weight: 700;
margin-bottom: 4px;
color: var(--card-accent, var(--semi-color-text-0));
color: var(--card-accent, @color-text);
}
&__desc {
color: var(--semi-color-text-3) !important;
color: @color-faint !important;
font-size: @text-xs;
}
&.blue {
--pulse-color: @color-blue-border;
--card-accent: @color-blue-text;
background-color: @color-blue-bg;
border-color: @color-blue-border;
box-shadow: 0 2px 16px -6px @color-blue-border;
--card-glow: @color-blue-border;
background-color: @color-blue-bg !important;
border-color: @color-blue-border !important;
animation: card-glow-rotate 8s linear infinite;
}
&.orange {
--pulse-color: @color-orange-border;
--card-accent: @color-orange-text;
background-color: @color-orange-bg;
border-color: @color-orange-border;
box-shadow: 0 2px 16px -6px @color-orange-border;
--card-glow: @color-orange-border;
background-color: @color-orange-bg !important;
border-color: @color-orange-border !important;
animation: card-glow-rotate 8s linear infinite;
}
&.green {
--pulse-color: @color-green-border;
--card-accent: @color-green-text;
background-color: @color-green-bg;
border-color: @color-green-border;
box-shadow: 0 2px 16px -6px @color-green-border;
--card-glow: @color-green-border;
background-color: @color-green-bg !important;
border-color: @color-green-border !important;
animation: card-glow-rotate 8s linear infinite;
}
&.purple {
--pulse-color: @color-purple-border;
--card-accent: @color-purple-text;
background-color: @color-purple-bg;
border-color: @color-purple-border;
box-shadow: 0 2px 16px -6px @color-purple-border;
--card-glow: @color-purple-border;
background-color: @color-purple-bg !important;
border-color: @color-purple-border !important;
animation: card-glow-rotate 8s linear infinite;
}
&.gray {
--pulse-color: @color-gray-border;
--card-accent: @color-gray-text;
background-color: @color-gray-bg;
border-color: @color-gray-border;
box-shadow: 0 2px 16px -6px @color-gray-border;
}
}
@keyframes pulse {
0%, 100% {
opacity: 0.1;
}
50% {
opacity: 0.4;
--card-glow: @color-gray-border;
background-color: @color-gray-bg !important;
border-color: @color-gray-border !important;
animation: card-glow-rotate 8s linear infinite;
}
}

View File

@@ -1,19 +1 @@
@color-blue-bg: rgba(96, 165, 250, 0.10);
@color-blue-border: #3b6ea8;
@color-blue-text: #60a5fa;
@color-orange-bg: rgba(251, 146, 60, 0.10);
@color-orange-border: #c2622a;
@color-orange-text: #fb923c;
@color-green-bg: rgba(52, 211, 153, 0.10);
@color-green-border: #2a8a61;
@color-green-text: #34d399;
@color-purple-bg: rgba(167, 139, 250, 0.10);
@color-purple-border: #6d4fc2;
@color-purple-text: #a78bfa;
@color-gray-bg: rgba(148, 163, 184, 0.10);
@color-gray-border: #323a47;
@color-gray-text: #94a3b8;
@import '../../tokens.less';

View File

@@ -6,15 +6,7 @@
import { Card, Typography, Space } from '@douyinfe/semi-ui-19';
import './DashboardCard.less';
export default function KpiCard({
title,
icon,
value,
valueFontSize = '1.5rem',
description,
color = 'gray',
children,
}) {
export default function KpiCard({ title, icon, value, description, color = 'gray', children }) {
const { Text } = Typography;
return (
<Card className={`dashboard-card ${color}`} bodyStyle={{ padding: '16px' }}>
@@ -26,12 +18,12 @@ export default function KpiCard({
</Text>
</Space>
<div className="dashboard-card__content">
<div className="dashboard-card__value" style={{ fontSize: valueFontSize }}>
<div className="dashboard-card__value">
{value}
{children}
</div>
{description && (
<Text size="small" type="tertiary" className="dashboard-card__desc">
<Text size="small" className="dashboard-card__desc">
{description}
</Text>
)}