# Popover

URL: https://ark-ui.com/docs/components/popover
Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/components/popover.mdx

An overlay that displays additional information or options when triggered.

---

<ComponentPreview id="Popover" />

## Anatomy

<Anatomy id="popover" />

```tsx
<Popover.Root>
  <Popover.Trigger />
  <Popover.Anchor />
  <Popover.Positioner>
    <Popover.Arrow>
      <Popover.ArrowTip />
    </Popover.Arrow>
    <Popover.Content>
      <Popover.Title />
      <Popover.Description />
      <Popover.CloseTrigger />
    </Popover.Content>
  </Popover.Positioner>
</Popover.Root>
```

## Examples

**Example: basic**

#### React

```tsx
import { Popover } from '@ark-ui/react/popover'
import { Portal } from '@ark-ui/react/portal'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const Basic = () => (
  <Popover.Root>
    <Popover.Trigger className={button.Root}>Click Me</Popover.Trigger>
    <Portal>
      <Popover.Positioner className={styles.Positioner}>
        <Popover.Content className={styles.Content}>
          <Popover.Title className={styles.Title}>Favorite Frameworks</Popover.Title>
          <Popover.Description className={styles.Description}>
            Manage and organize your favorite web frameworks.
          </Popover.Description>
        </Popover.Content>
      </Popover.Positioner>
    </Portal>
  </Popover.Root>
)

```

#### Solid

```tsx
import { Popover } from '@ark-ui/solid/popover'
import { Portal } from 'solid-js/web'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const Basic = () => (
  <Popover.Root>
    <Popover.Trigger class={button.Root}>Click Me</Popover.Trigger>
    <Portal>
      <Popover.Positioner class={styles.Positioner}>
        <Popover.Content class={styles.Content}>
          <Popover.Title class={styles.Title}>Favorite Frameworks</Popover.Title>
          <Popover.Description class={styles.Description}>
            Manage and organize your favorite web frameworks.
          </Popover.Description>
        </Popover.Content>
      </Popover.Positioner>
    </Portal>
  </Popover.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { Popover } from '@ark-ui/vue/popover'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'
</script>

<template>
  <Popover.Root portalled>
    <Popover.Trigger :class="button.Root">Click Me</Popover.Trigger>
    <Popover.Positioner :class="styles.Positioner">
      <Popover.Content :class="styles.Content">
        <Popover.Title :class="styles.Title">Favorite Frameworks</Popover.Title>
        <Popover.Description :class="styles.Description">
          Manage and organize your favorite web frameworks.
        </Popover.Description>
      </Popover.Content>
    </Popover.Positioner>
  </Popover.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { Popover } from '@ark-ui/svelte/popover'
  import { Portal } from '@ark-ui/svelte/portal'
  import button from 'styles/button.module.css'
  import styles from 'styles/popover.module.css'
</script>

<Popover.Root>
  <Popover.Trigger class={button.Root}>Click Me</Popover.Trigger>
  <Portal>
    <Popover.Positioner class={styles.Positioner}>
      <Popover.Content class={styles.Content}>
        <Popover.Title class={styles.Title}>Favorite Frameworks</Popover.Title>
        <Popover.Description class={styles.Description}>
          Manage and organize your favorite web frameworks.
        </Popover.Description>
      </Popover.Content>
    </Popover.Positioner>
  </Portal>
</Popover.Root>

```

### Controlled

Use the `open` and `onOpenChange` props to control the open state of the popover.

**Example: controlled**

#### React

```tsx
import { Popover } from '@ark-ui/react/popover'
import { Portal } from '@ark-ui/react/portal'
import { XIcon } from 'lucide-react'
import { useState } from 'react'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const Controlled = () => {
  const [open, setOpen] = useState(false)
  return (
    <Popover.Root open={open} onOpenChange={(e) => setOpen(e.open)}>
      <Popover.Trigger className={button.Root}>Click Me</Popover.Trigger>
      <Portal>
        <Popover.Positioner className={styles.Positioner}>
          <Popover.Content className={styles.Content}>
            <Popover.CloseTrigger className={styles.CloseTrigger}>
              <XIcon />
            </Popover.CloseTrigger>
            <Popover.Title className={styles.Title}>Team Members</Popover.Title>
            <Popover.Description className={styles.Description}>
              Invite colleagues to collaborate on this project.
            </Popover.Description>
          </Popover.Content>
        </Popover.Positioner>
      </Portal>
    </Popover.Root>
  )
}

```

#### Solid

```tsx
import { Popover } from '@ark-ui/solid/popover'
import { XIcon } from 'lucide-solid'
import { createSignal } from 'solid-js'
import { Portal } from 'solid-js/web'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const Controlled = () => {
  const [open, setOpen] = createSignal(false)
  return (
    <Popover.Root open={open()} onOpenChange={(e) => setOpen(e.open)}>
      <Popover.Trigger class={button.Root}>Click Me</Popover.Trigger>
      <Portal>
        <Popover.Positioner class={styles.Positioner}>
          <Popover.Content class={styles.Content}>
            <Popover.CloseTrigger class={styles.CloseTrigger}>
              <XIcon />
            </Popover.CloseTrigger>
            <Popover.Title class={styles.Title}>Team Members</Popover.Title>
            <Popover.Description class={styles.Description}>
              Invite colleagues to collaborate on this project.
            </Popover.Description>
          </Popover.Content>
        </Popover.Positioner>
      </Portal>
    </Popover.Root>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { Popover } from '@ark-ui/vue/popover'
import { XIcon } from 'lucide-vue-next'
import { ref } from 'vue'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

const open = ref(false)
</script>

<template>
  <Popover.Root v-model:open="open" portalled>
    <Popover.Trigger :class="button.Root">Click Me</Popover.Trigger>
    <Popover.Positioner :class="styles.Positioner">
      <Popover.Content :class="styles.Content">
        <Popover.CloseTrigger :class="styles.CloseTrigger">
          <XIcon />
        </Popover.CloseTrigger>
        <Popover.Title :class="styles.Title">Team Members</Popover.Title>
        <Popover.Description :class="styles.Description">
          Invite colleagues to collaborate on this project.
        </Popover.Description>
      </Popover.Content>
    </Popover.Positioner>
  </Popover.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { Popover } from '@ark-ui/svelte/popover'
  import { Portal } from '@ark-ui/svelte/portal'
  import { XIcon } from 'lucide-svelte'
  import button from 'styles/button.module.css'
  import styles from 'styles/popover.module.css'

  let open = $state(false)
</script>

<Popover.Root bind:open>
  <Popover.Trigger class={button.Root}>Click Me</Popover.Trigger>
  <Portal>
    <Popover.Positioner class={styles.Positioner}>
      <Popover.Content class={styles.Content}>
        <Popover.CloseTrigger class={styles.CloseTrigger}>
          <XIcon />
        </Popover.CloseTrigger>
        <Popover.Title class={styles.Title}>Team Members</Popover.Title>
        <Popover.Description class={styles.Description}>
          Invite colleagues to collaborate on this project.
        </Popover.Description>
      </Popover.Content>
    </Popover.Positioner>
  </Portal>
</Popover.Root>

```

### Root Provider

An alternative way to control the popover is to use the `RootProvider` component and the `usePopover` hook. This way you
can access the state and methods from outside the component.

**Example: root-provider**

#### React

```tsx
import { Popover, usePopover } from '@ark-ui/react/popover'
import { Portal } from '@ark-ui/react/portal'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const RootProvider = () => {
  const popover = usePopover({
    positioning: {
      placement: 'bottom-start',
    },
  })

  return (
    <div className="stack">
      <button className={button.Root} onClick={() => popover.setOpen(true)}>
        Popover is {popover.open ? 'open' : 'closed'}
      </button>
      <Popover.RootProvider value={popover}>
        <Portal>
          <Popover.Positioner className={styles.Positioner}>
            <Popover.Content className={styles.Content}>
              <Popover.Title className={styles.Title}>Controlled Externally</Popover.Title>
              <Popover.Description className={styles.Description}>
                This popover is controlled via the usePopover hook.
              </Popover.Description>
            </Popover.Content>
          </Popover.Positioner>
        </Portal>
      </Popover.RootProvider>
    </div>
  )
}

```

#### Solid

```tsx
import { Popover, usePopover } from '@ark-ui/solid/popover'
import { Portal } from 'solid-js/web'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const RootProvider = () => {
  const popover = usePopover()

  return (
    <div class="stack">
      <button class={button.Root} onClick={() => popover().setOpen(true)}>
        Popover is {popover().open ? 'open' : 'closed'}
      </button>
      <Popover.RootProvider value={popover}>
        <Portal>
          <Popover.Positioner class={styles.Positioner}>
            <Popover.Content class={styles.Content}>
              <Popover.Title class={styles.Title}>Controlled Externally</Popover.Title>
              <Popover.Description class={styles.Description}>
                This popover is controlled via the usePopover hook.
              </Popover.Description>
            </Popover.Content>
          </Popover.Positioner>
        </Portal>
      </Popover.RootProvider>
    </div>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { Popover, usePopover } from '@ark-ui/vue/popover'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

const popover = usePopover({
  positioning: {
    placement: 'bottom-start',
  },
})
</script>

<template>
  <div class="stack">
    <button :class="button.Root" @click="popover.setOpen(true)">
      Popover is {{ popover.open ? 'open' : 'closed' }}
    </button>

    <Popover.RootProvider :value="popover" portalled>
      <Popover.Positioner :class="styles.Positioner">
        <Popover.Content :class="styles.Content">
          <Popover.Title :class="styles.Title">Controlled Externally</Popover.Title>
          <Popover.Description :class="styles.Description">
            This popover is controlled via the usePopover hook.
          </Popover.Description>
        </Popover.Content>
      </Popover.Positioner>
    </Popover.RootProvider>
  </div>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { Popover, usePopover } from '@ark-ui/svelte/popover'
  import { Portal } from '@ark-ui/svelte/portal'
  import button from 'styles/button.module.css'
  import styles from 'styles/popover.module.css'

  const popover = usePopover({
    positioning: {
      placement: 'bottom-start',
    },
  })
</script>

<div class="stack">
  <button class={button.Root} onclick={() => popover().setOpen(true)}>
    Popover is {popover().open ? 'open' : 'closed'}
  </button>

  <Popover.RootProvider value={popover}>
    <Portal>
      <Popover.Positioner class={styles.Positioner}>
        <Popover.Content class={styles.Content}>
          <Popover.Title class={styles.Title}>Controlled Externally</Popover.Title>
          <Popover.Description class={styles.Description}>
            This popover is controlled via the usePopover hook.
          </Popover.Description>
        </Popover.Content>
      </Popover.Positioner>
    </Portal>
  </Popover.RootProvider>
</div>

```

### Arrow

Use `Popover.Arrow` and `Popover.ArrowTip` to render an arrow pointing to the trigger.

**Example: arrow**

#### React

```tsx
import { Popover } from '@ark-ui/react/popover'
import { Portal } from '@ark-ui/react/portal'
import { XIcon } from 'lucide-react'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const Arrow = () => (
  <Popover.Root>
    <Popover.Trigger className={button.Root}>Click Me</Popover.Trigger>
    <Portal>
      <Popover.Positioner className={styles.Positioner}>
        <Popover.Content className={styles.Content}>
          <Popover.Arrow className={styles.Arrow}>
            <Popover.ArrowTip className={styles.ArrowTip} />
          </Popover.Arrow>
          <Popover.CloseTrigger className={styles.CloseTrigger}>
            <XIcon />
          </Popover.CloseTrigger>
          <Popover.Title className={styles.Title}>Notifications</Popover.Title>
          <Popover.Description className={styles.Description}>
            You have 3 unread messages in your inbox.
          </Popover.Description>
        </Popover.Content>
      </Popover.Positioner>
    </Portal>
  </Popover.Root>
)

```

#### Solid

```tsx
import { Popover } from '@ark-ui/solid/popover'
import { XIcon } from 'lucide-solid'
import { Portal } from 'solid-js/web'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const Arrow = () => (
  <Popover.Root>
    <Popover.Trigger class={button.Root}>Click Me</Popover.Trigger>
    <Portal>
      <Popover.Positioner class={styles.Positioner}>
        <Popover.Content class={styles.Content}>
          <Popover.Arrow class={styles.Arrow}>
            <Popover.ArrowTip class={styles.ArrowTip} />
          </Popover.Arrow>
          <Popover.CloseTrigger class={styles.CloseTrigger}>
            <XIcon />
          </Popover.CloseTrigger>
          <Popover.Title class={styles.Title}>Notifications</Popover.Title>
          <Popover.Description class={styles.Description}>
            You have 3 unread messages in your inbox.
          </Popover.Description>
        </Popover.Content>
      </Popover.Positioner>
    </Portal>
  </Popover.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { Popover } from '@ark-ui/vue/popover'
import { XIcon } from 'lucide-vue-next'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'
</script>

<template>
  <Popover.Root portalled>
    <Popover.Trigger :class="button.Root">Click Me</Popover.Trigger>
    <Popover.Positioner :class="styles.Positioner">
      <Popover.Content :class="styles.Content">
        <Popover.Arrow :class="styles.Arrow">
          <Popover.ArrowTip :class="styles.ArrowTip" />
        </Popover.Arrow>
        <Popover.CloseTrigger :class="styles.CloseTrigger">
          <XIcon />
        </Popover.CloseTrigger>
        <Popover.Title :class="styles.Title">Notifications</Popover.Title>
        <Popover.Description :class="styles.Description">You have 3 unread messages in your inbox.</Popover.Description>
      </Popover.Content>
    </Popover.Positioner>
  </Popover.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { Popover } from '@ark-ui/svelte/popover'
  import { Portal } from '@ark-ui/svelte/portal'
  import { XIcon } from 'lucide-svelte'
  import button from 'styles/button.module.css'
  import styles from 'styles/popover.module.css'
</script>

<Popover.Root>
  <Popover.Trigger class={button.Root}>Click Me</Popover.Trigger>
  <Portal>
    <Popover.Positioner class={styles.Positioner}>
      <Popover.Content class={styles.Content}>
        <Popover.Arrow class={styles.Arrow}>
          <Popover.ArrowTip class={styles.ArrowTip} />
        </Popover.Arrow>
        <Popover.CloseTrigger class={styles.CloseTrigger}>
          <XIcon />
        </Popover.CloseTrigger>
        <Popover.Title class={styles.Title}>Notifications</Popover.Title>
        <Popover.Description class={styles.Description}>You have 3 unread messages in your inbox.</Popover.Description>
      </Popover.Content>
    </Popover.Positioner>
  </Portal>
</Popover.Root>

```

### Placement

To change the placement of the popover, set the `positioning` prop.

**Example: positioning**

#### React

```tsx
import { Popover } from '@ark-ui/react/popover'
import { Portal } from '@ark-ui/react/portal'
import { XIcon } from 'lucide-react'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const Positioning = () => (
  <Popover.Root
    positioning={{
      placement: 'left-start',
      offset: { mainAxis: 12, crossAxis: 12 },
    }}
  >
    <Popover.Trigger className={button.Root}>Click Me</Popover.Trigger>
    <Portal>
      <Popover.Positioner className={styles.Positioner}>
        <Popover.Content className={styles.Content}>
          <Popover.CloseTrigger className={styles.CloseTrigger}>
            <XIcon />
          </Popover.CloseTrigger>
          <Popover.Title className={styles.Title}>Left Placement</Popover.Title>
          <Popover.Description className={styles.Description}>
            This popover appears on the left with custom offset values.
          </Popover.Description>
        </Popover.Content>
      </Popover.Positioner>
    </Portal>
  </Popover.Root>
)

```

#### Solid

```tsx
import { Popover } from '@ark-ui/solid/popover'
import { XIcon } from 'lucide-solid'
import { Portal } from 'solid-js/web'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const Positioning = () => (
  <Popover.Root
    positioning={{
      placement: 'left-start',
      offset: { mainAxis: 12, crossAxis: 12 },
    }}
  >
    <Popover.Trigger class={button.Root}>Click Me</Popover.Trigger>
    <Portal>
      <Popover.Positioner class={styles.Positioner}>
        <Popover.Content class={styles.Content}>
          <Popover.CloseTrigger class={styles.CloseTrigger}>
            <XIcon />
          </Popover.CloseTrigger>
          <Popover.Title class={styles.Title}>Left Placement</Popover.Title>
          <Popover.Description class={styles.Description}>
            This popover appears on the left with custom offset values.
          </Popover.Description>
        </Popover.Content>
      </Popover.Positioner>
    </Portal>
  </Popover.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { Popover } from '@ark-ui/vue/popover'
import { XIcon } from 'lucide-vue-next'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'
</script>

<template>
  <Popover.Root
    :positioning="{
      placement: 'left-start',
      offset: { mainAxis: 12, crossAxis: 12 },
    }"
    portalled
  >
    <Popover.Trigger :class="button.Root">Click Me</Popover.Trigger>
    <Popover.Positioner :class="styles.Positioner">
      <Popover.Content :class="styles.Content">
        <Popover.CloseTrigger :class="styles.CloseTrigger">
          <XIcon />
        </Popover.CloseTrigger>
        <Popover.Title :class="styles.Title">Left Placement</Popover.Title>
        <Popover.Description :class="styles.Description">
          This popover appears on the left with custom offset values.
        </Popover.Description>
      </Popover.Content>
    </Popover.Positioner>
  </Popover.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { Popover } from '@ark-ui/svelte/popover'
  import { Portal } from '@ark-ui/svelte/portal'
  import { XIcon } from 'lucide-svelte'
  import button from 'styles/button.module.css'
  import styles from 'styles/popover.module.css'
</script>

<Popover.Root
  positioning={{
    placement: 'left-start',
    offset: { mainAxis: 12, crossAxis: 12 },
  }}
>
  <Popover.Trigger class={button.Root}>Click Me</Popover.Trigger>
  <Portal>
    <Popover.Positioner class={styles.Positioner}>
      <Popover.Content class={styles.Content}>
        <Popover.CloseTrigger class={styles.CloseTrigger}>
          <XIcon />
        </Popover.CloseTrigger>
        <Popover.Title class={styles.Title}>Left Placement</Popover.Title>
        <Popover.Description class={styles.Description}>
          This popover appears on the left with custom offset values.
        </Popover.Description>
      </Popover.Content>
    </Popover.Positioner>
  </Portal>
</Popover.Root>

```

### Close Behavior

The popover is designed to close on blur and when the <kbd>esc</kbd> key is pressed.

- To prevent it from closing on blur (clicking or focusing outside), pass the `closeOnInteractOutside` prop and set it
  to `false`.
- To prevent it from closing when the <kbd>esc</kbd> key is pressed, pass the `closeOnEsc` prop and set it to `false`.

**Example: close-behavior**

#### React

```tsx
import { Popover } from '@ark-ui/react/popover'
import { Portal } from '@ark-ui/react/portal'
import { XIcon } from 'lucide-react'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const CloseBehavior = () => (
  <Popover.Root closeOnEscape closeOnInteractOutside>
    <Popover.Trigger className={button.Root}>Click Me</Popover.Trigger>
    <Portal>
      <Popover.Positioner className={styles.Positioner}>
        <Popover.Content className={styles.Content}>
          <Popover.CloseTrigger className={styles.CloseTrigger}>
            <XIcon />
          </Popover.CloseTrigger>
          <Popover.Title className={styles.Title}>Quick Actions</Popover.Title>
          <Popover.Description className={styles.Description}>
            Press Escape or click outside to close this popover.
          </Popover.Description>
        </Popover.Content>
      </Popover.Positioner>
    </Portal>
  </Popover.Root>
)

```

#### Solid

```tsx
import { Popover } from '@ark-ui/solid/popover'
import { XIcon } from 'lucide-solid'
import { Portal } from 'solid-js/web'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const CloseBehavior = () => (
  <Popover.Root closeOnEscape closeOnInteractOutside>
    <Popover.Trigger class={button.Root}>Click Me</Popover.Trigger>
    <Portal>
      <Popover.Positioner class={styles.Positioner}>
        <Popover.Content class={styles.Content}>
          <Popover.CloseTrigger class={styles.CloseTrigger}>
            <XIcon />
          </Popover.CloseTrigger>
          <Popover.Title class={styles.Title}>Quick Actions</Popover.Title>
          <Popover.Description class={styles.Description}>
            Press Escape or click outside to close this popover.
          </Popover.Description>
        </Popover.Content>
      </Popover.Positioner>
    </Portal>
  </Popover.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { Popover } from '@ark-ui/vue/popover'
import { XIcon } from 'lucide-vue-next'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'
</script>

<template>
  <Popover.Root closeOnEscape closeOnInteractOutside portalled>
    <Popover.Trigger :class="button.Root">Click Me</Popover.Trigger>
    <Popover.Positioner :class="styles.Positioner">
      <Popover.Content :class="styles.Content">
        <Popover.CloseTrigger :class="styles.CloseTrigger">
          <XIcon />
        </Popover.CloseTrigger>
        <Popover.Title :class="styles.Title">Quick Actions</Popover.Title>
        <Popover.Description :class="styles.Description">
          Press Escape or click outside to close this popover.
        </Popover.Description>
      </Popover.Content>
    </Popover.Positioner>
  </Popover.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { Popover } from '@ark-ui/svelte/popover'
  import { Portal } from '@ark-ui/svelte/portal'
  import { XIcon } from 'lucide-svelte'
  import button from 'styles/button.module.css'
  import styles from 'styles/popover.module.css'
</script>

<Popover.Root closeOnEscape closeOnInteractOutside>
  <Popover.Trigger class={button.Root}>Click Me</Popover.Trigger>
  <Portal>
    <Popover.Positioner class={styles.Positioner}>
      <Popover.Content class={styles.Content}>
        <Popover.CloseTrigger class={styles.CloseTrigger}>
          <XIcon />
        </Popover.CloseTrigger>
        <Popover.Title class={styles.Title}>Quick Actions</Popover.Title>
        <Popover.Description class={styles.Description}>
          Press Escape or click outside to close this popover.
        </Popover.Description>
      </Popover.Content>
    </Popover.Positioner>
  </Portal>
</Popover.Root>

```

### Modality

In some cases, you might want the popover to be modal. This means that it'll:

- trap focus within its content
- block scrolling on the body
- disable pointer interactions outside the popover
- hide content behind the popover from screen readers

To make the popover modal, set the `modal` prop to `true`. When `modal={true}`, we set the `portalled` attribute to
`true` as well.

**Example: modal**

#### React

```tsx
import { Popover } from '@ark-ui/react/popover'
import { Portal } from '@ark-ui/react/portal'
import { XIcon } from 'lucide-react'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const Modal = () => (
  <Popover.Root modal>
    <Popover.Trigger className={button.Root}>Click Me</Popover.Trigger>
    <Portal>
      <Popover.Positioner className={styles.Positioner}>
        <Popover.Content className={styles.Content}>
          <Popover.CloseTrigger className={styles.CloseTrigger}>
            <XIcon />
          </Popover.CloseTrigger>
          <Popover.Title className={styles.Title}>Confirm Action</Popover.Title>
          <Popover.Description className={styles.Description}>
            Focus is trapped inside this modal popover until dismissed.
          </Popover.Description>
        </Popover.Content>
      </Popover.Positioner>
    </Portal>
  </Popover.Root>
)

```

#### Solid

```tsx
import { Popover } from '@ark-ui/solid/popover'
import { XIcon } from 'lucide-solid'
import { Portal } from 'solid-js/web'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const Modal = () => (
  <Popover.Root modal>
    <Popover.Trigger class={button.Root}>Click Me</Popover.Trigger>
    <Portal>
      <Popover.Positioner class={styles.Positioner}>
        <Popover.Content class={styles.Content}>
          <Popover.CloseTrigger class={styles.CloseTrigger}>
            <XIcon />
          </Popover.CloseTrigger>
          <Popover.Title class={styles.Title}>Confirm Action</Popover.Title>
          <Popover.Description class={styles.Description}>
            Focus is trapped inside this modal popover until dismissed.
          </Popover.Description>
        </Popover.Content>
      </Popover.Positioner>
    </Portal>
  </Popover.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { Popover } from '@ark-ui/vue/popover'
import { XIcon } from 'lucide-vue-next'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'
</script>

<template>
  <Popover.Root modal portalled>
    <Popover.Trigger :class="button.Root">Click Me</Popover.Trigger>
    <Popover.Positioner :class="styles.Positioner">
      <Popover.Content :class="styles.Content">
        <Popover.CloseTrigger :class="styles.CloseTrigger">
          <XIcon />
        </Popover.CloseTrigger>
        <Popover.Title :class="styles.Title">Confirm Action</Popover.Title>
        <Popover.Description :class="styles.Description">
          Focus is trapped inside this modal popover until dismissed.
        </Popover.Description>
      </Popover.Content>
    </Popover.Positioner>
  </Popover.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { Popover } from '@ark-ui/svelte/popover'
  import { Portal } from '@ark-ui/svelte/portal'
  import { XIcon } from 'lucide-svelte'
  import button from 'styles/button.module.css'
  import styles from 'styles/popover.module.css'
</script>

<Popover.Root modal>
  <Popover.Trigger class={button.Root}>Click Me</Popover.Trigger>
  <Portal>
    <Popover.Positioner class={styles.Positioner}>
      <Popover.Content class={styles.Content}>
        <Popover.CloseTrigger class={styles.CloseTrigger}>
          <XIcon />
        </Popover.CloseTrigger>
        <Popover.Title class={styles.Title}>Confirm Action</Popover.Title>
        <Popover.Description class={styles.Description}>
          Focus is trapped inside this modal popover until dismissed.
        </Popover.Description>
      </Popover.Content>
    </Popover.Positioner>
  </Portal>
</Popover.Root>

```

### Anchor

Use `Popover.Anchor` to position the popover relative to a different element than the trigger.

**Example: anchor**

#### React

```tsx
import { Popover } from '@ark-ui/react/popover'
import { XIcon } from 'lucide-react'
import button from 'styles/button.module.css'
import field from 'styles/field.module.css'
import styles from 'styles/popover.module.css'

export const Anchor = () => {
  return (
    <Popover.Root>
      <div className="hstack">
        <Popover.Trigger className={button.Root}>Click Me</Popover.Trigger>
        <Popover.Anchor className={styles.Anchor}>
          <input className={field.Input} placeholder="Type here..." />
        </Popover.Anchor>
      </div>

      <Popover.Positioner className={styles.Positioner}>
        <Popover.Content className={styles.Content}>
          <Popover.CloseTrigger className={styles.CloseTrigger}>
            <XIcon />
          </Popover.CloseTrigger>
          <Popover.Title className={styles.Title}>Title</Popover.Title>
          <Popover.Description className={styles.Description}>Description</Popover.Description>
        </Popover.Content>
      </Popover.Positioner>
    </Popover.Root>
  )
}

```

### Same Width

Use `positioning.sameWidth` to make the popover match the width of its trigger element.

**Example: same-width**

#### React

```tsx
import { Popover } from '@ark-ui/react/popover'
import { Portal } from '@ark-ui/react/portal'
import { XIcon } from 'lucide-react'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const SameWidth = () => {
  return (
    <Popover.Root positioning={{ sameWidth: true }}>
      <Popover.Trigger className={button.Root} style={{ minWidth: '200px' }}>
        Click Me
      </Popover.Trigger>
      <Portal>
        <Popover.Positioner className={styles.Positioner}>
          <Popover.Content className={styles.Content}>
            <Popover.CloseTrigger className={styles.CloseTrigger}>
              <XIcon />
            </Popover.CloseTrigger>
            <Popover.Title className={styles.Title}>Matched Width</Popover.Title>
            <Popover.Description className={styles.Description}>
              This popover matches the width of its trigger element.
            </Popover.Description>
          </Popover.Content>
        </Popover.Positioner>
      </Portal>
    </Popover.Root>
  )
}

```

### Dialog Integration

When rendering a popover inside a dialog, you have two options for proper layering:

1. **Keep the Portal with `lazyMount` and `unmountOnExit`** - This ensures the popover is properly unmounted when the
   dialog closes, preventing stale DOM nodes.

2. **Remove the Portal** - Render the popover inline within the dialog content. This works well but may have z-index
   considerations.

**Example: with-dialog**

#### React

```tsx
import { Dialog } from '@ark-ui/react/dialog'
import { Popover } from '@ark-ui/react/popover'
import { Portal } from '@ark-ui/react/portal'
import { XIcon } from 'lucide-react'
import button from 'styles/button.module.css'
import dialog from 'styles/dialog.module.css'
import styles from 'styles/popover.module.css'

export const WithDialog = () => (
  <Dialog.Root>
    <Dialog.Trigger className={button.Root}>Open Dialog</Dialog.Trigger>
    <Portal>
      <Dialog.Backdrop className={dialog.Backdrop} />
      <Dialog.Positioner className={dialog.Positioner}>
        <Dialog.Content className={dialog.Content}>
          <Dialog.CloseTrigger className={dialog.CloseTrigger}>
            <XIcon />
          </Dialog.CloseTrigger>
          <Dialog.Title className={dialog.Title}>Edit Profile</Dialog.Title>
          <Dialog.Description className={dialog.Description}>Update your profile information below.</Dialog.Description>
          <div className={dialog.Body}>
            <Popover.Root lazyMount unmountOnExit>
              <Popover.Trigger className={button.Root}>More Options</Popover.Trigger>
              <Portal>
                <Popover.Positioner className={styles.Positioner}>
                  <Popover.Content className={styles.Content}>
                    <Popover.Arrow className={styles.Arrow}>
                      <Popover.ArrowTip className={styles.ArrowTip} />
                    </Popover.Arrow>
                    <Popover.CloseTrigger className={styles.CloseTrigger}>
                      <XIcon />
                    </Popover.CloseTrigger>
                    <Popover.Title className={styles.Title}>Additional Settings</Popover.Title>
                    <Popover.Description className={styles.Description}>
                      This popover renders correctly above the dialog.
                    </Popover.Description>
                  </Popover.Content>
                </Popover.Positioner>
              </Portal>
            </Popover.Root>
          </div>
        </Dialog.Content>
      </Dialog.Positioner>
    </Portal>
  </Dialog.Root>
)

```

#### Solid

```tsx
import { Dialog } from '@ark-ui/solid/dialog'
import { Popover } from '@ark-ui/solid/popover'
import { XIcon } from 'lucide-solid'
import { Portal } from 'solid-js/web'
import button from 'styles/button.module.css'
import dialog from 'styles/dialog.module.css'
import styles from 'styles/popover.module.css'

export const WithDialog = () => (
  <Dialog.Root>
    <Dialog.Trigger class={button.Root}>Open Dialog</Dialog.Trigger>
    <Portal>
      <Dialog.Backdrop class={dialog.Backdrop} />
      <Dialog.Positioner class={dialog.Positioner}>
        <Dialog.Content class={dialog.Content}>
          <Dialog.CloseTrigger class={dialog.CloseTrigger}>
            <XIcon />
          </Dialog.CloseTrigger>
          <Dialog.Title class={dialog.Title}>Edit Profile</Dialog.Title>
          <Dialog.Description class={dialog.Description}>Update your profile information below.</Dialog.Description>
          <div class={dialog.Body}>
            <Popover.Root lazyMount unmountOnExit>
              <Popover.Trigger class={button.Root}>More Options</Popover.Trigger>
              <Portal>
                <Popover.Positioner class={styles.Positioner}>
                  <Popover.Content class={styles.Content}>
                    <Popover.Arrow class={styles.Arrow}>
                      <Popover.ArrowTip class={styles.ArrowTip} />
                    </Popover.Arrow>
                    <Popover.CloseTrigger class={styles.CloseTrigger}>
                      <XIcon />
                    </Popover.CloseTrigger>
                    <Popover.Title class={styles.Title}>Additional Settings</Popover.Title>
                    <Popover.Description class={styles.Description}>
                      This popover renders correctly above the dialog.
                    </Popover.Description>
                  </Popover.Content>
                </Popover.Positioner>
              </Portal>
            </Popover.Root>
          </div>
        </Dialog.Content>
      </Dialog.Positioner>
    </Portal>
  </Dialog.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { Dialog } from '@ark-ui/vue/dialog'
import { Popover } from '@ark-ui/vue/popover'
import { XIcon } from 'lucide-vue-next'
import { Teleport } from 'vue'
import button from 'styles/button.module.css'
import dialog from 'styles/dialog.module.css'
import styles from 'styles/popover.module.css'
</script>

<template>
  <Dialog.Root>
    <Dialog.Trigger :class="button.Root">Open Dialog</Dialog.Trigger>
    <Teleport to="body">
      <Dialog.Backdrop :class="dialog.Backdrop" />
      <Dialog.Positioner :class="dialog.Positioner">
        <Dialog.Content :class="dialog.Content">
          <Dialog.CloseTrigger :class="dialog.CloseTrigger">
            <XIcon />
          </Dialog.CloseTrigger>
          <Dialog.Title :class="dialog.Title">Edit Profile</Dialog.Title>
          <Dialog.Description :class="dialog.Description">Update your profile information below.</Dialog.Description>
          <div :class="dialog.Body">
            <Popover.Root lazyMount unmountOnExit>
              <Popover.Trigger :class="button.Root">More Options</Popover.Trigger>
              <Teleport to="body">
                <Popover.Positioner :class="styles.Positioner">
                  <Popover.Content :class="styles.Content">
                    <Popover.Arrow :class="styles.Arrow">
                      <Popover.ArrowTip :class="styles.ArrowTip" />
                    </Popover.Arrow>
                    <Popover.CloseTrigger :class="styles.CloseTrigger">
                      <XIcon />
                    </Popover.CloseTrigger>
                    <Popover.Title :class="styles.Title">Additional Settings</Popover.Title>
                    <Popover.Description :class="styles.Description">
                      This popover renders correctly above the dialog.
                    </Popover.Description>
                  </Popover.Content>
                </Popover.Positioner>
              </Teleport>
            </Popover.Root>
          </div>
        </Dialog.Content>
      </Dialog.Positioner>
    </Teleport>
  </Dialog.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { Dialog } from '@ark-ui/svelte/dialog'
  import { Popover } from '@ark-ui/svelte/popover'
  import { Portal } from '@ark-ui/svelte/portal'
  import { XIcon } from 'lucide-svelte'
  import button from 'styles/button.module.css'
  import dialog from 'styles/dialog.module.css'
  import styles from 'styles/popover.module.css'
</script>

<Dialog.Root>
  <Dialog.Trigger class={button.Root}>Open Dialog</Dialog.Trigger>
  <Portal>
    <Dialog.Backdrop class={dialog.Backdrop} />
    <Dialog.Positioner class={dialog.Positioner}>
      <Dialog.Content class={dialog.Content}>
        <Dialog.CloseTrigger class={dialog.CloseTrigger}>
          <XIcon />
        </Dialog.CloseTrigger>
        <Dialog.Title class={dialog.Title}>Edit Profile</Dialog.Title>
        <Dialog.Description class={dialog.Description}>Update your profile information below.</Dialog.Description>
        <div class={dialog.Body}>
          <Popover.Root lazyMount unmountOnExit>
            <Popover.Trigger class={button.Root}>More Options</Popover.Trigger>
            <Portal>
              <Popover.Positioner class={styles.Positioner}>
                <Popover.Content class={styles.Content}>
                  <Popover.Arrow class={styles.Arrow}>
                    <Popover.ArrowTip class={styles.ArrowTip} />
                  </Popover.Arrow>
                  <Popover.CloseTrigger class={styles.CloseTrigger}>
                    <XIcon />
                  </Popover.CloseTrigger>
                  <Popover.Title class={styles.Title}>Additional Settings</Popover.Title>
                  <Popover.Description class={styles.Description}>
                    This popover renders correctly above the dialog.
                  </Popover.Description>
                </Popover.Content>
              </Popover.Positioner>
            </Portal>
          </Popover.Root>
        </div>
      </Dialog.Content>
    </Dialog.Positioner>
  </Portal>
</Dialog.Root>

```

### Nested

Popovers can be nested within each other. Each nested popover maintains its own open state and positioning.

**Example: nested**

#### React

```tsx
import { Popover } from '@ark-ui/react/popover'
import { Portal } from '@ark-ui/react/portal'
import button from 'styles/button.module.css'
import styles from 'styles/popover.module.css'

export const Nested = () => {
  return (
    <Popover.Root>
      <Popover.Trigger className={button.Root}>Click Me</Popover.Trigger>
      <Portal>
        <Popover.Positioner className={styles.Positioner}>
          <Popover.Content className={styles.Content}>
            <Popover.Title className={styles.Title}>Settings</Popover.Title>
            <Popover.Description className={styles.Description}>
              Manage your preferences and account settings.
            </Popover.Description>
            <Popover.Root positioning={{ placement: 'right' }}>
              <Popover.Trigger className={button.Root}>Advanced</Popover.Trigger>
              <Portal>
                <Popover.Positioner className={styles.Positioner}>
                  <Popover.Content className={styles.Content}>
                    <Popover.Title className={styles.Title}>Advanced Settings</Popover.Title>
                    <Popover.Description className={styles.Description}>
                      Configure advanced options for power users.
                    </Popover.Description>
                  </Popover.Content>
                </Popover.Positioner>
              </Portal>
            </Popover.Root>
          </Popover.Content>
        </Popover.Positioner>
      </Portal>
    </Popover.Root>
  )
}

```

## Guides

### Available Size

The following css variables are exposed to the `Popover.Positioner` which you can use to style the `Popover.Content`

```css
/* width of the popover trigger */
--reference-width: <pixel-value>;
/* width of the available viewport */
--available-width: <pixel-value>;
/* height of the available viewport */
--available-height: <pixel-value>;
```

For example, if you want to make sure the maximum height doesn't exceed the available height, use the following css:

```css
[data-scope='popover'][data-part='content'] {
  max-height: calc(var(--available-height) - 100px);
}
```

## API Reference

### Props

**Component API Reference**

#### React

**Root Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `autoFocus` | `boolean` | No | Whether to automatically set focus on the first focusable
content within the popover when opened. |
| `closeOnEscape` | `boolean` | No | Whether to close the popover when the escape key is pressed. |
| `closeOnInteractOutside` | `boolean` | No | Whether to close the popover when the user clicks outside of the popover. |
| `defaultOpen` | `boolean` | No | The initial open state of the popover when rendered.
Use when you don't need to control the open state of the popover. |
| `id` | `string` | No | The unique identifier of the machine. |
| `ids` | `Partial<{
  anchor: string
  trigger: string
  content: string
  title: string
  description: string
  closeTrigger: string
  positioner: string
  arrow: string
}>` | No | The ids of the elements in the popover. Useful for composition. |
| `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame |
| `initialFocusEl` | `() => HTMLElement | null` | No | The element to focus on when the popover is opened. |
| `lazyMount` | `boolean` | No | Whether to enable lazy mounting |
| `modal` | `boolean` | No | Whether the popover should be modal. When set to `true`:
- interaction with outside elements will be disabled
- only popover content will be visible to screen readers
- scrolling is blocked
- focus is trapped within the popover |
| `onEscapeKeyDown` | `(event: KeyboardEvent) => void` | No | Function called when the escape key is pressed |
| `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state |
| `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component |
| `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component |
| `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function invoked when the popover opens or closes |
| `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component |
| `onRequestDismiss` | `(event: LayerDismissEvent) => void` | No | Function called when this layer is closed due to a parent layer being closed |
| `open` | `boolean` | No | The controlled open state of the popover |
| `persistentElements` | `(() => Element | null)[]` | No | Returns the persistent elements that:
- should not have pointer-events disabled
- should not trigger the dismiss event |
| `portalled` | `boolean` | No | Whether the popover is portalled. This will proxy the tabbing behavior regardless of the DOM position
of the popover content. |
| `positioning` | `PositioningOptions` | No | The user provided options used to position the popover content |
| `present` | `boolean` | No | Whether the node is present (controlled by the user) |
| `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. |
| `unmountOnExit` | `boolean` | No | Whether to unmount on exit. |


**Anchor Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Arrow Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Arrow CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--arrow-size` | The size of the arrow |
| `--arrow-size-half` | Half the size of the arrow |
| `--arrow-background` | Use this variable to style the arrow background |
| `--arrow-offset` | The offset position of the arrow |


**ArrowTip Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**CloseTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Content Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Content Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | popover |
| `[data-part]` | content |
| `[data-state]` | "open" | "closed" |
| `[data-nested]` | popover |
| `[data-has-nested]` | popover |
| `[data-expanded]` | Present when expanded |
| `[data-placement]` | The placement of the content |


**Content CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--layer-index` | The index of the dismissable in the layer stack |
| `--nested-layer-count` | The number of nested popovers |


**Description Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Indicator Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Indicator Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | popover |
| `[data-part]` | indicator |
| `[data-state]` | "open" | "closed" |


**Positioner Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Positioner CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--reference-width` | The width of the reference element |
| `--reference-height` | The height of the root |
| `--available-width` | The available width in viewport |
| `--available-height` | The available height in viewport |
| `--x` | The x position for transform |
| `--y` | The y position for transform |
| `--z-index` | The z-index value |
| `--transform-origin` | The transform origin for animations |


**RootProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `UsePopoverReturn` | Yes |  |
| `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame |
| `lazyMount` | `boolean` | No | Whether to enable lazy mounting |
| `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state |
| `present` | `boolean` | No | Whether the node is present (controlled by the user) |
| `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. |
| `unmountOnExit` | `boolean` | No | Whether to unmount on exit. |


**Title Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Trigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Trigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | popover |
| `[data-part]` | trigger |
| `[data-placement]` | The placement of the trigger |
| `[data-state]` | "open" | "closed" |


#### Solid

**Root Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `autoFocus` | `boolean` | No | Whether to automatically set focus on the first focusable
content within the popover when opened. |
| `closeOnEscape` | `boolean` | No | Whether to close the popover when the escape key is pressed. |
| `closeOnInteractOutside` | `boolean` | No | Whether to close the popover when the user clicks outside of the popover. |
| `defaultOpen` | `boolean` | No | The initial open state of the popover when rendered.
Use when you don't need to control the open state of the popover. |
| `id` | `string` | No | The unique identifier of the machine. |
| `ids` | `Partial<{
  anchor: string
  trigger: string
  content: string
  title: string
  description: string
  closeTrigger: string
  positioner: string
  arrow: string
}>` | No | The ids of the elements in the popover. Useful for composition. |
| `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame |
| `initialFocusEl` | `() => HTMLElement | null` | No | The element to focus on when the popover is opened. |
| `lazyMount` | `boolean` | No | Whether to enable lazy mounting |
| `modal` | `boolean` | No | Whether the popover should be modal. When set to `true`:
- interaction with outside elements will be disabled
- only popover content will be visible to screen readers
- scrolling is blocked
- focus is trapped within the popover |
| `onEscapeKeyDown` | `(event: KeyboardEvent) => void` | No | Function called when the escape key is pressed |
| `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state |
| `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component |
| `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component |
| `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function invoked when the popover opens or closes |
| `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component |
| `onRequestDismiss` | `(event: LayerDismissEvent) => void` | No | Function called when this layer is closed due to a parent layer being closed |
| `open` | `boolean` | No | The controlled open state of the popover |
| `persistentElements` | `(() => Element | null)[]` | No | Returns the persistent elements that:
- should not have pointer-events disabled
- should not trigger the dismiss event |
| `portalled` | `boolean` | No | Whether the popover is portalled. This will proxy the tabbing behavior regardless of the DOM position
of the popover content. |
| `positioning` | `PositioningOptions` | No | The user provided options used to position the popover content |
| `present` | `boolean` | No | Whether the node is present (controlled by the user) |
| `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. |
| `unmountOnExit` | `boolean` | No | Whether to unmount on exit. |


**Anchor Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Arrow Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Arrow CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--arrow-size` | The size of the arrow |
| `--arrow-size-half` | Half the size of the arrow |
| `--arrow-background` | Use this variable to style the arrow background |
| `--arrow-offset` | The offset position of the arrow |


**ArrowTip Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**CloseTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Content Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Content Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | popover |
| `[data-part]` | content |
| `[data-state]` | "open" | "closed" |
| `[data-nested]` | popover |
| `[data-has-nested]` | popover |
| `[data-expanded]` | Present when expanded |
| `[data-placement]` | The placement of the content |


**Content CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--layer-index` | The index of the dismissable in the layer stack |
| `--nested-layer-count` | The number of nested popovers |


**Description Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Indicator Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Indicator Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | popover |
| `[data-part]` | indicator |
| `[data-state]` | "open" | "closed" |


**Positioner Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Positioner CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--reference-width` | The width of the reference element |
| `--reference-height` | The height of the root |
| `--available-width` | The available width in viewport |
| `--available-height` | The available height in viewport |
| `--x` | The x position for transform |
| `--y` | The y position for transform |
| `--z-index` | The z-index value |
| `--transform-origin` | The transform origin for animations |


**RootProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `UsePopoverReturn` | Yes |  |
| `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame |
| `lazyMount` | `boolean` | No | Whether to enable lazy mounting |
| `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state |
| `present` | `boolean` | No | Whether the node is present (controlled by the user) |
| `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. |
| `unmountOnExit` | `boolean` | No | Whether to unmount on exit. |


**Title Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Trigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Trigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | popover |
| `[data-part]` | trigger |
| `[data-placement]` | The placement of the trigger |
| `[data-state]` | "open" | "closed" |


#### Vue

**Root Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `autoFocus` | `boolean` | No | Whether to automatically set focus on the first focusable
content within the popover when opened. |
| `closeOnEscape` | `boolean` | No | Whether to close the popover when the escape key is pressed. |
| `closeOnInteractOutside` | `boolean` | No | Whether to close the popover when the user clicks outside of the popover. |
| `defaultOpen` | `boolean` | No | The initial open state of the popover when rendered.
Use when you don't need to control the open state of the popover. |
| `id` | `string` | No | The unique identifier of the machine. |
| `ids` | `Partial<{
  anchor: string
  trigger: string
  content: string
  title: string
  description: string
  closeTrigger: string
  positioner: string
  arrow: string
}>` | No | The ids of the elements in the popover. Useful for composition. |
| `initialFocusEl` | `() => HTMLElement | null` | No | The element to focus on when the popover is opened. |
| `lazyMount` | `boolean` | No | Whether to enable lazy mounting |
| `modal` | `boolean` | No | Whether the popover should be modal. When set to `true`:
- interaction with outside elements will be disabled
- only popover content will be visible to screen readers
- scrolling is blocked
- focus is trapped within the popover |
| `open` | `boolean` | No | The controlled open state of the popover |
| `persistentElements` | `(() => Element | null)[]` | No | Returns the persistent elements that:
- should not have pointer-events disabled
- should not trigger the dismiss event |
| `portalled` | `boolean` | No | Whether the popover is portalled. This will proxy the tabbing behavior regardless of the DOM position
of the popover content. |
| `positioning` | `PositioningOptions` | No | The user provided options used to position the popover content |
| `unmountOnExit` | `boolean` | No | Whether to unmount on exit. |


**Anchor Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Arrow Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Arrow CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--arrow-size` | The size of the arrow |
| `--arrow-size-half` | Half the size of the arrow |
| `--arrow-background` | Use this variable to style the arrow background |
| `--arrow-offset` | The offset position of the arrow |


**ArrowTip Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**CloseTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Content Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Content Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | popover |
| `[data-part]` | content |
| `[data-state]` | "open" | "closed" |
| `[data-nested]` | popover |
| `[data-has-nested]` | popover |
| `[data-expanded]` | Present when expanded |
| `[data-placement]` | The placement of the content |


**Content CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--layer-index` | The index of the dismissable in the layer stack |
| `--nested-layer-count` | The number of nested popovers |


**Description Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Indicator Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Indicator Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | popover |
| `[data-part]` | indicator |
| `[data-state]` | "open" | "closed" |


**Positioner Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Positioner CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--reference-width` | The width of the reference element |
| `--reference-height` | The height of the root |
| `--available-width` | The available width in viewport |
| `--available-height` | The available height in viewport |
| `--x` | The x position for transform |
| `--y` | The y position for transform |
| `--z-index` | The z-index value |
| `--transform-origin` | The transform origin for animations |


**RootProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `PopoverApi<PropTypes>` | Yes |  |
| `lazyMount` | `boolean` | No | Whether to enable lazy mounting |
| `unmountOnExit` | `boolean` | No | Whether to unmount on exit. |


**Title Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Trigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Trigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | popover |
| `[data-part]` | trigger |
| `[data-placement]` | The placement of the trigger |
| `[data-state]` | "open" | "closed" |


#### Svelte

**Root Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `autoFocus` | `boolean` | No | Whether to automatically set focus on the first focusable
content within the popover when opened. |
| `closeOnEscape` | `boolean` | No | Whether to close the popover when the escape key is pressed. |
| `closeOnInteractOutside` | `boolean` | No | Whether to close the popover when the user clicks outside of the popover. |
| `defaultOpen` | `boolean` | No | The initial open state of the popover when rendered.
Use when you don't need to control the open state of the popover. |
| `id` | `string` | No | The unique identifier of the machine. |
| `ids` | `Partial<{
  anchor: string
  trigger: string
  content: string
  title: string
  description: string
  closeTrigger: string
  positioner: string
  arrow: string
}>` | No | The ids of the elements in the popover. Useful for composition. |
| `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame |
| `initialFocusEl` | `() => HTMLElement | null` | No | The element to focus on when the popover is opened. |
| `lazyMount` | `boolean` | No | Whether to enable lazy mounting |
| `modal` | `boolean` | No | Whether the popover should be modal. When set to `true`:
- interaction with outside elements will be disabled
- only popover content will be visible to screen readers
- scrolling is blocked
- focus is trapped within the popover |
| `onEscapeKeyDown` | `(event: KeyboardEvent) => void` | No | Function called when the escape key is pressed |
| `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state |
| `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component |
| `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component |
| `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function invoked when the popover opens or closes |
| `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component |
| `onRequestDismiss` | `(event: LayerDismissEvent) => void` | No | Function called when this layer is closed due to a parent layer being closed |
| `open` | `boolean` | No | The controlled open state of the popover |
| `persistentElements` | `(() => Element | null)[]` | No | Returns the persistent elements that:
- should not have pointer-events disabled
- should not trigger the dismiss event |
| `portalled` | `boolean` | No | Whether the popover is portalled. This will proxy the tabbing behavior regardless of the DOM position
of the popover content. |
| `positioning` | `PositioningOptions` | No | The user provided options used to position the popover content |
| `present` | `boolean` | No | Whether the node is present (controlled by the user) |
| `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. |
| `unmountOnExit` | `boolean` | No | Whether to unmount on exit. |


**Anchor Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**Arrow Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**Arrow CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--arrow-size` | The size of the arrow |
| `--arrow-size-half` | Half the size of the arrow |
| `--arrow-background` | Use this variable to style the arrow background |
| `--arrow-offset` | The offset position of the arrow |


**ArrowTip Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**CloseTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**Content Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**Content Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | popover |
| `[data-part]` | content |
| `[data-state]` | "open" | "closed" |
| `[data-nested]` | popover |
| `[data-has-nested]` | popover |
| `[data-expanded]` | Present when expanded |
| `[data-placement]` | The placement of the content |


**Content CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--layer-index` | The index of the dismissable in the layer stack |
| `--nested-layer-count` | The number of nested popovers |


**Context Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `render` | `Snippet<[UsePopoverContext]>` | No |  |


**Description Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'p'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**Indicator Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**Indicator Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | popover |
| `[data-part]` | indicator |
| `[data-state]` | "open" | "closed" |


**Positioner Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**Positioner CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--reference-width` | The width of the reference element |
| `--reference-height` | The height of the root |
| `--available-width` | The available width in viewport |
| `--available-height` | The available height in viewport |
| `--x` | The x position for transform |
| `--y` | The y position for transform |
| `--z-index` | The z-index value |
| `--transform-origin` | The transform origin for animations |


**RootProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `UsePopoverReturn` | Yes |  |
| `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame |
| `lazyMount` | `boolean` | No | Whether to enable lazy mounting |
| `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state |
| `present` | `boolean` | No | Whether the node is present (controlled by the user) |
| `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. |
| `unmountOnExit` | `boolean` | No | Whether to unmount on exit. |


**Title Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'h2'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**Trigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**Trigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | popover |
| `[data-part]` | trigger |
| `[data-placement]` | The placement of the trigger |
| `[data-state]` | "open" | "closed" |


### Context

**API:**

| Property | Type | Description |
|----------|------|-------------|
| `portalled` | `boolean` | Whether the popover is portalled. |
| `open` | `boolean` | Whether the popover is open |
| `setOpen` | `(open: boolean) => void` | Function to open or close the popover |
| `reposition` | `(options?: Partial<PositioningOptions>) => void` | Function to reposition the popover |


## Accessibility

### Keyboard Support

<KeyBindingsTable id="popover" />