feat(web): cria painel Svelte com shell, Ao vivo e Ajustes
- web/ com Vite + Svelte 5 + TypeScript; servidor entrega web/dist em "/" (telas antigas seguem em /dashboard, /painel, /braco...) - design system em tokens CSS, tema escuro e claro, fontes locais - estado unico: foto de /estado + um EventSource em /eventos, sem polling - shell com navegacao lateral/inferior, selos de status reais e E-Stop fixo - command palette (Ctrl+K), gestos favoritos com atalhos 1-9, g+letra navega - Ao vivo: camera WebRTC e rastreamento portados para TS, rosto, aparencia, sensores do celular, IA local e feed de acontecimentos - Ajustes: campos do celular agrupados com busca, salvamento otimista e restaurar padrao (GET /app/padrao); motor da conversa, Gemini e token - carinha.html ganha modo ?painel=1 dirigido por postMessage (sem polling) - teste Playwright de ponta a ponta do painel novo Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
<script lang="ts">
|
||||
import { X } from '@lucide/svelte';
|
||||
import { avisos } from '../avisos.svelte';
|
||||
</script>
|
||||
|
||||
<div class="avisos" role="status" aria-live="polite">
|
||||
{#each avisos.lista as a (a.id)}
|
||||
<div class="aviso {a.tipo}">
|
||||
<span>{a.texto}</span>
|
||||
{#if a.acao}
|
||||
<button
|
||||
class="btn pequeno"
|
||||
onclick={() => {
|
||||
a.acao!.fazer();
|
||||
avisos.fechar(a.id);
|
||||
}}>{a.acao.rotulo}</button
|
||||
>
|
||||
{/if}
|
||||
<button class="btn fantasma pequeno icone" aria-label="Fechar aviso" onclick={() => avisos.fechar(a.id)}>
|
||||
<X size={16} />
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.avisos {
|
||||
position: fixed;
|
||||
z-index: 90;
|
||||
right: var(--e-4);
|
||||
bottom: calc(var(--e-4) + env(safe-area-inset-bottom, 0px));
|
||||
display: grid;
|
||||
gap: var(--e-2);
|
||||
width: min(420px, calc(100vw - 2 * var(--e-4)));
|
||||
}
|
||||
.aviso {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--e-2);
|
||||
padding: var(--e-2) var(--e-2) var(--e-2) var(--e-4);
|
||||
border-radius: var(--raio);
|
||||
background: var(--superficie-2);
|
||||
border: 1px solid var(--borda-forte);
|
||||
border-left: 4px solid var(--destaque);
|
||||
box-shadow: var(--sombra-flutuante);
|
||||
font-size: var(--t-sm);
|
||||
}
|
||||
.aviso span {
|
||||
flex: 1;
|
||||
}
|
||||
.ok {
|
||||
border-left-color: var(--ok);
|
||||
}
|
||||
.erro {
|
||||
border-left-color: var(--perigo);
|
||||
}
|
||||
@media (max-width: 1023px) {
|
||||
.avisos {
|
||||
bottom: calc(76px + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user