From d4e7cbfdbeb3e7385573dfe6a4cac6d7218cf0d3 Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Mon, 22 Jun 2026 12:57:49 +0200 Subject: [PATCH] Associate the room address field helper text and error with the field The address field already had an accessibility label, but the section's helper text and validation error were only shown in a separate footer and weren't conveyed to VoiceOver when focusing the field. Compose them into the field's accessibility hint. Addresses #5258. --- .../SwiftUI/Views/EditRoomAddressListRow.swift | 17 ++++++++++++++--- .../View/CreateRoomScreen.swift | 3 ++- .../View/EditRoomAddressScreen.swift | 4 +++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/ElementX/Sources/Other/SwiftUI/Views/EditRoomAddressListRow.swift b/ElementX/Sources/Other/SwiftUI/Views/EditRoomAddressListRow.swift index d648a0640..bd1588b0a 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/EditRoomAddressListRow.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/EditRoomAddressListRow.swift @@ -12,12 +12,23 @@ import SwiftUI struct EditRoomAddressListRow: View { @Binding var aliasLocalPart: String var serverName: String - var shouldDisplayError: Bool + /// The error to display, if any. Also associated with the field for VoiceOver. + var errorDescription: String? + /// The section's helper text, associated with the field for VoiceOver. + var footerText: String? private var fullAddress: String { "#\(aliasLocalPart):\(serverName)" } + /// Associates the helper text and any error with the field, as they're otherwise + /// only shown in a separate section footer. + private var accessibilityHint: String { + [L10n.a11yEditRoomAddressHint(fullAddress), footerText, errorDescription] + .compactMap { $0 } + .joined(separator: "\n") + } + var body: some View { ListRow(kind: .custom { HStack(spacing: 0) { @@ -34,7 +45,7 @@ struct EditRoomAddressListRow: View { .foregroundStyle(.compound.textPrimary) .padding(.horizontal, 8) .accessibilityLabel(L10n.a11yAddress) - .accessibilityHint(L10n.a11yEditRoomAddressHint(fullAddress)) + .accessibilityHint(accessibilityHint) Text(":\(serverName)") .font(.compound.bodyLG) .foregroundStyle(.compound.textSecondary) @@ -42,7 +53,7 @@ struct EditRoomAddressListRow: View { } .padding(ListRowPadding.textFieldInsets) .environment(\.layoutDirection, .leftToRight) - .errorBackground(shouldDisplayError) + .errorBackground(errorDescription != nil) }) } } diff --git a/ElementX/Sources/Screens/CreateRoomScreen/View/CreateRoomScreen.swift b/ElementX/Sources/Screens/CreateRoomScreen/View/CreateRoomScreen.swift index 1e574c61f..590936203 100644 --- a/ElementX/Sources/Screens/CreateRoomScreen/View/CreateRoomScreen.swift +++ b/ElementX/Sources/Screens/CreateRoomScreen/View/CreateRoomScreen.swift @@ -193,7 +193,8 @@ struct CreateRoomScreen: View { Section { EditRoomAddressListRow(aliasLocalPart: aliasBinding, serverName: context.viewState.serverName, - shouldDisplayError: context.viewState.aliasErrors.errorDescription != nil) + errorDescription: context.viewState.aliasErrors.errorDescription, + footerText: L10n.screenCreateRoomRoomAddressSectionFooter) .focused($focus, equals: .alias) .id(Focus.alias) } header: { diff --git a/ElementX/Sources/Screens/EditRoomAddressScreen/View/EditRoomAddressScreen.swift b/ElementX/Sources/Screens/EditRoomAddressScreen/View/EditRoomAddressScreen.swift index 545553636..646c3b7c9 100644 --- a/ElementX/Sources/Screens/EditRoomAddressScreen/View/EditRoomAddressScreen.swift +++ b/ElementX/Sources/Screens/EditRoomAddressScreen/View/EditRoomAddressScreen.swift @@ -16,7 +16,9 @@ struct EditRoomAddressScreen: View { Form { Section { EditRoomAddressListRow(aliasLocalPart: $context.desiredAliasLocalPart, - serverName: context.viewState.serverName, shouldDisplayError: context.viewState.aliasErrors.errorDescription != nil) + serverName: context.viewState.serverName, + errorDescription: context.viewState.aliasErrors.errorDescription, + footerText: L10n.screenEditRoomAddressRoomAddressSectionFooter) .onChange(of: context.desiredAliasLocalPart) { _, newAliasLocalPart in context.desiredAliasLocalPart = newAliasLocalPart.lowercased() }