GrDivider

  • ядро
  • Данные
  • API · 8 props

Берут, когда блоки надо разделить.

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

Обзор

Когда брать

  • блоки надо разделить — секции формы, группы пунктов меню, части карточки;
  • у разделителя есть подпись — «или», «Ещё», дата в ленте сообщений;
  • разделять надо по горизонтали — вертикальная линия в тулбаре и панели действий;
  • нужна нативная семантика — без подписи рендерится <hr> с неявной ролью separator.

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

НужноБерите
Границу двигает пользовательGrSplitter
Разделяются разделы с заголовкамиGrFormSection
Разделяются пункты менюGrDropdownMenu с dividers
Разделяются строки спискаGrList с divided

Варианты все тона и виды — настоящим компонентом

variant

  • solid
  • dashed
  • dotted

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

Сцена

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

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

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

  • Слово в разрыве

    label кладёт «или» между двумя способами входа и становится доступным именем: скринридер слышит «или, разделитель». spacing даёт линии воздух с обеих сторон без отступов у соседей.

    Sign in to Acme

    Use your work account

  • Даты и отметка новых сообщений

    Слот по умолчанию принимает разметку — плашку даты, красное «New». Разделитель прячет содержимое от скринридера, поэтому слоту нужен aria-label. align="end" уводит слово к краю, а --gr-brd перекрашивает линию.

    GW
    Grace Wu 17:42

    Retries are in. Five attempts with backoff, then the event goes to the dead-letter queue.

    LR
    Linus Ray 09:05

    Ran it against staging overnight: 1,284 events, zero lost.

    AL
    Ada Lin 09:31

    Approved. Let’s ship it after the 10:00 deploy.

  • Группы инструментов в ряду

    orientation="vertical" делит панель инструментов на группы и сам тянется на высоту flex-ряда. В строке состояния линия короче ряда — её задаёт length, и вне flex-ряда это единственный способ дать линии высоту.

    Webhook retries

    Failed deliveries are retried five times with exponential backoff before the event moves to the dead-letter queue.

    Saved214 wordsMarkdown
  • Вес линии несёт смысл

    variant="dotted" между строками одного списка, dashed перед поправками, которые ещё не итог, и сплошная линия thickness="2", которая закрывает сумму. Толщина уходит в --gr-divider-thickness, поэтому её можно задать и контейнером.

    Order summary

    Team plan · 9 seats€432.00

    Extra storage · 180 GB€36.00

    Automation runs over quota€12.40

    Subtotal€480.40
    Annual discount-€48.00
    VAT 20 %€86.48

    Total due€518.88

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

Props

PropTypeпо умолчаниюОписание
lengthstring | number | undefinedundefinedДлина линии: высота вертикального разделителя, ширина горизонтального. Нужна вертикальному вне flex-родителя — там ему не от чего растянуться.
variantGrDividerVariant | undefinedundefinedНачертание линии. Не задано — берётся из `GrConfigProvider`, иначе `solid`.
ariaLabelstring | undefinedundefinedИмя разделителя для скринридера. Подпись из слота строкой не выразить, поэтому имя задаётся отдельно; при `label` оно берётся из него.
orientationGrDividerOrientation | undefined"horizontal"Направление линии: между блоками или между элементами в ряду. По умолчанию `horizontal`.
labelstring | undefinedundefinedПодпись в разрыве линии: «или», название раздела. Только у горизонтального; даёт и имя.
alignGrDividerAlign | undefined"center"Где стоит подпись на линии: `start`, `center` или `end`. По умолчанию `center`.
spacingGrDividerSpacing | undefinedundefinedОтступы вокруг разделителя. Не задано — из `GrConfigProvider`, иначе `none`.
thicknessstring | number | undefinedundefinedТолщина линии. Число трактуется как пиксели.

Слоты

SlotTypeОписание
defaultanyПодпись внутри линии: «или», название раздела.

Типы

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

Импорт
import type { GrDividerOrientation, GrDividerAlign, GrDividerVariant } from '@feugene/granularity/components/GrDivider'

Файлdist/types/components/GrDivider/grDividerStyles.d.ts

GrDividerOrientationtype
type GrDividerOrientation = 'horizontal' | 'vertical';
GrDividerAligntype
type GrDividerAlign = 'start' | 'center' | 'end';
GrDividerVarianttype
type GrDividerVariant = 'solid' | 'dashed' | 'dotted';
GrDividerSpacingtype

Отступы вокруг разделителя. none — вплотную, как было до появления пропа.

type GrDividerSpacing = 'none' | GrComponentSize;

Файлdist/types/components/GrDivider/defaults.d.ts

GrDividerConfigurablePropsinterface

Пропы GrDivider, настраиваемые глобально через <GrConfigProvider :component-defaults="{ GrDivider: { … } }">. Только оформление — см. GrButton/defaults.ts.

interface GrDividerConfigurableProps {
    variant: GrDividerVariant;
    spacing: GrDividerSpacing;
}

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

grDividerConfigconst
const grDividerConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrDivider">;

Файлdist/types/components/GrDivider/safelist.d.ts

grDividerSafelistconst
const grDividerSafelist: string[];

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

GrDividerPropsinterface
interface GrDividerProps {
    /** Направление линии: между блоками или между элементами в ряду. По умолчанию `horizontal`. */
    orientation?: GrDividerOrientation;
    /** Подпись в разрыве линии: «или», название раздела. Только у горизонтального; даёт и имя. */
    label?: string;
    /** Где стоит подпись на линии: `start`, `center` или `end`. По умолчанию `center`. */
    align?: GrDividerAlign;
    /** Начертание линии. Не задано — берётся из `GrConfigProvider`, иначе `solid`. */
    variant?: GrDividerVariant;
    /** Отступы вокруг разделителя. Не задано — из `GrConfigProvider`, иначе `none`. */
    spacing?: GrDividerSpacing;
    /** Толщина линии. Число трактуется как пиксели. */
    thickness?: number | string;
    /**
     * Длина линии: высота вертикального разделителя, ширина горизонтального.
     * Нужна вертикальному вне flex-родителя — там ему не от чего растянуться.
     */
    length?: number | string;
    /**
     * Имя разделителя для скринридера. Подпись из слота строкой не выразить,
     * поэтому имя задаётся отдельно; при `label` оно берётся из него.
     */
    ariaLabel?: string;
}

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

Три ветки рендера

Без подписи — нативный <hr>: у него уже есть неявная роль separator, и дублировать её атрибутом нельзя. С подписью и в вертикальном варианте — div с явными role="separator" и aria-orientation.

Подпись и имя

role="separator" делает содержимое презентационным: текст внутри роли до скринридера не доходит. Поэтому имя разделителя задаётся атрибутом:

vue
<GrDivider label="или" />
<!-- aria-label="или" — диктор объявит «или, разделитель» -->

Подпись из слота строкой не выразить, поэтому имя для неё задаётся отдельно — ariaLabel; он же перебивает label, когда видимый текст и озвучиваемое имя должны отличаться. Слот без ariaLabel остаётся безымянным осознанно: разделитель, подпись которого нельзя выразить строкой, декоративен.

align (start | center | end) решает, с какой стороны от подписи рисуются отрезки линии.

Начертание, отступы, толщина
  • variant — solid (по умолчанию), dashed, dotted. Линия рисуется бордюром, а не фоном: пунктир фоном не выразить, а два механизма на три варианта одного и того же расходятся при первой же правке;
  • spacing — none (по умолчанию) либо шкала пакета xs | sm | md | lg: вертикальные отступы у горизонтального разделителя, горизонтальные — у вертикального;
  • thickness — толщина линии, число трактуется как пиксели. Уезжает в --gr-divider-thickness, поэтому её можно задать и снаружи, стилями контейнера.

variant и spacing настраиваются глобально:

vue
<GrConfigProvider :component-defaults="{ GrDivider: { variant: 'dashed', spacing: 'md' } }">
Вертикальный разделитель и flex-контекст

Вертикальный разделитель растягивается по высоте flex-родителя (self-stretch). В блочном контексте растягиваться не от чего, и линия схлопывается в ничто — выглядит как пропавший компонент.

Два выхода: положить его во flex-контейнер (обычный случай — тулбар) либо задать длину явно:

vue
<div class="flex items-center gap-3">
  <span>Файл</span>
  <GrDivider orientation="vertical" />
  <span>Правка</span>
</div>

<!-- вне flex-родителя -->
<GrDivider orientation="vertical" :length="24" />

length задаёт высоту вертикальному разделителю и ширину горизонтальному.