Files
ds-galo/openspec/changes/archive/2026-10-11-grid-keyboard-navigation/specs/ui-workspace/spec.md
T

8.8 KiB

Spec Delta

ADDED Requirements

Requirement: Курсор в сетке фото

Сетка SHALL хранить курсор — текущую ячейку, отдельную от выделения. Перемещение курсора SHALL не менять выделение и не обновлять правую панель. Курсор SHALL отображаться контуром, отличимым от рамки выделения, SHALL сохраняться при снятии выделения и SHALL устанавливаться на фото при клике по нему мышью.

Scenario: Синхронизация с мышью

  • WHEN пользователь кликает по фото в сетке
  • THEN фото выделено, а курсор установлен на нём

Scenario: Перемещение не меняет выделение

  • WHEN фокус в сетке и пользователь нажимает стрелку
  • THEN курсор перемещается, а выделение и правая панель не меняются

Scenario: Курсор переживает снятие выделения

  • WHEN выделение снято кликом по пустому месту или клавишей Esc
  • THEN курсор остаётся на прежней ячейке

Scenario: Отображение курсора

  • WHEN сетка в фокусе и у курсора есть ячейка
  • THEN ячейка показывает контур, отличимый от рамки выделения, и он скрывается при уходе фокуса из сетки

Requirement: Клавиши сетки фото

При фокусе в сетке клавиши SHALL управлять курсором и выделением: ←/→ — на соседнее фото с переходом на соседнюю строку, ↑/↓ — на строку (density.cols) с упором в границы. Space SHALL переключать выделение ячейки под курсором, Shift+стрелки — двигать курсор и расширять выделение от якоря, Enter — открывать просмотр, Esc — снимать выделение. Вне фокуса сетки клавиши SHALL не действовать.

Scenario: Горизонтальное перемещение

  • WHEN курсор не в конце строки и нажато →
  • THEN курсор переходит на следующее фото

Scenario: Перенос на соседнюю строку

  • WHEN курсор в конце строки и нажато →
  • THEN курсор переходит на первое фото следующей строки

Scenario: Вертикальные границы

  • WHEN курсор в верхней или нижней строке и нажато ↑ или ↓
  • THEN курсор остаётся на месте, без переноса

Scenario: Переключение выделения

  • WHEN нажато Space
  • THEN ячейка под курсором добавляется или убирается из выделения, а правая панель обновляется

Scenario: Расширение выделения

  • WHEN нажато Shift вместе со стрелкой
  • THEN курсор двигается, а выделение расширяется от якоря до курсора

Scenario: Открытие просмотра

  • WHEN нажато Enter
  • THEN открывается просмотр фото под курсором

Scenario: Снятие выделения клавишей

  • WHEN нажато Esc
  • THEN выделение снимается, а курсор остаётся

Scenario: Прокрутка к курсору

  • WHEN курсор перемещается за пределы видимой области сетки
  • THEN сетка прокручивается так, чтобы ячейка под курсором стала видимой

Scenario: Догрузка при выходе за загруженные фото

  • WHEN курсор на последнем загруженном фото и нажата стрелка в сторону следующих фото
  • THEN следующая порция фото догружается, а курсор переходит на следующее фото

Scenario: Вне фокуса сетки

  • WHEN фокус находится в поле ввода или диалоге и нажаты стрелки или Space
  • THEN курсор и выделение сетки не меняются

Requirement: Снятие выделения кликом по пустому месту

Клик по области сетки и её отступам, не по фото и не по органам управления тулбара, рейла и панелей, SHALL снимать выделение и возвращать в правой панели свойства альбома. Фокус SHALL оставаться в сетке, чтобы клавиши продолжали действовать.

Scenario: Клик по пустому месту

  • WHEN есть выделение и пользователь кликает по пустому месту сетки или её отступам
  • THEN выделение снято, а правая панель показывает свойства альбома

Scenario: Мультивыделение

  • WHEN выделено несколько фото и пользователь кликает по пустому месту
  • THEN выделение снимается полностью

Scenario: Клик по фото

  • WHEN пользователь кликает по фото
  • THEN выделение устанавливается на фото, а не снимается

Scenario: Клик по органам управления

  • WHEN пользователь кликает по кнопке тулбара, элементу рейла или панели
  • THEN выделение не снимается

Scenario: Фокус остаётся в сетке

  • WHEN выделение снято кликом по пустому месту
  • THEN стрелки продолжают двигать курсор без дополнительного Tab

Requirement: Возврат фокуса из просмотра

При возврате в альбом из просмотра сетка SHALL выделить последнее просмотренное фото (одиночное), поставить на него курсор, вернуть фокус в сетку и прокрутить к ячейке. Если фото нет среди загруженных, сетка SHALL догружать страницы, пока оно не появится. Восстановление SHALL применяться только к тому альбому, из которого был открыт просмотр.

Scenario: Возврат из просмотра

  • WHEN пользователь открыл фото и закрыл просмотр
  • THEN в сетке это фото выделено, курсор на нём, фокус в сетке, а ячейка прокручена в видимую область

Scenario: Последнее просмотренное фото

  • WHEN пользователь пролистал несколько фото в просмотре и закрыл его
  • THEN восстанавливается последнее просмотренное фото

Scenario: Фото вне первой страницы

  • WHEN просмотренное фото отсутствует в первой загруженной странице
  • THEN сетка догружает страницы, пока фото не появится, и только затем ставит на него курсор

Scenario: Возврат в другой альбом

  • WHEN после просмотра пользователь открывает другой альбом
  • THEN восстановление не применяется, выборка пуста

Scenario: Клавиатура после возврата

  • WHEN фокус восстановлен после просмотра
  • THEN стрелки сразу двигают курсор без дополнительного Tab