Files
ruvnet--RuView/dashboard/src/components/nv-toast.ts
T
rUv 7f5a692632 feat(nvsim): full simulator stack — Rust crate, dashboard, server, App Store, Ghost Murmur [ADR-089/090/091/092/093]
Squashed merge of feat/nvsim-pipeline-simulator (29 commits).

## Shipped

- ADR-089 nvsim crate (Accepted) — 50/50 tests, ~4.5 M samples/s, pinned witness cc8de9b01b0ff5bd…
- ADR-092 dashboard implementation (Implemented) — 8/12 §11 gates , 4/12 ⚠ (external infra)
- ADR-093 dashboard gap analysis (Implemented) — 21/21 catalogued gaps closed
- Plus ADR-090 (proposed conditional) and ADR-091 (proposed research-only)

## Live deploy
https://ruvnet.github.io/RuView/nvsim/

## Infra

- nvsim-server Dockerfile + GHCR publish workflow (.github/workflows/nvsim-server-docker.yml)
- axe-core + Playwright cross-browser CI (.github/workflows/dashboard-a11y.yml)
- gh-pages auto-deploy workflow already in place (preserves observatory + pose-fusion siblings)

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-27 12:41:01 -04:00

65 lines
2.0 KiB
TypeScript

/* Toast notification — shown briefly via window.dispatchEvent('nv-toast', detail). */
import { LitElement, html, css } from 'lit';
import { customElement, state } from 'lit/decorators.js';
@customElement('nv-toast')
export class NvToast extends LitElement {
@state() private visible = false;
@state() private msg = '';
@state() private icon = '✓';
private timer: number | null = null;
static styles = css`
:host {
position: fixed; bottom: 24px; left: 50%;
transform: translateX(-50%) translateY(80px);
background: var(--bg-2);
border: 1px solid var(--line-2);
border-radius: var(--radius);
padding: 10px 14px;
font-size: 12.5px;
box-shadow: var(--shadow);
z-index: 100;
opacity: 0; pointer-events: none;
transition: opacity 0.2s, transform 0.2s;
display: flex; align-items: center; gap: 8px;
}
:host([visible]) {
opacity: 1;
transform: translateX(-50%) translateY(0);
pointer-events: auto;
}
.icon { color: var(--accent); }
`;
override connectedCallback(): void {
super.connectedCallback();
window.addEventListener('nv-toast', this.onToast as EventListener);
}
override disconnectedCallback(): void {
super.disconnectedCallback();
window.removeEventListener('nv-toast', this.onToast as EventListener);
}
private onToast = (e: Event): void => {
const detail = (e as CustomEvent).detail as { msg?: string; icon?: string };
this.msg = detail.msg ?? 'Done';
this.icon = detail.icon ?? '✓';
this.visible = true;
this.setAttribute('visible', '');
if (this.timer !== null) window.clearTimeout(this.timer);
this.timer = window.setTimeout(() => {
this.visible = false;
this.removeAttribute('visible');
}, 1800);
};
override render() {
return html`<span class="icon">${this.icon}</span><span>${this.msg}</span>`;
}
}
export function toast(msg: string, icon = '✓'): void {
window.dispatchEvent(new CustomEvent('nv-toast', { detail: { msg, icon } }));
}