Alt+H, O, A (AutoFit Row Height) and Alt+H, O, I (AutoFit Column Width)
ran nothing when Alt was still held for H, as Excel allows: any key with
Alt down cancelled keytips. KeyTips now tracks the left Alt key, and a
letter typed with it held that continues a known sequence is handled as
a keytip letter. Other Alt combinations still cancel; AltGr (right Alt)
and macOS Option are unchanged (#1864).
- Side-by-side and synchronous-scrolling keytips removed (do not exist in
James's Excel); Copy H,C / Spelling R,S / Fill H,H / Sparklines N,Z,K
confirmed already correct
- QAT digits 0-9 and Backstage account/home/options + legacy Share Workbook
sequences dropped (no meaningful GridCraft target; not left as trash)
- Colour palette (H,H fill and F,C font colour): arrow keys move a highlight
through the swatches, Enter applies; key events are stripped so the grid
behind the popup does not react
- Arrows/Enter while a keytip combo is open now navigate the list instead
of moving the filter field's text cursor (events stripped from TextEdit)
- Reopening a combo resets the filter: the reset frame requests a repaint
so the stale filtered list never lingers on screen
- Page Layout Sheet Options: Gridlines View/Print and Headings View/Print
checkboxes painted with VG/PG/VH/PH badges and keytip toggles
- Background rebound from PG to PGB (Excel's Page Setup GB badge); PG is
no longer terminal
- editable_combo: every dropdown keytip opens with a filter field focused;
typing narrows the list, Up/Down move the highlight (wrapping), Enter or
click applies, custom text applies where valid (font size). Fixes arrows
and typing in ALT+H FF/FS/N.
- Audited all 54 painted ribbon ids against the table: real mismatches fixed
(Data Sort/Text-to-Columns/Remove-Duplicates/Subtotal, Review Spelling/
Accessibility/New Comment/Notes, View Zoom/Freeze, Formulas Insert Function/
Name Manager/Define Name/Use-in-Formula/Error Checking/Evaluate, Insert Link/
Comment/Header-Footer/Sparklines, Home Protect Sheet).
- keytips.json: dialog kind for real dialog openers; control kind for the 6
chart-type buttons, 7 formula-category buttons, and Orientation (HFQ added,
was missing); M-family restructured to Excel semantics (ML/MT/ME/MO/MG/MQ
fire directly, MI1 opens Financial) with 14 unreachable children dropped;
383 entries total.
- New Action::Control routes a keytip to its ribbon control (popup/dropdown
open, checkbox toggle, button handler) instead of an engine command with
empty params. Fixes ALT+H FF/FS/N/H/H error boxes.
- Ribbon consumes a one-shot ui.keytip_invoke: font/size/number combos
converted to the popup pattern (ComboBox has no open_memory), fill/font
color menus force-open via SetOpenCommand, 100% zoom and Formula Bar run
their handlers.
- keytips.json: FF/FS/N/H/H -> control kind; View/Formulas/Data dialog
openers (WQ zoom, HFM format cells, HO*, MV, AWG, sparkline types) and
control WVF; MSP/HVP re-targeted; dropped 15 unreachable Home sub-items
and non-Excel HWS shrink-to-fit.
- View tab: badges on workbook views, gridlines/headings, formula bar.
- Generated suite: 399 tests incl control-kind arm; direct tests 18.
- Action::Pending now consults the engine catalog at fire time: silent
no-op while the command is missing, runs it once it exists - no table
edit needed when a future feature lands.
- Stripped stray backticks from 7 pending target ids so catalog lookup
can ever match them.
- gridcraft-engine: doc(hidden) register_test_command hook so UI tests
can prove the go-live path without touching production code.
- Tests: pending_sequences_are_silent_no_ops (no dialog/toast/journal),
pending_sequences_go_live_when_the_command_lands (fake command fires
via its reserved sequence), every_sequence_terminates_without_panicking
(all 413 sequences pressed end-to-end).
Population of keytips.json from the collected Excel Alt-sequence set:
- 408 curated entries: 10 tabs, 354 command binds (64 reserved pending,
290 live catalog commands), 2 dialog openers, 42 group levels.
- Bind-all policy: sequences whose command does not exist yet bind to the
canonical future id as Action::Pending -- badge shows, invocation is a
silent no-op until the command lands (ids from docs/parity-checklist).
- Group levels: 46 command entries that are strict prefixes of deeper
sequences were demoted to menu openers so the trie never fires early
(HV must not paste; it waits for the variant letter).
- Fire-immediately restores: HC Copy, HAN Accounting, FA Save As, FO Open,
FI Info. Unreachable legacy aliases (HCC, HANM, FA1, FAY3, FOC, FOO, FIP)
dropped: the parent fires first.
- ES stays a terminal dialog opener as in Excel: the A/F/T/V variants are
dialog mnemonics, not trie sequences.
- Escape pops one trie level and returns to the armed root at a single
letter; keytips.json is the single modifiable source; xtask keytips now
emits through rustfmt so --check is byte-stable.
- Tests: 99 pass (27 lib + 14 keytips + suite), all 8 CI gates green.
Move the hardcoded keytip sequence list into keytip_table.rs as the single
source of truth for both the matcher and the ribbon badge painter.
- Generalize Action::Home into Action::Tab(&'static str); the legacy
Edit/Format prefix special-case in lib.rs is absorbed into the table.
- Badge helpers: tab_sequence (tabs), group_extension (menu anchors),
item_letter (menu items), control_badges (command controls).
- Add tab letters for Insert (N), Page Layout (P), Formulas (M), Data (A),
Review (R), View (W); Draw/Automate stay unbadged until contextual
letters land.
- Tests: 5 table unit tests + tab_letters_switch_to_their_ribbon_tabs
integration test. All 7 xtask ci gates green.
The sequence table is no longer hand-maintained Rust: keytips.json is the
single human-edited source (one line per sequence, grouped by tab, pending
reserves sequences for future commands), and `cargo xtask keytips`
regenerates keytip_table/generated.rs deterministically. `cargo xtask ci`
now fails if the generated table is stale.
- Action::Pending: reserved sequences show their badge and invoke silently
until the command exists (bind-all policy).
- Intermediate group levels are implicit: the matcher waits whenever a
pressed letter starts a deeper sequence; only terminal entries are
listed (two-letter units like Draw's "JI" work with no extra rows).
- First populated sequence beyond the legacy set: W,V,G toggles gridlines,
proven end-to-end by view_gridlines_sequence_runs_end_to_end.
Excel shows some access keys as one multi-letter unit (Draw's "JI") that
fires only once complete. The matcher now follows the trie shape:
- A pressed letter that matches a complete sequence fires immediately.
- If it only starts deeper sequences, the matcher waits for more input
(implicit group level, no table entry required).
- A tab with deeper sequences stays as an active level so group badges
show; a terminal unit clears the prefix.
- tab_sequence() returns multi-letter tab units as one badge.
Draw: Alt+JI switches to the Draw tab; deeper Draw letters are left
blank for future contributors (GridCraft's Draw differs from Excel's).
Move the hardcoded keytip sequence list into keytip_table.rs as the single
source of truth for both the matcher and the ribbon badge painter.
- Generalize Action::Home into Action::Tab(&'static str); the legacy
Edit/Format prefix special-case in lib.rs is absorbed into the table.
- Badge helpers: tab_sequence (tabs), group_extension (menu anchors),
item_letter (menu items), control_badges (command controls).
- Add tab letters for Insert (N), Page Layout (P), Formulas (M), Data (A),
Review (R), View (W); Draw/Automate stay unbadged until contextual
letters land.
- Tests: 5 table unit tests + tab_letters_switch_to_their_ribbon_tabs
integration test. All 7 xtask ci gates green.
ribbon_keys ran ui.ribbonTab every frame while the prefix was E/O/OC,
forcing the Home tab continuously. Run it once on the prefix change and
add a regression test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>