- app.css: HEL-649 §一 tokens (bg/line/accent/status/text/type/space/radius/shadow/motion), legacy names aliased, reduced-motion via prefers-reduced-motion and data-reduce - shared .a-btn/.status-chip/.a-panel/inputs reskinned; new .a-tag/.a-progress/.a-sprocket/.a-stage/.a-float - tailwind colors/radii reference the same CSS variables - ui primitives (StatusChip/ProgressBar/Modal/Button/ConfirmDialog/Skeleton/Switch/Card/Toast) on tokens - running state -> --run, awaiting confirm -> --warn, --cloud purple removed, old palette literals -> tokens Co-authored-by: multica-agent <github@multica.ai>
87 lines
1.5 KiB
Svelte
87 lines
1.5 KiB
Svelte
<script lang="ts">
|
|
import type { Snippet } from 'svelte';
|
|
|
|
interface Props {
|
|
hoverable?: boolean;
|
|
title?: string;
|
|
actions?: Snippet;
|
|
header?: Snippet;
|
|
children: Snippet;
|
|
class?: string;
|
|
}
|
|
|
|
let {
|
|
hoverable = false,
|
|
title,
|
|
actions,
|
|
header,
|
|
children,
|
|
class: klass = '',
|
|
}: Props = $props();
|
|
</script>
|
|
|
|
<div class="card {klass}" class:hoverable>
|
|
{#if header}
|
|
<div class="card-header">
|
|
{@render header()}
|
|
</div>
|
|
{:else if title || actions}
|
|
<div class="card-header">
|
|
{#if title}
|
|
<h3 class="card-title">{title}</h3>
|
|
{/if}
|
|
{#if actions}
|
|
<div class="card-actions">
|
|
{@render actions()}
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
<div class="card-body">
|
|
{@render children()}
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.card {
|
|
background: var(--bg-surface);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--r-lg);
|
|
}
|
|
.card.hoverable {
|
|
transition:
|
|
border-color var(--d-state) ease,
|
|
transform var(--d-state) var(--ease-out);
|
|
}
|
|
@media (hover: hover) and (pointer: fine) {
|
|
.card.hoverable:hover {
|
|
border-color: var(--line-2);
|
|
transform: translateY(-1px);
|
|
}
|
|
}
|
|
.card-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 12px;
|
|
padding: 14px 16px;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
.card-title {
|
|
margin: 0;
|
|
font-family: var(--font-display);
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: var(--text-primary);
|
|
}
|
|
.card-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin-left: auto;
|
|
}
|
|
.card-body {
|
|
padding: 16px;
|
|
}
|
|
</style>
|