API

nsh/accessibility

The accessibility API reads the user’s accessibility settings (is a screen reader running, did they ask for less motion) and talks to the screen reader. Rust code calls screen_reader(), reduce_motion() and announce_for_accessibility() from nsh_core::ui::prelude and moves the focus with an ElementRef; TSX imports screenReaderEnabled(), reduceMotion(), announce() and setAccessibilityFocus() from nsh/accessibility. The settings are reactive: read them in a binding, computed or effect, and what reads them updates when the user changes them. The accessibility props of elements (accessibilityLabel, role, …) are documented under Elements; the guide is Accessibility.

use nsh_core::ui::prelude::*; // screen_reader, reduce_motion, announce_for_accessibility, element_ref

#screenReaderEnabled

const screenReaderEnabled: Accessor<boolean>;

Whether a screen reader (VoiceOver, TalkBack) is running. Reactive: what reads it updates when the user turns the screen reader on or off. Rust: screen_reader() -> bool, reactive in the same way.

when(move || !screen_reader(), || text("Swipe for the next photo"))
    .otherwise(move || text("Next photo").on_press(next))

#reduceMotion

const reduceMotion: Accessor<boolean>;

Whether the user asked for less motion (Reduce Motion on iOS, Remove animations on Android). Reactive. Rust: reduce_motion() -> bool. Tailwind classes follow it too with the motion-reduce: variant.

let open = move || {
    if reduce_motion() {
        panel.set(0.0);
    } else {
        let _ = panel.spring(0.0, Spring::default());
    }
};

#announce

function announce(message: string): void;

The screen reader reads message (a VoiceOver announcement, TalkBack). Use it for results that appear without focus moving, such as “Saved”. Rust: announce_for_accessibility(message).

#setAccessibilityFocus

function setAccessibilityFocus(node: YNode): void;

Moves the screen reader’s focus to node (an element’s ref). Rust: ElementRef::set_accessibility_focus().

use nsh_core::ui::prelude::*;

#[component]
fn Saved() -> impl IntoElement {
    let note = element_ref();
    let save = move || {
        announce_for_accessibility("Saved");
        note.set_accessibility_focus();
    };
    // Runs again when the setting changes, until the component goes.
    effect(|| log::info!("screen reader {}", screen_reader()));
    view()
        .gap_2()
        .child(text("Save").role(AccessibilityRole::Button).on_press(save))
        .child(text("Your changes are kept on this device.").element_ref(&note))
}