Layout

Пакет @cloud-ru/ds-uikit-product-layout — блоки-состояния продуктового экрана поверх @cloud-ru/ds-info-block и @cloud-ru/ds-block:

  • EmptyBlock — заглушка пустого состояния (иконка, заголовок, описание, опциональный слот действий).
  • NoAccess — экран ограниченного доступа с локализованным сообщением и lock-иконкой.

Демо

EmptyBlock

Preview
Title text
Body text
Prop
Type
Value
align
horizontal | vertical
className
text
content
text
data-test-id
text
footer
text
title
text
Code
<EmptyBlock title="Title text" content="Body text" icon={"icon":{}} data-test-id="empty-block-demo" />

NoAccess

Preview
Название сервиса
Доступ ограничен
У вас нет прав для просмотра этого контента.
Для получения доступа обратитесь к администратору организации или проекта.
Prop
Type
Value
className
text
data-test-id
text
serviceName
text
Code
<NoAccess serviceName="Название сервиса" data-test-id="no-access-demo" />

Когда использовать

  • EmptyBlock:
    • список, таблица или экран без данных;
    • нужна подсказка-действие («создать», «импортировать») через слот footer.
  • NoAccess:
    • у пользователя нет прав на контент;
    • текст сообщения берётся из локали и не задаётся вручную.

Анатомия

Оба компонента строятся на @cloud-ru/ds-block + @cloud-ru/ds-info-block: нейтральная подложка, иконка, заголовок, описание. У EmptyBlock опционален слот footer; у NoAccess — опциональный serviceName над блоком и локализованный текст.

Установка

pnpm add @cloud-ru/ds-uikit-product-layout
import { EmptyBlock, NoAccess } from '@cloud-ru/ds-uikit-product-layout';
import '@cloud-ru/ds-uikit-product-layout/style.css';

NoAccess берёт текст из @cloud-ru/ds-locale — оберните приложение в LocaleProvider.

Примеры использования

EmptyBlock со слотом действий

EmptyBlock со слотом действий
Нет данных
Создайте первую запись, чтобы начать работу
tsx
import { ButtonGroup } from '@cloud-ru/ds-button';
import { PlaceholderSVG } from '@cloud-ru/ds-icons/interface/system';
import { EmptyBlock } from '@cloud-ru/ds-uikit-product-layout';

export function EmptyBlockWithFooter() {
  return (
    <EmptyBlock
      icon={{ icon: PlaceholderSVG }}
      title='Нет данных'
      content='Создайте первую запись, чтобы начать работу'
      footer={<ButtonGroup primaryAction={{ label: 'Создать' }} secondaryAction={{ label: 'Импортировать' }} />}
    />
  );
}

NoAccess с названием сервиса

NoAccess с названием сервиса
Название сервиса
Доступ ограничен
У вас нет прав для просмотра этого контента.
Для получения доступа обратитесь к администратору организации или проекта.
tsx
import { LocaleProvider } from '@cloud-ru/ds-locale';
import { NoAccess } from '@cloud-ru/ds-uikit-product-layout';

export function NoAccessBasic() {
  return (
    <LocaleProvider lang='ru-RU'>
      <NoAccess serviceName='Название сервиса' />
    </LocaleProvider>
  );
}

Props

EmptyBlock

Types

PropsEmptyBlockProps
PropTypeDefaultRequiredDescription
align"horizontal" | "vertical"noВыравнивание иконки и текста
classNamestringnoДополнительный класс
contentReactNodenoОписание под заголовком
data-test-idstringno
footerReactNodenoСлот действий под текстом (например, `ButtonGroup`)
iconIconPredefinedPropsnoИконка
layoutPresetsPartial<Record<LayoutType, Partial<EmptyBlockLayoutDefaults>>>noOverride mobile-дефолтов адаптива для этого инстанса (deep-merge поверх `EMPTY_BLOCK_LAYOUT_PRESETS`). Escape-hatch: обычно не нужен — DS-пресет применяется автоматически по `AdaptiveProvider`.
titlestringnoЗаголовок

Types

EmptyBlockProps

NoAccess

Types

PropsNoAccessProps
PropTypeDefaultRequiredDescription
classNamestringnoДополнительный класс
data-test-idstringno
serviceNamestringnoЗаголовок над блоком (например, название сервиса)

Types

NoAccessProps

Адаптивность

Оба компонента читают раскладку из контекста @cloud-ru/ds-adaptive — отдельного пропа layoutType нет. Поставьте один <AdaptiveProvider> в корне приложения — mobile-поведение применяется автоматически.

Desktop-first. Верстайте под desktop; override нужен только как escape-hatch.

EmptyBlock

EmptyBlock — компонент класса preset-defaults: DOM один, по раскладке меняется дефолт align в InfoBlock.

Пропdesktopmobile
alignhorizontalvertical

Источник mobile-дефолтов — экспортируемая константа EMPTY_BLOCK_LAYOUT_PRESETS.

import { EmptyBlock } from '@cloud-ru/ds-uikit-product-layout'

// Явный проп — задаёт DESKTOP-значение; mobile остаётся vertical
<EmptyBlock align='horizontal' title='…' content='…' />

// Изменить mobile — только через layoutPresets
<EmptyBlock layoutPresets={{ mobile: { align: 'horizontal' } }} title='…' content='…' />

NoAccess

На mobile контейнер сужается (max-width: 360px); на desktop — широкий (max-width: 1200px). Отдельных адаптивных пропов нет — поведение полностью определяется раскладкой из AdaptiveProvider.

Подробнее о модели раскладки — в @cloud-ru/ds-adaptive.

Storybook

Figma