diff --git a/Sources/AccessibilityDocumentation/Constants.swift b/Sources/AccessibilityDocumentation/Constants.swift index 28ec870..37f509d 100644 --- a/Sources/AccessibilityDocumentation/Constants.swift +++ b/Sources/AccessibilityDocumentation/Constants.swift @@ -306,24 +306,28 @@ extension UIAccessibilityTraits_ { // public static var requiresActivation: UIAccessibility.DirectTouchOptions { get } // } //} -//extension UIAccessibility.Notification { -// -// public static var screenChanged: UIAccessibility.Notification -// -// public static var layoutChanged: UIAccessibility.Notification -// -// @available(iOS 4.0, *) -// public static var announcement: UIAccessibility.Notification -// -// @available(iOS 4.2, *) -// public static var pageScrolled: UIAccessibility.Notification -// -// @available(iOS 8.0, *) -// public static var pauseAssistiveTechnology: UIAccessibility.Notification -// -// @available(iOS 8.0, *) -// public static var resumeAssistiveTechnology: UIAccessibility.Notification -//} + +extension Book { + + /// Call this notification when entire screen had changed to rebuild accessibility tree. VoiceOver will notify by special signal. Modal and push presentation call this notification automatically. + public static var screenChanged: Notification = Notification(name: Notification.Name(rawValue: "screenChanged")) + + /// Call this notification when part of a screen had changed to rebuild accessibility tree. Great for some disclosures area for e.g. + public static var layoutChanged: Notification = Notification(name: Notification.Name(rawValue: "screenChanged")) + + /// Notify user when some process had completed. Examples: finish loading, complete order in restaurant + @available(iOS 4.0, *) + public static var announcement: Notification = Notification(name: Notification.Name(rawValue: "screenChanged")) + + @available(iOS 4.2, *) + public static var pageScrolled: Notification = Notification(name: Notification.Name(rawValue: "screenChanged")) + + @available(iOS 8.0, *) + public static var pauseAssistiveTechnology: Notification = Notification(name: Notification.Name(rawValue: "screenChanged")) + + @available(iOS 8.0, *) + public static var resumeAssistiveTechnology: Notification = Notification(name: Notification.Name(rawValue: "screenChanged")) +} //extension UIAccessibility.AssistiveTechnologyIdentifier { // // @available(iOS 8.0, *) diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Articles/0.AssistiveTechnologies/SwitchControl.md b/Sources/AccessibilityDocumentation/Documentation.docc/Articles/0.AssistiveTechnologies/SwitchControl.md index 48b0070..5295a21 100644 --- a/Sources/AccessibilityDocumentation/Documentation.docc/Articles/0.AssistiveTechnologies/SwitchControl.md +++ b/Sources/AccessibilityDocumentation/Documentation.docc/Articles/0.AssistiveTechnologies/SwitchControl.md @@ -1,8 +1,14 @@ # Switch Control -Allows to connect external devices and link them to any command. As a result paralyzed people can control a phone by simple signals: finger movement, muscle stretches, etc. Also, a iPhone's camera can recognize facial expression or any sound like a command. In the end user moves focus on screen and pass command to focused element by submenu that is presented after selection. +@Metadata { + @PageImage( + purpose: card, + source: "SwitchControlCover", + alt: "Switch Control with opened popover with actions: Select All, Deselect, Cut, Copy") +} + -## Overview +Allows to connect external devices and link them to any command. As a result paralyzed people can control a phone by simple signals: finger movement, muscle stretches, etc. Also, a iPhone's camera can recognize facial expression or any sound like a command. In the end user moves focus on screen and pass command to focused element by submenu that is presented after selection. ![Switch control modes: focus groups on elements, cross selection and submenu](SwitchControlOverview) diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Articles/0.AssistiveTechnologies/VoiceControl.md b/Sources/AccessibilityDocumentation/Documentation.docc/Articles/0.AssistiveTechnologies/VoiceControl.md index d652ce5..8e059c8 100644 --- a/Sources/AccessibilityDocumentation/Documentation.docc/Articles/0.AssistiveTechnologies/VoiceControl.md +++ b/Sources/AccessibilityDocumentation/Documentation.docc/Articles/0.AssistiveTechnologies/VoiceControl.md @@ -1,7 +1,13 @@ # Voice Control -Adds additional commands over graphical UI to control a phone by voice commands. A user of VoiceControl can see, but can't touch their phone, as a result he can pronounce commands lite "select Pepperoni", "tap purchase" or "close screen". iPhone recognizes speach, convert it to text and links command to elements' description. +Adds additional commands over graphical UI to control a phone by voice commands. A user of VoiceControl can see, but can't touch their phone, as a result he can pronounce commands lite "select Pepperoni", "tap purchase" or "close screen". iPhone recognizes speech, convert it to text and links command to elements' description. +@Metadata { + @PageImage( + purpose: card, + source: "Voice Control Cover", + alt: "Switch Control with opened popover with actions: Select All, Deselect, Cut, Copy") +} ## Overview diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Articles/0.AssistiveTechnologies/VoiceOver.md b/Sources/AccessibilityDocumentation/Documentation.docc/Articles/0.AssistiveTechnologies/VoiceOver.md index b8bbc83..41218a7 100644 --- a/Sources/AccessibilityDocumentation/Documentation.docc/Articles/0.AssistiveTechnologies/VoiceOver.md +++ b/Sources/AccessibilityDocumentation/Documentation.docc/Articles/0.AssistiveTechnologies/VoiceOver.md @@ -2,6 +2,13 @@ Helps blind or low-visioned persons to use a phone by listening audio description of UI and command by different swipes and non-direct touches. Developer prepare text description of the element, iPhone will generate voice description from text. +@Metadata { + @PageImage( + purpose: card, + source: "VoiceOver Cover", + alt: "Switch Control with opened popover with actions: Select All, Deselect, Cut, Copy") +} + ## Overview ![VoiceOver gestures](VoiceOverGestures) diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Articles/1.Basic/ControlHierarchy.md b/Sources/AccessibilityDocumentation/Documentation.docc/Articles/1.Basic/ControlHierarchy.md index b9872f1..0db2ffc 100644 --- a/Sources/AccessibilityDocumentation/Documentation.docc/Articles/1.Basic/ControlHierarchy.md +++ b/Sources/AccessibilityDocumentation/Documentation.docc/Articles/1.Basic/ControlHierarchy.md @@ -56,21 +56,21 @@ Visual hierarchy is based on child-parent relation and accessibility tree use th // TODO: Container can has a label when use .semantic } +### Focus order +``AccessibilityContainer/accessibilityElements`` + +@Comment { + // TODO: It should be part of +} + +#### Dynamic number of elements +https://github.com/akaDuality/RotorHeaders + ### Tutorial Read for example -### Modal views - -Modal view should done three main things: -- Limit focus movement by himself. To mark a node as modal we use property ``Book/accessibilityViewIsModal``. -- Set focus to the first element by posting ``Book/post(notification:argument:)`` with type `.screenChanged`. -- Support escape gesture to close the screen by adding function ``Book/accessibilityPerformEscape`` to first responder -@Comment { - // TODO: Add link to notification - // TODO: Add Product Card tutorial -} ## Topics diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Articles/1.Basic/DescribeElements.md b/Sources/AccessibilityDocumentation/Documentation.docc/Articles/1.Basic/DescribeElements.md index d4ab36b..10dea2c 100644 --- a/Sources/AccessibilityDocumentation/Documentation.docc/Articles/1.Basic/DescribeElements.md +++ b/Sources/AccessibilityDocumentation/Documentation.docc/Articles/1.Basic/DescribeElements.md @@ -5,8 +5,7 @@ Core properties that describes element for VoiceOver To describe element we can use label, value and trait (like a type) ## Label - -- ``Book/accessibilityLabel`` +``Book/accessibilityLabel`` The main property is `accessibilityLabel` – defines element's name. It should be name in one or two words for buttons or represents full text from `UILabel` @@ -21,8 +20,7 @@ The main property is `accessibilityLabel` – defines element's name. It should > Tip: Voice Control can have synonims for label. Check ``Book/accessibilityUserInputLabels`` for more details. ## Value - -- ``Book/accessibilityValue`` +``Book/accessibilityValue`` `AccessibilityValue` is optional second part of the element's description. It can contain additional details or represents current value of the element - *1.4 billions views* – no value for regular text is ofter situation @@ -42,7 +40,7 @@ Important to understand differences between label and value. Label should be as Otherwise, adjustable elements allow to change only value part and after change only value part will be pronounced to user. ## Trait -- ``Book/accessibilityTraits`` +``Book/accessibilityTraits`` The last part of element's description is trait. Some traits may add additional text to element's description, other just changes behaviour. @@ -57,21 +55,28 @@ The most common trait is ``UIAccessibilityTraits_/button`` – it helps user to - *Pizza Pepperoni, Pepperoni, Mozzarella. **Button*** – tappable cell should contain button semantic, that's how user will understand that the cell is interactive and can be tapped. - *Size, Medium. **Adjustable*** – VoiceOver can change inner value by vertical swipe. - -@Image(source: "TraitsOrder", alt: "Reading order is controlled by designer") - > Note: Label and Value are separated by comma, but trait represents another sentence and separated by dot automatically. > Important: Label and Value are `String` properties, but Trait can be selected only from limited amount of variants. > > Not duplicate trait's textual description inside Label or Value, because different technologies uses trait in different manear, not only for textual description. -### Tutorial +## Hint +``Book/accessibilityHint`` -@Tutorial() { - +Always disabled + +@Comment { + // TODO: Describe hint } +## Full formula +@Image(source: "TraitsOrder", alt: "Reading order is controlled by designer") + +> Note: Container prefix is described in + +### Tutorial + Read for example ## Topics diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Articles/1.Basic/Navigation.md b/Sources/AccessibilityDocumentation/Documentation.docc/Articles/1.Basic/Navigation.md index 5b5d894..f95553c 100644 --- a/Sources/AccessibilityDocumentation/Documentation.docc/Articles/1.Basic/Navigation.md +++ b/Sources/AccessibilityDocumentation/Documentation.docc/Articles/1.Basic/Navigation.md @@ -1,23 +1,88 @@ # Navigation -To simplify navigation developer had to achieve several goals: reduce number of elements, fix focus order and support several additional actions +To simplify navigation developer had to achieve several goals: call a notification to update accessibility tree, manage focus when a new screen is opened, support action for closing or completing the screen. ## Overview Text -### Reduce number of elements +### Notifications -@Comment { - // TODO: It should be part of +Notifications is mechanism to keep in sync current view hierarchy with accessibility tree. Every time when you update your UI you should call proper notification. Hopefully, some of them is called automatically. + +@Links(visualStyle: list) { + - ``Book/announcement`` + - ``Book/screenChanged`` + - ``Book/layoutChanged`` + - ``Book/pageScrolled`` + - ``Book/pauseAssistiveTechnology`` + - ``Book/resumeAssistiveTechnology`` } -### Focus order +### Modal view +``Book/accessibilityViewIsModal`` + +Set this property to any modal view to limit focus movement by this view. + +Modal view should done three main things: +- Limit focus movement by himself. To mark a node as modal we use property ``Book/accessibilityViewIsModal``. +- Set focus to the first element by posting ``Book/post(notification:argument:)`` with type `.screenChanged` and set focus to first onscreen element. +- Support escape gesture to close the screen by adding function ``Book/accessibilityPerformEscape()`` to first responder + +@Comment { + // TODO: Add link to notification + // TODO: Add Product Card tutorial +} ### Escape gesture +``Book/accessibilityPerformEscape()`` + +Escape gesture allows to close current screen by special gesture without focusing on "close" button. +- **For macOS app** it happened by *pressing "esc" button*, +- **For VoiceOver** you should swipe by *two finger up and down on screen several times like drawing N-symbol*. + + +@Comment { + // TODO: Add escape gesture video + // Do Switch control and voice control have support for this gesture? Can't find it for Switch Control + // TODO: Check https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/SupportingAccessibility.html +} + +To handle escape gesture on your view you should override default implementation: + +``` +class ProductCardViewController: UIViewController { + override func accessibilityPerformEscape() -> Bool { + ingredientsCustomizationPopover.removeFromSuperView() // <- Call your type function + return true + } +} +``` + +> Note: Default modal and push navigation already supported escape gesture, but if you create your own custom navigation or modal screen you should implement escape function manually + ### Magic tap +``Book/accessibilityPerformMagicTap()`` + +User can call "magic tap" gesture to perform main operation on the screen. Examples: +- Phone app: picks up or hangs up a call +- Clock app: start or stop a stopwatch +- Product card in food ordering app: add to cart +- Cart in food ordering app: create an order +- Taxi app: order a ride +- Focused textfield: start dictation + +**VoiceOver** allows to *tap twice by two finger* in any place on the screen to perform magic tap +@Comment { + // TODO: how to call by switch control and voice control? +} + +> Important: The action after magic tap gesture should be obvious to a user: absolutely nothing tell to user what action will be triggered. You can add hint to main button on screen that this button can be triggered by magic tap, but user offen distable hints, check for more details + +### Container + ### Switch control and grouping #### VoiceOver supports grouping diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Getting Started.md b/Sources/AccessibilityDocumentation/Documentation.docc/Getting Started.md index 4f0b425..3079b48 100644 --- a/Sources/AccessibilityDocumentation/Documentation.docc/Getting Started.md +++ b/Sources/AccessibilityDocumentation/Documentation.docc/Getting Started.md @@ -23,20 +23,51 @@ To prototype interaction on early stage of development you can use [VoiceOver De ![Screenshot of the application](VoiceOverDesigner.png) +### Assistive Technologies +@Links(visualStyle: compactGrid) { + - + - + - +} + ## Tutorials + Step by step practice course. -- -- +@Links(visualStyle: detailedGrid) { + - + - +} + +@Comment { + + // TODO: Uncomment? + + @TabNavigator { + @Tab("Switch Control") { + Allows to connect external devices and link them to any command. As a result paralyzed people can control a phone by simple signals: finger movement, muscle stretches, etc. Also, a iPhone's camera can recognize facial expression or any sound like a command. In the end user moves focus on screen and pass command to focused element by submenu that is presented after selection. + ![Switch control modes: focus groups on elements, cross selection and submenu](SwitchControlOverview) + } + + + @Tab("Voice Control") { + Adds additional commands over graphical UI to control a phone by voice commands. A user of VoiceControl can see, but can't touch their phone, as a result he can pronounce commands lite "select Pepperoni", "tap purchase" or "close screen". iPhone recognizes speach, convert it to text and links command to elements' description. + + ![Voice Control modes: with labels, enumerated elements or grid](VoiceControlOverview) + } + + @Tab("Voice Over") { + Helps blind or low-visioned persons to use a phone by listening audio description of UI and command by different swipes and non-direct touches. Developer prepare text description of the element, iPhone will generate voice description from text. + + ![VoiceOver gestures](VoiceOverGestures) + } + } + } + ## Topics -### Assistive Technologies -- -- -- - ### Basic - - diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/SwitchControlCover.png b/Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/SwitchControlCover.png new file mode 100644 index 0000000..c66801a Binary files /dev/null and b/Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/SwitchControlCover.png differ diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Resources/SwitchControlOverview.png b/Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/SwitchControlOverview.png similarity index 100% rename from Sources/AccessibilityDocumentation/Documentation.docc/Resources/SwitchControlOverview.png rename to Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/SwitchControlOverview.png diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/Voice Control Cover.png b/Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/Voice Control Cover.png new file mode 100644 index 0000000..d53856c Binary files /dev/null and b/Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/Voice Control Cover.png differ diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Resources/VoiceControlOverview.png b/Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/VoiceControlOverview.png similarity index 100% rename from Sources/AccessibilityDocumentation/Documentation.docc/Resources/VoiceControlOverview.png rename to Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/VoiceControlOverview.png diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/VoiceOver Cover.png b/Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/VoiceOver Cover.png new file mode 100644 index 0000000..3b008e0 Binary files /dev/null and b/Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/VoiceOver Cover.png differ diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Resources/VoiceOverDesigner.png b/Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/VoiceOverDesigner.png similarity index 100% rename from Sources/AccessibilityDocumentation/Documentation.docc/Resources/VoiceOverDesigner.png rename to Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/VoiceOverDesigner.png diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Resources/VoiceOverDesigner~dark.png b/Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/VoiceOverDesigner~dark.png similarity index 100% rename from Sources/AccessibilityDocumentation/Documentation.docc/Resources/VoiceOverDesigner~dark.png rename to Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/VoiceOverDesigner~dark.png diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Resources/VoiceOverGestures.png b/Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/VoiceOverGestures.png similarity index 100% rename from Sources/AccessibilityDocumentation/Documentation.docc/Resources/VoiceOverGestures.png rename to Sources/AccessibilityDocumentation/Documentation.docc/Resources/Covers/VoiceOverGestures.png diff --git a/Sources/AccessibilityDocumentation/Documentation.docc/Tutorials/1,Basic/AdoptingCell.tutorial b/Sources/AccessibilityDocumentation/Documentation.docc/Tutorials/1,Basic/AdoptingCell.tutorial index b4ce0ab..da89850 100644 --- a/Sources/AccessibilityDocumentation/Documentation.docc/Tutorials/1,Basic/AdoptingCell.tutorial +++ b/Sources/AccessibilityDocumentation/Documentation.docc/Tutorials/1,Basic/AdoptingCell.tutorial @@ -268,6 +268,4 @@ } } } - } - diff --git a/Sources/AccessibilityDocumentation/UIAccessibility_.swift b/Sources/AccessibilityDocumentation/UIAccessibility_.swift index d084053..1d92b6c 100644 --- a/Sources/AccessibilityDocumentation/UIAccessibility_.swift +++ b/Sources/AccessibilityDocumentation/UIAccessibility_.swift @@ -782,6 +782,12 @@ public class Book { @available(iOS 4.2, *) open func accessibilityScroll(_ direction: UIAccessibilityScrollDirection) -> Bool { false } + + /// Is called when user perform special closing gesture. VoiceOver calls this after drawing N-symbol by two finger. + /// + /// See for more details + /// + /// - Returns: `true` if this class handles gestures. If `false` UIKit will traverse firstResponders for next element that can handle this gesture @available(iOS 5.0, *) open func accessibilityPerformEscape() -> Bool { false }