From 0b3a154add2c57c585aadae1733569c0049515c1 Mon Sep 17 00:00:00 2001 From: BlackSpirits Date: Sun, 13 Sep 2026 18:06:21 +0200 Subject: [PATCH 1/6] Accessibility: ignore empty visual labels --- src/ui/Logic/AccessibleLabels.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ui/Logic/AccessibleLabels.cs b/src/ui/Logic/AccessibleLabels.cs index 69d045946c..055666d300 100644 --- a/src/ui/Logic/AccessibleLabels.cs +++ b/src/ui/Logic/AccessibleLabels.cs @@ -211,18 +211,19 @@ private static bool IsLabel(Control control) { if (control is Label label) { - return label.Content is not Control; + return label.Content is string labelText && !string.IsNullOrWhiteSpace(labelText); } if (control is CheckBox or RadioButton) { - return ((ContentControl)control).Content is string; + return ((ContentControl)control).Content is string contentText && + !string.IsNullOrWhiteSpace(contentText); } if (control is TextBlock textBlock) { var text = textBlock.Text; - return text == null || (text.Length <= 80 && !text.Contains('\n')); + return !string.IsNullOrWhiteSpace(text) && text.Length <= 80 && !text.Contains('\n'); } return false; From 61c174152d786959d18ffeb39c14563706e970b5 Mon Sep 17 00:00:00 2001 From: BlackSpirits Date: Sun, 13 Sep 2026 18:06:23 +0200 Subject: [PATCH 2/6] Tests: reject empty accessibility labels --- tests/UI/Logic/AccessibleLabelsTests.cs | 61 +++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 tests/UI/Logic/AccessibleLabelsTests.cs diff --git a/tests/UI/Logic/AccessibleLabelsTests.cs b/tests/UI/Logic/AccessibleLabelsTests.cs new file mode 100644 index 0000000000..1a5fb8442d --- /dev/null +++ b/tests/UI/Logic/AccessibleLabelsTests.cs @@ -0,0 +1,61 @@ +using Avalonia.Automation; +using Avalonia.Controls; +using Avalonia.Headless.XUnit; +using Nikse.SubtitleEdit.Logic; +using Xunit; + +namespace UITests.Logic; + +public class AccessibleLabelsTests +{ + [AvaloniaFact] + public void Apply_DoesNotUseEmptyTextBlockAsLabel() + { + var grid = new Grid(); + var label = new TextBlock(); + var input = new TextBox(); + + Grid.SetColumn(input, 1); + grid.Children.Add(label); + grid.Children.Add(input); + + AccessibleLabels.Apply(grid); + + Assert.Null(AutomationProperties.GetLabeledBy(input)); + Assert.False(AccessibleLabels.HasAccessibleName(input)); + } + + [AvaloniaFact] + public void Apply_DoesNotUseEmptyLabelAsLabel() + { + var grid = new Grid(); + var label = new Label(); + var input = new TextBox(); + + Grid.SetColumn(input, 1); + grid.Children.Add(label); + grid.Children.Add(input); + + AccessibleLabels.Apply(grid); + + Assert.Null(AutomationProperties.GetLabeledBy(input)); + Assert.False(AccessibleLabels.HasAccessibleName(input)); + } + + [AvaloniaFact] + public void Apply_StillUsesVisibleShortTextAsLabel() + { + var grid = new Grid(); + var label = new TextBlock { Text = "Frame rate" }; + var input = new ComboBox(); + + Grid.SetColumn(input, 1); + grid.Children.Add(label); + grid.Children.Add(input); + + AccessibleLabels.Apply(grid); + + Assert.Same(label, AutomationProperties.GetLabeledBy(input)); + Assert.True(AccessibleLabels.HasAccessibleName(input)); + } +} From 3c041a229a1e0756ecdffd0107ffcc3641f9f943 Mon Sep 17 00:00:00 2001 From: BlackSpirits Date: Sun, 13 Sep 2026 18:15:52 +0200 Subject: [PATCH 3/6] Accessibility: make dynamic label relationships explicit --- .../Files/ManualChosenEncoding/ManualChosenEncodingWindow.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/Features/Files/ManualChosenEncoding/ManualChosenEncodingWindow.cs b/src/ui/Features/Files/ManualChosenEncoding/ManualChosenEncodingWindow.cs index 371f92594b..fb3efa753c 100644 --- a/src/ui/Features/Files/ManualChosenEncoding/ManualChosenEncodingWindow.cs +++ b/src/ui/Features/Files/ManualChosenEncoding/ManualChosenEncodingWindow.cs @@ -171,7 +171,7 @@ private static Control MakePreviewBox(ManualChosenEncodingViewModel vm) textBox.Bind(TextBox.TextProperty, new Binding(nameof(vm.PreviewText)) { Source = vm, Mode = BindingMode.OneWay }); grid.Add(label, 0); - grid.Add(textBox, 1); + grid.Add(textBox.WithLabeledBy(label), 1); return UiUtil.MakeBorderForControl(grid); } From a854402cf615ab1f021e67f4a59c77af7b5ccc21 Mon Sep 17 00:00:00 2001 From: BlackSpirits Date: Sun, 13 Sep 2026 18:15:56 +0200 Subject: [PATCH 4/6] Accessibility: make dynamic label relationships explicit --- src/ui/Features/SpellCheck/EditWholeText/EditWholeTextWindow.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/Features/SpellCheck/EditWholeText/EditWholeTextWindow.cs b/src/ui/Features/SpellCheck/EditWholeText/EditWholeTextWindow.cs index ae45f7d3e9..5b7cc2054b 100644 --- a/src/ui/Features/SpellCheck/EditWholeText/EditWholeTextWindow.cs +++ b/src/ui/Features/SpellCheck/EditWholeText/EditWholeTextWindow.cs @@ -64,7 +64,7 @@ public EditWholeTextWindow(EditWholeTextViewModel vm) }; grid.Add(labelLineInfo, 0, 0); - grid.Add(textBoxWholeText, 1, 0); + grid.Add(textBoxWholeText.WithLabeledBy(labelLineInfo), 1, 0); grid.Add(panelButtons, 2, 0); Content = grid; From dd9a6c5cb4401c508451a0691551aee7e0477778 Mon Sep 17 00:00:00 2001 From: BlackSpirits Date: Sun, 13 Sep 2026 18:16:01 +0200 Subject: [PATCH 5/6] Accessibility: make dynamic label relationships explicit --- .../Tools/ApplyDurationLimits/ApplyDurationLimitsWindow.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ui/Features/Tools/ApplyDurationLimits/ApplyDurationLimitsWindow.cs b/src/ui/Features/Tools/ApplyDurationLimits/ApplyDurationLimitsWindow.cs index 48013cb42b..e41a613ee2 100644 --- a/src/ui/Features/Tools/ApplyDurationLimits/ApplyDurationLimitsWindow.cs +++ b/src/ui/Features/Tools/ApplyDurationLimits/ApplyDurationLimitsWindow.cs @@ -191,6 +191,7 @@ private static Grid MakeFixesView(ApplyDurationLimitsViewModel vm) item => item.Apply, (item, v) => item.Apply = v); grid.Add(labelFixesAvailable, 0); + dataGrid.WithLabeledBy(labelFixesAvailable); grid.Add(UiUtil.MakeBorderForControlNoPadding(dataGrid), 1); return grid; @@ -281,6 +282,7 @@ private static Grid MakeCannotFixView(ApplyDurationLimitsViewModel vm) }, RoutingStrategies.Tunnel); grid.Add(labelFixesAvailable, 0); + dataGrid.WithLabeledBy(labelFixesAvailable); grid.Add(UiUtil.MakeBorderForControlNoPadding(dataGrid), 1); return grid; From a6f3570b8ffdc905b590845dab2134692a1f1f79 Mon Sep 17 00:00:00 2001 From: BlackSpirits Date: Sun, 13 Sep 2026 18:16:06 +0200 Subject: [PATCH 6/6] Accessibility: make dynamic label relationships explicit --- src/ui/Features/Video/RemuxVideo/PickAudioTrackWindow.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/Features/Video/RemuxVideo/PickAudioTrackWindow.cs b/src/ui/Features/Video/RemuxVideo/PickAudioTrackWindow.cs index da02be3cb7..e7e7fc5b8d 100644 --- a/src/ui/Features/Video/RemuxVideo/PickAudioTrackWindow.cs +++ b/src/ui/Features/Video/RemuxVideo/PickAudioTrackWindow.cs @@ -42,6 +42,7 @@ public PickAudioTrackWindow(PickAudioTrackViewModel vm) }; comboBox.Bind(ComboBox.ItemsSourceProperty, new Binding(nameof(PickAudioTrackViewModel.Tracks))); comboBox.Bind(ComboBox.SelectedItemProperty, new Binding(nameof(PickAudioTrackViewModel.SelectedTrack))); + comboBox.WithAccessibleName(Se.Language.Video.RemuxVideoSelectAudioTrack); var buttonOk = UiUtil.MakeButtonOk(vm.OkCommand); var buttonCancel = UiUtil.MakeButtonCancel(vm.CancelCommand);