UX/UI Canon
Этот документ - главный источник UX/UI-правил шаблона.
Если AGENTS.md, patch notes, canary notes, checklist или старый porting guide спорят между собой, сначала выполняйте этот документ. Остальные документы - история решений, примеры и диагностика.
Главный Принцип
GUI Audion - это рабочий пульт над CLI, а не лендинг и не демонстрационный дизайн. Пользователь должен быстро понять:
- где входные данные;
- что будет запущено;
- какие параметры реально меняют результат;
- где смотреть живой вывод;
- чем закончилась последняя операция.
Не прячьте правду CLI. Терминал, команда, статус и отчеты - часть UX, а не debug-мусор.
Приоритеты При Конфликте
- Надежность запуска, логов, кодировок и cleanup.
- Сохранение удачной рабочей структуры проекта.
- Читаемый терминал и постоянный финальный статус.
- Компактные контролы без потери смысла.
- Визуальная красота.
Если правка делает интерфейс "современнее", но уменьшает терминал до декоративной щели, растягивает поля путей, ломает muscle memory или прячет запуск, это regression.
Layout
Стартовое окно: 1600x900. Минимальный практичный размер: около 1180x720.
Базовая схема:
- верх: короткий header, тема/язык, глобальные рабочие папки, если проект работает с файлами;
- левая или центральная рабочая область: модули, пресеты, параметры операции;
- правая область: always-used настройки, диагностика, статус, терминал;
- низ/правая колонка: терминал с кнопками
STATUS,LOGS,OUT,REPORTили проектными аналогами.
Терминал нельзя превращать в 1/16 окна. Для CLI-наследства он должен занимать заметную высоту: обычно от 1/3 до 2/3 доступной правой области. Если места мало, сначала уплотняйте поля и кнопки, затем вводите splitter, и только потом уменьшайте терминал.
Две колонки должны жить до примерно 900px CSS-ширины. Не ставьте ранний breakpoint вроде 1420px, из-за которого терминал падает вниз на ноутбуках WUXGA при Windows scale 150%.
Не Ломать Удачный Скелет
Радикальная перестройка хуже точечного уплотнения, если пользователь уже получил рабочую mental model.
Перед изменением layout задайте вопрос:
- что пользователь уже понял и запомнил;
- какие controls используются всегда;
- какие controls относятся только к выбранному модулю;
- какие поля просто занимают место из-за формы, а не из-за смысла.
Удачные блоки лучше уплотнять, вытягивать в строки, делать full-row, переносить в child screen или splitter. Не надо без причины заменять список пресетов на узкие вытянутые карточки, огромные path inputs или декоративные панели.
Root И Child Screens
Root screen - это стартовый пульт, а не экран конкретной операции.
На root хорошо держать:
- крупные модули верхнего уровня;
- проверку окружения / Doctor;
- статус железа / runtime / кодеков, если это важно проекту;
- быстрый
STATUS/probe входных файлов; - глобальные папки и путь вывода;
- терминал и последние логи.
Если root содержит операции над разными объектами, разделяйте их на логические блоки. Документы отдельно, PDF отдельно, медиа отдельно, сервис/обслуживание отдельно. Не смешивайте конвертацию документов, постобработку PDF и диагностику в один плоский список, когда команд уже достаточно для группировки. Внутри блока команда остается обычной двухколоночной строкой: короткое действие слева, пояснение результата справа.
Модульные группы вроде Precision, Film Looks, Restoration, Batch, Service, Profiles можно открывать как child screens. На child screen:
Назадслева;- название модуля и текущий preset по центру/рядом;
- основная кнопка запуска справа в той же строке;
- глобальные always-used controls остаются там, где пользователь ожидает их видеть;
- меняется только содержимое текущего модуля.
На root не показывайте Назад.
Как это применено здесь. Программа небольшая, и вместо блоков со ссылками внутрь root сделан свитчером: ряд вкладок по числу групп верхнего уровня (Установка, Обновление, Обслуживание), под ними - команды активной вкладки. Команда с полями разворачивается прямо на вкладке: своя кнопка запуска, названная действием, и свои параметры, - отдельного child screen с одинаковой кнопкой Запустить для неё нет. Child screen остаётся у команд с собственным деревом. Служебные операции стоят строкой над вкладками: они относятся к программе, а не к вкладке.
Workspace И Пути
Поля путей не должны съедать экран.
Предпочтительный паттерн:
- единый внешний Workbench с подписями
Источник,Добавить файл...,Назначение,Сбросить,Удалить,Список; - compact dropdown/cache для источника и назначения;
- кэш путей и pin/favorite для часто используемых путей;
- одиночный файл или папка источника без скрытой staging-копии;
- отдельные маленькие кнопки выбора, открытия и защищённого удаления;
- read-only отображение текущего пути;
- крупный ручной текстовый input только там, где пользователь реально вводит путь руками.
Renderer, история путей, подписи и CSS Workbench живут в одном каноническом workbench.py. Проектный app.py содержит только адаптер к backend и обработчики предметных действий.
Если проект работает с папкой входа, кнопка STATUS должна запускать явный probe/status, а не постоянный фоновый анализ.
Presets
Списки пресетов должны быть строками, а не декоративными плитками, если пресетов много.
Правила:
- вся строка пресета кликабельна;
- имя пресета нормальным читаемым размером;
- имя в нормальном человеческом Caps/Title Case, если это пользовательский GUI;
- технический id можно показывать вторично, если он нужен для CLI;
- описание выравнивается по левому краю и не ломает высоту сверх меры;
- не ставьте иконку/булавку у каждого пресета, если это не реальное действие pin;
- selected row должен быть заметен, но не кричать.
Если preset имеет глобальные параметры, показывайте их широкими низкими строками или компактными блоками сверху. Для Restoration-подобных параметров группируйте кванты и offsets в строки/колонки: label, number input, slider. Slider не должен уезжать за границу блока.
Parameters
Порядок параметров следует решению пользователя, а не порядку CLI-флагов.
Схожие вещи рядом:
- codec + profile/container/quality;
- provider key + model;
- source mode + input filter;
- quant fields together;
- offset fields together.
Малый фиксированный выбор: radio/segmented controls. Длинный или динамический список: searchable select. Несколько вариантов: checkboxes.
Как это применено здесь. Взаимоисключающий выбор нарисован рядом кнопок-переключателей, а не радио: выбранная залита полупрозрачным синим, остальные контурные, ряд стоит по центру блока. Короткие значения (Авто, x64, ZIP) - одной ширины 120px; ряд с названиями продуктов - по содержимому с запасом, растянут до краёв блока. Множественный выбор из нескольких вариантов тоже кнопки. Одиночная галка - карточка в сетке блока: рамка в тоне блока, высота 38px, контрол 20x20. Подпись у контрола короткая, объяснение - в тултипе.
Строкам параметров нужен видимый воздух. Radio-группы, checkbox-строки, подсказки и числовые поля не должны прилипать друг к другу: закладывайте заметный вертикальный gap примерно 10-14px и увеличивайте его, если рядом есть подсказка или несколько взаимоисключающих режимов. Плотность полезна только пока пользователь без усилия видит, что относится к одной группе, а что уже следующий блок.
У плотных Quasar-полей есть важная визуальная тонкость: правые стрелки dropdown/append и нативные стрелки input[type="number"] нужно центрировать по высоте, а само значение поля не нужно насильно поднимать. Не правьте .q-field__native, .q-field__input или само поле через line-height/padding ради вертикального центра; текст в dense outlined fields лучше читается с естественной чуть нижней посадкой.
Редкие поля - ниже, тише, в Дополнительно, но внутри Дополнительно всё равно нужны логические секции.
Always-Used Blocks
Если блок используется почти всегда, он не должен исчезать в глубине модуля.
Примеры:
- кодек/контейнер/quality для media-проекта;
- backend encode/decode;
- глобальный режим CPU/CUDA;
- Workbench источника/назначения;
- терминал.
Такие блоки можно держать справа, сверху или в отдельной стабильной панели. Но они должны быть компактными и не отнимать у терминала всю высоту.
Mutually Exclusive Blocks
Если пользователь выбирает один codec/backend/provider, вся область выбранного варианта должна быть кликабельна, не только маленький radio или заголовок.
Неактивные варианты затемняются:
- controls видны, чтобы пользователь понимал доступные возможности;
- disabled state не выглядит как сломанный UI;
- при переключении верхнего выбора включается только релевантная группа.
Пример для media:
ProRes | x264 | x265 | DNxHR | Image;- у каждого свой профиль/container/quality;
- hardware encode может быть disabled или принудительно CPU для codec, который не поддерживает выбранный backend.
Buttons И Icons
В одном проекте должен быть один визуальный язык кнопок.
Не смешивайте случайно:
- material icons;
- monochrome emoji-like glyphs;
- настоящие emoji;
- текстовые кнопки разных размеров;
- filled buttons и ghost buttons без системы.
Если emoji: true, emoji остаются акцентами, а не заменой архитектуры. Хорошие места: headings и редкие service accents. Плохие места: длинные строки команд, terminal output, paths, filenames, machine-readable config.
Кнопка должна иметь нормальный внутренний воздух вокруг текста. Все короткие toolbar buttons центрируются. Operation rows обычно left-aligned. Если всё центрировано, проверяйте, не режется ли начало текста.
Tooltips
Tooltip используется для коротких ограничений, последствий действия и неочевидных условий запуска. Не переносите в tooltip длинную документацию.
Фон tooltip всегда фиксированный и не зависит от темы: rgb(23, 33, 43).
Header, Themes, Language
Header - самая хрупкая зона NiceGUI/Quasar. Theme select, language switch и title часто визуально сидят на разных вертикалях.
Правила:
- проверять screenshot, не доверять CSS-замыслу;
- сохранять стабильную высоту header;
- не поднимать весь shell ради исправления select;
- корректировать только header title/control group, если нужно;
Code Темная- безопасная тема по умолчанию;- RU/EN switch может делать full reload;
emojiхранится вconfig/gui_settings.yaml.
Terminal
Терминал должен быть оформлен как часть приложения:
- скругленная рамка;
- отдельная, но компактная toolbar-плашка;
- status/progress не ломают высоту;
- кнопки terminal toolbar отделены от окна вывода;
- моноширинный шрифт;
- live output и auto-scroll;
- постоянный итоговый индикатор под терминалом.
ui.notify не считается финальным статусом. Пользователь может его пропустить.
Всплывающие уведомления полезны как короткий сигнал о завершении или ошибке, но долгие операции не должны вызывать ui.notify из устаревшего контекста кнопки. Если операция стартовала с child screen, пользователь может перейти в другое меню, и NiceGUI удалит старый slot. Финальный toast нужно отправлять через живой client/app-контекст, а не через slot обработчика, который пережил долгий await.
Переходы по child/root меню во время выполнения должны быть безопасными: операция продолжает работать child-процессом или io-bound задачей, статус/прогресс/терминал обновляются из общего state, а не из элементов удалённого экрана.
Открытие источника, назначения и служебных папок (LOGS, CONFIG, REPORT, TOOLS) не требует toast-уведомления: проводник уже подтверждает действие. Выбор нового пути, импорт профиля или удаление меняют состояние, поэтому там toast для успеха, отмены или ошибки уместен.
Visual Smoke
После заметной UX/UI-правки обязательно сохраняйте или хотя бы просматривайте smoke screenshots:
- root;
- child/module screen;
- длинный список пресетов;
- экран с параметрами;
- terminal после короткого успешного запуска;
- светлая/темная тема, если менялись CSS tokens;
- узкий профиль окна, если менялись колонки/splitter.
Скриншот нужен не для красоты. Он ловит то, что тесты не видят: слишком узкий dropdown, съехавший select, пропавший статус, несогласованные кнопки, терминал-щель, плашку, кликабельную только по заголовку.
Что Является Историей, А Не Каноном
Patch notes и docs/MEMORY.md описывают, почему правило появилось. Они могут содержать canary-специфичные формулировки.
docs/KNOWN_PITFALLS_RU.md - каталог граблей. Это не layout spec.
docs/GUI_TEMPLATE_RECOMMENDATIONS_RU.md - короткая памятка. Если она короче или мягче этого документа, побеждает этот документ.
docs/SYSTEM_OPERATIONS_GUIDE_RU.md применяйте только к admin/system projects.
Для конкретного проекта можно отступить от канона, но это решение нужно записать в project docs/AGENTS, чтобы следующий перенос не "исправил" намеренный дизайн обратно.