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:
57
frontend/src/components/ds/data/Panel.vue
Normal file
57
frontend/src/components/ds/data/Panel.vue
Normal file
@@ -0,0 +1,57 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* Panel — standard section container.
|
||||
* Header: optional eyebrow / title / subtitle / right-aligned actions.
|
||||
* Body: padding removed when flushBody=true (tables / lists manage their own).
|
||||
*/
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
title?: string
|
||||
subtitle?: string
|
||||
eyebrow?: string
|
||||
variant?: 'base' | 'raised' | 'flush'
|
||||
flushBody?: boolean
|
||||
}>(),
|
||||
{ variant: 'base', flushBody: false },
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section
|
||||
:class="[
|
||||
'cc-panel',
|
||||
variant === 'raised' && 'cc-panel--raised',
|
||||
variant === 'flush' && 'cc-panel--flush',
|
||||
]"
|
||||
>
|
||||
<header v-if="title || subtitle || eyebrow || $slots.actions" class="cc-panel__head">
|
||||
<div class="cc-panel__titles">
|
||||
<div v-if="eyebrow" class="t-eyebrow">{{ eyebrow }}</div>
|
||||
<div v-if="title" class="cc-panel__title">
|
||||
{{ title }}
|
||||
<slot name="title-append" />
|
||||
</div>
|
||||
<div v-if="subtitle" class="cc-panel__sub">{{ subtitle }}</div>
|
||||
</div>
|
||||
<div v-if="$slots.actions" class="cc-panel__actions">
|
||||
<slot name="actions" />
|
||||
</div>
|
||||
</header>
|
||||
<div :class="['cc-panel__body', flushBody && 'cc-panel__body--flush']">
|
||||
<slot />
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.cc-panel { background: var(--surface-base); border-radius: var(--radius-lg); box-shadow: var(--ring-default); display: flex; flex-direction: column; min-width: 0; }
|
||||
.cc-panel--raised { background: var(--surface-raised); }
|
||||
.cc-panel--flush { box-shadow: none; background: transparent; }
|
||||
.cc-panel__head { display: flex; align-items: center; gap: 12px; padding: 13px 16px; border-bottom: 1px solid var(--border-subtle); }
|
||||
.cc-panel__titles { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
|
||||
.cc-panel__title { font-size: var(--text-sm); font-weight: 600; color: var(--text-primary); display: flex; align-items: center; gap: 8px; }
|
||||
.cc-panel__sub { font-size: var(--text-xs); color: var(--text-tertiary); }
|
||||
.cc-panel__actions { display: flex; align-items: center; gap: 6px; flex: none; }
|
||||
.cc-panel__body { padding: 16px; min-width: 0; }
|
||||
.cc-panel__body--flush { padding: 0; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user