New Document: screen readers hear each Preset Details field's name

The fields under Preset Details had captions drawn above them but no accessible name. Each field is now named by its caption, and the units dropdown beside Width is named Units. Preset Name is also named in More Settings.
This commit is contained in:
dotCooCoo
2026-11-08 23:00:08 -08:00
parent 4bde73708e
commit 26522b27b5
3 changed files with 45 additions and 16 deletions
+4 -3
View File
@@ -1109,10 +1109,11 @@ pub(super) fn bleed(ui: &mut egui::Ui, d: &mut Dialog, unit: vectorcraft_doc::Un
}
}
/// A small grey caption above a field (New Document's details column).
pub(super) fn caption(ui: &mut egui::Ui, text: &str) {
/// A small grey caption above a field (New Document's details column) → its response, so the field
/// can be named by it.
pub(super) fn caption(ui: &mut egui::Ui, text: &str) -> egui::Response {
let t = Tokens::get(ui.ctx());
ui.label(egui::RichText::new(tl!(text)).size(11.0).color(t.text_dim));
ui.label(egui::RichText::new(tl!(text)).size(11.0).color(t.text_dim))
}
#[cfg(test)]
+14 -13
View File
@@ -358,9 +358,9 @@ fn details(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog, b: &mut
let top = ui.cursor().top();
ui.label(egui::RichText::new(tl!("PRESET DETAILS")).font(theme::semibold(11.0)).color(t.text_dim));
ui.add_space(8.0);
form::caption(ui, tl!("Document Name"));
let caption = form::caption(ui, tl!("Document Name"));
ui.horizontal(|ui| {
form::text(ui, d, "name", DETAILS - 50.0);
ui.label_inputs_by(caption.id, |ui| form::text(ui, d, "name", DETAILS - 50.0));
save_button(app, ui, d);
});
if d.bool(SAVING) {
@@ -368,16 +368,16 @@ fn details(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog, b: &mut
}
ui.add_space(8.0);
let unit = unit(d);
form::caption(ui, tl!("Width"));
let caption = form::caption(ui, tl!("Width"));
ui.horizontal(|ui| {
form::length(ui, d, "width", unit, DETAILS - 124.0);
units_dropdown(ui, d, 112.0);
ui.label_inputs_by(caption.id, |ui| form::length(ui, d, "width", unit, DETAILS - 124.0));
ui.name_inputs(tl!("Units"), |ui| units_dropdown(ui, d, 112.0));
});
ui.add_space(4.0);
ui.horizontal_top(|ui| {
ui.vertical(|ui| {
form::caption(ui, tl!("Height"));
form::length(ui, d, "height", unit, 104.0);
let caption = form::caption(ui, tl!("Height"));
ui.label_inputs_by(caption.id, |ui| form::length(ui, d, "height", unit, 104.0));
});
ui.add_space(6.0);
ui.vertical(|ui| {
@@ -386,16 +386,16 @@ fn details(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog, b: &mut
});
ui.add_space(6.0);
ui.vertical(|ui| {
form::caption(ui, tl!("Artboards"));
artboards(ui, d, 76.0);
let caption = form::caption(ui, tl!("Artboards"));
ui.label_inputs_by(caption.id, |ui| artboards(ui, d, 76.0));
});
});
ui.add_space(8.0);
form::caption(ui, tl!("Bleed"));
form::bleed(ui, d, unit, 52.0);
ui.add_space(8.0);
form::caption(ui, tl!("Background Contents"));
background(ui, d, DETAILS - 34.0);
let caption = form::caption(ui, tl!("Background Contents"));
ui.label_inputs_by(caption.id, |ui| background(ui, d, DETAILS - 34.0));
ui.add_space(8.0);
advanced(ui, d, 110.0, DETAILS - 116.0);
ui.add_space(12.0);
@@ -427,9 +427,10 @@ fn save_button(app: &VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) {
/// Save Preset: the preset's name, Save and Cancel.
fn save_row(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) {
ui.add_space(4.0);
form::caption(ui, tl!("Preset Name"));
let caption = form::caption(ui, tl!("Preset Name"));
ui.horizontal(|ui| {
let enter = form::text_edit(ui, d, "presetName", DETAILS - 140.0).lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter));
let name = ui.label_inputs_by(caption.id, |ui| form::text_edit(ui, d, "presetName", DETAILS - 140.0));
let enter = name.lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter));
if widgets::flat_button(ui, tl!("Save"), 54.0).clicked() || enter {
let mut p: Map<String, Value> = PARAMS.iter().filter_map(|k| Some((k.to_string(), d.fields.get(*k)?.clone()))).collect();
p.insert("name".into(), json!(d.str("presetName")));
@@ -81,6 +81,33 @@ fn document_setup_names_each_bleed_side() {
}
}
/// New Document's Preset Details column names each field by the caption above it.
#[test]
fn new_document_names_its_fields_by_their_captions() {
let mut app = app();
app.run("file.newDialog", json!({})).unwrap();
app.ui.dialog.as_mut().expect("New Document is open").fields.insert("__saving".into(), json!(true));
let h = strict(app);
for name in ["Document Name", "Preset Name", "Width", "Height", "Artboards"] {
let _ = h.get_by_role_and_label(Role::TextInput, name);
}
for name in ["Units", "Background Contents"] {
let _ = h.get_by_role_and_label(Role::ComboBox, name);
}
}
/// New Document's More Settings, with Save Preset open, leaves no field unnamed.
#[test]
fn new_document_more_settings_names_its_fields() {
let mut app = app();
app.run("file.newDialog", json!({})).unwrap();
let d = app.ui.dialog.as_mut().expect("New Document is open");
d.kind = super::new_document::MORE.into();
d.fields.insert("__saving".into(), json!(true));
let h = strict(app);
let _ = h.get_by_role_and_label(Role::TextInput, "Preset Name");
}
/// Split Into Grid keeps translated visible labels while naming row and column gutter and total
/// inputs by axis and context.
#[test]