Карточка

Карточка собирает связанное содержимое на собственной поверхности. Её части — cardHeader(), cardMedia(), cardBody(), cardFooter() — это отдельные функции, а не пропсы, поэтому вы берёте только нужные и ставите их в том порядке, какого требует макет.

Простая карточка

Файловая маршрутизация

src/about.ht.js → /about

Папки становятся путями. Скобки становятся параметрами. Никакого роутера настраивать не нужно.

card(
  cardHeader({ title: 'Файловая маршрутизация', subtitle: 'src/about.ht.js → /about' }),
  cardBody(text({ variant: 'small', tone: 'muted' }, 'Папки становятся путями. Скобки становятся параметрами. Никакого роутера настраивать не нужно.')),
)

Варианты

Outlined — по умолчанию. Elevated меняет рамку на тень, а flat вместо того и другого подкрашивает поверхность.

Outlined

Elevated

Flat

grid({ min: '13rem' },
  card({ variant: 'outlined' }, cardBody(text({ variant: 'small' }, 'Outlined'))),
  card({ variant: 'elevated' }, cardBody(text({ variant: 'small' }, 'Elevated'))),
  card({ variant: 'flat' }, cardBody(text({ variant: 'small' }, 'Flat'))),
)

С подвалом

divided добавляет тонкую линию над подвалом. Подвал прижимается к низу, поэтому у карточек в ряд действия выстраиваются на одной линии, даже когда текст сверху разной длины.

Базовый сайт

Минимальный проект плюс конфигурации развёртывания.

Блог на Markdown

Папка .md-файлов, отрендеренных в статические страницы, с RSS-лентой и вообще без клиентского JavaScript.

grid({ min: '14rem' },
  card(
    cardHeader({ title: 'Базовый сайт' }),
    cardBody(text({ variant: 'small', tone: 'muted' }, 'Минимальный проект плюс конфигурации развёртывания.')),
    cardFooter({ divided: true }, button({ size: 'sm', variant: 'soft' }, 'Открыть')),
  ),
  card(
    cardHeader({ title: 'Блог на Markdown' }),
    cardBody(text({ variant: 'small', tone: 'muted' }, 'Папка .md-файлов, отрендеренных в статические страницы, с RSS-лентой и вообще без клиентского JavaScript.')),
    cardFooter({ divided: true }, button({ size: 'sm', variant: 'soft' }, 'Открыть')),
  ),
)

Медиа

cardMedia() заполняет верх карточки с фиксированным соотношением сторон, поэтому ряд карточек остаётся ровным, какими бы ни были исходные картинки.

По умолчанию 16 / 9

ratio: 4 / 3

grid({ min: '13rem' },
  card(
    cardMedia({ src: '/logo.svg', alt: '', style: 'background: var(--su-surface-2); object-fit: contain; padding: 1rem' }),
    cardBody(text({ variant: 'small' }, 'По умолчанию 16 / 9')),
  ),
  card(
    cardMedia({ src: '/logo.svg', alt: '', ratio: '4 / 3', style: 'background: var(--su-surface-2); object-fit: contain; padding: 1rem' }),
    cardBody(text({ variant: 'small' }, 'ratio: 4 / 3')),
  ),
)

Вся карточка как ссылка

Задайте карточке href — и вся поверхность станет одной ссылкой, вместе с приподниманием при наведении. Не кладите кнопки и другие ссылки внутрь карточки в таком виде: интерактивное содержимое не может быть вложено в ссылку. Лучше поставьте кнопку в подвал обычной карточки.

grid({ min: '14rem' },
  card({ href: '/ru/docs/routing' },
    cardHeader({ title: 'Маршрутизация', subtitle: 'Читать руководство' }),
    cardBody(text({ variant: 'small', tone: 'muted' }, 'Динамические маршруты, перехватчики и группы маршрутов.')),
  ),
  card({ href: '/ru/docs/data' },
    cardHeader({ title: 'Загрузка данных', subtitle: 'Читать руководство' }),
    cardBody(text({ variant: 'small', tone: 'muted' }, 'data() выполняется на сборке, с кэшированием fetch.')),
  ),
)

Внутренние отступы

Один проп задаёт отступы сразу для всех частей карточки.

padding: sm

padding: xl

stack({ gap: 'md' },
  card({ padding: 'sm' }, cardBody(text({ variant: 'small' }, 'padding: sm'))),
  card({ padding: 'xl' }, cardBody(text({ variant: 'small' }, 'padding: xl'))),
)

Свободное содержимое

Части — это удобство, а не обязанность: карточка принимает любых потомков, а cardHeader() принимает собственных потомков рядом с заголовком — для аватара или кнопки меню справа.

Paul Browne

Развёрнуто 4 минуты назад

PB
Сборка прошла12 страниц4,1 кБ
card(
  cardHeader(
    { title: 'Paul Browne', subtitle: 'Развёрнуто 4 минуты назад' },
    avatar({ name: 'Paul Browne', size: 'sm' }),
  ),
  cardBody(
    stack({ direction: 'row', gap: 'sm', wrap: true },
      chip({ color: 'success', dot: true }, 'Сборка прошла'),
      chip({ color: 'neutral' }, '12 страниц'),
      chip({ color: 'neutral' }, '4,1 кБ'),
    ),
  ),
)

Пропсы

card():

ПропТипПо умолчаниюОписание
variant'outlined' | 'elevated' | 'flat''outlined'Как поверхность отделяется от страницы.
hrefstring—Рендерит всю карточку как ссылку.
paddingSpace'lg'Отступы, которые использует каждая часть карточки.

Части:

ЧастьПропсыПо умолчаниюОписание
cardHeadertitle, subtitle—Заголовок и подзаголовок плюс любые потомки рядом с ними.
cardTitleas'h3'Заголовок сам по себе, когда шапка собирается вручную.
cardSubtitle—Приглушённая строка под заголовком.
cardMediasrc, alt, ratio'16 / 9'Обложка с фиксированным соотношением сторон.
cardBody—Основная область содержимого.
cardFooterdividedfalseНижний ряд действий; divided добавляет тонкую линию сверху.