# FloatingDelayGroup

Provides context for a group of floating elements that should
share a `delay{:.objectKey}` which temporarily becomes `1{:js}`
ms after the first floating element of the group opens.

This allows higher discovery of floating elements when they have
a hover delay (like tooltips) when their reference elements are
placed near each other.

```js
import {FloatingDelayGroup} from '@floating-ui/react';

function App() {
  return (
    <FloatingDelayGroup delay={{open: 1000, close: 200}}>
      <Tooltip label="One">
        <button>Ref</button>
      </Tooltip>
      <Tooltip label="Two">
        <button>Ref</button>
      </Tooltip>
      <Tooltip label="Three">
        <button>Ref</button>
      </Tooltip>
    </FloatingDelayGroup>
  );
}
```

## Example

- [Tooltip delay group](https://codesandbox.io/s/clever-aryabhata-yq3xyc?file=/src/Group.tsx)

## Hooks

These hooks are used:

- `useDelayGroupContext(){:js}` — accessible due to a
  `<FloatingDelayGroup />{:js}` context wrapper, which provides
  the contextual delay for the group.
- `useDelayGroup(){:js}` — a hook called inside the component.

<Notice gap="above">
  The `id` must be unique. The label of a tooltip for example is
  usually unique in a given group, but you could use the `useId(){:js}` hook.
</Notice>

```js {2,13,20-23} /delay/
function Tooltip() {
  const {delay} = useDelayGroupContext();
  const id = useId();

  const [isOpen, setIsOpen] = useState(false);

  const {context} = useFloating({
    open: isOpen,
    onOpenChange: setIsOpen,
  });

  const hover = useHover(context, {
    delay,
  });

  const {getReferenceProps, getFloatingProps} = useInteractions([
    hover,
  ]);

  useDelayGroup(context, {
    // Must be unique
    id,
  });

  // ...
}
```

## Props

```ts
interface Props {
  delay: Delay;
  timeoutMs?: number;
}
```

### delay

**Required**

default: `0{:js}`

The delay to use for the group.

```js
<FloatingDelayGroup
  // Both open and close
  delay={200}
  // Or, configured individually
  delay={{open: 1000, close: 200}}
>
  {/* ... */}
</FloatingDelayGroup>
```

### timeoutMs

default: `0{:js}`

An optional explicit timeout to use for the group, which
represents when grouping logic will no longer be active after the
close delay completes. This is useful if you want grouping to
"last" longer than the close delay, for example if there is no
close delay at all.

```js
<FloatingDelayGroup timeoutMs={500}>
  {/* ... */}
</FloatingDelayGroup>
```

## Transitions

The `isInstantPhase{:.const}` boolean determines whether the
delay is currently in the instant phase. This allows you to make
transitions instant/faster. See
[`useTransitionStyles`](/docs/useTransition#usetransitionstyles).

```js /isInstantPhase/
const {currentId, isInstantPhase} = useDelayGroupContext();
const id = useId();

useDelayGroup(context, {
  id,
});

const instantDuration = 0;
const duration = 200;

const {isMounted, styles} = useTransitionStyles(context, {
  duration: isInstantPhase
    ? {
        open: instantDuration,
        // `id` is this component's `id`
        // `currentId` is the current group's `id`
        close: currentId === id ? duration : instantDuration,
      }
    : duration,
  // ...
});
```
