Settings screen Accessibility tweaks (#1258)

* Remove `.button` trait from `Link`s on Account Settings screen

SwiftUI currently sets both the `.button` and `.link` traits on these elements, which is a failure for WCAG 2.1 4.12: Name, Role, Value: https://www.w3.org/WAI/WCAG21/Understanding/name-role-value.html

There is a radar for this issue: FB11507660

* Improve accessibility by making `AppAccountView`s a Button

Previously, the component elements of the `fullView` would be rendered as 3-4 individual views that would _all_ be interactive and perform the same action.

Now, as a Button, only one accessibility element is vended.

* Fix account label color

---------

Co-authored-by: Thomas Ricouard <ricouard77@gmail.com>
This commit is contained in:
Chris Kolbu 2023-03-17 16:38:50 +11:00 committed by GitHub
parent fa090f5663
commit c5b4a0dd07
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 49 deletions

View file

@ -208,6 +208,7 @@ struct SettingsTabs: View {
Link(destination: URL(string: "https://github.com/Dimillian/IceCubesApp")!) {
Label("settings.app.source", systemImage: "link")
}
.accessibilityRemoveTraits(.isButton)
.tint(theme.labelColor)
NavigationLink(destination: SupportAppView()) {
@ -218,6 +219,7 @@ struct SettingsTabs: View {
Link(destination: reviewURL) {
Label("settings.rate", systemImage: "link")
}
.accessibilityRemoveTraits(.isButton)
.tint(theme.labelColor)
}

View file

@ -4,6 +4,7 @@ import Env
import SwiftUI
public struct AppAccountView: View {
@EnvironmentObject private var theme: Theme
@EnvironmentObject private var routerPath: RouterPath
@EnvironmentObject private var appAccounts: AppAccountsManager
@EnvironmentObject private var preferences: UserPreferences
@ -41,55 +42,7 @@ public struct AppAccountView: View {
}
private var fullView: some View {
HStack {
if let account = viewModel.account {
ZStack(alignment: .topTrailing) {
AvatarView(url: account.avatar)
if viewModel.appAccount.id == appAccounts.currentAccount.id {
Image(systemName: "checkmark.circle.fill")
.foregroundStyle(.white, .green)
.offset(x: 5, y: -5)
} else if viewModel.showBadge,
let token = viewModel.appAccount.oauthToken,
preferences.getNotificationsCount(for: token) > 0
{
let notificationsCount = preferences.getNotificationsCount(for: token)
ZStack {
Circle()
.fill(.red)
Text(notificationsCount > 99 ? "99+" : String(notificationsCount))
.foregroundColor(.white)
.font(.system(size: 9))
}
.frame(width: 20, height: 20)
.offset(x: 5, y: -5)
}
}
} else {
ProgressView()
Text(viewModel.appAccount.accountName ?? viewModel.acct)
.font(.scaledSubheadline)
.foregroundColor(.gray)
.padding(.leading, 6)
}
VStack(alignment: .leading) {
if let account = viewModel.account {
EmojiTextApp(.init(stringValue: account.safeDisplayName), emojis: account.emojis)
Text("\(account.username)@\(viewModel.appAccount.server)")
.font(.scaledSubheadline)
.emojiSize(Font.scaledSubheadlineFont.emojiSize)
.emojiBaselineOffset(Font.scaledSubheadlineFont.emojiBaselineOffset)
.foregroundColor(.gray)
}
}
if viewModel.isInNavigation {
Spacer()
Image(systemName: "chevron.right")
.foregroundColor(.gray)
}
}
.contentShape(Rectangle())
.onTapGesture {
Button {
if appAccounts.currentAccount.id == viewModel.appAccount.id,
let account = viewModel.account
{
@ -103,6 +56,55 @@ public struct AppAccountView: View {
HapticManager.shared.fireHaptic(of: .notification(.success))
}
}
} label: {
HStack {
if let account = viewModel.account {
ZStack(alignment: .topTrailing) {
AvatarView(url: account.avatar)
if viewModel.appAccount.id == appAccounts.currentAccount.id {
Image(systemName: "checkmark.circle.fill")
.foregroundStyle(.white, .green)
.offset(x: 5, y: -5)
} else if viewModel.showBadge,
let token = viewModel.appAccount.oauthToken,
preferences.getNotificationsCount(for: token) > 0
{
let notificationsCount = preferences.getNotificationsCount(for: token)
ZStack {
Circle()
.fill(.red)
Text(notificationsCount > 99 ? "99+" : String(notificationsCount))
.foregroundColor(.white)
.font(.system(size: 9))
}
.frame(width: 20, height: 20)
.offset(x: 5, y: -5)
}
}
} else {
ProgressView()
Text(viewModel.appAccount.accountName ?? viewModel.acct)
.font(.scaledSubheadline)
.foregroundColor(.gray)
.padding(.leading, 6)
}
VStack(alignment: .leading) {
if let account = viewModel.account {
EmojiTextApp(.init(stringValue: account.safeDisplayName), emojis: account.emojis)
.foregroundColor(theme.labelColor)
Text("\(account.username)@\(viewModel.appAccount.server)")
.font(.scaledSubheadline)
.emojiSize(Font.scaledSubheadlineFont.emojiSize)
.emojiBaselineOffset(Font.scaledSubheadlineFont.emojiBaselineOffset)
.foregroundColor(.gray)
}
}
if viewModel.isInNavigation {
Spacer()
Image(systemName: "chevron.right")
.foregroundColor(.gray)
}
}
}
}
}