KeyTips: inline badges over the label's letter, header mnemonics for menu rows, collision suffixes, KeyTip-themed cue - #76
Merged
Conversation
… their header mnemonic; colliding auto letters get digit suffixes; AccessText.HasKey needs a key Ports the maintainer's 2026-09-12 prototype, cleaned up: - Placement: a badge sits where the access-key cue would — over the mnemonic's cluster, else over the first cluster spelling the badge letter (the cluster index is converted to a cell column, so a wide cluster before the key shifts the badge correctly); the badge shows the letter in the label's case; a multi-letter badge starts there and runs right; a control without a plain-monospace label keeps the anchor rule. Helpers: UIElement.TranslateTo, TextElement.GetGlyphSource. - KeyTipModel derives a HeaderedItemsControl's mnemonic from its header (a MenuItem "E_xit" badges X, not E); GetAccessText moves from MenuItem to HeaderedItemsControl. - Collisions: auto letters that collide all survive with digit suffixes in document order (B -> B0, B1, B2 — the earlier survivor is renamed, by ENTRY index, when the second arrives); an explicit key still beats an auto letter. - AccessText.HasKey requires a key character as well as an index (a default value is not a mnemonic). KeyTipTests: placement (mnemonic, first match, wide clusters, icon-only fallback, label case, suffixed collision, menu row) — each fails without the inline anchor — and the suffix drill. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013qbF5ru6uh5w7fqhP3yoPE
…for accent buttons; context menu closes when focus leaves it; Gallery logs KeyTip diagnostics The rest of the maintainer's 2026-09-12 prototype: - The inline access-key cue takes the KeyTip look — the active mnemonic draws in the KeyTip brushes with the underline removed (an inline badge where the letter is), the inactive cue is plain on colour tiers; KeyTipTextWeight is resolved from the theme (Ansi16 bold) with the tier fallback. ThemeKeys.InteractiveCueActiveAlternateStyle (inverse) for a button whose accent fill would clash with the cue brushes (the warning button style uses it). - Tests assert cues through AccessKeyTestHelpers (AssertCue / AssertNoCue resolve the presenter's effective cue styles) instead of hard-coding the underline attribute. - ContextMenu closes when keyboard focus moves out of it to an element elsewhere (Section20 C7.7b). - The Gallery's diagnostics pane shows KeyTipDiagnostics messages (dropped / suffixed badge letters). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013qbF5ru6uh5w7fqhP3yoPE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The maintainer's 2026-09-12 KeyTip prototype, reviewed, cleaned up and tested. Two commits.
Inline badge placement. A badge sits where the access-key cue would be: over the mnemonic's cluster, else over the first cluster spelling the badge letter, showing that letter in the label's own case (deliberate — it reads as the label's letter). Fixes over the prototype: the presenter's key index is a cluster index and is now converted to a cell column (a wide cluster before the key shifts the badge correctly); a multi-letter badge starts at the letter and runs right rather than being pushed left of the control. A control without a plain-monospace label keeps the anchor rule. Helpers:
UIElement.TranslateTo,TextElement.GetGlyphSource.Menu rows badge their header mnemonic.
KeyTipModelderives aHeaderedItemsControl's letter from its header (E_xitbadgesx, notE);GetAccessTextmoves up fromMenuItem.Collision suffixes. Colliding auto letters all survive, suffixed in document order (
B→B0,B1,B2); an explicit key still beats an auto letter. Fix over the prototype: the earlier survivor was renamed through the pending index, which is wrong once any earlier pending was dropped — it now uses the entry index.AccessText.HasKeyrequires a key character as well as an index.Also included (per your call): the KeyTip-themed access-key cue (active mnemonic in the KeyTip brushes, underline removed; plain inactive cue on colour tiers;
KeyTipTextWeightresolved from the theme),InteractiveCueActiveAlternateStylefor accent-filled buttons, theAccessKeyTestHelpersrefactor,ContextMenuclosing when focus leaves it, and the Gallery diagnostics hookup forKeyTipDiagnostics(only that subscription — the other re-enabled diagnostics stay in your tree).Tests. Placement: mnemonic cluster, first matching letter, wide clusters before the key, icon-only fallback, label case, suffixed collision, menu row — each verified to fail without the inline anchor. Collision: the
B0/B1/B2drill and explicit-beats-auto. Context menu: focus-leaving close (fails without the change). Suites: UI 3963, Bars 319, Xaml 647 green.Not in this PR: KeyTips vs Backstage (queued separately — the ribbon only sees whether the request was handled).
🤖 Generated with Claude Code
https://claude.ai/code/session_013qbF5ru6uh5w7fqhP3yoPE