# FloatingTree

Provides context for nested floating elements when they are not
children of each other on the DOM.

A nested floating element may look like the following, where
there is a popover **inside** the content of another one:

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

function App() {
  return (
    <FloatingTree>
      <Popover
        render={() => (
          <Popover render={() => 'Nested Popover'}>
            <button>Child</button>
          </Popover>
        )}
      >
        <button>Root</button>
      </Popover>
    </FloatingTree>
  );
}
```

<Notice>
  If your floating elements are not portalled, this may not be
  necessary, however the additional context can help. By always
  portalling your floating element, you can avoid clipping
  issues.
</Notice>

## Usage

The following creates an infinitely nestable `<Popover />{:js}`
component. Usage of this component must be wrapped within a
single `<FloatingTree />{:js}` component as seen in the previous
code snippet:

```js /nodeId/
function Popover({children}) {
  // Subscribe this component to the <FloatingTree />
  const nodeId = useFloatingNodeId();

  // Pass the subscribed `nodeId` to useFloating()
  useFloating({
    nodeId
  });

  // Wrap the rendered element(s) in a `<FloatingNode />`,
  // passing in the subscribed `nodeId`
  return (
    <FloatingNode id={nodeId}>
      <FloatingPortal>
        {isOpen && /* floating element */}
      </FloatingPortal>
    </FloatingNode>
  );
}
```

## Hooks

- `useFloatingNodeId(){:js}` subscribes the component to the tree
  context. Call this only once as it has side effects.
- `useFloatingParentNodeId(){:js}` returns the parent
  `FloatingNode{:.class}` id, if it exists. This will be
  `null{:js}` for roots (not nested).
- `useFloatingTree(){:js}` for accessing the tree object, which
  includes an event emitter to communicate across the tree
  components (`events{:.objectKey}`).

```js
interface FloatingTreeType {
  nodesRef: React.MutableRefObject<Array<FloatingNodeType>>;
  events: FloatingEvents;
  addNode: (node: FloatingNodeType) => void;
  removeNode: (node: FloatingNodeType) => void;
}
```

## Custom parent

By default, the parent node is the closest
`<FloatingNode />{:js}`, but you can specify a custom parent node
by passing in the `parentId` to `useFloatingNodeId(){:js}`:

```js
const nodeId = useFloatingNodeId(parentId);
```

This is useful if you want to mark a sibling floating element in
the React tree as the child of another sibling.

## FloatingTree wrapper

You can use the following technique to avoid having the consumer
specify the `<FloatingTree />{:js}` wrapper:

```js
function PopoverComponent() {
  // Main logic as seen earlier
}

// This is the component the consumer uses
export function Popover(props) {
  const parentId = useFloatingParentNodeId();

  // This is a root, so we wrap it with the tree
  if (parentId === null) {
    return (
      <FloatingTree>
        <PopoverComponent {...props} />
      </FloatingTree>
    );
  }

  return <PopoverComponent {...props} />;
}
```
