mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-10-03 08:02:02 +00:00
feat(a11y): label the remaining lists and let VoiceOver open files from the tree
Editor tabs are tabs named by file (and unsaved state) with a named close button; Info rows read as 'label, value'; keyboard shortcut rows as 'action, keys'; SSH hosts as 'name, address' with their expanded state. File-tree rows open on the press, which assistive tech cannot send, so they take its press action directly: a screen reader could select a file but never open it.
This commit is contained in:
@@ -3443,6 +3443,8 @@ impl Tty7App {
|
||||
let muted = cx.theme().muted_foreground;
|
||||
let close = div()
|
||||
.id(("editor-file-tab-close", pos))
|
||||
.role(gpui::Role::Button)
|
||||
.aria_label(format!("{} {name}", t(L10nKey::Close)))
|
||||
.flex_none()
|
||||
.size(px(slot))
|
||||
.flex()
|
||||
@@ -3474,6 +3476,12 @@ impl Tty7App {
|
||||
});
|
||||
div()
|
||||
.id(("editor-file-tab", pos))
|
||||
.role(gpui::Role::Tab)
|
||||
.aria_label(match dirty {
|
||||
true => format!("{name}, {}", t(L10nKey::SettingsUnsaved)),
|
||||
false => name.to_string(),
|
||||
})
|
||||
.aria_selected(active)
|
||||
.group(group.clone())
|
||||
.occlude()
|
||||
.flex_none()
|
||||
|
||||
@@ -2084,6 +2084,20 @@ impl Tty7App {
|
||||
}
|
||||
}),
|
||||
)
|
||||
// A row opens on the press, not the click, so it has no click
|
||||
// handler for assistive technology's "press" to reach. Give it
|
||||
// the same act directly, or VoiceOver could select a file and
|
||||
// never open it.
|
||||
.on_a11y_action(gpui::AccessibleAction::Click, {
|
||||
let path = path.clone();
|
||||
let app = cx.entity().downgrade();
|
||||
move |_, window, cx| {
|
||||
let _ = app.update(cx, |this, cx| {
|
||||
this.file_tree.focus_handle.focus(window, cx);
|
||||
this.file_tree_activate(&path, is_dir, window, cx);
|
||||
});
|
||||
}
|
||||
})
|
||||
// The menu acts on the row it was opened on, so that row is the
|
||||
// one lit while it is up (#942) — selected without being opened,
|
||||
// the way Explorer and every editor's tree do it.
|
||||
|
||||
@@ -1072,6 +1072,16 @@ impl Tty7App {
|
||||
_ => t(L10nKey::CmdCopy),
|
||||
};
|
||||
|
||||
// "cwd, /tmp/project": the row as one line. The path drawn is split
|
||||
// and may be elided; this is the whole of it.
|
||||
let a11y_name = format!(
|
||||
"{}, {}",
|
||||
row.label,
|
||||
match &row.value {
|
||||
InfoValue::Text(v) | InfoValue::Path(v) => v.clone(),
|
||||
InfoValue::Diff { added, removed, .. } => format!("+{added} −{removed}"),
|
||||
}
|
||||
);
|
||||
let value = match row.value {
|
||||
// A path identifies a pane by its last segment, and plain
|
||||
// truncation eats exactly that: a deep checkout read
|
||||
@@ -1212,6 +1222,8 @@ impl Tty7App {
|
||||
|
||||
h_flex()
|
||||
.id(id.clone())
|
||||
.role(gpui::Role::Label)
|
||||
.aria_label(a11y_name)
|
||||
.group(id)
|
||||
.relative()
|
||||
.items_center()
|
||||
|
||||
@@ -447,6 +447,12 @@ impl Tty7App {
|
||||
|
||||
let head = div()
|
||||
.id(SharedString::from(format!("ssh-host-{}", id.as_u128())))
|
||||
.role(gpui::Role::Button)
|
||||
.aria_label(match address.is_empty() {
|
||||
true => title.clone(),
|
||||
false => format!("{title}, {address}"),
|
||||
})
|
||||
.aria_expanded(open)
|
||||
.h(px(40.))
|
||||
.px(px(10.))
|
||||
.flex()
|
||||
|
||||
@@ -159,6 +159,17 @@ impl Tty7App {
|
||||
(_, Some((_, spec, _))) => vec![spec.clone()],
|
||||
_ => keys,
|
||||
};
|
||||
// "New Tab, ⌘T": the action and what it is bound to, the way
|
||||
// the row reads — a screen reader says ⌘ as "command".
|
||||
let a11y_keys = match shown.is_empty() {
|
||||
true => "—".to_string(),
|
||||
false => shown
|
||||
.iter()
|
||||
.map(|spec| crate::ui::keymap::key_tokens(spec).join(""))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" "),
|
||||
};
|
||||
let a11y_name = format!("{label}, {a11y_keys}");
|
||||
let modified = overridden.contains(&action) && !is_recording;
|
||||
let ring = if is_recording {
|
||||
vec![kit::ring(tk.fg, 1., true)]
|
||||
@@ -175,6 +186,8 @@ impl Tty7App {
|
||||
let record_action = action.clone();
|
||||
let keys_button = h_flex()
|
||||
.id(SharedString::from(format!("kb-{action}")))
|
||||
.role(gpui::Role::Button)
|
||||
.aria_label(a11y_name)
|
||||
.h(px(26.))
|
||||
.min_w(px(72.))
|
||||
.pl(px(8.))
|
||||
|
||||
Reference in New Issue
Block a user