Список

Список — это обведённая поверхность из строк. У каждой строки есть заголовок, необязательное описание и слоты в начале и в конце — под аватар, иконку или элемент управления.

Простой список

  • Маршрутизация
    src/about.ht.js превращается в /about
  • Загрузка данных
    data() выполняется один раз, на сборке
  • Ресурсы
    В бандл попадает только то, на что ссылается ваш HTML
list(
  listItem({ title: 'Маршрутизация', description: 'src/about.ht.js превращается в /about' }),
  listItem({ title: 'Загрузка данных', description: 'data() выполняется один раз, на сборке' }),
  listItem({ title: 'Ресурсы', description: 'В бандл попадает только то, на что ссылается ваш HTML' }),
)

Слоты в начале и в конце

  • AL
    Ada Lovelace
    Отправила 3 коммита в main
    2 ч назад
  • GH
    Grace Hopper
    Открыла пул-реквест
    открыт
list(
  listItem({
    start: avatar({ name: 'Ada Lovelace', size: 'sm' }),
    title: 'Ada Lovelace',
    description: 'Отправила 3 коммита в main',
    end: chip({ size: 'sm', color: 'neutral' }, '2 ч назад'),
  }),
  listItem({
    start: avatar({ name: 'Grace Hopper', size: 'sm', color: 'success' }),
    title: 'Grace Hopper',
    description: 'Открыла пул-реквест',
    end: chip({ size: 'sm', color: 'success', dot: true }, 'открыт'),
  }),
)

Строки-ссылки

Строка с href кладёт якорь внутрь <li>, а не вокруг него, поэтому список остаётся корректным списком. Не ставьте в такую строку ещё и кнопку: интерактивное содержимое не может быть вложено в ссылку.

list(
  listItem({ title: 'Начало работы', description: 'Установка и первая страница', href: '/ru/docs' }),
  listItem({ title: 'Маршрутизация', description: 'Файловая, с динамическими сегментами', href: '/ru/docs/routing' }),
  listItem({ title: 'Развёртывание', description: 'Netlify, Vercel, Pages, Amplify', href: '/ru/docs/deployment' }),
)

Строки с элементами управления

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

  • Поиск Pagefind
    Индексирует каждую страницу в конце сборки
  • Оптимизация изображений
    Меняет размер и формат картинок. Нужен sharp.
  • Серверные острова
    Рендерит помеченные области в момент запроса
list(
  listItem({
    title: 'Поиск Pagefind',
    description: 'Индексирует каждую страницу в конце сборки',
    end: toggle({ 'aria-label': 'Поиск Pagefind', checked: true }),
  }),
  listItem({
    title: 'Оптимизация изображений',
    description: 'Меняет размер и формат картинок. Нужен sharp.',
    end: toggle({ 'aria-label': 'Оптимизация изображений', checked: true }),
  }),
  listItem({
    title: 'Серверные острова',
    description: 'Рендерит помеченные области в момент запроса',
    end: toggle({ 'aria-label': 'Серверные острова' }),
  }),
)

Без оформления

plain убирает рамку и фон — для списка, который лежит в карточке или боковой панели с собственной поверхностью.

Последние сборки

  • 94a837a
    main · 4 минуты назад
    прошла
  • dcfaaae
    main · 2 часа назад
    прошла
  • a46a461
    main · вчера
    упала
card(
  cardHeader({ title: 'Последние сборки' }),
  cardBody(
    list({ plain: true },
      listItem({ title: '94a837a', description: 'main · 4 минуты назад', end: chip({ size: 'sm', color: 'success', dot: true }, 'прошла') }),
      listItem({ title: 'dcfaaae', description: 'main · 2 часа назад', end: chip({ size: 'sm', color: 'success', dot: true }, 'прошла') }),
      listItem({ title: 'a46a461', description: 'main · вчера', end: chip({ size: 'sm', color: 'danger', dot: true }, 'упала') }),
    ),
  ),
)

Произвольные строки

Без title и description строка рисует ровно тех потомков, которых ей дали, — для раскладки, которую двухстрочная форма не покрывает.

  • Своя строка

    Внутри что угодно
list(
  listItem(
    stack({ direction: 'row', gap: 'md', align: 'center', justify: 'space-between', style: 'width: 100%' },
      stack({ gap: 'none' },
        text({ variant: 'small' }, 'Своя строка'),
        text({ variant: 'caption', tone: 'muted' }, 'Внутри что угодно'),
      ),
      button({ size: 'sm', variant: 'soft' }, 'Действие'),
    ),
  ),
)

Из данных

  • E
    English
    24 страниц
    en
  • E
    Español
    24 страниц
    es
  • Z
    简体中文
    24 страниц
    zh
return (() => {
  const locales = [
    { code: 'en', name: 'English', pages: 24 },
    { code: 'es', name: 'Español', pages: 24 },
    { code: 'zh', name: '简体中文', pages: 24 },
  ]

  return list(
    locales.map((locale) =>
      listItem({
        start: avatar({ name: locale.code, size: 'sm', color: 'neutral', square: true }),
        title: locale.name,
        description: locale.pages + ' страниц',
        end: chip({ size: 'sm', color: 'neutral' }, locale.code),
      }),
    ),
  )
})()

Пропсы

list():

ПропТипПо умолчаниюОписание
plainbooleanfalseУбрать рамку и фон.
asstring'ul'Какой элемент рендерить, например ol.

listItem():

ПропТипПо умолчаниюОписание
titleChild—Основная строка ряда.
descriptionChild—Приглушённая вторая строка.
startChild—Слот в начале — аватар или иконка.
endChild—Слот в конце — чип, элемент управления, отметка времени.
hrefstring—Делает строку ссылкой, помещая якорь внутрь li.
interactivebooleanfalseПодсветка при наведении без превращения в ссылку.