palabras: a11y — Ctrl+. abre el panel del bloque activo por teclado (F3.6)

Acceso al panel de propiedades SIN ratón (INTERACCION §4.5, atajo ratificado). En
`palabras-activate` el keydown (que ya lleva la escalera Esc) gana Ctrl/⌘+.: resuelve el
bloque del CARET desde el DOM (activeBlockId puede sentarse a nivel documento), lo activa
y pide abrir el panel vía `onOpenPanel` (el shell lo abre en modo flotante; acoplado ya
está visible, menubar usa la barra).

Verificado Chrome real (recorrido sin ratón): caret en un párrafo → Ctrl+. → el panel abre
anclado a ESE bloque («T Párrafo», migas Documento › Párrafo) Y el foco ENTRA en el panel
(focus-trap del FloatPanel, del framework); Esc → el panel cierra Y el foco VUELVE al
editor (focus-return). check sin errores nuevos en palabras. Pendiente de F3.6: announce
(aria-live) de acciones de bloque (mover/eliminar/insertar).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
alpha-0.1-sec-dom
dev 3 months ago
parent 38452a3900
commit a8a75b196b

@ -32,7 +32,8 @@
enabled = true,
onActivate,
panelOpen = false,
onPanelClose
onPanelClose,
onOpenPanel
}: {
api: ProviderSnippetProps;
content: HTMLElement;
@ -49,6 +50,9 @@
panelOpen?: boolean;
/** Close the host's panel (first Esc while it's open). */
onPanelClose?: () => void;
/** Open the host's panel for the CARET's block (Ctrl/⌘+. — keyboard access to
* the properties without the mouse grip; INTERACCION §4.5, F3.6 a11y). */
onOpenPanel?: () => void;
} = $props();
// Build the MATERIALIZED-PATH id of the clicked block: walk the DOM up
@ -128,6 +132,22 @@
if (!content || !enabled) return;
const onKeydown = (e: Event) => {
const ev = e as KeyboardEvent;
// Ctrl/⌘+. (INTERACCION §4.5) — open the properties panel for the CARET's
// block: keyboard access to what the grip opens with the mouse. Resolve the
// block from the DOM caret (activeBlockId may sit at document level) and
// activate it first, so the panel inspects where the caret is.
if ((ev.ctrlKey || ev.metaKey) && ev.key === '.') {
ev.preventDefault();
const sel = dom.getDocument(content).getSelection?.();
const node = sel?.anchorNode ?? null;
const host =
node?.nodeType === 1 ? (node as HTMLElement) : (node?.parentElement ?? null);
const blockEl = host?.closest('[data-words-id]') as HTMLElement | null;
const idPath = blockEl ? idPathOf(blockEl) : null;
if (idPath) api.setActiveBlock(idPath);
onOpenPanel?.();
return;
}
if (ev.key !== 'Escape') return;
if (panelOpen) {
onPanelClose?.();

@ -168,6 +168,7 @@
{dom}
panelOpen={floating ? panelOpen : false}
onPanelClose={() => (panelOpen = false)}
onOpenPanel={() => floating && (panelOpen = true)}
onActivate={(_id, type) => {
// An atomic image can't be edited inline — in floating mode a
// click opens its inspector window. Docked/menubar only activate:

Loading…
Cancel
Save

Powered by TurnKey Linux.