Перейти до вмісту

UI-примітиви — Польовий довідник

Якщо ви коли-небудь дивилися на сучасний застосунок і думали «а як воно взагалі називається?» — ця сторінка для вас.

Кожен інтерфейс, яким ви користуєтеся, побудований із напрочуд невеликого набору повторно використовуваних будівельних блоків, що називаються UI-примітивами. Вони мають назви. Інколи дивні. Але коли ви вловлюєте метафору, ви вже не можете її «розбачити».

En Parlant~ використовує Mantine — бібліотеку React-компонентів, яка надає все це «з коробки». Ось ваш польовий довідник.


Toast (тост) — це невелике сповіщення, що з’являється з краю екрана, затримується на кілька секунд, а потім зникає. Наче шматок хліба, що вистрибує з тостера — тільки гравітація працює навпаки, і він врешті повертається назад.

В En Parlant~ тости з’являються в нижньому правому куті (через @mantine/notifications від Mantine) для таких повідомлень, як:

  • «Базу даних успішно завантажено» — поп
  • «TTS-голос не налаштовано» — поп
  • «Не вдалося підключитися до Lichess» — поп, і вам трохи сумно

Ви їх не просили. Вони просто з’являються, доносять своє повідомлення і зникають. Це поштові голуби світу інтерфейсів.

Card (картка) — це прямокутний контейнер із рамкою або тінню, що групує пов’язаний вміст. Уявіть картотечну картку на столі — вона має чіткий край, містить одну річ, і її можна підняти й перемістити.

В En Parlant~ картки використовуються для:

  • Попереднього перегляду партій у браузері бази даних (GameCard) — імена гравців, результат, дата
  • Редактора позиції на дошці (EditingCard) — картка, яку ви перевертаєте при налаштуванні довільної позиції
  • Записів баз даних на сторінці баз даних — кожна база отримує власну картку в сітці

У картки є близький родич — Paper, який, по суті, є карткою, що закінчила мистецьку школу. Та сама ідея — контейнер із рамкою або тінню — але з меншим семантичним навантаженням. Paper просто каже: «Я — поверхня». Він з’являється як фон за панелями аналізу та відображенням інформації про бази даних.

Наразі не використовується в En Parlant~, але варто знати: drawer (шухляда) — це панель, що висувається з краю екрана, як шухляда письмового столу. (Ось і все. Вся метафора. UI-дизайнери того дня були дуже буквальними.)


Modal (модальне вікно) — це спливаючий діалог, який вимагає вашої уваги. Він затемнює фон і змушує вас розібратися з ним, перш ніж робити щось інше. Це малюк серед UI-патернів — «ДИВИСЬ НА МЕНЕ ПРЯМО ЗАРАЗ».

En Parlant~ використовує модальні вікна для моментів, що справді потребують вашої зосередженості:

  • «Ви впевнені, що хочете очистити всі дані?» (ClearDataModal) — із чекбоксами, щоб вибрати, які саме дані знищити
  • «Доступне оновлення» (UpdateModal) — із індикатором прогресу під час завантаження
  • «Імпортувати партію» (ImportModal) — вставте PGN, введіть FEN або перетягніть посилання
  • «Створити новий репертуар» (CreateRepertoireModal) — назвіть його, налаштуйте, починайте
  • «Про En Parlant~» (About) — інформація про версію, подяки, звичайний прохід за лаштунки

Модальні вікна кажуть: «Це розмова. І ми ведемо її зараз.»

Dialog (діалог) — це ввічливий родич модального вікна. В Mantine це, по суті, той самий компонент, але в теорії UI-дизайну діалог менший і більш сфокусований — одне запитання й одна відповідь. «Зберегти зміни?» Так / Ні. Готово.

En Parlant~ використовує ConfirmModal для таких швидких моментів «так чи ні», як-от підтвердження того, що ви хочете відкинути незбережені зміни.


Ті, що приходять і йдуть

Section titled “Ті, що приходять і йдуть”

Tooltip (підказка) — це крихітний напис, що з’являється, коли ви наводите курсор на щось. Це та привітна людина поруч, яка нашіптує відповідь, коли ви виглядаєте розгубленим.

Підказки є всюди в En Parlant~. Наведіть курсор майже на будь-яку кнопку-іконку — і ви її побачите:

  • Наведіть на кнопку ↻ → «Перезавантажити»
  • Наведіть на обрізаний шлях файлу → з’явиться повний шлях
  • Наведіть на символ анотації → що означає цей символ
  • Наведіть на хід у панелі аналізу → з’являється мініатюрний попередній перегляд дошки

Підказки — це оригінальне «інструкція не потрібна».

Popover (спливаюче вікно) — це підказка, що закінчила аспірантуру. Замість простого текстового напису він може містити що завгодно — кнопки, зображення, навіть крихітну шахівницю.

В En Parlant~, коли ви наводите курсор на хід у аналізі рушія, popover відображає попередній перегляд дошки в цій позиції. Це підказка, але з наочними матеріалами.

Menu (меню) — це список дій, що з’являється, коли ви клацаєте (або клацаєте правою кнопкою) на чомусь. Ви користуєтеся ними з початку комп’ютерної ери — File, Edit, View. Знаєте цю справу.

En Parlant~ має два різновиди:

  • Меню верхньої панелі — класична панель меню File / Edit / View, побудована з компонентом Menu від Mantine. Клавіатурні скорочення вказані праворуч. Патерн дизайну настільки давній, що вже отримує пенсію.
  • Контекстні меню — клацніть правою кнопкою на ході в дереві партії та отримаєте опції на кшталт «Підвищити варіант», «Видалити звідси» та «Копіювати лінію». Вони використовують бібліотеку mantine-contextmenu для додаткової витонченості.

Меню мають власний підсловник: Menu.Target (те, на чому ви клацаєте), Menu.Dropdown (список, що з’являється), Menu.Item (кожен варіант) та Menu.Divider (тонка лінія, що каже «тепер інший розділ»).


Ті, що організовують простір

Section titled “Ті, що організовують простір”

Це масло й хліб компонування.

  • Stack розташовує елементи вертикально — один над одним. Як складання книг у стопку.
  • Group розташовує елементи горизонтально — поруч. Як вишикування шахових фігур на полиці.

Вони з’являються буквально у 100+ файлах кожен. Це найпоширеніші компоненти у всьому застосунку. Кожного разу, коли елементи акуратно розташовані, за це відповідає Stack або Group.

Flex — це швейцарський армійський ніж, родич Stack і Group. Коли елементи мають переноситися, розтягуватися, стискатися, змінювати порядок або іншим чином поводитися нестандартно, Flex бере на себе повний контроль над моделлю CSS Flexbox.

Використовується в списку ходів панелі аналізу — ті послідовності ходів, що переносяться й течуть як текст? Це Flex виконує важку роботу.

Box — це <div> у капелюсі-циліндрі. Він нічого не робить сам по собі — це просто загальний контейнер. Але він приймає стилістичні пропси Mantine, що робить його неймовірно зручною обгорткою для «мені потрібна штука навколо цієї іншої штуки».

Box з’являється в 150+ файлах. Це ізострічка бібліотеки компонентів.

Робить саме те, що каже назва. Розміщує щось по центру. Горизонтально. Вертикально. І те, й інше. Готово.

З’являється в порожніх станах — коли немає підключених акаунтів, завантажених баз даних, ще немає даних. Велика іконка, повідомлення, і Center стежить, щоб все було ідеально розташовано. Ніхто не любить зміщений порожній стан.

Сітка, яка проста. Ви кажете їй, скільки стовпців, і вона розташовує ваші картки в акуратну сітку, що перебудовується при зміні розміру вікна. Сторінка баз даних використовує її для розміщення карток баз даних у адаптивній сітці.

Контейнер, що прокручується, коли його вміст виходить за межі. Ви б подумали, що це безкоштовно — і певною мірою так, з CSS overflow: auto — але ScrollArea додає стилізовані смуги прокрутки, інерційну прокрутку та виявлення переповнення. Він обгортає панель дерева партії, лінії аналізу та будь-яке місце, де вміст може вирости вищим за свій контейнер.

AppShell — це основний макет — скелет усього застосунку. Він визначає, де розташовується заголовок, де бічна панель і де живе основний вміст. Все інше вкладається в нього.

Ви використовуєте його лише раз. Це фундамент будинку.

Portal — це магічний портал-червоточина. Він відображає компонент за межами його звичайного місця в DOM-дереві й поміщає його кудись інше — зазвичай у корінь документа. Саме так попозери та попередній перегляд дошки уникають обрізання батьківськими контейнерами з overflow: hidden.

Ви ніколи не бачите Portal. Ви бачите лише його ефекти. Це бригада за лаштунками серед UI-компонентів.


Ті, з якими ви взаємодієте

Section titled “Ті, з якими ви взаємодієте”

Прямокутник із текстом, на який можна клацнути. Це ви знаєте. В Mantine кнопки мають варіанти:

  • filled — суцільний колір, високий акцент. «Натисни мене, я важливий.»
  • outline — лише рамка. «Я варіант, але без тиску.»
  • subtle — ледь помітний. «Я тут, якщо потрібен.»
  • default — нейтральна золота середина.

En Parlant~ використовує всі ці варіанти у 150+ файлах. Найпоширеніший патерн: Group кнопок внизу модального вікна — «Скасувати» (subtle) та «Підтвердити» (filled). Класика.

ActionIcon — це кнопка, яка відмовилася від текстового напису й повністю обрала стиль життя іконки. Вона компактна, квадратна і покладається на свою іконку (плюс підказку), щоб повідомити про своє призначення.

Кнопки панелі інструментів, елементи керування панелей, кнопки закриття — все це ActionIcon. Це найефективніший за площею спосіб запропонувати дію.

Switch (перемикач) — це тоґл, що виглядає як крихітний вимикач світла. Ліворуч, праворуч. Увімкнено. Вимкнено.

У налаштуваннях перемикачі керують бінарними виборами:

  • Звук увімк./вимк.
  • TTS-озвучення увімкнене/вимкнене
  • Темна тема / світла тема

Фізична метафора настільки вдала, що навіть ваші бабуся з дідусем її розуміють.

Slider (повзунок) — це доріжка з ручкою, яку ви перетягуєте вперед-назад для вибору значення. Як регулятор гучності, який розплющили.

En Parlant~ використовує повзунки для:

  • Розмір шрифту — перетягніть для налаштування
  • Гучність — перетягніть для налаштування (звісно)
  • Ядра CPU — скільки ядер має використовувати рушій?
  • Хеш-пам’ять — скільки оперативної пам’яті для хеш-таблиці рушія?

Є також RangeSlider із двома ручками для вибору діапазону — використовується для фільтрації партій за рейтингом Elo (наприклад, 2000–2200) та часовими періодами.

Ряд кнопок, де одночасно обрана рівно одна. Це як пресети автомобільного радіо — натискаєте одну, решта вискакує.

Використовується для перемикання між:

  • Оцінкою в сантипішаках проти відсотків перемога/нічия/програш на графіку аналізу
  • Різними форматами нотації ходів
  • Кількістю ліній рушія

Це ви знаєте. Checkbox (чекбокси) для «оберіть будь-які з підходящих», Select (випадаючі списки) для «оберіть один із цього списку». Вони з’являються в налаштуваннях, фільтрах і формах по всьому застосунку. Модальне вікно очищення даних має особливо задовільний набір чекбоксів, де ви можете обирати власне знищення.

Текстове поле, яке пропонує варіанти завершення під час введення. Пошук гравців у браузері бази даних використовує це — почніть вводити ім’я, і відповідні гравці з’являються нижче.

FileInput відкриває вибір файлу при натисканні — використовується в модальному вікні імпорту для завантаження PGN-файлів. DateInput відкриває календар для вибору дати — використовується для фільтрації партій за датою. Є також MonthPickerInput та YearPickerInput для випадків, коли потрібна менша точність (фільтрація бази Lichess за місяцем, фільтрація бази Masters за роком).


Ті, що показують прогрес

Section titled “Ті, що показують прогрес”

Горизонтальна смуга, що заповнюється зліва направо, показуючи, наскільки далеко просунувся процес. Використовується під час оновлення застосунку (прогрес завантаження) та — більш креативно — для відображення ймовірностей перемоги/нічиї/програшу в панелі аналізу. Три кольорові секції (біла, сіра, чорна) заповнюють смугу пропорційно. Це крихітна стовпчикова діаграма, замаскована під індикатор прогресу.

Loader (завантажувач) — це обертова анімація, яка каже «я працюю над цим, дайте мені секунду». З’являється під час завантаження баз даних, отримання статистики гравців або будь-якого асинхронного процесу.

Skeleton (скелетон) — це сірий заповнювач, що імітує форму вмісту, який ще не завантажився. Замість порожнього екрана чи спінера ви бачите примарні контури місць, де будуть картки та текст. Це архітектурний план стану завантаження — «справжні меблі вже в дорозі».

Сторінка баз даних використовує скелетони, поки завантажується сітка карток. Набагато елегантніше, ніж просто спінер.

Напівпрозоре покривало, накинуте на компонент під час його завантаження. Графік аналізу використовує це — ви все ще бачите графік за накладенням, але він затемнений, а зверху крутиться спінер. «Я ще тут, просто оновлюються дані.»


Badge (значок) — це невелика кольорова мітка — як бейджик на конференції. В En Parlant~ компонент SpeedBadge використовує значки для відображення контролю часу з кольоровим кодуванням:

  • 🩷 Рожевий — UltraBullet
  • 🔴 Червоний — Bullet
  • 🟠 Помаранчевий — Blitz
  • 🟢 Зелений — Rapid
  • 🔵 Синій — Classical
  • 🟣 Фіолетовий — Correspondence

Кожен значок крихітний, барвистий і миттєво передає швидкість гри одним поглядом.

Скорочення від keyboard (клавіатура). Відображає клавішу клавіатури з характерним стилем «піднятої клавіші». Використовується в налаштуваннях гарячих клавіш для відображення речей на кшталт Ctrl + Z. Це CSS-відтворення справжньої фізичної клавіші на вашій клавіатурі. Чудово скевоморфічне.


Ті, що розділяють і згортають

Section titled “Ті, що розділяють і згортають”

Горизонтальна лінія, що відокремлює секції. Ось і все. Це лінія. Але це стилізована лінія, і вона може опціонально мати текстову мітку посередині — як розділювач «— АБО —» у модальному вікні імпорту, що відокремлює «вставте PGN» від «введіть FEN».

Понад тридцять файлів використовують Divider. Виявляється, речі часто потрібно розділяти.

Collapse (згортання) — це секція, що розгортається й згортається з плавною анімацією. Клацніть — щоб показати, клацніть — щоб сховати. Опції фільтрів бази даних використовують це — вам не завжди потрібно бачити кожен фільтр, тому вони ховаються за Collapse, поки ви їх не захочете.


Повноцінний текстовий редактор «що бачиш — те й отримуєш», побудований на TipTap. Жирний шрифт, курсив, списки — все як належить. Використовується для написання анотацій до партій — тих коментарів, які ви додаєте, щоб пояснити, чому хід був геніальним або жахливим.

Це єдиний примітив, який більше нагадує складний організм, аніж окрему клітину. Під капотом це TipTap + ProseMirror + стилізація Mantine. Але з точки зору користувача — це просто текстове поле, де форматування працює.

Із @mantine/charts (який обгортає Recharts), AreaChart забезпечує роботу графіка оцінки — тієї хвилеподібної кривої вздовж нижньої частини панелі аналізу. Біла область вище середньої лінії означає, що білі виграють; чорна нижче — що чорні виграють.

Ви можете клацнути на будь-яку точку графіка, щоб перейти до цього ходу. Інтерактивна візуалізація даних зустрічається з шаховим аналізом. Він навіть має кастомні підказки та референсні лінії, що позначають фази гри (дебют → міттельшпіль → ендшпіль).

Через бібліотеку 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.


Наступного разу, коли побачите маленьке повідомлення, що виїжджає з кутка екрана, — це тост. Прямокутник навколо попереднього перегляду партії — це картка. Сірі блоки, що мерехтять перед завантаженням вмісту, — це скелетони.

Коли вивчаєте назви, починаєте бачити їх усюди. У кожному застосунку. На кожному вебсайті. Ті самі кілька десятків примітивів, перекомпоновані тисячею різних способів.

Це конструктор Lego — від самого початку і до кінця.