GrChipGroup
Берут, когда фильтры списка строкой.
Обзор
Когда брать
- фильтры списка строкой — статусы, категории, метки: видно все варианты сразу, выбранных может быть несколько;
- выбор из коротких вариантов вместо списка — период отчёта, приоритет: вариантов до десятка, и прятать их под кнопку незачем;
- набор меток записи, который правят на месте —
closableдаёт крестик каждому чипу, аDeleteснимает тот, что под фокусом; - поле формы, где значение — набор — группа читает контекст
GrFormFieldи отдаёт значение в нативную форму поname.
Когда взять другое
| Нужно | Берите |
|---|---|
| Один выбор, вариантов немного, вид переключателя | GrSegmented |
| Один выбор с описаниями у вариантов | GrRadioGroup |
| Множественный выбор списком с отметками | GrCheckboxGroup |
| Вариантов десятки, их ищут вводом | GrSelect / GrAutocomplete |
| Ряд снимаемых меток без выбора | GrChip без группы |
Варианты все тона и виды — настоящим компонентом
tone \ dark | false | true |
|---|---|---|
primary | ||
neutral | ||
success | ||
warning | ||
danger | ||
info | ||
slate | ||
azure |
Размеры
xssmmdlg
Состояния
обычнаяdisabledreadonlyinvalid
Матрица живая: наводите и нажимайте. Состояний наведения, фокуса и нажатия здесь нет — они за браузером, а не за пропом.
Playground контролы выводятся из API, а не пишутся руками
Загружается…
0 изменено· состояние — в адресе
<GrChipGroup v-model="value">
<GrChip value="design" label="Design" />
<GrChip value="api" label="API" />
<GrChip value="docs" label="Docs" />
</GrChipGroup>Примеры 4 у каждого — живое демо и его код
Фильтры каталога: несколько и один
Комнаты и материалы сочетаются, поэтому их группы держат массив — это
listboxс одной остановкой Tab и стрелками внутри. Доставка — одно из двух или любая:selection="single"делаетradiogroup, а повторный клик по выбранному чипу сбрасывает значение вnull, и страница читает его как «любой срок».RoomMaterialDelivery3 desks · any delivery date- Halden desk
- Brekka standing desk
- Lune vanity
- Orsa writing desk
- Tove kids desk
- Kalla corner desk
Приоритет в форме заявки
У каждого приоритета свой смысл, поэтому у каждого чипа свой
tone. ВнутриGrFormFieldгруппа берёт подпись и обязательность у поля, аnameкладёт значение в нативную форму — отправьте её и посмотрите на данные.Не больше трёх выделенных
Группа не ограничивает выбор: предел — правило приложения, поэтому приложение и отказывает в четвёртом выборе, и объясняет почему.
closableдаёт каждому чипу крестик с его именем, Delete снимает чип под фокусом, аremove— только просьба: навык из списка убирает страница.SkillsPick up to three to highlight · Delete removes the focused one1 highlight left Первый вопрос после регистрации
size="lg"иradius="round"дают ряд, по которому легко попасть с телефона; группа раздаётtoneвсем чипам, а выбранный берёт плотную заливку того же оттенка. Недоступный чип остаётся читаемым, поэтому «Payroll · soon» видно, а не пропущено.What will you use Acme Billing for?Pick all that apply — we will set up the workspace around them
API порождается из пакета · разойтись не может
Props
| Prop | Type | по умолчанию | Описание |
|---|---|---|---|
disabled | boolean | undefined | false | Набор недоступен: чипы не выбираются и не снимаются. Включается и от `GrFormField`. |
tone |
| undefined | Тон всех чипов набора; проп чипа сильнее. Не задан — `GrConfigProvider`, иначе `neutral`. |
closable | boolean | undefined | false | Крестик у всех чипов набора. Точечно перебивается пропом самого чипа. |
modelValuev-model | GrChipValue | GrChipValue[] | null | undefined | undefined | Одиночный выбор — значение, множественный — массив. |
readonly | boolean | undefined | false | Выбор видно, но он не меняется. |
invalid | boolean | undefined | false | Значение с ошибкой: `aria-invalid` на группе. Включается и от ошибки `GrFormField`. |
required | boolean | undefined | false | Выбор обязателен: `aria-required` на группе. Включается и от `GrFormField`. |
size | "xs" | "sm" | "md" | "lg" | undefined | undefined | Ступень шкалы для всех чипов набора; проп чипа сильнее. По умолчанию `md`. |
ariaLabel | string | undefined | undefined | Доступное имя набора. Внутри `GrFormField` не нужно: группу именует подпись поля. |
name | string | undefined | undefined | Имя для нативной формы. Множественный выбор отдаёт по полю на значение. |
dark | boolean | undefined | undefined | Заливка тоном вместо мягкой подложки у всех чипов набора; проп чипа сильнее. |
radius | GrBadgeRadius | undefined | undefined | Форма всех чипов набора: `round`, `semi` или `square`; проп чипа сильнее. |
selection | GrChipSelection | undefined | "multiple" | Множественность выбора: `multiple` — массив значений и роль `listbox`, `single` — одно значение или `null` и роль `radiogroup`. По умолчанию `multiple`. |
Слоты
| Slot | Type | Описание |
|---|---|---|
default | any | Чипы набора. |
События
| Event | Сигнатура | Описание |
|---|---|---|
update:modelValue | (event: "update:modelValue", value: GrChipValue | GrChipValue[] | null): void | — |
change | (event: "change", value: GrChipValue | GrChipValue[] | null): void | — |
focus | (event: "focus", event: FocusEvent): void | — |
blur | (event: "blur", event: FocusEvent): void | — |
remove | (event: "remove", value: GrChipValue): void | — |
Методы
| Methods | Сигнатура | Описание |
|---|---|---|
focus | () => void | undefined | Фокус на активный чип — тот, что держит остановку `Tab` набора. |
blur | () => void | undefined | Снять фокус с активного чипа набора. |
Типы
Все экспортируемые типы подпути, по файлам, где они объявлены. Имена, дженерики и тела читаются из файлов деклараций пакета и разойтись не могут.
import type { GrChipGroupConfigurableProps, GrChipGroupProps, GrChipGroupEmits } from '@feugene/granularity/components/GrChipGroup'Файлdist/types/components/GrChipGroup/config.d.ts
const grChipGroupConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrChipGroup">;Файлdist/types/components/GrChipGroup/defaults.d.ts
Пропы GrChipGroup, настраиваемые глобально через componentDefaults.
Размер группы доезжает до чипов контекстом — задавать его на каждом не нужно.
interface GrChipGroupConfigurableProps {
size: GrChipSize;
}Файлdist/types/components/GrChipGroup/safelist.d.ts
const grChipGroupSafelist: string[];Файлdist/types/components/GrChipGroup/GrChipGroup.vue.d.ts
GrChipGroup — набор выбираемых чипов: фильтры, теги записи, быстрый выбор.
Составной виджет: одна остановка Tab, внутрь попадают стрелками
(roving tabindex). Роль зависит от множественности выбора — radiogroup
в одиночном, listbox с aria-multiselectable во множественном; чипы
получают парную роль через контекст и сами её не выбирают.
Состав группа не рисует: чипы приходят слотом, потому что у каждого своя
подпись и иконка. Отсюда же и remove — группа его ретранслирует, а снимает
чип потребитель, у которого лежит массив.
interface GrChipGroupProps {
/** Одиночный выбор — значение, множественный — массив. */
modelValue?: GrChipValue | GrChipValue[] | null;
/**
* Множественность выбора: `multiple` — массив значений и роль `listbox`, `single` — одно
* значение или `null` и роль `radiogroup`. По умолчанию `multiple`.
*/
selection?: GrChipSelection;
/** Имя для нативной формы. Множественный выбор отдаёт по полю на значение. */
name?: string;
/** Набор недоступен: чипы не выбираются и не снимаются. Включается и от `GrFormField`. */
disabled?: boolean;
/** Выбор видно, но он не меняется. */
readonly?: boolean;
/** Значение с ошибкой: `aria-invalid` на группе. Включается и от ошибки `GrFormField`. */
invalid?: boolean;
/** Выбор обязателен: `aria-required` на группе. Включается и от `GrFormField`. */
required?: boolean;
/** Крестик у всех чипов набора. Точечно перебивается пропом самого чипа. */
closable?: boolean;
/** Ступень шкалы для всех чипов набора; проп чипа сильнее. По умолчанию `md`. */
size?: GrChipSize;
/** Тон всех чипов набора; проп чипа сильнее. Не задан — `GrConfigProvider`, иначе `neutral`. */
tone?: GrChipTone;
/** Форма всех чипов набора: `round`, `semi` или `square`; проп чипа сильнее. */
radius?: GrChipRadius;
/** Заливка тоном вместо мягкой подложки у всех чипов набора; проп чипа сильнее. */
dark?: boolean;
/** Доступное имя набора. Внутри `GrFormField` не нужно: группу именует подпись поля. */
ariaLabel?: string;
}interface GrChipGroupEmits {
/** Новое значение (`v-model`): массив в `multiple`, значение или `null` в `single`. */
(e: 'update:modelValue', value: GrChipValue | GrChipValue[] | null): void;
/** Пользователь изменил выбор кликом или клавишей; приходит вместе с `update:modelValue`. */
(e: 'change', value: GrChipValue | GrChipValue[] | null): void;
/**
* Чип просят снять — крестиком или `Delete`. Группа его не убирает: значение удаляет из
* массива потребитель.
*/
(e: 'remove', value: GrChipValue): void;
/** Фокус вошёл в набор. Переходы между чипами стрелками событием не считаются. */
(e: 'focus', event: FocusEvent): void;
/** Фокус ушёл из набора целиком. */
(e: 'blur', event: FocusEvent): void;
}Файлdist/types/components/GrChipGroup/index.d.ts
type GrChipGroupInstance = ComponentExposed<typeof GrChipGroupComponent>;Доступность
Паттерн APG
listbox / radiogroup (roving tabindex)
Клавиши
Home / EndDelete / Backspace
| Клавиша | Действие |
|---|---|
| — | Набор — одна остановка Tab, внутрь ведут стрелки по обеим осям (чипы переносятся на новую строку) |
| Home / End | к краям |
| Delete / Backspace | снять чип под фокусом. **Стрелка двигает только фокус, даже в одиночном режиме**: у чипа есть второе действие, и менять значение по дороге к нужному чипу нельзя |
Полный контракт пакета: docs/keyboard.md ↗
Использование из прозы библиотеки
Роль зависит от множественности выбора
selection="multiple" (по умолчанию) объявляет группу listbox с
aria-multiselectable, а чипы — option с aria-selected.
selection="single" — radiogroup и radio с aria-checked, как у
GrSegmented.
Роль чипы получают из контекста и сами её не выбирают: иначе набор из чипов с разными ролями объявлялся бы скринридеру как что угодно, кроме одного виджета.
Одна остановка Tab, внутрь — стрелками
Группа составная, поэтому занимает одну остановку в таб-порядке: активный чип
держит tabindex="0", остальные -1. Стрелки работают по обеим осям — чипы
переносятся на новую строку, и «вниз» означает следующий чип так же, как
«вправо». Home/End уводят к краям.
Стрелка двигает только фокус, даже в одиночном режиме. У чипов есть второе
действие — снятие по Delete, — и переносить выбор вместе с фокусом значило бы
менять модель при попытке дойти до нужного чипа. В radiogroup формы принято
обратное, но там у элементов одного действия.
Повторный выбор снимает отметку
В одиночном режиме клик по уже выбранному чипу сбрасывает значение в null.
Набор фильтров без выбранного значения осмыслен («любой»), и отменить выбор
иначе было бы нечем — в отличие от переключателей формы, где пустое значение
обычно запрещено.
Состав рисует потребитель
Пропа options у группы нет: у каждого чипа своя подпись, иконка и тон, и
генерировать их из плоского массива значило бы завести второй, более бедный
способ описать то же самое. Отсюда же remove — группа его только
ретранслирует, а убирает элемент из массива приложение.
Границы
- своего порядка у группы нет — она рисует чипы в порядке слота;
- группа не ограничивает число выбранных. Предел — правило приложения, и сообщение о нём тоже: группа не знает, что показать вместо отказа;
- вложенных групп не бывает. Набор внутри набора даёт неразрешимый вопрос, чья стрелка обрабатывается.
Пропы этого примера