Skip to content
Closed
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
303149b
test(accessibility): require toolbar shortcut semantics
seonghobae Aug 7, 2026
29d8c15
feat(accessibility): expose editor shortcut semantics
seonghobae Aug 7, 2026
513dcdc
test(docs): require shortcut accessibility evidence
seonghobae Aug 7, 2026
d943a90
docs(accessibility): document shortcut semantics
seonghobae Aug 7, 2026
6229e0a
docs(doctoring): record shortcut accessibility evidence
seonghobae Aug 7, 2026
ae8448d
docs(changelog): record shortcut discoverability
seonghobae Aug 7, 2026
57f5ef8
test(accessibility): reject unimplemented link shortcut claim
seonghobae Aug 7, 2026
e89f51e
fix(accessibility): stop claiming unimplemented link shortcut
seonghobae Aug 7, 2026
251d660
test(docs): bind link shortcut claim to implemented behavior
seonghobae Aug 7, 2026
3bd1dd3
docs(accessibility): document only implemented shortcuts
seonghobae Aug 7, 2026
20925ba
docs(doctoring): correct link shortcut evidence
seonghobae Aug 7, 2026
3cfdc68
docs(changelog): record implemented-shortcut boundary
seonghobae Aug 7, 2026
9c8a6b0
test(accessibility): bind README to implemented link shortcuts
seonghobae Aug 7, 2026
a6c472e
docs(accessibility): remove stale link shortcut claim
seonghobae Aug 7, 2026
8ffa719
test(accessibility): bind README correction to release evidence
seonghobae Aug 7, 2026
312033a
docs(accessibility): record README shortcut correction
seonghobae Aug 7, 2026
ddc00c0
docs(changelog): record README shortcut correction
seonghobae Aug 7, 2026
1143973
test(accessibility): cover alternate redo shortcut
seonghobae Aug 7, 2026
bc634bf
fix(accessibility): expose alternate redo shortcut
seonghobae Aug 7, 2026
52d3847
test(accessibility): bind redo alternatives to public evidence
seonghobae Aug 7, 2026
877ee37
docs(accessibility): document alternate redo shortcut
seonghobae Aug 7, 2026
02c0c9c
docs(accessibility): doctor alternate redo bindings
seonghobae Aug 7, 2026
df7696a
docs(changelog): record alternate redo bindings
seonghobae Aug 7, 2026
8790b4e
test(accessibility): require link shortcut discoverability
seonghobae Aug 8, 2026
19f4d99
fix(accessibility): expose implemented link shortcut
seonghobae Aug 8, 2026
920fdb2
fix(toolbar): preserve existing delete-row command
seonghobae Aug 8, 2026
f38b098
test(docs): require truthful link shortcut evidence
seonghobae Aug 8, 2026
8d12af4
docs(accessibility): document shipped link shortcut
seonghobae Aug 8, 2026
b9af679
docs(doctoring): correct link shortcut evidence
seonghobae Aug 8, 2026
cbd6a40
test(docs): scope README shortcut assertion safely
seonghobae Aug 8, 2026
e23358b
docs(changelog): correct link shortcut provenance
seonghobae Aug 8, 2026
bf1ef37
test(docs): require README link shortcut truth
seonghobae Aug 9, 2026
c847a21
docs(readme): restore shipped link shortcut guidance
seonghobae Aug 9, 2026
ba8256d
test(accessibility): require consistent Tiptap terminology
seonghobae Aug 9, 2026
e56c0e2
docs(accessibility): align Tiptap product naming
seonghobae Aug 9, 2026
1340cac
chore(accessibility): reconcile protected release gate
seonghobae Aug 9, 2026
2675414
Merge branch 'main' into feat/toolbar-shortcut-discoverability
seonghobae Aug 9, 2026
b74216e
chore(accessibility): preserve protected-main release and security state
seonghobae Aug 9, 2026
3a45305
chore(accessibility): reconcile protected changelog
seonghobae Aug 9, 2026
626c414
chore: reconcile shortcut changelog with autosave lifecycle
seonghobae Aug 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim

## [Unreleased]

### Accessibility
- Added programmatic toolbar shortcut discoverability with WAI-ARIA `aria-keyshortcuts` for the implemented bold, italic, undo, and redo commands, preserving the same native-button behavior, visible labels, roving focus model, and host-owned shortcut-conflict policy
- Completed redo shortcut metadata with `Control+Shift+Z Meta+Shift+Z Control+Y Meta+Y`, matching the configured Tiptap history and collaboration behavior and exposing both `Ctrl/Cmd+Shift+Z` and `Ctrl/Cmd+Y` alternatives without adding new key handling
- Removed the unimplemented link shortcut claim from `aria-keyshortcuts`, the visible link tooltip, and buyer-facing README guidance after authoritative Tiptap Link documentation and the configured `SafeLink` extension confirmed that Inkspan does not bind `Ctrl/Cmd+K`
- Added deterministic regression and documentation contracts plus APA 7th doctoring for exact `Control`/`Meta` shortcut alternatives, the descriptive-only accessibility boundary, and omission of unsupported shortcut claims

### Documentation
- Added an authoritative standalone and modular MSA architecture contract with reviewable deployment, optimistic-concurrency, data-ownership, security, and acquisition-evidence diagrams and tables
- Added a beginner-readable naruon compose and ui.panel integration guide covering narrow client hydration, server-selected strong validators, accessible conflict handling, host-owned Yjs lifecycle, contextual-orchestrator boundaries, and local-versus-shareable evidence
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,9 @@ contract and host responsibilities.

### Safe hyperlink boundary

Inkspan applies one link policy to initial content, toolbar and Ctrl/Cmd+K
commands, pasted/autolinked URLs, direct ProseMirror transactions, collaborative
changes, and HTML output. Accepted targets are credential-free HTTP(S),
Inkspan applies one link policy to initial content, toolbar commands,
pasted/autolinked URLs, direct ProseMirror transactions, collaborative changes,
and HTML output. Accepted targets are credential-free HTTP(S),
non-empty `mailto:` and `tel:`, ordinary document-relative paths, query-only
references, and fragments.

Expand Down
14 changes: 11 additions & 3 deletions docs/accessibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ Disabled table, image, undo, and redo controls are skipped by directional naviga

Toggle controls expose `aria-pressed`; one-shot command buttons do not claim a pressed state. The toolbar declares horizontal orientation and ships visible `:focus-visible` styling, including a forced-colors fallback.

Shortcuts that the editor already implements are also exposed programmatically with `aria-keyshortcuts` so assistive technology can discover the same commands that appear in the button titles. Inkspan publishes `Control+B Meta+B` for bold, `Control+I Meta+I` for italic, `Control+K Meta+K` for link editing, `Control+Z Meta+Z` for undo, and `Control+Shift+Z Meta+Shift+Z Control+Y Meta+Y` for redo. The redo alternatives reflect Tiptap's configured history and collaboration behavior: both `Ctrl/Cmd+Shift+Z` and `Ctrl/Cmd+Y` invoke redo. `aria-keyshortcuts` describes shortcuts that Inkspan already implements; it does not create keyboard behavior, replace the visible button label, or authorize hosts to intercept those combinations. The explicit values remain `Control` and `Meta` rather than a presentation-only `Ctrl/Cmd` abbreviation because WAI-ARIA defines those modifier tokens and permits a space-separated list of alternatives.

The link shortcut is implemented by Inkspan's editor surface rather than by Tiptap's Link extension: `Ctrl/Cmd+K` opens the same prompt-driven, safe-link-validated command as the toolbar button. The Link extension itself still provides no default keyboard shortcut. Inkspan therefore exposes `Control+K Meta+K` on the link toolbar button because the shipped editor surface implements that binding. Hosts remain responsible for application-level shortcut conflicts and must not shadow an advertised command without an equivalent accessible path.

## Host responsibilities

Inkspan cannot determine the complete accessibility of an embedding application. Hosts remain responsible for:
Expand All @@ -95,8 +99,8 @@ Inkspan cannot determine the complete accessibility of an embedding application.
- identifying errors in text, supplying known correction guidance, and synchronizing `ariaInvalid` with the visible validation state;
- preserving sufficient contrast when overriding Inkspan CSS variables;
- announcing persistence and network failures in an appropriate live region;
- ensuring surrounding dialogs, forms, and application shortcuts do not trap or steal focus;
- testing the integrated workflow with representative browsers, screen readers, zoom levels, scripts, writing directions, and input methods.
- ensuring surrounding dialogs, forms, and application shortcuts do not trap or steal focus, suppress Inkspan's advertised shortcuts, or bind conflicting actions without an equivalent accessible command;
- testing the integrated workflow with representative browsers, screen readers, zoom levels, scripts, writing directions, input methods, and advertised keyboard shortcuts.

## Standards basis

Expand All @@ -107,10 +111,14 @@ Inkspan cannot determine the complete accessibility of an embedding application.
- [HTML Living Standard: resetting a form](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#resetting-a-form) — the bubbling, cancelable reset event and resettable-control algorithm.
- [React: queueing state updates](https://react.dev/learn/queueing-a-series-of-state-updates) — state setters request a later render and React batches updates until event handling completes.
- [WAI-ARIA 1.2 textbox role](https://www.w3.org/TR/wai-aria/#textbox) — accessible name, multiline, readonly, required, invalid, description, and error-message states.
- [WAI-ARIA 1.2 `aria-keyshortcuts`](https://www.w3.org/TR/wai-aria-1.2/#aria-keyshortcuts) — programmatic exposure of implemented shortcuts, exact modifier tokens, plus-separated key combinations, and space-separated alternatives.
- [Tiptap Undo/Redo extension](https://tiptap.dev/docs/editor/extensions/functionality/undo-redo) — the editor's history behavior includes both Shift+Control/Cmd+Z and Control/Cmd+Y redo alternatives.
- [Tiptap Collaboration extension](https://tiptap.dev/docs/editor/extensions/functionality/collaboration) — collaborative history provides the same two redo alternatives while host-owned collaboration remains separate from accessibility metadata.
- [Tiptap Link extension](https://tiptap.dev/docs/editor/extensions/marks/link) — the configured link extension provides commands and link behavior but no default keyboard shortcut; Inkspan's editor surface supplies its own `Ctrl/Cmd+K` binding.
- [WAI-ARIA APG: Accessible names and descriptions](https://www.w3.org/WAI/ARIA/apg/practices/names-and-descriptions/) — visible-label preference and `aria-labelledby`/`aria-describedby` relationships.
- [WCAG 2.2, Guideline 3.3 Input Assistance](https://www.w3.org/TR/WCAG22/#input-assistance) — labels or instructions, textual error identification, and correction suggestions.
- [ARIA in HTML](https://www.w3.org/TR/html-aria/) — valid readonly semantics for custom contenteditable textboxes.

## Verification

The TypeScript test suite verifies the single-tab-stop invariant, remembered focus, disabled-control fallback, wrapping arrow navigation, Home/End behavior, toggle semantics, toolbar orientation, accessible-name precedence, blank language and ID-reference omission, `lang`/`dir` propagation, validation states, read-only semantics, native form submission, same-task form-entry synchronization, disabled/external form behavior, live serialization-mode changes, imperative replacement, allowed and canceled standalone resets, reset-only form ownership, unrelated-form isolation, callback-only reset handling, queued-reset cleanup, collaborative automatic-reset rejection, collaborative callback-only observation without shared-state mutation, collaborative updates, and live prop updates for standalone and collaborative surfaces under the repository-wide 100% statement/branch/function/line coverage gate.
The TypeScript test suite verifies the single-tab-stop invariant, remembered focus, disabled-control fallback, wrapping arrow navigation, Home/End behavior, toggle semantics, toolbar orientation, exact `aria-keyshortcuts` exposure for implemented cross-platform formatting/history shortcuts including the editor-surface link binding and both documented redo alternatives, omission of shortcut metadata from controls without a defined shortcut, accessible-name precedence, blank language and ID-reference omission, `lang`/`dir` propagation, validation states, read-only semantics, native form submission, same-task form-entry synchronization, disabled/external form behavior, live serialization-mode changes, imperative replacement, allowed and canceled standalone resets, reset-only form ownership, unrelated-form isolation, callback-only reset handling, queued-reset cleanup, collaborative automatic-reset rejection, collaborative callback-only observation without shared-state mutation, collaborative updates, and live prop updates for standalone and collaborative surfaces under the repository-wide 100% statement/branch/function/line coverage gate.
Loading
Loading