# @cloud-ru/ds-portal-context > React Context, который задаёт DOM-узел для портальных компонентов (Tooltip, Popover, Dropdown, Modal, Drawer). Docs: /snack-v2/components/portal-context/ ## Установка ```sh pnpm add @cloud-ru/ds-portal-context ``` ## Когда использовать - DS встраивается в micro-frontend / shadow DOM — `document.body` недоступен или принадлежит host-приложению. - Необходимо поднимать stacking-контекст всех порталов в один контейнер (например, ради scoped CSS). - E2E или Storybook-тесты — портал нужно монтировать в фиксированный узел `iframe`. В обычном SPA-приложении провайдер не требуется — компоненты по умолчанию используют `document.body`. ## API ### PortalContextProvider | Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | `children` | `string \| number \| boolean \| ReactElement> \| Iterable \| ReactPortal \| null \| undefined` | — | no | | | `root` | `RefObject` | — | no | | ## Примеры ### CascadingThemes ```tsx import { Button } from '@cloud-ru/ds-button'; import { Popover } from '@cloud-ru/ds-popover'; import { PortalContextProvider } from '@cloud-ru/ds-portal-context'; import { COLOR_SCHEME, ColorScheme, useThemeClassnames } from '@cloud-ru/ds-theme'; import { Tooltip } from '@cloud-ru/ds-tooltip'; import { useRef } from 'react'; import styles from './CascadingThemes.module.scss'; // Тематический блок: useThemeClassnames форсит colorScheme и эмитит полный набор sn-* на свой div. // Этот же div — корень порталов блока (PortalContextProvider root={paneRef}), поэтому тултип и // поповер монтируются ВНУТРЬ него и наследуют тему блока через CSS-каскад токенов. function ThemedPane({ scheme, title }: { scheme: ColorScheme; title: string }) { const themeClassName = useThemeClassnames({ colorScheme: scheme }); const paneRef = useRef(null); return (

{title}

); } export function CascadingThemes() { return (
); } ``` ### CustomRoot ```tsx import { PortalContextProvider, usePortalContext } from '@cloud-ru/ds-portal-context'; import { useMemo, useState } from 'react'; import { createPortal } from 'react-dom'; function PortalChild() { const root = usePortalContext(); if (!root.current) return null; return createPortal(Я отрендерен в кастомном root-узле через PortalContext, root.current); } export function CustomRoot() { const [node, setNode] = useState(null); const root = useMemo(() => ({ current: node }), [node]); return (
Хост-компонент
); } ```