# 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.
