GrTabPanels

  • ядро
  • Навигация
  • API · 2 props

Берут, когда к вкладкам нужны панели.

import { GrTabPanels } from '@feugene/granularity/components/GrTabPanels'

Обзор

Когда брать

  • к вкладкам нужны панели — компонент связывает их с GrTabs по ARIA, без ручных id;
  • панель тяжёлая — ленивое монтирование не строит содержимое до первого показа;
  • состояние панели надо сохранить — скрытая панель остаётся смонтированной, и введённое в ней не пропадает;
  • раскладка вкладок своя — панели стоят отдельно от списка вкладок, а не под ним.

Когда взять другое

НужноБерите
Нужен сам список вкладокGrTabs
Разделы раскрываются, а не переключаютсяGrCollapse
Переключается вид одного содержимогоGrSegmented

Playground контролы выводятся из API, а не пишутся руками

Сцена

Загружается…

0 изменено· состояние — в адресе

Примеры 1 у каждого — живое демо и его код

  • Вкладки в шапке, панели в содержимом

    Ряд живёт в шапке страницы, а панели — далеко под ним, поэтому это два компонента с одной моделью и одним id-base — именно он даёт каждой панели aria-labelledby на её вкладку. История счетов — lazy и keep-alive: строится при первом показе и дальше остаётся скрытой, и запрос при возврате не повторяется. Заметки тоже keep-alive — набранный там черновик переживает поход на другую вкладку.

    Fabrikam GmbHCustomer since March 2024 · Team plan

API порождается из пакета · разойтись не может

Props

PropTypeпо умолчаниюОписание
idBasestring | undefinedundefinedОбщая база id со `GrTabs`: с ней панели получают `aria-labelledby` на свои вкладки. Без неё id генерируется, и связи с вкладками нет.
modelValueобязательныйstring—`value` видимой панели — та же модель, что у `GrTabs`.

Слоты

SlotTypeОписание
defaultanyПанели (`GrTabPanel`).

Типы

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

Импорт
import type { GrTabPanelsContext, GrTabPanelsProps, GrTabPanelProps } from '@feugene/granularity/components/GrTabPanels'

Файлdist/types/components/GrTabPanels/context.d.ts

GrTabPanelsContextinterface

Контекст, который GrTabPanels предоставляет своим GrTabPanel.

interface GrTabPanelsContext {
    /** Значение активной вкладки (совпадает с `modelValue` у `GrTabs`). */
    activeValue: ComputedRef<string>;
    /** Общая база id для связки `tab`↔`tabpanel` (см. проп `idBase` у `GrTabs`). */
    idBase: ComputedRef<string>;
    /**
     * Задал ли `idBase` потребитель. Без него вкладок с подходящими id не
     * существует: `GrTabs` проставляет их **только** при явном `idBase`, — и
     * ссылаться на них панели нечем.
     */
    tabsLinked: ComputedRef<boolean>;
}

Файлdist/types/components/GrTabPanels/config.d.ts

grTabPanelsConfigconst

Granular-конфиг семейства GrTabPanels (контейнер GrTabPanels + панель GrTabPanel). Companion к GrTabs для ARIA-связки tab↔tabpanel.

const grTabPanelsConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrTabPanels">;

Файлdist/types/components/GrTabPanels/GrTabPanels.vue.d.ts

GrTabPanelsPropsinterface
interface GrTabPanelsProps {
    /** `value` видимой панели — та же модель, что у `GrTabs`. */
    modelValue: string;
    /**
     * Общая база id со `GrTabs`: с ней панели получают `aria-labelledby` на свои вкладки. Без неё
     * id генерируется, и связи с вкладками нет.
     */
    idBase?: string;
}

Файлdist/types/components/GrTabPanels/GrTabPanel.vue.d.ts

GrTabPanelPropsinterface
interface GrTabPanelProps {
    value: string;
    keepAlive?: boolean;
    /**
       * Не монтировать содержимое, пока панель не показали впервые. Имеет смысл
       * вместе с `keepAlive`: без него неактивная панель и так не в DOM.
       */
    lazy?: boolean;
}

Использование из прозы библиотеки

Связка держится на общем idBase
vue
<GrTabs v-model="tab" :tabs="tabs" id-base="settings" />

<GrTabPanels v-model="tab" id-base="settings">
  <GrTabPanel value="profile">…</GrTabPanel>
  <GrTabPanel value="billing">…</GrTabPanel>
</GrTabPanels>

idBase реактивен: его изменение доезжает до панелей. Раньше он вычислялся один раз при setup — панели оставались со старыми id, GrTabs уезжал на новые, и aria-controls ↔ aria-labelledby разъезжались молча.

Без idBase он генерируется сам — на собственный id панели этого хватает, а вот связи с вкладкой не будет: GrTabs проставляет вкладкам id только при явном idBase. В этом случае панель aria-labelledby не выставляет вовсе. Ссылка в пустоту хуже её отсутствия: диктор объявил бы имя панели пустой строкой вместо «имени нет», и потребитель уже не смог бы это починить. В dev-сборке случай выводится предупреждением — тем же приёмом, каким GrFormField ловит забытый контрол.

Смена панели

Входящая панель проявляется за --gr-duration-fast, слегка подъезжая снизу. Уходящая исчезает мгновенно, и это не экономия: держи контейнер обе панели разом, он на время перехода вырос бы на высоту обеих и дёрнул страницу.

При keepAlive перехода нет вовсе — панель из DOM не уходит, а hidden это display: none, который не анимируется в принципе. Системная настройка «уменьшить движение» гасит появление, как и всюду в пакете (docs/motion.md).

keepAlive и lazy

По умолчанию неактивная панель не в DOM. keepAlive оставляет её скрытой (hidden) — состояние форм не теряется. lazy добавляет к этому «не монтировать, пока не показали впервые»: вместе они дают «смонтировать один раз по требованию и больше не разрушать».

keepAlivelazyПоведение
——панель монтируется при показе, размонтируется при уходе
✓—все панели в DOM сразу, неактивные скрыты
✓✓панель появляется в DOM при первом показе и остаётся