feat(redesign): design-system tokens, 23 Vue components, game-aware shell + Fleet/Solo dashboard
All checks were successful
Test Asgard Runner / test (push) Successful in 4s
All checks were successful
Test Asgard Runner / test (push) Successful in 4s
Tokens ported 1:1 from the Claude Design bundle (colors/game-themes/type/spacing/elevation/motion/fonts) with the data-theme/data-game theming contract via useThemeGame (+ cc-skin-swap repaint guard). 23 design-system components reimplemented as Vue SFCs (core/forms/data/navigation/feedback/brand). DashboardLayout rebuilt as the game-aware shell (GameSwitcher, grouped nav with permission gating preserved, agent-health footer, topbar). DashboardView: Fleet + Solo with per-game GAME_FIELDS rows and the themed ECharts PlayersChart; Solo wired to the real server store, Fleet on representative data pending the multi-instance backend. All four game skins (Rust/Dune/Conan/Soulmask). vue-tsc + vite build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
62
frontend/src/components/ds/data/StatCard.vue
Normal file
62
frontend/src/components/ds/data/StatCard.vue
Normal file
@@ -0,0 +1,62 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* StatCard — KPI tile with icon, big mono value, and optional delta + note row.
|
||||
* Green delta = up/good, red = down/bad, muted = flat.
|
||||
*/
|
||||
import { computed } from 'vue'
|
||||
import Icon from '@/components/ds/core/Icon.vue'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
label: string
|
||||
value: string | number
|
||||
unit?: string
|
||||
icon?: string
|
||||
delta?: string | number
|
||||
deltaDir?: 'up' | 'down' | 'flat'
|
||||
note?: string
|
||||
}>(),
|
||||
{ deltaDir: 'up' },
|
||||
)
|
||||
|
||||
const deltaIcon = computed(() =>
|
||||
props.deltaDir === 'up' ? 'trending-up' : props.deltaDir === 'down' ? 'trending-down' : 'minus',
|
||||
)
|
||||
|
||||
const showFoot = computed(() => props.delta != null || !!props.note)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="cc-stat">
|
||||
<div class="cc-stat__top">
|
||||
<div v-if="icon" class="cc-stat__ico">
|
||||
<Icon :name="icon" :size="15" :stroke-width="2.25" />
|
||||
</div>
|
||||
<div class="cc-stat__label">{{ label }}</div>
|
||||
</div>
|
||||
<div class="cc-stat__value">
|
||||
{{ value }}<span v-if="unit" class="cc-stat__unit">{{ unit }}</span>
|
||||
</div>
|
||||
<div v-if="showFoot" class="cc-stat__foot">
|
||||
<span v-if="delta != null" :class="['cc-stat__delta', 'cc-stat__delta--' + deltaDir]">
|
||||
<Icon :name="deltaIcon" :size="13" :stroke-width="2.5" />{{ delta }}
|
||||
</span>
|
||||
<span v-if="note" class="cc-stat__note">{{ note }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.cc-stat { background: var(--surface-base); border-radius: var(--radius-lg); box-shadow: var(--ring-default); padding: 14px 16px; display: flex; flex-direction: column; gap: 10px; min-width: 0; position: relative; overflow: hidden; }
|
||||
.cc-stat__top { display: flex; align-items: center; gap: 8px; }
|
||||
.cc-stat__ico { width: 28px; height: 28px; border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; background: var(--accent-soft); color: var(--accent-text); flex: none; }
|
||||
.cc-stat__label { font-size: var(--text-xs); font-weight: 500; color: var(--text-tertiary); letter-spacing: .01em; }
|
||||
.cc-stat__value { font-family: var(--font-mono); font-weight: 600; font-size: 28px; letter-spacing: -0.02em; color: var(--text-primary); font-variant-numeric: tabular-nums; line-height: 1; display: flex; align-items: baseline; gap: 4px; }
|
||||
.cc-stat__unit { font-size: 14px; color: var(--text-muted); font-weight: 500; }
|
||||
.cc-stat__foot { display: flex; align-items: center; gap: 6px; font-family: var(--font-mono); font-size: var(--text-xs); }
|
||||
.cc-stat__delta { display: inline-flex; align-items: center; gap: 3px; font-weight: 600; }
|
||||
.cc-stat__delta--up { color: var(--status-online); }
|
||||
.cc-stat__delta--down { color: var(--status-offline); }
|
||||
.cc-stat__delta--flat { color: var(--text-tertiary); }
|
||||
.cc-stat__note { color: var(--text-tertiary); }
|
||||
</style>
|
||||
Reference in New Issue
Block a user