import { Meta } from '@storybook/addon-docs/blocks';

<Meta
    title="Conventions/Popovers"
    summary="How popover-like components work, how to use and combine them."
/>

# Popovers

Popover components — [Tooltip](/docs/components-tooltip--docs),
[OnboardingTooltip](/docs/components-onboardingtooltip--docs), and
[DropdownMenu](/docs/components-dropdownmenu--docs) — share one model. Understanding it explains
how they compose and what they require from their triggers.

## Popovers don't render an element of their own

A popover attaches behavior to its child (or `trigger`) element instead of wrapping it in extra
DOM. The floating content renders elsewhere — in the Design System's shared portal — so it can
escape `overflow` and stacking contexts:

```tsx
<Tooltip content="Delete this lesson">
    <IconButton svg={<TokyoUITrash />} assistiveText="Delete" />
</Tooltip>
```

The `IconButton` above is rendered exactly once, by itself; `Tooltip` only adds event handlers and
ARIA attributes to it.

If you build a custom overlay that needs the same portal, use
[usePortalElement](/docs/utilities-useportalelement--docs).

## Triggers must forward refs

Because a popover needs a real DOM element to attach to, its direct child must accept a `ref`.
Design System components do. A custom component used as a trigger must use `React.forwardRef` and
pass both the ref and its props down to the underlying element — otherwise the popover silently
fails to position or open:

```tsx
const MyTrigger = React.forwardRef<HTMLButtonElement, Props>((props, ref) => (
    <button ref={ref} {...props} />
));
```

## Popovers compose in either order

Multiple popovers can share one trigger by nesting — for example a `Tooltip` explaining an action
and an `OnboardingTooltip` announcing it. The wrapping order doesn't matter; each popover forwards
the trigger to the next:

```tsx
<Tooltip content="This is a tooltip">
    <OnboardingTooltip title="New feature!" text="Try it out.">
        <IconButton svg={<TokyoUIFav />} assistiveText="Favourite" />
    </OnboardingTooltip>
</Tooltip>
```

Supported combinations of `Tooltip`, `OnboardingTooltip`, and `DropdownMenu` are verified by
[interaction tests](/story/conventions-popovers-tests--tooltip-with-onboarding-tooltip), covering
each pair in both nesting orders. Each popover opens and dismisses independently: hover and focus
drive the `Tooltip`, click drives the `DropdownMenu`, and the `OnboardingTooltip` shows until
acknowledged.
