Drive develop, the grid, the sidebar and People from the keyboard

An audit of every action by view against the keys the handlers bind left
develop without zoom, pan, fit or a way back to the grid, the grid without
select-none, thumbnail size or keywording, People with no key at all, and
the export and copy sheets without Enter. It also found the reverse gap
FR-UI-5 forbids: pick and reject had no route but P, X and U, and the
2026-09-19 amendment's judging in develop had not been built.

Develop: Ctrl+= and Ctrl+Plus zoom in and Ctrl+- out about the middle of the
view, Ctrl+0 fits and Ctrl+1 goes to 1:1, Shift and an arrow pan a magnified
view, G goes back to the grid, Ctrl+Y redoes, and Enter keeps a crop that hid
a mask. 0-5, P, X and U rate and flag the open photograph without moving on,
with stars and Pick/Reject in the top bar as the pointer and touch route.
= and - nudge the control last moved by a hundredth of its travel; the
framing sliders, perspective included, now count as "last moved", so R puts
them back as well. J turns the selected mask part's join chip.

Grid: Ctrl+D and Ctrl+Shift+A clear the selection, = and - resize the
thumbnails, Ctrl+K opens keywording, and Flag in the selection bar gives
pick and reject a pointer and touch route. Sidebar: Enter commits a
collection's name, and Enter or Escape hands the keyboard back to the grid,
where it used to go nowhere until something was clicked. People: Up and Down
walk the rail, F2 puts the name field under the keys, and Escape or Back now
leave the screen the way its back button does instead of doing nothing.
Sheets: Enter does what the export or copy sheet's button does.

The choices follow Lightroom where it has one. No new key steals typing: the
grid's and People's keys live on focus holders that are not ancestors of any
text field, and the sheets' Enter comes after a focused field has had it.
Every binding is tagged beside its handler, and the gate added in the
previous commit holds the two to each other.
This commit is contained in:
2026-09-24 23:42:26 -04:00
parent 9d1e31ffbb
commit d489a34190
15 changed files with 975 additions and 160 deletions
+18 -1
View File
@@ -106,6 +106,11 @@ component TreeRow inherits Rectangle {
callback rename-committed(string);
/// Renaming abandoned with Escape; the old name stands.
callback rename-cancelled();
/// TRACES: FR-UI-5
/// Enter or Escape finished the name, and the keyboard should go back to
/// whatever had it. Not raised when the name is committed by clicking
/// away: the click has already put focus where the user wanted it.
callback keys-released();
height: Theme.row-height;
@@ -255,6 +260,15 @@ component TreeRow inherits Rectangle {
// the input has focus and consumes it.
if (Keys.chord(event) == "Escape") {
root.rename-cancelled();
root.keys-released();
return accept;
}
// Enter keeps the name. The input's own `accepted`
// would do the same; answering it here is what puts the
// key where the checker can see it bound.
if (Keys.chord(event) == "Enter") {
root.rename-committed(self.text);
root.keys-released();
return accept;
}
return reject;
@@ -375,7 +389,7 @@ component TreeRow inherits Rectangle {
// where: Collections sidebar
// touch: Hold the collection, then "Rename"
// pointer: Double-click its name, or right-click it and choose "Rename"
// keys: `Escape` while typing abandons the new name
// keys: Type the name and press `Enter`; `Escape` abandons it
// why: Double-click is what a file manager and a Lightroom panel use
// for the same thing, so it needs no discovering — but nothing
// on screen says so, which is what the menu item is for.
@@ -506,6 +520,8 @@ export component CollectionsPanel inherits Rectangle {
callback rename-commit(int, string);
/// Renaming was abandoned.
callback rename-cancel();
/// A key finished a rename; see `CollectionRow.keys-released`.
callback keys-released();
// --- trash (FR-CAT-15) ---
//
@@ -698,6 +714,7 @@ export component CollectionsPanel inherits Rectangle {
rename-requested => { root.rename-start(row.id); }
rename-committed(name) => { root.rename-commit(row.id, name); }
rename-cancelled => { root.rename-cancel(); }
keys-released => { root.keys-released(); }
}
}