Basic Modal
A titled dialog with a focus trap, Escape to close and focus returned to the trigger.
6 个框架中级
A consent dialog with three real choices - Accept all, Reject non-essential and Manage.
<!--
Consent needs three real choices - Accept all, Reject non-essential, Manage -
not a single "OK" that consents by exhaustion. Focus opens on Reject, the least
committal option, and Escape resolves to onDismiss (a reject), never a silent
accept. It is items-end on a phone (a bottom sheet) and centres from sm: up.
-->
<div class="fixed inset-0 z-50 flex items-end justify-center p-4 sm:items-center">
<div class="absolute inset-0 bg-black/40" data-modal-close></div>
<div role="dialog" aria-modal="true" aria-labelledby="cookie-modal-title" aria-describedby="cookie-modal-desc" class="relative max-h-[calc(100dvh-2rem)] w-full max-w-md overflow-y-auto rounded-2xl border border-gray-200 bg-white p-5 shadow-2xl dark:border-gray-800 dark:bg-gray-900">
<h2 id="cookie-modal-title" class="text-base font-semibold text-gray-900 dark:text-gray-100">We value your privacy</h2>
<p id="cookie-modal-desc" class="mt-2 text-sm leading-relaxed text-gray-600 dark:text-gray-400">
We use cookies to keep you signed in and to understand how the product is used. You can accept all, reject the non-essential ones, or choose which to allow.
</p>
<div class="mt-4 grid gap-2 sm:grid-cols-2">
<button type="button" data-modal-accept class="w-full rounded-lg bg-blue-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-blue-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-900">Accept all</button>
<button type="button" data-modal-reject class="w-full rounded-lg border border-gray-300 bg-white px-4 py-2.5 text-sm font-semibold text-gray-700 hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 focus-visible:ring-offset-white 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">Reject non-essential</button>
</div>
<button type="button" data-modal-manage class="mt-3 inline-flex min-h-[40px] items-center text-sm font-medium text-blue-700 underline-offset-2 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 dark:text-blue-400">Manage preferences</button>
</div>
</div>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
open必填 | boolean | - | 组件当前是否显示。 |
title必填 | string | - | 卡片的标题文本。 |
message必填 | string | - | 通知的正文文本。 |
onAccept必填 | () => void | - | On accept |
onReject必填 | () => void | - | On reject |
onManage必填 | () => void | - | On manage |
onDismiss必填 | () => void | - | 用户关闭通知时触发。 |
Consent needs three real choices rather than a single "OK" that consents by exhaustion. Focus opens on Reject, the least committal option, and Escape resolves to `onDismiss` (a reject), never a silent accept. It is `items-end` on a phone - a bottom sheet - and centres from `sm:` up. The Manage link is padded to a 40px tap target so it is not a hairline on touch.