# Popover

A popover is an overlay element positioned relative to a trigger.

```tsx
import {Popover, DialogTrigger, ActionButton, CheckboxGroup, Checkbox, Form} from '@react-spectrum/s2';
import Filter from '@react-spectrum/s2/icons/Filter';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

function Example(props) {
  return (
    <DialogTrigger>
      <ActionButton aria-label="Filters">
        <Filter />
      </ActionButton>
      {/*- begin focus -*/}
      <Popover {...props}>
        <Form>
          <CheckboxGroup label="Stops">
            <Checkbox value={0}>Non-stop</Checkbox>
            <Checkbox value={1}>1 stop</Checkbox>
            <Checkbox value={2}>2+ stops</Checkbox>
          </CheckboxGroup>
          <CheckboxGroup label="Bags">
            <Checkbox value={0}>Carry on</Checkbox>
            <Checkbox value={1}>Checked bag</Checkbox>
          </CheckboxGroup>
          <CheckboxGroup label="Times">
            <Checkbox value={0}>Morning</Checkbox>
            <Checkbox value={1}>Afternoon</Checkbox>
            <Checkbox value={2}>Evening</Checkbox>
          </CheckboxGroup>
        </Form>
      </Popover>
      {/*- end focus -*/}
    </DialogTrigger>
  );
}
```

## Custom anchor

To position a popover relative to a different element than its trigger, use the `triggerRef` and `isOpen` props instead of `<DialogTrigger>`. `onOpenChange` will be called when the user closes the popover.

```tsx
import {Popover, Button} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState, useRef} from 'react';

function Example() {
  let [isOpen, setOpen] = useState(false);
  let triggerRef = useRef(null);

  return (
    <div style={{display: 'flex', gap: '12px', alignItems: 'center'}}>
      <Button onPress={() => setOpen(!isOpen)}>
        Open popover
      </Button>
      <div 
        ref={triggerRef}
        className={style({
          padding: 8, 
          backgroundColor: 'gray-100', 
          borderRadius: 'default',
          font: 'ui'
        })}>
        Popover appears here
      </div>
      <Popover 
        /*- begin highlight -*/
        triggerRef={triggerRef}
        isOpen={isOpen}
        onOpenChange={setOpen}>
        {/*- end highlight -*/}
        <div className={style({font: 'ui'})}>
          Popover with custom trigger reference
        </div>
      </Popover>
    </div>
  );
}

<Example />
```

## API

```tsx
<DialogTrigger>
  <Button />
  <Popover>
    {/* ... */}
  </Popover>
</DialogTrigger>
```

### DialogTrigger

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `ReactNode` | — |  |
| `defaultOpen` | `boolean | undefined` | — | Whether the overlay is open by default (uncontrolled). |
| `isOpen` | `boolean | undefined` | — | Whether the overlay is open by default (controlled). |
| `onOpenChange` | `((isOpen: boolean) => void) | undefined` | — | Handler that is called when the overlay's open state changes. |

### Popover

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `aria-describedby` | `string | undefined` | — | Identifies the element (or elements) that describes the object. |
| `aria-details` | `string | undefined` | — | Identifies the element (or elements) that provide a detailed, extended description for the object. |
| `aria-label` | `string | undefined` | — | Defines a string value that labels the current element. |
| `aria-labelledby` | `string | undefined` | — | Identifies the element (or elements) that labels the current element. |
| `arrowRef` | `RefObject<Element | null> | undefined` | — | A ref for the popover arrow element. |
| `boundaryElement` | `Element | undefined` | document.body | Element that that serves as the positioning boundary. |
| `children` | `ChildrenOrFunction<PopoverRenderProps>` | — | The children of the component. A function may be provided to alter the children based on component state. |
| `className` | `(string | ((values: PopoverRenderProps & { defaultClassName: string | undefined; }) => string)) | undefined` | — | The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the element. A function may be provided to compute the class based on component state. |
| `containerPadding` | `number | undefined` | 12 | The placement padding that should be applied between the element and its surrounding container. |
| `crossOffset` | `number | undefined` | 0 | The additional offset applied along the cross axis between the element and its anchor element. |
| `defaultOpen` | `boolean | undefined` | — | Whether the overlay is open by default (uncontrolled). |
| `hideArrow` | `boolean | undefined` | false | Whether a popover's arrow should be hidden. |
| `isEntering` | `boolean | undefined` | — | Whether the popover is currently performing an entry animation. |
| `isExiting` | `boolean | undefined` | — | Whether the popover is currently performing an exit animation. |
| `isOpen` | `boolean | undefined` | — | Whether the overlay is open by default (controlled). |
| `maxHeight` | `number | undefined` | — | The maxHeight specified for the overlay element. By default, it will take all space up to the current viewport height. |
| `offset` | `number | undefined` | 8 | The additional offset applied along the main axis between the element and its anchor element. |
| `onOpenChange` | `((isOpen: boolean) => void) | undefined` | — | Handler that is called when the overlay's open state changes. |
| `placement` | `Placement | undefined` | 'bottom' | The placement of the element with respect to its anchor element. |
| `scrollRef` | `RefObject<Element | null> | undefined` | overlayRef | A ref for the scrollable region within the overlay. |
| `shouldFlip` | `boolean | undefined` | true | Whether the element should flip its orientation (e.g. top to bottom or left to right) when there is insufficient room for it to render completely. |
| `size` | `"S" | "M" | "L" | undefined` | — | The size of the Popover. If not specified, the popover fits its contents. |
| `slot` | `string | null | undefined` | — | A slot name for the component. Slots allow the component to receive props from a parent component. An explicit `null` value indicates that the local props completely override all props received from a parent. |
| `style` | `(CSSProperties | ((values: PopoverRenderProps & { defaultStyle: CSSProperties; }) => CSSProperties | undefined)) | undefined` | — | The inline [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) for the element. A function may be provided to compute the style based on component state. |
| `styles` | `StyleString | undefined` | — |  |
| `trigger` | `string | undefined` | — | The name of the component that triggered the popover. This is reflected on the element as the `data-trigger` attribute, and can be used to provide specific styles for the popover depending on which element triggered it. |
| `triggerRef` | `RefObject<Element | null> | undefined` | — | The ref for the element which the popover positions itself with respect to. When used within a trigger component such as DialogTrigger, MenuTrigger, Select, etc., this is set automatically. It is only required when used standalone. |
| `UNSAFE_className` | `UnsafeClassName | undefined` | — | Sets the CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the element. Only use as a **last resort**. Use the `style` macro via the `styles` prop instead. |
| `UNSAFE_style` | `CSSProperties | undefined` | — | Sets inline [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) for the element. Only use as a **last resort**. Use the `style` macro via the `styles` prop instead. |
| `UNSTABLE_portalContainer` | `Element | undefined` | document.body | The container element in which the overlay portal will be placed. This may have unknown behavior depending on where it is portalled to. |
