# Popover

> Positioned floating panel for menus, forms, and custom UI. `role="dialog"` with focus management.

- Available in: `@sisyphos-ui/react`, `@sisyphos-ui/vue`, `@sisyphos-ui/angular`
- Docs: https://www.sisyphosui.com/docs/components/popover

## Installation

Pick the framework binding that matches your stack:

```bash
pnpm add @sisyphos-ui/react   # React 18+
pnpm add @sisyphos-ui/vue     # Vue 3+
pnpm add @sisyphos-ui/angular # Angular 17+
```

## Import

```tsx
import "@sisyphos-ui/react/styles.css";
import { Popover } from "@sisyphos-ui/react";
```

## Framework usage

### React 18+

```tsx
import { Popover, Button } from "@sisyphos-ui/react";

export const Help = () => (
  <Popover content={<div>Popovers carry rich interactive content.</div>}>
    <Button variant="outlined">Help</Button>
  </Popover>
);
```

### Vue 3+

```vue
<script setup lang="ts">
import { Popover, Button } from "@sisyphos-ui/vue";
</script>

<template>
  <Popover>
    <Button variant="outlined">Help</Button>
    <template #content>
      <div>Popovers carry rich interactive content.</div>
    </template>
  </Popover>
</template>
```

### Angular 17+

```ts
import { Component } from "@angular/core";
import { Popover, Button } from "@sisyphos-ui/angular";

@Component({
  selector: "app-help",
  standalone: true,
  imports: [Popover, Button],
  template: `
    <sui-popover>
      <sui-button variant="outlined">Help</sui-button>
      <div popover-content>Popovers carry rich interactive content.</div>
    </sui-popover>
  `,
})
export class HelpComponent {}
```

## Examples

### Default

Interactive floating panel — focusable, outside-click dismissable.

```tsx
import { useState } from "react";
import { Button, Popover } from "@sisyphos-ui/react";

export function Example() {
  const [open, setOpen] = useState(false);

  return (
    <Popover
      open={open}
      onOpenChange={setOpen}
      content={
        <div className="w-64 p-4">
          <h4 className="text-sm font-semibold">Workspace settings</h4>
          <p className="mt-1 text-xs text-neutral-500">
            Update your workspace name and default timezone.
          </p>
          <div className="mt-3 flex justify-end gap-2">
            <Button size="sm" variant="text" onClick={() => setOpen(false)}>Cancel</Button>
            <Button size="sm" onClick={() => setOpen(false)}>Save</Button>
          </div>
        </div>
      }
    >
      <Button variant="outlined">Open popover</Button>
    </Popover>
  );
}
```

### Hover trigger

`trigger="hover"` shows the popover on hover/focus like a richer tooltip.

```tsx
import { Button, Popover } from "@sisyphos-ui/react";

export function Example() {
  return (
    <Popover
      trigger="hover"
      openDelay={150}
      closeDelay={200}
      content={
        <div>
          <div>@ada.lovelace</div>
          <div>Admin · joined 3 years ago · 142 projects</div>
        </div>
      }
    >
      <Button variant="text">@ada.lovelace</Button>
    </Popover>
  );
}
```

### Manual trigger

`trigger="manual"` hands full open/close control to the parent — ideal for form flows and shortcuts.

```tsx
import { useState } from "react";
import { Button, Popover } from "@sisyphos-ui/react";

export function Example() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Popover
        trigger="manual"
        open={open}
        onOpenChange={setOpen}
        content={<div>Triggered from outside.</div>}
      >
        <span>Anchor element</span>
      </Popover>
      <Button size="sm" onClick={() => setOpen(v => !v)}>
        {open ? "Close" : "Open"} from outside
      </Button>
    </>
  );
}
```

### Placements

Auto-flipping placement reroutes the popover when it doesn't fit.

```tsx
import { useState } from "react";
import { Button, Popover } from "@sisyphos-ui/react";

export function Example() {
  const [placement, setPlacement] = useState<"top" | "bottom" | "left" | "right">("top");

  return (
    <>
      {(["top", "bottom", "left", "right"] as const).map((p) => (
        <Button key={p} size="sm" onClick={() => setPlacement(p)}>{p}</Button>
      ))}
      <Popover key={placement} placement={placement} content={<div>Placement = {placement}</div>}>
        <Button variant="outlined">Anchor</Button>
      </Popover>
    </>
  );
}
```

<!-- exports: { "Popover": "@sisyphos-ui/react" } -->