Skip to content

Popover and Sheet

import { Calendar, Popover } from '@lunisolar-picker/react';
<Popover.Root>
<Popover.Trigger render={<FilterChip />}>Due date</Popover.Trigger>
<Popover.Content aria-label="Choose due date">
<Calendar.Root value={value} onValueChange={(next) => setValue(next)} />
<Popover.Close>Done</Popover.Close>
</Popover.Content>
</Popover.Root>;

Popover.Trigger and Popover.Close take a render prop to use your own button. Popover.Close runs your onClick first, then closes unless you call event.preventDefault(). Popover.Root takes open, defaultOpen, onOpenChange and placement (default 'bottom-start').

Popover Sheet
Role dialog dialog, aria-modal="true"
Name Give Content an aria-label Same
Opening Popover.Trigger Your own button sets open (there is no Sheet.Trigger)
Position Next to the trigger, flips and shifts to stay on screen Bottom of the viewport
Focus Moves to the selected day or today, stays inside, returns to the trigger on close Same
Closing Escape, outside click, Close Escape, backdrop tap, Close
Background Interactive inert, scroll locked

Content is rendered in a portal at the end of body, or at the end of the open modal <dialog> (opened with showModal()) that contains it so it stays above the dialog and usable, and unmounted when closed, so a calendar inside it starts fresh each time it opens. Put .dark or data-theme and your font on html or body so portal content inherits them.

The finished pickers pick a sheet automatically on narrow touch screens (presentation="auto", which matches (pointer: coarse) and (max-width: 640px)). In your own compositions, usePresentation('auto') gives the same answer.

Swipe-to-close is not supported, because it competes with wheel scrolling inside the sheet.