ItemContent
ItemContent — каноничная разметка основного контента item’а: заголовок (label), мета справа (caption), подпись снизу (description). Используется как значение поля item.content, а также экспортируется отдельно для кастомного рендеринга внутри contentRender.
Когда использовать
- Всегда, когда элемент списка можно описать как «заголовок + мета-подпись + короткое описание».
- Когда нужен одинаковый truncate-алгоритм во всех списках пакета.
- Когда
contentзадаётся как объект вitems— ровно это и естьItemContentпод капотом.
Когда не нужен:
- Совсем кастомный layout внутри item — передавайте в
contentсвойReactNode, но тогда единый visual-signal и truncate ложатся на вас. - Элемент с одной иконкой без текста — передавайте
beforeContent/afterContentи оставьтеcontentпустым.
Анатомия
Slots
label(required) — заголовок item’а (имя файла, название валюты, email-адрес).caption— короткая мета справа (счётчик, дата, badge, shortcut).description— подпись под заголовком (хвост описания, короткая справка, секундный статус).
Вне ItemContent, но рядом (поля item’а):
beforeContent— иконка / аватар слева.afterContent— слот справа: чеврон / trailing-иконка в иконочном квадрате; произвольный контент (счётчик, badge, tag) рендерится в натуральном размере без обрезки.switch: true— заменяет чекбокс/маркер наSwitchсправа; состояние тумблера берётся изselection. Для списков-настроек, где выбор = включение функции.showSwitchIconзарезервирован под иконку тумблера.
Group variant
У групповых item’ов (type: 'group' / 'group-select') заголовок оформляется ItemContent-независимо, через groupVariant:
subtitle— контрастный подзаголовок секции.subtitleTertiary(default) — приглушённый третичный текст.
Truncate
- Дефолт:
label— 1 строка,description— 2 строки, вариант обрезки —end(многоточие в конце). - Переопределяется через
truncate.label,truncate.description,truncate.variant(end/middle).
Установка
ItemContent поставляется вместе с @cloud-ru/ds-list:
import { ItemContent } from '@cloud-ru/ds-list'
Примеры использования
99% случаев — content передаётся как объект, компонент сам строит <ItemContent /> под капотом:
content как объект
- Входящие12
- Отправленные
- Архив238
- КорзинаУдаляется через 30 дней
import { List } from '@cloud-ru/ds-list';
import styles from './styles.module.scss';
export function BasicList() {
return (
<div className={styles.box}>
<List
size='s'
items={[
{ id: 'inbox', content: { label: 'Входящие', caption: '12' } },
{ id: 'sent', content: { label: 'Отправленные' } },
{ id: 'archive', content: { label: 'Архив', caption: '238' } },
{ id: 'trash', content: { label: 'Корзина', description: 'Удаляется через 30 дней' } },
]}
/>
</div>
);
}Слоты beforeContent / afterContent
- Отчёты24
- invoice-2024.pdf1.2 МБ
import { FileSVG, FolderSVG, StarSVG } from '@cloud-ru/ds-icons/interface/system';
import { List } from '@cloud-ru/ds-list';
import styles from './styles.module.scss';
export function ItemContentSlots() {
return (
<div className={styles.box}>
<List
size='m'
items={[
{
id: 'reports',
beforeContent: <FolderSVG />,
content: { label: 'Отчёты', caption: '24' },
afterContent: <StarSVG />,
},
{
id: 'invoice',
beforeContent: <FileSVG />,
content: { label: 'invoice-2024.pdf', caption: '1.2 МБ' },
},
]}
/>
</div>
);
}Заголовок, caption и description вместе
- eu-west-1ДоступноИрландия — основной регион размещения
- us-east-1ДеградацияСеверная Виргиния — повышенная задержка отклика
import { List } from '@cloud-ru/ds-list';
import styles from './styles.module.scss';
export function ItemContentDescription() {
return (
<div className={styles.box}>
<List
size='l'
items={[
{
id: 'eu-west',
content: {
label: 'eu-west-1',
caption: 'Доступно',
description: 'Ирландия — основной регион размещения',
},
},
{
id: 'us-east',
content: {
label: 'us-east-1',
caption: 'Деградация',
description: 'Северная Виргиния — повышенная задержка отклика',
},
},
]}
/>
</div>
);
}Обрезка текста (truncate)
- very-long-instance-name-that-overflows.example.internalvery-long-instance-name-that-overflows.example.internal8Длинное описание ресурса, которое не помещается в одну строку и обрезается по заданному числу строк
import { List } from '@cloud-ru/ds-list';
import styles from './styles.module.scss';
export function ItemContentTruncate() {
return (
<div className={styles.narrowBox}>
<List
size='m'
items={[
{
id: 'truncated',
content: {
label: 'very-long-instance-name-that-overflows.example.internal',
caption: '8',
description:
'Длинное описание ресурса, которое не помещается в одну строку и обрезается по заданному числу строк',
truncate: { label: 1, description: 2, variant: 'middle' },
},
},
]}
/>
</div>
);
}Если нужен кастомный слот (бейдж, превью, аватар) поверх стандартной разметки — используйте contentRender на List. Внутри возвращайте <ItemContent {...props} /> плюс свои дополнения. Это сохраняет типографику и truncate.
Доступность
labelостаётся текстовым заголовком — ассистивные технологии прочитают его как основное имя элемента.captionиdescriptionнаходятся в том же DOM-узле и читаются следом за заголовком.- Визуальные truncate-поведения реализованы через CSS
-webkit-line-clamp, текст не вырезается из DOM и остаётся доступен скринридеру целиком. - Disabled-элементы получают уменьшенный контраст +
data-disabled, но цвет не единственный сигнал: интерактивность выключается и на уровне родительского item’а.
Props
Types
ItemContentProps| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
caption | string | — | no | |
className | string | — | no | |
data-test-id | string | — | no | |
description | string | — | no | |
disabled | boolean | — | no | |
label | string | number | — | yes | |
truncate | TruncateProps | — | no |
Types
ItemContentProps
TruncateProps
Storybook
ItemContent живёт внутри List, отдельной истории нет — все сценарии видны в List playground.