# UX/UI-аудит Windows-клиента Дата: 2026-07-08 ## Область аудита Проверен текущий React UI `apps/windows-client` для Vite/Tauri как компактная Windows-утилита управления proxy-маршрутизацией приложений. Аудит выполнялся в browser-preview на `http://127.0.0.1:5174/`, поэтому нативные Tauri-команды были недоступны, а интерфейс показывал preview/runtime-ошибки. Все выводы ниже привязаны к скриншотам, снятым в этом прогоне. ## Цель пользователя Главная задача пользователя - быстро управлять службами и понять: - какие компоненты установлены; - какие службы запущены, остановлены или отсутствуют; - какое действие доступно прямо сейчас: установить, удалить, запустить, остановить, обновить, добавить или применить; - что сейчас маршрутизируется; - через какую цепочку компонентов идет трафик; - готовы ли ProxiFyre и опциональный Local sing-box; - можно ли безопасно применить изменения; - что делать дальше, если что-то сломано. Цель по доступности: интерфейс должен быть управляемым с клавиатуры, с понятными статусами, читаемым восстановлением после ошибок, предсказуемыми focus states и устойчивой адаптацией к узким размерам Windows-окна. ## Доказательства 1. `01-summary-desktop.png` - панель "Сводка", desktop-ширина. Состояние: смешанное. Главный статус виден, но примененное состояние еще "загружается", а рядом уже показан бейдж "Совпадает". 2. `02-proxifyre-desktop.png` - панель ProxiFyre, desktop-ширина. Состояние: в целом рабочее. Состав компонента и список приложений компактны, но главное действие apply доступно даже при отсутствующих prerequisites. 3. `03-proxy-desktop.png` - панель "VPN / Прокси", desktop-ширина. Состояние: рабочее. Настройка маршрута понятна, но route path выглядит как вторичный текст, а apply-action выглядит валидным до того, как маршрут может успешно примениться. 4. `04-proxy-validation-desktop.png` - невалидный proxy input. Состояние: хорошая база. Inline-валидация находится рядом с полем и отключает действие проверки. 5. `05-summary-narrow.png` - панель "Сводка", узкая ширина. Состояние: напряженное. Контент перестраивается, но нижний log dock и длинные сообщения обрезают важную информацию. 6. `06-proxifyre-narrow.png` - панель ProxiFyre, узкая ширина. Состояние: напряженное. Контролы складываются неплохо, но setup chips переполняются по горизонтали, а нижний dock конкурирует с основной задачей. ## Доменное направление Ключевые понятия домена: цепочка маршрута, здоровье компонентов, локальный runtime, внешний endpoint, выбранные приложения, сгенерированный конфиг, граница apply/restart, диагностика. Цветовой мир: темная Windows-оболочка, терминальный черный, зеленый для driver/service ready, amber для предупреждений, красный для блокеров/firewall, синий для links/actions, slate для config-файлов. Сигнатурный элемент, который стоит усилить: `Service Control Row` - повторяемая строка компонента, где слева состояние службы, в центре человекочитаемый статус, справа одно главное действие и меню дополнительных действий. Route-chain readout тоже нужен, но как объяснение эффекта этих служб: `Apps -> ProxiFyre -> target -> VPN/server`. Дефолты, которые стоит отбрасывать: - generic dashboard cards -> service-control utility; - большая зеленая apply-кнопка всегда видна -> apply gated by readiness + inline blockers; - raw logs как главный error surface -> сначала человеческое recovery-сообщение, raw details вторым уровнем. - разрозненные кнопки и анимации -> shared component base с едиными variants/states/motion tokens. ## Сильные стороны - Приложение уже ощущается как компактная desktop-утилита, а не как сайт. Фиксированный header, tabs, плотные панели и темная системная палитра подходят задаче. - Продуктовая модель сильная: ProxiFyre и Local sing-box разделены, sing-box не сделан обязательным. - Inline-валидация SOCKS5-поля расположена рядом с полем и отключает "Проверить", когда формат неверный. - Зона добавления приложения использует иконки с доступными labels и tooltip, поэтому плотный workflow остается сканируемым. - Для основных анимаций есть `prefers-reduced-motion`. - UI использует настоящие `button` и tab roles, а не click-only divs. Это хорошая база для доступности. ## UX-риски 1. Apply выглядит доступным, когда маршрут еще не actionable. - Доказательства: `02-proxifyre-desktop.png`, `03-proxy-desktop.png`. - ProxiFyre отсутствует и список приложений пуст, но "Обновить конфиг" / "Обновить маршрут" ярко-зеленые. Это провоцирует failed action вместо направленного setup. 2. Главная цепочка маршрута не является визуальным фокусом. - Доказательства: `01-summary-desktop.png`, `03-proxy-desktop.png`. - Самая важная mental model - путь трафика, но сейчас он показан plain text в таблице или вторичном блоке. Пользователь вынужден читать фрагменты статуса вместо того, чтобы сразу увидеть цепочку. 3. В "Сводке" есть противоречивое состояние. - Доказательство: `01-summary-desktop.png`. - "Состояние загружается" показано рядом с "Совпадает", а система одновременно говорит "Не настроено". Это может создать ощущение, что действий не требуется. 4. Preview/native command failures слишком сырые. - Доказательства: все скриншоты. - Dock показывает `Cannot read properties of undefined (reading 'invoke')`. Для разработчика это полезно, но как первичный пользовательский error surface это шум. 5. Bottom log dock конфликтует с узкой компоновкой. - Доказательства: `05-summary-narrow.png`, `06-proxifyre-narrow.png`. - Важные сообщения обрезаются до "Компонен..." и "Cannot read prop..."; dock постоянно занимает вертикальное место в и так коротком окне. 6. ProxiFyre setup chips плохо перестраиваются. - Доказательство: `06-proxifyre-narrow.png`. - Горизонтальная chip-лента скрывает третий dependency и ухудшает диагностическую ясность. 7. Терминология немного смешана. - Доказательства: `01-summary-desktop.png`, `03-proxy-desktop.png`. - `config`, `TCP check`, `VPN сервер`, `Local sing-box`, `ProxiFyre` - все эти термины допустимы, но нужен единый принцип: сначала пользовательский русский, технический идентификатор вторым уровнем. 8. Компонентная база пока не выражена как система. - Доказательства: `02-proxifyre-desktop.png`, `03-proxy-desktop.png`, `06-proxifyre-narrow.png`. - Кнопки "Обновить", "Установить", "Открыть", "Проверить", add-icon buttons и service actions выглядят близко, но пока не читаются как строгая система variants. Из-за этого сложно гарантировать одинаковые hover/loading/disabled/focus states и одинаковую motion-модель. ## Риски доступности - Tablist использует `role="tab"`, но не видно поддержки ожидаемого arrow-key behavior и roving tab index. Пользователю с клавиатурой, вероятно, придется проходить все tabs через Tab вместо Left/Right. - Focus visibility есть через browser defaults, но визуально она тяжелая и не согласована со стилем приложения. Нужен отдельный `:focus-visible` token для buttons, tabs, inputs и icon controls. - Status dots сильно полагаются на цвет. Стоит дублировать состояние видимым текстом или `aria-label`/screen-reader text там, где текст рядом не объясняет статус. - Footer использует `aria-live`, но повторяющиеся raw runtime errors могут быть шумными для assistive tech. Сначала стоит объявлять короткий статус, а подробный error text держать за "Посмотреть". - На узкой ширине truncation может скрывать actionable-часть сообщений и button labels. - Скриншоты не доказывают полный keyboard order, screen-reader output или contrast ratios. Для этого нужен интерактивный accessibility pass. ## План улучшений ### P0 - Сделать service-control flow заслуживающим доверия 1. Ввести shared component base: - `Button` с variants: `primary`, `neutral`, `add`, `danger`, `icon`; - `Tabs` с единым keyboard behavior и animation contract; - `ServiceControlRow` для ProxiFyre, Local sing-box и будущих служб; - `StatusPill`, `Field`, `ActionMenu`, `LogDock`; - единые states: default, hover, active, focus-visible, disabled, loading. 2. Нормализовать motion tokens: - button press: 100-140ms; - tab switch: 180-240ms, только `opacity` + `transform`; - popover/menu: 150-180ms; - service operation: видимый loading state, чтобы интерфейс не ощущался зависшим; - не использовать `transition: all`. 3. Заменить raw preview/native invocation failures на дружелюбное состояние: - "Desktop-команды недоступны в browser preview. Запусти через Tauri для управления службами." - Raw error оставить только в деталях лога. 4. Заблокировать primary apply actions до готовности: - disabled + explanation, когда список приложений пуст; - disabled + explanation, когда ProxiFyre отсутствует; - disabled + explanation, когда выбран local route без установленного/запущенного sing-box или выбранного сервера; - "Открыть конфиг" оставить вторичным действием, не равным apply по весу. 5. Исправить язык summary-state: - использовать взаимоисключающие состояния: "Проверяю", "Не готово", "Готово к применению", "Применено", "Есть черновик"; - не показывать "Совпадает", пока saved/applied state реально не загружен. ### P1 - Пересобрать главную mental model 6. Вынести route-chain component как объясняющий элемент: - узел `Apps` с количеством; - узел `ProxiFyre` со статусом installed/running; - узел `Target`: external SOCKS5 или Local sing-box; - узел `Server`, когда активен local sing-box; - каждый сломанный узел показывает одно следующее действие. 7. Переработать "Сводку" в command center: - сверху: route-chain и readiness системы; - посередине: applied vs draft diff, только если есть отличие; - снизу: максимум два next actions; - длинные config paths и подробный состав компонентов убрать из первого взгляда. 8. Разделить "настроить маршрут" и "применить маршрут": - Proxy panel отвечает за endpoint choice и connection check; - ProxiFyre panel отвечает за app selection и service readiness; - Summary подтверждает объединенный маршрут и применяет только при готовности. ### P2 - Усилить responsive и component craft 7. Превратить setup chips в wrapping checklist на узких ширинах. 8. Сделать log dock адаптивным: - desktop: persistent compact dock подходит; - narrow: collapsed toast/details sheet вместо постоянного full-width footer. 9. Определить design tokens: - surfaces: canvas, panel, inset, elevated; - text: primary, secondary, muted, disabled; - status: ready, warning, blocked, checking; - focus ring и border intensities. 10. Стандартизировать copy: - последовательно использовать "конфиг" или "конфигурация"; - заменить "TCP check" на "TCP-проверка"; - `Local sing-box` оставить техническим именем компонента, но в user-facing headings связывать с "локальный прокси". ### P3 - Verification pass 11. Добавить focused interaction QA: - keyboard tab order; - arrow-key tab navigation; - focus return из menus/popovers; - disabled-action explanations; - empty, loading, error, missing-component, ready и unapplied-change states. 12. Добавить responsive visual snapshots: - 1280x720 desktop; - 800x600 compact desktop; - 420x720 narrow window; - длинные proxy/server names и длинные Windows paths. ## Рекомендуемый первый redesign slice Сначала стоит сделать shared UI foundation: `Button`, `Tabs`, `ServiceControlRow`, `StatusPill`, `Field`, `ActionMenu`, `LogDock` и motion tokens. После этого собрать ProxiFyre и Local sing-box через один `ServiceControlRow`, а route-chain использовать как объясняющий компонент в "Сводке" и "VPN / Прокси". Такой порядок сначала стабилизирует поведение кнопок/табы/анимации, затем улучшит ориентацию и recovery без переписывания всего UI.