# Popover: Controlled

> Pass `open` and `onOpenChange` to drive it from your own state. The second argument tells you why it changed, such as `trigger-press`, `outside-press` or `escape-key`.

Example: https://hextaui.com/docs/popover/examples/controlled
Component docs: https://hextaui.com/docs/popover.md

## Add this example

```bash
npx shadcn@latest add https://hextaui.com/r/popover-controlled.json
```

This adds `components/examples/popover/controlled.tsx` with the Popover component and the HextaUI theme tokens.

## Source

```tsx title="components/examples/popover/controlled.tsx"
"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import {
  Popover,
  PopoverContent,
  PopoverDescription,
  PopoverHeader,
  PopoverTitle,
  PopoverTrigger,
} from "@/components/ui/popover"

export function PopoverControlled() {
  const [open, setOpen] = React.useState(false)
  const [reason, setReason] = React.useState("none")

  return (
    <div className="flex flex-col items-center gap-3">
      <div className="flex flex-wrap justify-center gap-2">
        <Popover
          open={open}
          onOpenChange={(next, details) => {
            setOpen(next)
            setReason(details.reason)
          }}
        >
          <PopoverTrigger render={<Button variant="outline" />}>
            Controlled
          </PopoverTrigger>
          <PopoverContent>
            <PopoverHeader>
              <PopoverTitle>Controlled</PopoverTitle>
              <PopoverDescription>
                The open state lives in the parent.
              </PopoverDescription>
            </PopoverHeader>
          </PopoverContent>
        </Popover>
        <Button variant="ghost" onClick={() => setOpen(!open)}>
          Toggle from outside
        </Button>
      </div>
      <p className="text-sm text-muted-foreground">
        Open: {String(open)} · Last reason: {reason}
      </p>
    </div>
  )
}
```

## Props in this example

### Popover

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `open` | `boolean` | – |  |
| `onOpenChange` | `(open: boolean, details) => void` | – | details.reason says what caused the change. |

### PopoverTrigger

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement \| (props, state) => ReactElement` | `<button>` |  |

## More Popover examples

- [Content that changes size](https://hextaui.com/docs/popover/examples/resizing.md)
- [Placement](https://hextaui.com/docs/popover/examples/placement.md)
- [Open on hover](https://hextaui.com/docs/popover/examples/hover.md)
- [Detached triggers](https://hextaui.com/docs/popover/examples/detached.md)
- [With a calendar](https://hextaui.com/docs/popover/examples/calendar.md)
- [Nested](https://hextaui.com/docs/popover/examples/nested.md)
- [Long content](https://hextaui.com/docs/popover/examples/long-content.md)
- [Modal](https://hextaui.com/docs/popover/examples/modal.md)
- [Disabled](https://hextaui.com/docs/popover/examples/disabled.md)
- [Right to left](https://hextaui.com/docs/popover/examples/rtl.md)
