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>
87 lines
3.4 KiB
Vue
87 lines
3.4 KiB
Vue
<script setup lang="ts">
|
||
/**
|
||
* Alert — contextual inline alert strip.
|
||
* Tones: info | warn | danger | online | accent | neutral.
|
||
* Pass `title` for a bold heading, default slot for body text, `actions` slot
|
||
* for inline action buttons. Set `dismissible` to show an × ghost button that
|
||
* emits `dismiss`.
|
||
*/
|
||
import Icon from '@/components/ds/core/Icon.vue'
|
||
|
||
type Tone = 'info' | 'warn' | 'danger' | 'online' | 'accent' | 'neutral'
|
||
|
||
const ICONS: Record<Tone, string> = {
|
||
info: 'info',
|
||
warn: 'triangle-alert',
|
||
danger: 'octagon-alert',
|
||
online: 'circle-check',
|
||
accent: 'sparkles',
|
||
neutral: 'info',
|
||
}
|
||
|
||
const props = withDefaults(
|
||
defineProps<{
|
||
tone?: Tone
|
||
title?: string
|
||
dismissible?: boolean
|
||
icon?: string
|
||
}>(),
|
||
{ tone: 'info', dismissible: false },
|
||
)
|
||
|
||
defineEmits<{ dismiss: [] }>()
|
||
</script>
|
||
|
||
<template>
|
||
<div
|
||
:class="['cc-alert', 'cc-alert--' + tone]"
|
||
role="status"
|
||
>
|
||
<span class="cc-alert__icon">
|
||
<Icon :name="icon ?? ICONS[tone]" :size="17" :stroke-width="2" />
|
||
</span>
|
||
<div class="cc-alert__main">
|
||
<div v-if="title" class="cc-alert__title">{{ title }}</div>
|
||
<div v-if="$slots.default" class="cc-alert__body"><slot /></div>
|
||
<div v-if="$slots.actions" class="cc-alert__actions"><slot name="actions" /></div>
|
||
</div>
|
||
<button
|
||
v-if="dismissible"
|
||
class="cc-alert__dismiss"
|
||
type="button"
|
||
aria-label="Dismiss"
|
||
@click="$emit('dismiss')"
|
||
>
|
||
<Icon name="x" :size="15" :stroke-width="2.25" />
|
||
</button>
|
||
</div>
|
||
</template>
|
||
|
||
<style>
|
||
.cc-alert { display:flex; gap:11px; padding:12px 13px; border-radius:var(--radius-md); background:var(--surface-raised); box-shadow:var(--ring-default); }
|
||
.cc-alert__icon { flex:none; margin-top:1px; }
|
||
.cc-alert__main { flex:1; min-width:0; display:flex; flex-direction:column; gap:3px; }
|
||
.cc-alert__title { font-size:var(--text-sm); font-weight:600; color:var(--text-primary); }
|
||
.cc-alert__body { font-size:var(--text-xs); color:var(--text-secondary); line-height:1.5; }
|
||
.cc-alert__actions { display:flex; gap:8px; margin-top:8px; }
|
||
.cc-alert--info { background:var(--status-info-soft); box-shadow: inset 0 0 0 1px var(--status-info-border); }
|
||
.cc-alert--info .cc-alert__icon { color:var(--status-info); }
|
||
.cc-alert--warn { background:var(--status-warn-soft); box-shadow: inset 0 0 0 1px var(--status-warn-border); }
|
||
.cc-alert--warn .cc-alert__icon { color:var(--status-warn); }
|
||
.cc-alert--danger { background:var(--status-offline-soft); box-shadow: inset 0 0 0 1px var(--status-offline-border); }
|
||
.cc-alert--danger .cc-alert__icon { color:var(--status-offline); }
|
||
.cc-alert--online { background:var(--status-online-soft); box-shadow: inset 0 0 0 1px var(--status-online-border); }
|
||
.cc-alert--online .cc-alert__icon { color:var(--status-online); }
|
||
.cc-alert--accent { background:var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent-border); }
|
||
.cc-alert--accent .cc-alert__icon { color:var(--accent-text); }
|
||
.cc-alert__dismiss {
|
||
flex: none; display:inline-flex; align-items:center; justify-content:center;
|
||
width:26px; height:26px; border-radius:var(--radius-sm); border:none; cursor:pointer;
|
||
background:transparent; color:var(--text-secondary);
|
||
transition: var(--transition-colors);
|
||
margin-top:-3px; margin-right:-3px;
|
||
}
|
||
.cc-alert__dismiss:hover { background:var(--surface-hover); color:var(--text-primary); }
|
||
.cc-alert__dismiss:focus-visible { outline:none; box-shadow:var(--focus-ring); }
|
||
</style>
|