# @cloud-ru/ds-adaptive > React Context текущей раскладки (layoutType) — переключает компоненты дизайн-системы между mobile и desktop поверхностями. Docs: /snack-v2/components/adaptive/ ## Установка ```sh pnpm add @cloud-ru/ds-adaptive ``` ## Когда использовать - Приложение использует адаптивные компоненты дизайн-системы и должно переключать их между mobile и desktop поверхностями. Провайдер ставится один раз в корне. - Раскладка считается в корне через `useAdaptiveBootstrap()` (user-agent + media-query) и раздаётся вложенным компонентам без проброса пропа. - Микрофронт получает раскладку из реактивного стора хост-приложения — провайдер подключается через `store` (адаптер собирается `createAdaptiveStore`). - Серверный рендеринг: раскладка вычисляется из user-agent запроса через подпуть `@cloud-ru/ds-adaptive/ssr` (чистые функции без React Context). Точечно зафиксировать платформу для поддерева можно вложенным `` или HOC `withLayoutType(Component, …)` — он затеняет внешний контекст. Пропа `layoutType` у самих компонентов нет: форс идёт только через контекст. ## API ### AdaptiveProvider | Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | `children` | `string \| number \| boolean \| ReactElement> \| Iterable \| ReactPortal \| null \| undefined` | — | yes | | | `layoutType` | `desktop \| desktopSmall \| mobile \| tablet` | — | no | Статичная раскладка (SSR — значение на запрос, либо `useAdaptiveBootstrap()` в корне CSR). Реактивный источник — через `store`. | | `store` | `AdaptiveStore` | — | no | Внешний реактивный стор раскладки; приоритетнее `layoutType`, обновляет подписчиков без перерендера провайдера. | #### Related types - `AdaptiveStore` (interface) - `LayoutType` = `desktop | desktopSmall | mobile | tablet` ## Примеры ### CustomBreakpoints ```tsx import { AdaptiveProvider, isMobileLayout, useAdaptiveBootstrap, useAdaptiveLayout } from '@cloud-ru/ds-adaptive'; import { Tag } from '@cloud-ru/ds-tag'; import { Typography } from '@cloud-ru/ds-typography'; import { Flex } from '@cloud-ru/ds-uikit-product-flex'; // Раскладка приходит из контекста; Tag перекрашивается, когда ширина окна пересекает порог. function LayoutSurface() { const { layoutType } = useAdaptiveLayout(); const mobile = isMobileLayout(layoutType); return ; } export function CustomBreakpoints() { // Брейкпоинты переопределяются на уровне приложения: mobile-порог опущен с 767 до 480 px. // useAdaptiveBootstrap() читает ширину окна в корне приложения и передаёт результат в AdaptiveProvider. const { layoutType } = useAdaptiveBootstrap({ breakpoints: { mobile: 480 } }); return ( Порог mobile опущен до 480 px. Сузьте окно до этой ширины, чтобы раскладка стала мобильной. ); } ``` ### LayoutTypeOverride ```tsx import { AdaptiveProvider, isMobileLayout, LAYOUT_TYPE, LayoutType, useAdaptiveLayout } from '@cloud-ru/ds-adaptive'; import { SegmentControl } from '@cloud-ru/ds-segment-control'; import { Tag } from '@cloud-ru/ds-tag'; import { Typography } from '@cloud-ru/ds-typography'; import { Flex } from '@cloud-ru/ds-uikit-product-flex'; import { useState } from 'react'; const CONTEXT_ITEMS = [ { value: LAYOUT_TYPE.Mobile, label: 'mobile' }, { value: LAYOUT_TYPE.Desktop, label: 'desktop' }, ]; // Раскладка из общего контекста (AdaptiveProvider выше) — следует за переключателем. function FromContext() { const { layoutType } = useAdaptiveLayout(); return ( из контекста: ); } // Форс раскладки в поддереве — вложенный `` затеняет внешний // контекст (то же делает HOC `withLayoutType(Component, 'desktop')` на module-scope). Эта ветка // остаётся desktop при любом значении переключателя — пропа `layoutType` у компонента нет. function ForcedDesktop() { const { layoutType } = useAdaptiveLayout(); return ( форс поддерева на desktop: ); } export function LayoutTypeOverride() { const [context, setContext] = useState(LAYOUT_TYPE.Mobile); return ( setContext(value as LayoutType)} /> ); } ``` ### ProviderBasic ```tsx import { AdaptiveProvider, isMobileLayout, LAYOUT_TYPE, LayoutType, useAdaptiveLayout } from '@cloud-ru/ds-adaptive'; import { SegmentControl } from '@cloud-ru/ds-segment-control'; import { Tag } from '@cloud-ru/ds-tag'; import { Typography } from '@cloud-ru/ds-typography'; import { Flex } from '@cloud-ru/ds-uikit-product-flex'; import { useState } from 'react'; const LAYOUT_ITEMS = Object.values(LAYOUT_TYPE).map(value => ({ value, label: value })); // Потребитель берёт раскладку из AdaptiveProvider через useAdaptiveLayout() — без пропа и обёрток. // Так же ведут себя Adaptive*-компоненты внутри (на mobile уходят в BottomSheet). function LayoutSurface() { const { layoutType } = useAdaptiveLayout(); const mobile = isMobileLayout(layoutType); return ( useAdaptiveLayout(): {layoutType} ); } export function ProviderBasic() { const [layoutType, setLayoutType] = useState(LAYOUT_TYPE.Desktop); return ( setLayoutType(value as LayoutType)} /> ); } ```