Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add accessibilityElements to accessibilityContainer API [UI-6096] #491

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions BlueprintUICommonControls/Sources/AccessibilityContainer.swift
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems reasonable, but a couple questions:

  1. When we're using this in practice, what are the a11y elements here exactly? Are they instances of UIView? Instances of UIAccessibilityElement? Something else?

  2. Are these elements that are already in the view / element hierarchy, or are they additions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm gonna put this on hold for a minute, i think there might be a cleaner way?

Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ public struct AccessibilityContainer: Element {
/// An optional `accessibilityIdentifier` to give the container. Defaults to `nil`.
public var identifier: String?
public var wrapped: Element
public var accessibilityElements: [Any]?

/// Creates a new `AccessibilityContainer` wrapping the provided element.
public init(identifier: String? = nil, wrapping element: Element) {
public init(identifier: String? = nil, accessibilityElements: [Any]? = nil, wrapping element: Element) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: May be nicer as a result builder?

self.identifier = identifier
self.accessibilityElements = accessibilityElements
wrapped = element
}

Expand All @@ -36,6 +38,7 @@ public struct AccessibilityContainer: Element {
public func backingViewDescription(with context: ViewDescriptionContext) -> ViewDescription? {
AccessibilityContainerView.describe { config in
config[\.accessibilityIdentifier] = identifier
config[\.explicitAccessibilityElements] = self.accessibilityElements
}
}
}
Expand All @@ -44,15 +47,17 @@ extension Element {

/// Acts as an accessibility container for any subviews
/// where `isAccessibilityElement == true`.
public func accessibilityContainer(identifier: String? = nil) -> Element {
AccessibilityContainer(identifier: identifier, wrapping: self)
public func accessibilityContainer(identifier: String? = nil, accessibilityElements: [Any]? = nil) -> Element {
AccessibilityContainer(identifier: identifier, accessibilityElements: accessibilityElements, wrapping: self)
}
}

extension AccessibilityContainer {
private final class AccessibilityContainerView: UIView {
var explicitAccessibilityElements: [Any]?

override var accessibilityElements: [Any]? {
get { recursiveAccessibleSubviews() }
get { explicitAccessibilityElements ?? recursiveAccessibleSubviews() }
set { fatalError("This property is not settable") }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,50 @@ class AccessibilityContainerTests: XCTestCase {

XCTAssertNil(accessibleSubviews.first)
}

func test_overrideAccessibility() {
let label1 = Label(text: "One")
let label2 = Label(text: "Two")
let label3 = Label(text: "Three")
let element = Column {
label1
label2
label3
}

let view = BlueprintView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

element
.accessibilityContainer()
.accessBackingView(in: view) { view in
let textVals: [String] = view.accessibilityElements!.map {
($0 as! UILabel).text!
}

XCTAssertEqual(view.accessibilityElements?.count, 3)
XCTAssertEqual(textVals, ["One", "Two", "Three"])
}

element
.accessibilityContainer(accessibilityElements: [label1, label3])
.accessBackingView(in: view) { view in
let textVals: [String] = view.accessibilityElements!.map {
($0 as! BlueprintUICommonControls.Label).text
}

XCTAssertEqual(view.accessibilityElements?.count, 2)
XCTAssertEqual(textVals, ["One", "Three"])
}

element
.accessibilityContainer(accessibilityElements: [label3, label2, label1])
.accessBackingView(in: view) { view in
let textVals: [String] = view.accessibilityElements!.map {
($0 as! BlueprintUICommonControls.Label).text
}

XCTAssertEqual(view.accessibilityElements?.count, 3)
XCTAssertEqual(textVals, ["Three", "Two", "One"])
}
}
}
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added
- `AccessibilityElement.CustomContent` now exposes previously internal methods for creating `AXCustomContent` objects.
- Expose `accessibilityElements` on `accessibilityContainer`

### Removed

Expand Down
Loading