diff --git a/input/keyboard-accessibility.md b/input/keyboard-accessibility.md new file mode 100644 index 0000000..6466312 --- /dev/null +++ b/input/keyboard-accessibility.md @@ -0,0 +1,107 @@ +Keyboard accessibility +====================== + +- Pull request: https://github.com/kas-gui/design/pull/4 + +**Scope:** keyboard navigation, focus, shortcuts + +**Status:** partial implementation + +Introduction +------------ + +This is a specific sub-set of accessibility, including: + +- Tab-key navigation +- Focus-specific key handling (e.g. use of arrow keys to move a slider) +- Mnemonics (e.g. pressing Alt+F to open the File menu) +- Context-sensitive shortcuts (e.g. Ctrl+C to copy the focussed/selected item) +- Global shortcuts (e.g. Ctrl+P to print a page) +- Following platform conventions (e.g. Ctrl+C on Linux/Windows, Command+C on MacOS) + +Excluded: + +- Screen reader and use of other external accessibility tools (this is a separate issue) +- Focus indication: this comes under theme design + +This document discusses what interaction should be supported and the implementation status, with minimal discussion of how. + + +Tab-key navigation +------------------ + +### Requirements + +- That there is a *keyboard focus* (implemented: `EventState::nav_focus`) +- That widgets can define whether they are a valid navigation target (implemented: `navigation` method/property) +- Pressing Tab advances to the next valid widget, and Shift+Tab does the reverse (implemented) +- That container widgets can specify the navigation order of their children (implemented: `Widget::nav_next` method) +- That special UIs (e.g. a small `calculator` or a spreadsheet) can disable Tab-key navigation (implemented) +- That when a widget receives navigation focus it is notified (implemented: `Event::NavFocus`) and made visible (implemented: special handling of `Event::NavFocus` to scroll as required; is a bit hacky) + +### Large containers + +If e.g. a 1000-element list has navigable items, this interacts poorly with Tab-key navigation. Applicable Kas examples are `data-list`, `data-list-view` and `times-tables`. Some apps (e.g. spreadsheets) will provide their own navigation for such cases, but we should aim to provide a decent experience by default. + +The status quo: + +- The `List` widget (used in `data-list`) is not intended for very long lists and interacts with Tab-navigation like other containers +- The `ListView` and `MatrixView` widgets (used in `data-list-view` and `times-tables`) have several special features: + - Tab-navigation where the prior focus is not a child jumps to the first mapped item (i.e. the first visible item, or only just outside the visible range). + - Tab-navigation where the prior focus is a child scrolls as necessary to focus the next item, until the end of the list (the "obvious" behaviour). + - The navigation keys Home, End, arrow-keys, PageUp, PageDown may be used to navigate the list + +### Interaction with mouse/touch + +Clicking on / touching a widget will assign navigation focus to that widget. + + +Focus-specific key handling +--------------------------- + +It is expected that e.g. a slider with navigation focus may be adjusted with the arrow keys and that Home may be used to navigate a list. + +This is implemented, roughly as follows: + +- If any widget (usually an `EditField`) has claimed keyboard input focus, key events go there; otherwise... +- A sub-set of keyboard keys map to a special enum, [`Command`](https://docs.rs/kas/latest/kas/event/enum.Command.html) +- A `Command` is sent to the widget with navigation focus (e.g. if Home is pressed and the focus is a `Slider`, that widget handles the event) +- If unused, the [event handling model](https://docs.rs/kas/latest/kas/event/index.html#event-handling-model) gives each ancestor a chance to use the event during unwinding (so e.g. if Home is pressed but the focussed widget does not use it, but is part of a `ListView`, then that may navigate to the start of the list) + + +Mnemonics +--------- + +See [#8: Access Keys](https://github.com/kas-gui/design/pull/8). + + +Shortcuts +--------- + +Context-local shortcuts are implemented by using a platform-specific map to convert the key-sequence to a [`Command`](https://docs.rs/kas/latest/kas/event/enum.Command.html), then sending that `Command` to the keyboard focus (see above). + +This system is under-developed, especially regarding custom (app-specific) shortcuts and global shortcuts. + + +Alternatives +------------ + +Probably Tab-navigation on a `ListView` should jump to the first visible item, not the first mapped item (which may be just outside the visible range). This is a small bug/TODO. + +### Alternate Tab-navigation style + +A short press of Tab or Shift+Tab behaves like usual. Holding Tab instead activates a special "navigation mode": + +- While Tab is held, focus is indicated via an extra box/highlight. Focus does not move (no key repeat). +- Tab+Esc moves focus to the parent (or none) +- Tab + arrow keys moves focus in the appropriate direction (requires a new method, `spatial_nav`) +- Tab + Home/kbd> or End moves focus to the first/last child of its container (possibly using event-handling's unwinding, i.e. the first ancestor to handle `TabHome` moves focus). +- Tab + PageUp/kbd> or PageDown moves focus within a container + +Advantage: if well implemented this might be intuitive and much easier to use, at least in some cases. + +Disadvantage: non-standard. + +Disadvantage: not trivial to implement (but should be viable). + +Disadvantage: it is possible that some widgets would be hard or impossible reach. A few cases might cause problems, e.g. floats (widgets on top of one another).