diff --git a/openspec/changes/grid-keyboard-navigation/.openspec.yaml b/openspec/changes/archive/2026-10-11-grid-keyboard-navigation/.openspec.yaml similarity index 100% rename from openspec/changes/grid-keyboard-navigation/.openspec.yaml rename to openspec/changes/archive/2026-10-11-grid-keyboard-navigation/.openspec.yaml diff --git a/openspec/changes/grid-keyboard-navigation/design.md b/openspec/changes/archive/2026-10-11-grid-keyboard-navigation/design.md similarity index 100% rename from openspec/changes/grid-keyboard-navigation/design.md rename to openspec/changes/archive/2026-10-11-grid-keyboard-navigation/design.md diff --git a/openspec/changes/grid-keyboard-navigation/proposal.md b/openspec/changes/archive/2026-10-11-grid-keyboard-navigation/proposal.md similarity index 100% rename from openspec/changes/grid-keyboard-navigation/proposal.md rename to openspec/changes/archive/2026-10-11-grid-keyboard-navigation/proposal.md diff --git a/openspec/changes/grid-keyboard-navigation/specs/ui-workspace/spec.md b/openspec/changes/archive/2026-10-11-grid-keyboard-navigation/specs/ui-workspace/spec.md similarity index 100% rename from openspec/changes/grid-keyboard-navigation/specs/ui-workspace/spec.md rename to openspec/changes/archive/2026-10-11-grid-keyboard-navigation/specs/ui-workspace/spec.md diff --git a/openspec/changes/grid-keyboard-navigation/tasks.md b/openspec/changes/archive/2026-10-11-grid-keyboard-navigation/tasks.md similarity index 100% rename from openspec/changes/grid-keyboard-navigation/tasks.md rename to openspec/changes/archive/2026-10-11-grid-keyboard-navigation/tasks.md diff --git a/openspec/specs/ui-workspace/spec.md b/openspec/specs/ui-workspace/spec.md index e622bf3..9cb2a85 100644 --- a/openspec/specs/ui-workspace/spec.md +++ b/openspec/specs/ui-workspace/spec.md @@ -382,3 +382,123 @@ Ctrl/Cmd-клик — добавить или убрать, Shift-клик — #### Scenario: Прозрачная панель просмотра - **WHEN** открыт режим просмотра фото - **THEN** верхняя панель нарисована поверх фото без фона и не уменьшает область изображения + +### 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