Basic Popover
A click-triggered panel anchored to its button, with Escape and outside-click dismiss.
6 frameworksIntermediate
A compact month grid in a dialog: leading blanks, pressed selection, pick-to-close.
<div class="relative inline-block">
<button type="button" aria-haspopup="dialog" aria-expanded="true" aria-controls="pdate-panel" class="rounded-lg border border-gray-300 bg-white px-3.5 py-2 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">
Due date: July 14
</button>
<div id="pdate-panel" role="dialog" aria-label="July 2026" class="absolute left-0 top-[calc(100%+0.5rem)] z-20 w-64 max-w-[calc(100vw-2rem)] rounded-xl border border-gray-200 bg-white p-3 shadow-lg dark:border-gray-700 dark:bg-gray-900">
<p class="px-1 text-sm font-semibold text-gray-900 dark:text-gray-100">July 2026</p>
<div class="mt-2 grid grid-cols-7 gap-0.5">
<span class="py-1 text-center text-[0.65rem] font-medium uppercase text-gray-400 dark:text-gray-500">Su</span>
<span class="py-1 text-center text-[0.65rem] font-medium uppercase text-gray-400 dark:text-gray-500">Mo</span>
<span class="py-1 text-center text-[0.65rem] font-medium uppercase text-gray-400 dark:text-gray-500">Tu</span>
<span class="py-1 text-center text-[0.65rem] font-medium uppercase text-gray-400 dark:text-gray-500">We</span>
<span class="py-1 text-center text-[0.65rem] font-medium uppercase text-gray-400 dark:text-gray-500">Th</span>
<span class="py-1 text-center text-[0.65rem] font-medium uppercase text-gray-400 dark:text-gray-500">Fr</span>
<span class="py-1 text-center text-[0.65rem] font-medium uppercase text-gray-400 dark:text-gray-500">Sa</span>
<!-- Leading blanks pad the first weekday; days follow. -->
<span></span><span></span><span></span>
<button type="button" aria-pressed="false" class="flex h-8 items-center justify-center rounded-md text-sm tabular-nums text-gray-700 hover:bg-gray-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 dark:text-gray-300 dark:hover:bg-gray-800 dark:focus-visible:ring-blue-400">1</button>
<button type="button" aria-pressed="true" class="flex h-8 items-center justify-center rounded-md bg-blue-600 text-sm font-semibold tabular-nums text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 dark:focus-visible:ring-blue-400">14</button>
<!-- ...remaining days... -->
</div>
</div>
</div>| Prop | Type | Default | Description |
|---|---|---|---|
labelrequired | string | - | Accessible label announced while loading. |
yearrequired | number | - | Year |
monthrequired | number | - | Month |
selected | number | - | Selected |
onSelect | (day: number) => void | - | Fired with the menu item the user chose. |
A single-month grid built from the Date API: `getDay()` of the 1st gives the leading blank count and day 0 of the next month gives the last day. The selected day is a real `aria-pressed` button, and picking one closes and restores focus to the trigger. `month` is 0-based to match the Date constructor. The panel stays inside a 320px viewport via `w-64 max-w-[calc(100vw-2rem)]`.