|
|
<!--
|
|
|
Floating toast for incoming chat messages received while the user
|
|
|
is not on that conversation. Stacks up to a small max so a chatty
|
|
|
counterpart doesn't fill the screen, and each toast auto-dismisses
|
|
|
after a few seconds. Visuals come from the Nexo design system
|
|
|
(`.nx-toast-host` / `.nx-toast`).
|
|
|
-->
|
|
|
<script lang="ts">
|
|
|
import { goto } from '$app/navigation';
|
|
|
|
|
|
export interface MessageToastEntry {
|
|
|
readonly id: string;
|
|
|
readonly matchId: string;
|
|
|
readonly title: string;
|
|
|
readonly body: string;
|
|
|
}
|
|
|
|
|
|
interface Props {
|
|
|
toasts: MessageToastEntry[];
|
|
|
dismiss: (id: string) => void;
|
|
|
}
|
|
|
let { toasts, dismiss }: Props = $props();
|
|
|
|
|
|
async function open(toast: MessageToastEntry) {
|
|
|
dismiss(toast.id);
|
|
|
await goto(`/dating/chat/${toast.matchId}`);
|
|
|
}
|
|
|
|
|
|
function onKey(event: KeyboardEvent, toast: MessageToastEntry) {
|
|
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
|
event.preventDefault();
|
|
|
void open(toast);
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
{#if toasts.length > 0}
|
|
|
<div class="nx-toast-host" aria-live="polite" aria-label="Notificaciones">
|
|
|
{#each toasts as toast (toast.id)}
|
|
|
<!-- The whole row is clickable; the close button gets its own
|
|
|
stopPropagation. We use role="button" instead of a real
|
|
|
<button> so the inner close <button> stays valid HTML. -->
|
|
|
<div
|
|
|
class="nx-toast"
|
|
|
role="button"
|
|
|
tabindex="0"
|
|
|
onclick={() => open(toast)}
|
|
|
onkeydown={(event) => onKey(event, toast)}
|
|
|
>
|
|
|
<span class="icon" aria-hidden="true">✉</span>
|
|
|
<span class="body">
|
|
|
<div class="title">{toast.title}</div>
|
|
|
<div class="msg">{toast.body}</div>
|
|
|
</span>
|
|
|
<button
|
|
|
type="button"
|
|
|
class="close"
|
|
|
aria-label="Descartar"
|
|
|
onclick={(event) => {
|
|
|
event.stopPropagation();
|
|
|
dismiss(toast.id);
|
|
|
}}
|
|
|
>
|
|
|
×
|
|
|
</button>
|
|
|
</div>
|
|
|
{/each}
|
|
|
</div>
|
|
|
{/if}
|