Basic Toast
A transient, auto-dismissing confirmation announced politely.
6 frameworksIntermediate
A soft opt-in card shown before the one-shot browser permission dialog.
<!--
A soft opt-in shown BEFORE you call the real Notification.requestPermission() -
the browser prompt only fires once, so earn the yes here first. Both choices are
real <button>s; the actions stack full-width at 320px (flex-col) and only sit
side by side once there's room (sm:flex-row). The bell repeats what the copy says.
-->
<section aria-labelledby="perm-title" class="w-full max-w-sm rounded-xl border border-gray-200 bg-white p-4 shadow-[0_10px_30px_-10px_rgba(0,0,0,0.35)] dark:border-gray-800 dark:bg-gray-900">
<div class="flex items-start gap-3">
<span class="flex h-10 w-10 flex-none items-center justify-center rounded-full bg-blue-50 text-blue-700 dark:bg-blue-950 dark:text-blue-300">
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M10 2a5 5 0 0 0-5 5v3.6l-1.3 2.6A1 1 0 0 0 4.6 15h10.8a1 1 0 0 0 .9-1.8L15 10.6V7a5 5 0 0 0-5-5Zm0 16a2.5 2.5 0 0 0 2.5-2.5h-5A2.5 2.5 0 0 0 10 18Z" /></svg>
</span>
<div class="min-w-0 flex-1">
<h2 id="perm-title" class="text-sm font-semibold text-gray-900 dark:text-gray-100">Turn on notifications?</h2>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">Get notified about mentions and replies, even when this tab is closed.</p>
</div>
</div>
<div class="mt-4 flex flex-col gap-2 sm:flex-row sm:justify-end">
<button type="button" class="inline-flex items-center justify-center rounded-lg border border-gray-300 bg-white px-4 py-2.5 text-sm font-semibold text-gray-700 transition hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 motion-reduce:transition-none dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 dark:hover:bg-gray-800 dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-900">Not now</button>
<button type="button" class="inline-flex items-center justify-center rounded-lg bg-blue-600 px-4 py-2.5 text-sm font-semibold text-white transition hover:bg-blue-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 motion-reduce:transition-none dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-900">Allow</button>
</div>
</section>| Prop | Type | Default | Description |
|---|---|---|---|
title | string | 'Turn on notifications?' | Heading text for the card. |
description | string | - | Description |
allowLabel | string | 'Allow' | Allow label |
dismissLabel | string | 'Not now' | Accessible name for the dismiss button. |
onAllow | () => void | - | On allow |
onDismiss | () => void | - | Fired when the user dismisses the notification. |
className | string | - | Additional classes merged onto the root element. |
The native Notification.requestPermission() prompt fires once and a "block" is hard to reverse, so earn the yes here first and only call it after the user taps Allow. Both choices are real buttons; they stack full-width at 320px and sit side by side once there is room.