diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-17 14:32:37 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-17 14:32:37 +0800 |
| commit | 5c0ba37eda80d39e6ceca59bb1d5f4942f858995 (patch) | |
| tree | 948723f9cedf7ccb0707fa6ee516bd30fe20fd10 /frontend/src/components/Status.svelte | |
| download | strategy-lab-5c0ba37eda80d39e6ceca59bb1d5f4942f858995.tar.gz | |
chore: establish Strategy Lab source baseline (development, not release)
Diffstat (limited to 'frontend/src/components/Status.svelte')
| -rw-r--r-- | frontend/src/components/Status.svelte | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/frontend/src/components/Status.svelte b/frontend/src/components/Status.svelte new file mode 100644 index 0000000..019c224 --- /dev/null +++ b/frontend/src/components/Status.svelte @@ -0,0 +1,66 @@ +<script lang="ts"> + interface Props { + error?: string | null; + busy?: boolean; + busyText?: string; + empty?: string | boolean | null; + emptyHint?: string; + warnings?: string[]; + } + let { error, busy, busyText = '加载中…', empty, emptyHint, warnings }: Props = $props(); +</script> + +{#if busy} + <div class="status" role="status"> + <span class="spinner" aria-hidden="true"></span> + {busyText} + </div> +{:else if error} + <div class="banner error" role="alert"> + <span aria-hidden="true">⚠</span> + <span>{error}</span> + </div> +{:else if empty !== null && empty !== undefined && empty !== false} + <div class="state empty"> + <p class="empty-title">{empty}</p> + {#if emptyHint}<p class="hint">{emptyHint}</p>{/if} + </div> +{/if} +{#if warnings && warnings.length > 0} + <div class="stack"> + {#each warnings as w, i (i)} + <div class="banner warn"><span aria-hidden="true">△</span><span>{w}</span></div> + {/each} + </div> +{/if} + +<style> + .status { + color: var(--text-3); + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.9rem 0; + font-size: 0.9rem; + } + .spinner { + width: 15px; + height: 15px; + border: 2px solid var(--teal); + border-top-color: transparent; + border-radius: 50%; + animation: spin 0.8s linear infinite; + } + @keyframes spin { + to { transform: rotate(360deg); } + } + .empty { + text-align: center; + padding: 2.2rem 1rem; + border: 1px dashed var(--border-strong); + border-radius: var(--radius); + color: var(--text-2); + background: var(--surface); + } + .empty-title { font-weight: 600; margin-bottom: 0.2rem; } +</style> |
