Паттерны
Раздел настроек
Когда использовать:
- экран настроек содержит несколько связанных переключателей
- группа должна восприниматься как одна область настроек
Заметки о композиции:
- делайте
FieldsetLegendкороткой и неизменной - используйте
FieldsetHeaderдля дополнительных пояснений - рендерите сами переключатели сразу после заголовка
Компромиссы:
- улучшает семантическую группировку и считываемость
- добавляет больше вертикальной структуры, чем свободный список элементов управления
import {
Checkbox,
CheckboxCheckedIcon,
CheckboxIndicator,
CheckboxInput,
Fieldset,
FieldsetHeader,
FieldsetLegend,
Text,
} from '@vega-ui/react';
import { useId } from 'react';
Прозрачная группа в существующей панели
Когда использовать:
- видимый контейнер уже даёт родительская раскладка
- не хватает только семантики группировки
Заметки о композиции:
- переключитесь на
appearance='transparent' - сохраняйте legend, даже когда рамка и отступы убраны
Компромиссы:
- сохраняет семантику без дублирования контейнеров
- граница группы зависит от окружающей раскладки
import type { CSSProperties } from 'react';
import {
Button,
Dialog,
DialogClose,
DialogContent,
DialogTrigger,
Fieldset,
FieldsetLegend,
Heading,
Icon,
IconButton,Текст валидации для группы
Когда использовать:
- несколько связанных элементов управления нарушают одно бизнес-правило
- ошибка относится к группе, а не к отдельному полю
Заметки о композиции:
- оставляйте legend неизменным названием группы
- поместите сообщение сразу после legend и укажите его в
aria-describedbyу fieldset - дочерние элементы при необходимости по-прежнему могут показывать своё локальное состояние
Компромиссы:
- проясняет валидацию на уровне группы
- может стать шумным, если каждый дочерний элемент повторяет то же сообщение
import {
Button,
Checkbox,
CheckboxCheckedIcon,
CheckboxIndicator,
CheckboxInput,
Fieldset,
FieldsetLegend,
HelperText,
} from '@vega-ui/react';
import { FormEvent, useId, useState } from 'react';
Заголовок с действием
Когда использовать:
- у группы есть действие для всех её полей, например автозаполнение или сброс
Заметки о композиции:
- держите
FieldsetLegendпервым дочерним элементом, чтобы она давала имя группе - поместите пояснение и
ButtonвFieldsetHeader, сtype='button', чтобы кнопка не отправляла форму
Компромиссы:
- действие находится рядом с полями, которые оно меняет
- отключённый fieldset отключает и действие
import {
Button,
Fieldset,
FieldsetHeader,
FieldsetLegend,
Label,
Text,
TextField,
TextFieldInput,
} from '@vega-ui/react';
import { useId, useState } from 'react';
Сравнение
Быстрое правило выбора
Используйте Fieldset, когда нескольким связанным элементам управления нужна одна семантическая подпись группы. Используйте обычный div или Card, только если группировка чисто визуальная.
Fieldset или Card
Используйте Fieldset, когда:
- группировка — это семантическая структура формы
Используйте Card, когда:
- контейнер нужен только для раскладки или отображения
Fieldset или Separator
Используйте Fieldset, когда:
- поля относятся к одной именованной группе элементов управления
Используйте Separator, когда:
- нужно лишь визуальное разделение
Fieldset или Heading
Используйте FieldsetLegend, когда:
- текст подписывает одну группу элементов управления
Используйте Heading, когда:
- текст — это структура документа или раздела, а не нативная семантика группы
Выбирайте этот компонент, когда
- несколько элементов формы относятся к одному именованному понятию
- группе нужно нативное поведение
<fieldset>и<legend> - нужен необязательный описательный текст перед элементами управления
- вспомогательные технологии должны воспринимать элементы управления как один сгруппированный вопрос или область настроек
Не выбирайте этот компонент, когда
- группировка только декоративная
- одному отдельному полю нужна лишь подпись рядом
- достаточно обычного контейнера раскладки
Решение проблем
Группа выглядит правильно, но скринридеры не объявляют её подпись
Симптом
Элементы управления визуально сгруппированы, но вспомогательные технологии не объявляют осмысленное название группы.
Вероятная причина
Нет FieldsetLegend или вместо него использован обычный текстовый элемент.
Как проверить
- изучите разметку
- убедитесь, что внутри
<fieldset>рендерится настоящий<legend>
Исправление
Рендерите FieldsetLegend первым значимым дочерним элементом корня.
Рамка группы дублируется внутри диалога или карточки
Симптом
Раздел выглядит визуально тяжёлым, потому что границы рисуют и родительский контейнер, и fieldset.
Вероятная причина
appearance='outlined' используется внутри другой поверхности с выраженной рамкой.
Как проверить
- сравните раздел с
outlinedиtransparent - проверьте, даёт ли родитель уже достаточную границу
Исправление
Используйте appearance='transparent', когда нужна только семантическая группировка.
Текст валидации группы заменяет legend
Симптом
Сообщение об ошибке видно, но постоянная подпись группы отсутствует или всё время меняется.
Вероятная причина
Текст валидации использован как сама legend.
Как проверить
- проверьте отрендеренный текст legend
- убедитесь, не содержит ли он временный текст валидации
Исправление
Оставьте legend постоянной подписью группы, а текст валидации поместите в FieldsetHeader или во вспомогательный текст рядом.
Вложенные группы трудно понять
Симптом
Вложенные разделы рендерятся, но пользователи не могут понять, какие элементы к какой области относятся.
Вероятная причина
Внешняя и внутренняя legend не задают ясной иерархии.
Как проверить
- прочитайте legend по порядку без окружающей раскладки
- убедитесь, что каждая группа по-прежнему понятна сама по себе
Исправление
Уменьшите вложенность или перепишите legend так, чтобы каждый уровень называл отдельную область.