mirror of
https://github.com/ruvnet/RuView
synced 2026-07-17 16:33:18 +00:00
7f5a692632
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>
65 lines
2.0 KiB
TypeScript
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 } }));
|
|
}
|