Примитивы UI — Полевой справочник
Если вы когда-нибудь смотрели на современное приложение и думали: «а как вообще называется эта штука?» — эта страница для вас.
Каждый интерфейс, которым вы пользуетесь, построен из удивительно небольшого набора переиспользуемых строительных блоков, называемых примитивами UI. У них есть названия. Иногда странные. Но стоит уловить метафору — и вы уже не сможете её развидеть.
En Parlant~ использует Mantine — библиотеку компонентов React, которая предоставляет всё это из коробки. Перед вами — ваш полевой справочник.
Те, что звучат как мебель
Заголовок раздела «Те, что звучат как мебель»Toast (тост) — это небольшое уведомление, которое всплывает у края экрана, задерживается на несколько секунд и плавно исчезает. Как кусочек хлеба, выскакивающий из тостера — только гравитация работает наоборот, и он в конце концов возвращается обратно.
В En Parlant~ тосты появляются в правом нижнем углу (через @mantine/notifications от Mantine) для таких сообщений:
- «База данных успешно загружена» — хоп
- «Голос TTS не настроен» — хоп
- «Не удалось подключиться к Lichess» — хоп, и вам немного грустно
Вы их не вызывали. Они просто появляются, доставляют сообщение и уходят. Это почтовые голуби мира интерфейсов.
Card (карточка) — это прямоугольный контейнер с рамкой или тенью, объединяющий связанное содержимое. Представьте карточку для записей, лежащую на столе — у неё чёткие края, она содержит одну вещь, и её можно взять и переложить.
В En Parlant~ карточки используются для:
- Превью партий в браузере базы данных (
GameCard) — имена игроков, результат, дата - Редактора позиции (
EditingCard) — карточка, которую вы «переворачиваете» при настройке произвольной позиции - Записей баз данных на странице баз данных — каждая база получает собственную карточку в сетке
У карточек есть близкий родственник — Paper, который по сути является карточкой, окончившей художественную школу. Та же идея — контейнер с рамкой или тенью — но с меньшей семантической нагрузкой. Paper просто говорит: «Я — поверхность». Он появляется как подложка за панелями анализа и отображением информации о базах данных.
Drawer / Sheet
Заголовок раздела «Drawer / Sheet»В настоящее время в En Parlant~ не используется, но знать полезно: drawer (выдвижная панель) — это панель, которая выезжает с края экрана, как ящик письменного стола. (Вот и вся метафора. Дизайнеры интерфейсов были очень буквальны в тот день.)
Те, что преграждают путь
Заголовок раздела «Те, что преграждают путь»Modal (модальное окно) — это всплывающий диалог, требующий вашего внимания. Он затемняет фон и заставляет вас разобраться с ним, прежде чем делать что-либо ещё. Это малыш-капризуля среди паттернов UI — «СМОТРИ НА МЕНЯ ПРЯМО СЕЙЧАС».
En Parlant~ использует модальные окна для моментов, которые действительно требуют вашего внимания:
- «Вы уверены, что хотите очистить все данные?» (
ClearDataModal) — с чекбоксами, чтобы вы могли выбрать, какие именно данные уничтожить - «Доступно обновление» (
UpdateModal) — с индикатором прогресса загрузки - «Импортировать партию» (
ImportModal) — вставьте PGN, введите FEN или бросьте ссылку - «Создать новый репертуар» (
CreateRepertoireModal) — назовите, настройте, вперёд - «О программе En Parlant~» (
About) — информация о версии, авторы, стандартный закулисный проход
Модальные окна говорят: «Это разговор. И мы ведём его прямо сейчас.»
Dialog — вежливый кузен модального окна. В Mantine это по сути тот же компонент, но в теории UI-дизайна диалог меньше и более фокусированный — один вопрос и ответ. «Сохранить изменения?» Да / Нет. Готово.
En Parlant~ использует ConfirmModal для таких быстрых «да или нет»-моментов, например, для подтверждения того, что вы хотите отбросить несохранённые изменения.
Те, что приходят и уходят
Заголовок раздела «Те, что приходят и уходят»Tooltip
Заголовок раздела «Tooltip»Tooltip (подсказка) — это крошечная надпись, появляющаяся при наведении курсора на элемент. Это тот доброжелательный незнакомец, который шепчет ответ, когда вы выглядите растерянным.
Подсказки повсюду в En Parlant~. Наведите курсор практически на любую кнопку-иконку — и вы увидите одну:
- Наведите на кнопку ↻ → «Перезагрузить»
- Наведите на обрезанный путь к файлу → появится полный путь
- Наведите на символ аннотации → узнаете, что этот символ означает
- Наведите на ход в панели анализа → появится миниатюрная превью-доска
Подсказки — оригинальное «инструкция не нужна».
Popover
Заголовок раздела «Popover»Popover (поповер) — это подсказка, окончившая аспирантуру. Вместо простого текстового ярлыка он может содержать что угодно — кнопки, изображения, даже крошечную шахматную доску.
В En Parlant~, когда вы наводите курсор на ход в анализе движка, поповер отображает превью доски в этой позиции. Это подсказка, которая пришла с наглядными пособиями.
Menu (меню) — это список действий, появляющийся при клике (или правом клике) на элемент. Вы пользуетесь ими с зари компьютерной эры — Файл, Редактирование, Вид. Знакомая история.
En Parlant~ предлагает два варианта:
- Меню верхней панели — классическая строка меню Файл / Редактирование / Вид, построенная с помощью компонента
Menuот Mantine. Горячие клавиши перечислены справа. Паттерн дизайна настолько старый, что уже получает пенсию. - Контекстные меню — щёлкните правой кнопкой по ходу в дереве партии и получите опции вроде «Повысить вариант», «Удалить отсюда» и «Копировать линию». Они используют библиотеку
mantine-contextmenuдля дополнительного лоска.
У меню есть свой мини-словарь: Menu.Target (элемент, по которому вы кликаете), Menu.Dropdown (появляющийся список), Menu.Item (каждый пункт) и Menu.Divider (тонкая линия, которая говорит: «теперь другой раздел»).
Те, что организуют пространство
Заголовок раздела «Те, что организуют пространство»Stack и Group
Заголовок раздела «Stack и Group»Это масло и хлеб компоновки.
- Stack располагает элементы вертикально — один над другим. Как если бы вы складывали книги в стопку.
- Group располагает элементы горизонтально — бок о бок. Как если бы вы выстраивали шахматные фигуры на полке.
Каждый из них встречается буквально в 100+ файлах. Это самые распространённые компоненты во всём приложении. Каждый раз, когда элементы аккуратно расставлены — за это отвечает Stack или Group.
Flex — швейцарский армейский нож в семействе Stack и Group. Когда элементам нужно переноситься, растягиваться, сжиматься, переворачиваться или как-то ещё «плохо себя вести», Flex берёт дело в свои руки с полным контролем над моделью CSS Flexbox.
Используется в списке ходов панели анализа — те последовательности ходов, которые переносятся и текут, как текст? Это Flex делает всю тяжёлую работу.
Box — это <div> в цилиндре и с тростью. Сам по себе не делает ничего — просто универсальный контейнер. Но он принимает стилевые пропсы Mantine, что делает его невероятно удобной обёрткой для ситуаций «мне нужна штука вокруг этой другой штуки».
Box встречается в 150+ файлах. Это изолента среди компонентов библиотеки.
Делает ровно то, что написано. Размещает что-то по центру. По горизонтали. По вертикали. И то и другое. Готово.
Появляется в пустых состояниях — когда нет привязанных аккаунтов, нет загруженных баз данных, нет данных. Большая иконка, сообщение, и Center следит, чтобы всё было идеально расположено. Никто не любит пустое состояние со смещённым центром.
SimpleGrid
Заголовок раздела «SimpleGrid»Сетка, которая простая. Вы указываете количество колонок, и она расставляет ваши карточки в аккуратную сетку, которая перестраивается при изменении размера окна. Страница баз данных использует её для отображения карточек баз данных в адаптивной сетке.
ScrollArea
Заголовок раздела «ScrollArea»Контейнер, который прокручивается, когда содержимое выходит за границы. Казалось бы, это должно быть бесплатно — и в каком-то смысле так и есть, с CSS overflow: auto — но ScrollArea добавляет стилизованные полосы прокрутки, инерционную прокрутку и обнаружение переполнения. Оборачивает панель дерева партии, линии анализа и любые места, где содержимое может вырасти выше своего контейнера.
AppShell
Заголовок раздела «AppShell»AppShell — это мастер-компоновка, скелет всего приложения. Он определяет, где находится шапка, где боковая панель и где живёт основной контент. Всё остальное вложено в него.
Используется только один раз. Это фундамент дома.
Portal — это магическая червоточина. Он рендерит компонент за пределами его нормального положения в DOM-дереве и размещает его в другом месте — обычно в корне документа. Именно так поповеры и превью досок избегают обрезания родительскими контейнерами с overflow: hidden.
Вы никогда не видите Portal. Вы видите только его эффекты. Это закулисная команда среди UI-компонентов.
Те, с которыми вы взаимодействуете
Заголовок раздела «Те, с которыми вы взаимодействуете»Кликабельный прямоугольник с текстом. Вы его знаете. В Mantine кнопки бывают разных вариантов:
- filled — сплошной цвет, максимальный акцент. «Нажми на меня, я важная.»
- outline — только рамка. «Я опция, но без давления.»
- subtle — едва заметная. «Я здесь, если понадоблюсь.»
- default — нейтральная золотая середина.
En Parlant~ использует все эти варианты в 150+ файлах. Самый распространённый паттерн: Group кнопок внизу модального окна — «Отмена» (subtle) и «Подтвердить» (filled). Классика.
ActionIcon
Заголовок раздела «ActionIcon»ActionIcon — это кнопка, которая отказалась от текстовой подписи и полностью посвятила себя иконочному образу жизни. Она компактная, квадратная и полагается на иконку (плюс подсказку) для передачи своего назначения.
Кнопки панелей инструментов, элементы управления панелей, кнопки закрытия — всё это ActionIcon. Это самый экономичный по пространству способ предложить действие.
Switch (переключатель) — это тумблер, похожий на крошечный выключатель света. Щёлкнули влево, щёлкнули вправо. Включено. Выключено.
В настройках переключатели управляют бинарными выборами:
- Звук вкл./выкл.
- Озвучка TTS включена/отключена
- Тёмная тема / светлая тема
Физическая метафора настолько удачна, что даже ваши бабушки и дедушки её понимают.
Slider (ползунок) — это дорожка с ручкой, которую вы перетаскиваете вперёд-назад для выбора значения. Как регулятор громкости, которого расплющили.
En Parlant~ использует ползунки для:
- Размера шрифта — перетащите для настройки
- Громкости — перетащите для настройки (разумеется)
- Ядер процессора — сколько ядер выделить движку?
- Памяти для хеш-таблиц — сколько оперативной памяти отдать под хеш-таблицу движка?
Есть также RangeSlider с двумя ручками для выбора диапазона — используется для фильтрации партий по рейтингу Эло (например, 2000–2200) и временным периодам.
SegmentedControl
Заголовок раздела «SegmentedControl»Ряд кнопок, из которых ровно одна выбрана в любой момент времени. Как пресеты автомагнитолы — нажмите одну, остальные «отщёлкнутся».
Используется для переключения между:
- Оценкой в сантипешках vs. процентами выигрыша/ничьей/проигрыша на графике анализа
- Различными форматами записи ходов
- Количеством линий движка
Checkbox и Select
Заголовок раздела «Checkbox и Select»Вы их знаете. Checkbox (чекбокс) для «выберите всё подходящее», Select (выпадающий список) для «выберите одно из списка». Они встречаются в настройках, фильтрах и формах по всему приложению. В модальном окне очистки данных есть особенно приятный набор чекбоксов, где вы можете выбрать свой собственный вариант уничтожения.
Autocomplete
Заголовок раздела «Autocomplete»Текстовое поле, которое предлагает варианты завершения по мере ввода. Поиск игроков в браузере базы данных использует его — начните вводить имя, и совпадающие игроки появятся ниже.
FileInput и DateInput
Заголовок раздела «FileInput и DateInput»FileInput открывает диалог выбора файла при клике — используется в модальном окне импорта для загрузки файлов PGN. DateInput открывает календарь для выбора даты — используется для фильтрации партий по дате. Также есть MonthPickerInput и YearPickerInput для случаев, когда нужна меньшая точность (фильтрация базы данных Lichess по месяцам, фильтрация базы мастеров по годам).
Те, что показывают прогресс
Заголовок раздела «Те, что показывают прогресс»Progress Bar
Заголовок раздела «Progress Bar»Горизонтальная полоса, заполняющаяся слева направо, чтобы показать, насколько что-то продвинулось. Используется при обновлении приложения (прогресс загрузки) и — более креативно — для отображения вероятностей выигрыша/ничьей/проигрыша в панели анализа. Три цветных сегмента (белый, серый, чёрный) заполняют полосу пропорционально. Это крошечная столбчатая диаграмма, замаскированная под индикатор прогресса.
Loader (загрузчик) — это вращающаяся анимация, которая говорит: «Работаю над этим, дайте секунду.» Появляется, пока загружаются базы данных, подгружается статистика игроков или происходит что-нибудь асинхронное.
Skeleton
Заголовок раздела «Skeleton»Skeleton (скелетон) — это серый заполнитель, повторяющий форму ещё не загрузившегося контента. Вместо пустого экрана или спиннера вы видите призрачные очертания того, где будут карточки и текст. Это архитектурный чертёж состояния загрузки — «настоящая мебель уже в пути».
Страница баз данных использует скелетоны, пока загружается сетка карточек. Гораздо элегантнее, чем просто спиннер.
LoadingOverlay
Заголовок раздела «LoadingOverlay»Полупрозрачное покрывало, наброшенное на компонент во время его загрузки. Это используется для графика анализа — вы всё ещё видите график за оверлеем, но он затемнён, а сверху крутится спиннер. «Я здесь, просто обновляюсь.»
Те, что подписывают вещи
Заголовок раздела «Те, что подписывают вещи»Badge (значок) — это маленькая цветная метка, как бейдж на конференции. В En Parlant~ компонент SpeedBadge использует значки для отображения контролей времени с цветовой кодировкой:
- 🩷 Розовый — UltraBullet
- 🔴 Красный — Bullet
- 🟠 Оранжевый — Blitz
- 🟢 Зелёный — Rapid
- 🔵 Синий — Classical
- 🟣 Фиолетовый — Correspondence
Каждый значок крошечный, красочный и мгновенно передаёт темп игры с одного взгляда.
Сокращение от keyboard (клавиатура). Отображает клавишу клавиатуры с характерным «выпуклым» стилем. Используется в настройках горячих клавиш для отображения комбинаций вроде Ctrl + Z. Это CSS-воссоздание реальной физической клавиши на вашей клавиатуре. Восхитительно скевоморфно.
Те, что разделяют и сворачивают
Заголовок раздела «Те, что разделяют и сворачивают»Divider
Заголовок раздела «Divider»Горизонтальная линия, разделяющая секции. Вот и всё. Это линия. Но она стилизованная, и опционально может содержать текстовую метку посередине — вроде разделителя «— ИЛИ —» в модальном окне импорта, отделяющего «вставьте PGN» от «введите FEN».
Более тридцати файлов используют Divider. Оказывается, вещи нужно разделять довольно часто.
Collapse
Заголовок раздела «Collapse»Collapse (коллапс) — это секция, которая раскрывается и сворачивается с плавной анимацией. Кликнуть, чтобы показать, кликнуть, чтобы скрыть. Параметры фильтрации базы данных используют это — вам не всегда нужно видеть каждый фильтр, поэтому они прячутся за Collapse, пока не понадобятся.
Продвинутые компоненты
Заголовок раздела «Продвинутые компоненты»RichTextEditor
Заголовок раздела «RichTextEditor»Полноценный WYSIWYG-редактор текста, построенный на TipTap. Жирный, курсив, списки — всё как положено. Используется для написания аннотаций к партиям — тех комментариев, которые вы добавляете, чтобы объяснить, почему ход был блестящим или ужасным.
Это единственный примитив, который больше похож на составной организм, чем на отдельную клетку. Под капотом это TipTap + ProseMirror + стилизация Mantine. Но с точки зрения пользователя — это просто текстовое поле, где работает форматирование.
AreaChart
Заголовок раздела «AreaChart»Из @mantine/charts (обёртка над Recharts), AreaChart обеспечивает работу графика оценки — той волнообразной линии внизу панели анализа. Белая область выше средней линии означает преимущество белых; чёрная ниже — преимущество чёрных.
Вы можете кликнуть на любую точку графика, чтобы перейти к этому ходу. Интерактивная визуализация данных встречается с шахматным анализом. Здесь даже есть пользовательские подсказки и вспомогательные линии, обозначающие фазы партии (дебют → миттельшпиль → эндшпиль).
DataTable
Заголовок раздела «DataTable»Через библиотеку mantine-datatable — полнофункциональная таблица данных с сортировкой, пагинацией, выбором строк и фильтрацией. Обеспечивает работу списка партий, списка игроков и списка турниров в браузере базы данных. Это электронная таблица, которая знает, что она в шахматном приложении.
Невидимые компоненты
Заголовок раздела «Невидимые компоненты»Некоторые примитивы сами по себе ничего не отображают, но обеспечивают работу всего остального:
- MantineProvider — оборачивает всё приложение и предоставляет тему (цвета, тёмный режим, настройки компонентов по умолчанию)
- Portal — телепортирует отрендеренный контент в другую часть DOM
- useHotkeys — хук (не компонент), который привязывает горячие клавиши
- useForm — управляет состоянием формы, валидацией и обработкой ошибок
- useDebouncedValue — ждёт, пока вы закончите печатать, прежде чем запустить поиск. Вежливый хук.
Полная инвентаризация
Заголовок раздела «Полная инвентаризация»Для справки — вот все семейства примитивов, используемых в En Parlant~, сгруппированные по назначению:
| Категория | Примитивы |
|---|---|
| Компоновка | AppShell, Box, Center, Flex, Group, Stack, SimpleGrid, ScrollArea, Portal |
| Поверхности | Card, Paper |
| Оверлеи | Modal, Tooltip, Popover, Menu, ContextMenu, LoadingOverlay |
| Уведомления | Toast (через @mantine/notifications) |
| Кнопки | Button, ActionIcon, CloseButton, ThemeIcon |
| Поля ввода | TextInput, Textarea, NumberInput, Select, Autocomplete, Checkbox, Switch, Slider, RangeSlider, SegmentedControl, FileInput, DateInput, MonthPickerInput, YearPickerInput |
| Отображение данных | Table, DataTable, Badge, Code, Kbd, Rating, Image |
| Типографика | Text, Title, Anchor |
| Прогресс | Progress, Loader, Skeleton |
| Структура | Divider, Collapse |
| Богатый контент | RichTextEditor (TipTap), AreaChart (Recharts) |
| Темизация | MantineProvider, createTheme, useColorScheme |
| Хуки | useForm, useHotkeys, useToggle, useDebouncedValue, useClickOutside, useElementSize |
Всё взято из Mantine v8 и его экосистемных пакетов: @mantine/core, @mantine/notifications, @mantine/dates, @mantine/charts, @mantine/form, @mantine/tiptap, mantine-datatable и mantine-contextmenu.
Теперь вы знаете
Заголовок раздела «Теперь вы знаете»В следующий раз, когда увидите маленькое сообщение, выплывающее из угла экрана — это тост. Прямоугольник вокруг превью партии — это карточка. Серые мерцающие пятна перед загрузкой контента — это скелетоны.
Стоит выучить названия — и вы начинаете видеть их повсюду. В каждом приложении. На каждом сайте. Одни и те же пара десятков примитивов, переставленных тысячью различных способов.
Это конструктор Лего — до самого основания.