feat(readmymind): alternates row, phone accessory key, phone-sized modal (phase 3 part 1)

The Read My Mind modal grows up and reaches phones:

- Alternate suggestions (the predictor's verify/redirect kinds) now render
  as tappable rows below the main field. Tapping one swaps it into the
  editable field; the edit you were making folds back into the row you
  leave, so toggling between alternates never loses typing. Rethink now
  records the WHOLE shown set (main + alternates) as rejected.
- Phones get a 🧠 key on the keyboard accessory bar (both simple and
  extended layouts), gated on the same synced readMyMindEnabled setting
  via an rmm-enabled marker class on the BAR element: setMode() rebuilds
  the buttons' innerHTML, so per-key state would be wiped. Synced at init
  and re-synced by applyHeaderVisibilitySettings() on every settings
  apply, so a live toggle needs no reload. The header button stays off
  phones.
- On phones the modal renders as a small dialog (mirrors modal-sm) instead
  of the full-screen default, with wrap-friendly finger-sized footer
  buttons. Not modal-sm itself: that caps desktop width at 340px and this
  modal wants 560px there.
- On touch devices the ready/swap paths no longer focus the field, so the
  OS keyboard does not pop over the alternates that just rendered.
- New static guard test/readmymind-phone-key.test.ts pins the dual-template
  key, the marker-class gating, the phone-hidden header button, the
  small-dialog phone modal, and the no-innerHTML discipline.

Part 2 of phase 3 (rethink steering, the free-text steer note) is next;
the API already accepts steer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-08-10 03:57:06 +02:00
parent c891a8045d
commit a070fc43ea
11 changed files with 272 additions and 26 deletions
+50
View File
@@ -10757,6 +10757,56 @@ kbd {
padding: 12px 4px;
color: var(--text-dim);
}
/* Alternate suggestions (the predictor's verify/redirect kinds): tappable rows
that swap into the editable field (readmymind-ui.js _rmmSelect). */
.readmymind-alternates {
margin-top: 10px;
display: flex;
flex-direction: column;
gap: 6px;
}
.readmymind-alt {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
min-width: 0;
text-align: left;
padding: 7px 10px;
background: transparent;
border: 1px solid var(--control-border);
border-radius: 8px;
color: var(--text-dim);
cursor: pointer;
font-size: 12px;
}
.readmymind-alt:hover,
.readmymind-alt:focus-visible {
border-color: var(--accent);
color: var(--text);
}
.readmymind-alt-text {
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-family: var(--mono-font, monospace);
}
/* Keyboard-accessory 🧠 key: the phone surface for the same opt-in setting
(the header 🧠 button stays phone-hidden in mobile.css). The key ships in
BOTH bar templates (keyboard-accessory.js) but stays hidden until the bar
carries the marker class: setMode() rebuilds the bar's innerHTML on every
layout switch, so the gate must live on the bar element, not on the key.
Lives here rather than mobile.css because large touch tablets (>1023px)
never load mobile.css but do render the accessory bar. */
.keyboard-accessory-bar .accessory-btn-rmm {
display: none;
}
.keyboard-accessory-bar.rmm-enabled .accessory-btn-rmm {
display: inline-flex;
}
.approvals-badge {
position: absolute;