InfoRow

InfoRow показывает одну или две пары “метка - значение” в строке. Компонент подходит для кратких сводок в карточках, сайдбарах и деталках сущностей.

Поддерживаются:

  • одна колонка (column="1");
  • две колонки в одной строке (column="2");
  • разделители, скелетон, tooltip к метке;
  • действия справа (rowActions, secondaryRowActions);
  • обрезка длинных заголовков через labelTruncate.

Если нужно отрисовать несколько строк по данным, используйте useGetContent и InfoRowFieldItem (пример ниже).

Демо

Preview
Очень длинный заголовок первого поля, который должен обрезаться по настройке truncate
Content
Prop
Type
Value
bottomDivider
boolean
className
text
column
1 | 2
content
text
data-test-id
text
label
text
labelClassName
text
labelTruncate
number
labelWidth
auto | fixed
loading
boolean
maxWidth
boolean
position
first | inner | last
rowActionsSlot
text
rowClassName
text
secondaryContent
text
secondaryLabel
text
secondaryLabelClassName
text
secondaryLabelTruncate
number
secondaryRowActionsSlot
text
topDivider
boolean
width
fixed | full
Code
<InfoRow label="Очень длинный заголовок первого поля, который должен обрезаться по настройке truncate" secondaryLabel="Очень длинный заголовок второго поля, который тоже должен обрезаться" content="Content" secondaryContent="Column 2" labelTruncate={1} secondaryLabelTruncate={1} column="1" maxWidth={false} data-test-id="info-row-demo" />

Несколько строк по данным

Список полей

Список полейНесколько строк: useGetContent и map по массиву полей
Name
Project
Active
Да
tsx
import { PlaceholderSVG } from '@cloud-ru/ds-icons/interface/system';
import { InfoRow, InfoRowFieldItem, useGetContent } from '@cloud-ru/ds-uikit-product-info-row';

type Row = { name: string; active: boolean };

const data: Row = { name: 'Project', active: true };

const items: InfoRowFieldItem<Row>[] = [
  {
    label: 'Name',
    accessorKey: 'name',
    rowActions: {
      first: {
        icon: <PlaceholderSVG />,
        'aria-label': 'Изменить',
        'data-test-id': 'data-list-action-first',
      },
      second: {
        icon: <PlaceholderSVG />,
        'aria-label': 'Копировать',
        'data-test-id': 'data-list-action-second',
      },
    },
  },
  { label: 'Active', accessorKey: 'active' },
];

export function DataListExample() {
  const getContent = useGetContent();

  return (
    <div>
      {items.map((item, index) => {
        const { label, accessorKey, render, ...rowProps } = item;
        const content = getContent<Row>({ data, render, accessorKey });
        return (
          <InfoRow
            key={String(accessorKey ?? label)}
            label={label}
            content={content}
            topDivider={index === 0}
            bottomDivider
            width='full'
            column='1'
            data-test-id={`data-list-row-${index}`}
            {...rowProps}
          />
        );
      })}
    </div>
  );
}

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

  • Короткая сводка полей “ключ - значение” в карточке или панели.
  • Детальная страница объекта, где важна компактная подача.
  • Когда таблица избыточна, а данных немного.

Когда лучше выбрать другой компонент

  • InfoGroup - когда данные уже описаны схемой полей и нужно вывести список строк по объекту.

InfoRow адаптивен сам по себе — на mobile (раскладка из AdaptiveProvider) он переключается в вертикальный comfort-формат, отдельный компонент для этого не нужен.

Установка

pnpm add @cloud-ru/ds-uikit-product-info-row
import { InfoRow, useGetContent, NO_DATA_PLACEHOLDER } from '@cloud-ru/ds-uikit-product-info-row'
import '@cloud-ru/ds-uikit-product-info-row/style.css'

Базовый пример

<InfoRow
  label='Статус'
  content='Активен'
  column='1'
  width='fixed'
/>

Props

Types

PropsInfoRowProps
PropTypeDefaultRequiredDescription
bottomDividerbooleannoРазделитель под строкой
classNamestringno
column"1" | "2"noОсь Figma `column`: одна или две колонки значений
contentReactNodenoПервая колонка значений (ось Figma `column=1` или левая при `column=2`)
data-test-idstringno
labelstringyesТекст метки
labelClassNamestringno
labelTooltipstring | Pick<QuestionTooltipProps, "open" | "onOpenChange" | "trigger" | "placement" | "tip" | "disableMaxWidth">noПодсказка у метки: строка или пропсы QuestionTooltip
labelTruncatenumbernoМаксимальное число строк метки (TruncateString)
labelWidth"auto" | "fixed"noШирина колонки метки
loadingbooleanno
maxWidthbooleannoОсь Figma `maxWidth`
position"first" | "inner" | "last"noТолько mobile: позиция строки в группе (`first`/`inner`/`last`) — задаёт скругление/разделители мобильной карточки. На desktop игнорируется (обычно проставляется `InfoGroup` автоматически).
rowActionsRowActionsPairnoДо двух кнопок `@cloud-ru/ds-button` (tonal neutral, size m) у первой колонки; при `column="2"` в макете — одна (`first`). Игнорируется, если задан `rowActionsSlot`
rowActionsSlotReactNodenoКастомная область действий у первой колонки; рендерится вместо `rowActions`.
rowClassNamestringno
secondaryContentReactNodenoВторая колонка значений (только при `column="2"`, ось Figma)
secondaryLabelstringnoВторая метка слева от второго значения (только при `column="2"`)
secondaryLabelClassNamestringnoКласс блока второй метки при `column="2"`
secondaryLabelTooltipstring | Pick<QuestionTooltipProps, "open" | "onOpenChange" | "trigger" | "placement" | "tip" | "disableMaxWidth">noПодсказка у второй метки
secondaryLabelTruncatenumbernoМакс. строк второй метки при `column="2"`
secondaryRowActionsRowActionsPairnoКнопки у второй колонки значений; в макете при `column="2"` — одна (`first`)
secondaryRowActionsSlotReactNodenoКастомные действия у второй колонки; если задано, вместо `secondaryRowActions`
topDividerbooleannoРазделитель над строкой
width"fixed" | "full"noШирина строки относительно контейнера

Unions

Types

InfoRowProps

Unions

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

InfoRow — адаптивный компонент с переключением поверхности (surface-swap). Раскладку он берёт из AdaptiveProvider (контекст @cloud-ru/ds-adaptive); публичный API единый для обеих платформ:

  • desktop (по умолчанию) — строка «метка — значение» в одну или две колонки.
  • mobile — вертикальный comfort-формат: метка и значение друг под другом, карточка со скруглением и разделителями.

Верстайте под desktop и поставьте один <AdaptiveProvider> в корне приложения — mobile-поверхность включается автоматически (desktop-first). Пропа layoutType у компонента нет: источник раскладки — только контекст.

Как форсировать платформу

Форс — только контекстом, не пропом:

  • Поддерево — вложенный провайдер:
    import { AdaptiveProvider } from '@cloud-ru/ds-adaptive'
    
    <AdaptiveProvider layoutType='mobile'>
      <InfoRow label='Статус' content='Активен' />
    </AdaptiveProvider>
  • Отдельный компонент — withLayoutType (module-scope, сахар над провайдером):
    import { withLayoutType } from '@cloud-ru/ds-adaptive'
    import { InfoRow } from '@cloud-ru/ds-uikit-product-info-row'
    
    const MobileInfoRow = withLayoutType(InfoRow, 'mobile')

Платформенные пропы

Таблица синхронизирована с JSDoc-пометками у InfoRowProps.

Пропdesktopmobile
position (first / inner / last)игнорируетсяиспользуется

position задаёт скругление и разделители мобильной карточки. Внутри InfoGroup он проставляется автоматически по месту строки в группе.

Mobile — карточка

Mobile — карточкаРаскладка форсирована в mobile: строки превращаются в карточку (скругления и разделители по `position`).
Имя
Mercury
Статус
Running
Регион
ru-moscow-1
Активен
Да
tsx
import { AdaptiveProvider, LAYOUT_TYPE } from '@cloud-ru/ds-adaptive';
import { InfoGroup } from '@cloud-ru/ds-uikit-product-info-row';

type Project = { name: string; status: string; region: string; active: boolean };

const data: Project = { name: 'Mercury', status: 'Running', region: 'ru-moscow-1', active: true };

export function MobileLayout() {
  return (
    <div style={{ maxWidth: 360 }}>
      <AdaptiveProvider layoutType={LAYOUT_TYPE.Mobile}>
        <InfoGroup
          data={data}
          items={[
            { label: 'Имя', accessorKey: 'name' },
            { label: 'Статус', accessorKey: 'status' },
            { label: 'Регион', accessorKey: 'region' },
            { label: 'Активен', accessorKey: 'active' },
          ]}
        />
      </AdaptiveProvider>
    </div>
  );
}

Подробнее о модели адаптивности — Адаптивность — паттерн.

Storybook

Figma

Доступность

  • Разделители: role="separator".
  • Для иконок в rowActions добавляйте aria-label.
  • Кнопки наследуют поведение и доступность @cloud-ru/ds-button.
  • QuestionTooltip: кнопка-триггер с aria-label.