From 33c38e18090f4a3e0b4e3ebf97645894ae8862f7 Mon Sep 17 00:00:00 2001 From: Amogh Aralimatti <amogh@Amoghs-MacBook-Pro.local> Date: Tue, 25 Feb 2025 00:24:14 -0800 Subject: [PATCH 1/4] prototype changes --- .../People Picker/PeoplePicker.swift | 127 +++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) diff --git a/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift b/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift index 506c0a5920..269326e970 100644 --- a/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift +++ b/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift @@ -165,6 +165,9 @@ open class PeoplePicker: BadgeField { func initialize() { personaSuggestionsView.addSubview(personaListView) personaSuggestionsView.addSubview(separator) + + // DEBUG: doesn't work +// personaSuggestionsView.accessibilityElements = [personaListView] personaListView.onPersonaSelected = { [unowned self] persona in self.pickPersona(persona: persona) @@ -179,6 +182,8 @@ open class PeoplePicker: BadgeField { tokenSet.registerOnUpdate(for: self) { [weak self] in self?.updateAppearance() } + +// self.accessibilityElements = []; } /// Returns the badge for the associated persona @@ -224,7 +229,14 @@ open class PeoplePicker: BadgeField { /// layouts personaSuggestionsView in available window frame @objc open func showPersonaSuggestions() { personaListView.contentOffset = .zero + + // DEBUG: making this false to get it not added to window's accessibilityElements +// personaSuggestionsView.isAccessibilityElement = false + + // DEBUG: The subView is added to `window` and not the PeoplePickerView, which might cause the weird FocusOrder window?.addSubview(personaSuggestionsView) +// self.addSubview(personaSuggestionsView) // Can't do this. There's probably some benefits to adding it to the window. ie. Layouting wrt. the entire window's contents like keyboard. + containingViewBoundsObservation = window?.observe(\.bounds) { [unowned self] (_, _) in self.layoutPersonaSuggestions() } @@ -233,13 +245,123 @@ open class PeoplePicker: BadgeField { setNeedsLayout() layoutIfNeeded() delegate?.peoplePickerDidShowPersonaSuggestions?(self) - } + +// DEBUG: this makes it so that the elements of the entire peoplePicker view behind are not VO accessible. + personaSuggestionsView.accessibilityViewIsModal = true + + // layoutChanged - because if the focus is on the personaBadge text field, it doesn't automaticaly move to window +// UIAccessibility.post(notification: .layoutChanged, argument: nil) + UIAccessibility.post(notification: .layoutChanged, argument: personaSuggestionsView) + + // DEBUG: I can't do the below with totally hiding the containingViewController's ccessibilityElements + // because it's similar to doing `personaSuggestionsView.accessibilityViewIsModal=true` which don't let me + // swipe into the parent view's elements +// let containingViewController = findContainingViewController() +// containingViewController?.view.accessibilityElementsHidden = true +// UIAccessibility.post(notification: .layoutChanged, argument: nil) + + //self.isAccessibilityElement = true + + // DEBUG: below, doesn't work because self.accessibilityElements is nil +// self.accessibilityElements?.append(personaSuggestionsView) + + + //DEBUG: At this point, `containingViewController?.view.accessibilityElements` = nil + // perhaps it's not yet called. I may need to lean into the `override var accessibilityElements` +// let containingViewController = findContainingViewController() +// var elements = containingViewController?.view.accessibilityElements +// +// if let index = elements?.firstIndex(where: { $0 as? UIView == self }) { +// // Insert the personaSuggestionsView immediately after the PeoplePicker view +// elements?.insert(personaSuggestionsView, at: index + 1) +// } + + // This works partially - It doesn't accommodate the current elements of the PeoplePicker view. + // current elements - Label and BadgeView, +// self.accessibilityElements = [personaSuggestionsView] + +// self.accessibilityElements?.append(personaSuggestionsView) + } + +// open override var accessibilityElements: [Any]? { +// get { +// +// // Test 1 +//// let containingViewController = findContainingViewController() +//// var elements = containingViewController?.view.accessibilityElements +//// +//// var elements = super.accessibilityElements ?? [] +//// +//// // Find the index of the PeoplePicker view in the accessibility elements +//// if let index = elements?.firstIndex(where: { $0 as? UIView == self }) { +//// // Insert the personaSuggestionsView immediately after the PeoplePicker view +//// elements?.insert(personaSuggestionsView, at: index + 2) +//// } else { +//// // If PeoplePicker view is not found, append personaSuggestionsView at the end +//// elements.append(personaSuggestionsView) +//// } +//// +//// return elements +// +// // Test 2 + + // super.accessibilityElements is returning 0. +// var elements = super.accessibilityElements ?? [] +// elements.append(label) +// elements.append(badges) +// elements.append(personaSuggestionsView) +// +// return elements +// } +// set { +// super.accessibilityElements = newValue +// } +// } + +// open override var accessibilityElements: [Any]? { +// get { +// var elements: [Any] = [] +// +// let count = accessibilityElementCount() +// for index in 0..<count { +// if let element = accessibilityElement(at: index) { +// elements.append(element) +// } +// } +// +// if let window = window, personaSuggestionsView.isDescendant(of: window) { +// +//// var margins: UIEdgeInsets = .zero +//// margins.bottom = personaSuggestionsView.frame.height +//// +//// if let containingViewController = findContainingViewController() { +//// containingViewController.view.accessibilityFrame = containingViewController.view.frame.inset(by: margins) +//// } +// +//// personaSuggestionsView.isAccessibilityElement = true +// elements.append(personaSuggestionsView) +// } +// +// return elements +// } +// set { +// // Ensure any manually set elements are respected +//// super.accessibilityElements = newValue +// } +// } /// Hides personaSuggestionsView @objc open func hidePersonaSuggestions() { personaSuggestionsView.removeFromSuperview() containingViewBoundsObservation = nil + + personaSuggestionsView.accessibilityViewIsModal = true + delegate?.peoplePickerDidHidePersonaSuggestions?(self) + +// let containingViewController = findContainingViewController() +// containingViewController?.view.accessibilityElementsHidden = false +// UIAccessibility.post(notification: .layoutChanged, argument: nil) } open override func updateAppearance() { @@ -358,6 +480,8 @@ open class PeoplePicker: BadgeField { if fromUserAction { pickPersona(persona: personaBadgeDataSource.persona) } + +// self.accessibilityElements?.append(badge) } override func addBadge(_ badge: BadgeView) { @@ -369,6 +493,7 @@ open class PeoplePicker: BadgeField { personaBadgeDataSource.style = isValid ? .default : .danger badge.reload() super.addBadge(badge) +// self.accessibilityElements?.append(badge) } override func deleteBadge(_ badge: BadgeView, fromUserAction: Bool, updateConstrainedBadges: Bool) { From 02462a793fa79dfaeae2a8c0d14661ee1c40443a Mon Sep 17 00:00:00 2001 From: Amogh Aralimatti <amogh@Amoghs-MacBook-Pro.local> Date: Tue, 25 Feb 2025 00:27:48 -0800 Subject: [PATCH 2/4] sanitization --- .../FluentUI_iOS/Components/People Picker/PeoplePicker.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift b/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift index 269326e970..18e6917236 100644 --- a/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift +++ b/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift @@ -355,7 +355,7 @@ open class PeoplePicker: BadgeField { personaSuggestionsView.removeFromSuperview() containingViewBoundsObservation = nil - personaSuggestionsView.accessibilityViewIsModal = true + personaSuggestionsView.accessibilityViewIsModal = false delegate?.peoplePickerDidHidePersonaSuggestions?(self) From 9c2854bfeef1a5095a6f772bee4467a66ca2f28a Mon Sep 17 00:00:00 2001 From: Amogh Aralimatti <amogh@Amoghs-MacBook-Pro.local> Date: Tue, 25 Feb 2025 00:55:07 -0800 Subject: [PATCH 3/4] reset all prototype changes --- .../Components/People Picker/PeoplePicker.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift b/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift index 18e6917236..19fc3f9d2b 100644 --- a/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift +++ b/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift @@ -247,11 +247,11 @@ open class PeoplePicker: BadgeField { delegate?.peoplePickerDidShowPersonaSuggestions?(self) // DEBUG: this makes it so that the elements of the entire peoplePicker view behind are not VO accessible. - personaSuggestionsView.accessibilityViewIsModal = true +// personaSuggestionsView.accessibilityViewIsModal = true // layoutChanged - because if the focus is on the personaBadge text field, it doesn't automaticaly move to window // UIAccessibility.post(notification: .layoutChanged, argument: nil) - UIAccessibility.post(notification: .layoutChanged, argument: personaSuggestionsView) +// UIAccessibility.post(notification: .layoutChanged, argument: personaSuggestionsView) // DEBUG: I can't do the below with totally hiding the containingViewController's ccessibilityElements // because it's similar to doing `personaSuggestionsView.accessibilityViewIsModal=true` which don't let me @@ -355,7 +355,7 @@ open class PeoplePicker: BadgeField { personaSuggestionsView.removeFromSuperview() containingViewBoundsObservation = nil - personaSuggestionsView.accessibilityViewIsModal = false +// personaSuggestionsView.accessibilityViewIsModal = false delegate?.peoplePickerDidHidePersonaSuggestions?(self) From 8c1637699b207667475cc21e68cd9fef042bed6d Mon Sep 17 00:00:00 2001 From: Amogh Aralimatti <amogh@mac.lan> Date: Thu, 13 Mar 2025 13:16:50 -0700 Subject: [PATCH 4/4] More prototype Changes --- .../Demos/TableViewHeaderFooterViewDemoController.swift | 6 ++++++ .../Components/People Picker/PeoplePicker.swift | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Demos/FluentUIDemo_iOS/FluentUI.Demo/Demos/TableViewHeaderFooterViewDemoController.swift b/Demos/FluentUIDemo_iOS/FluentUI.Demo/Demos/TableViewHeaderFooterViewDemoController.swift index e54e8d67a0..434e56b0cc 100644 --- a/Demos/FluentUIDemo_iOS/FluentUI.Demo/Demos/TableViewHeaderFooterViewDemoController.swift +++ b/Demos/FluentUIDemo_iOS/FluentUI.Demo/Demos/TableViewHeaderFooterViewDemoController.swift @@ -79,6 +79,12 @@ extension TableViewHeaderFooterViewDemoController { let section = groupedSections[section] if let header = header, section.hasHandler { header.onHeaderViewTapped = { [weak self] in self?.forHeaderTapped(header: header, section: index) } +// let state = collapsedSections[index] ? "Expand" : "Collapse" + + // header.accessibilityLabel isn't assigned here yet. Currently I suspect it's being read out from the private +// `titleView` property which is a `TableViewHeaderFooterTitleView`. The trait on that is set as + // `titleView.accessibilityTraits.insert(.header)` + header.accessibilityLabel = "\(header.accessibilityLabel ?? ""), \(collapsedSections[index] ? "Collapse" : "Expand")" } if section.hasCustomAccessoryView { diff --git a/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift b/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift index 19fc3f9d2b..f4ab24c561 100644 --- a/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift +++ b/Sources/FluentUI_iOS/Components/People Picker/PeoplePicker.swift @@ -234,7 +234,7 @@ open class PeoplePicker: BadgeField { // personaSuggestionsView.isAccessibilityElement = false // DEBUG: The subView is added to `window` and not the PeoplePickerView, which might cause the weird FocusOrder - window?.addSubview(personaSuggestionsView) + self.addSubview(personaSuggestionsView) // self.addSubview(personaSuggestionsView) // Can't do this. There's probably some benefits to adding it to the window. ie. Layouting wrt. the entire window's contents like keyboard. containingViewBoundsObservation = window?.observe(\.bounds) { [unowned self] (_, _) in