diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/AdaptionStrategy.tutorial b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/AdaptionStrategy.tutorial index 7b84562..7da0dbb 100644 --- a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/AdaptionStrategy.tutorial +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/AdaptionStrategy.tutorial @@ -90,9 +90,6 @@ @TutorialReference(tutorial: "doc:HowTextInputWorks") @TutorialReference(tutorial: "doc:HandleErrorsInTextField") } - } - - @Volume(name: "Visual properties") { @Chapter(name: "Colors And Shapes") { @Image(source: chapter-placeholder.png, alt: "") diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Advanced/VerticalSwipes/AdjustableElements.tutorial b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Advanced/VerticalSwipes/AdjustableElements.tutorial index cb0afa8..5a15e97 100644 --- a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Advanced/VerticalSwipes/AdjustableElements.tutorial +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Advanced/VerticalSwipes/AdjustableElements.tutorial @@ -3,88 +3,91 @@ Simplifies interactions with complex elements for VoiceOver. } - @Section(title: "Basic Setup") { - @ContentAndMedia { - By default any element can contain ``Book/accessibilityValue`` to expose *additional data* to user. Some elements come complicated and may contain a *dynamic value* controlled by a vertical swipe. Here some examples: - } + @Comment { - @Steps { - @Step { - Accessible element can be marked by ``UIAccessibilityTraits_/adjustable`` trait to make ``Book/accessibilityValue`` dynamic. - - @Code(name: "", file: "AdjustableTutorialStep_1.swift") - } - - @Step { - Accessible element can be marked by ``UIAccessibilityTraits_/adjustable`` trait to make ``Book/accessibilityValue`` dynamic. - - @Code(name: "", file: "AdjustableTutorialStep_2.swift") + @Section(title: "Basic Setup") { + @ContentAndMedia { + By default any element can contain ``Book/accessibilityValue`` to expose *additional data* to user. Some elements come complicated and may contain a *dynamic value* controlled by a vertical swipe. Here some examples: } - @Step {` - As a result the element will react on a vertical swipe by calling ``Book/accessibilityIncrement()`` and ``Book/accessibilityDecrement()``. - - After each swipe the ``Book/accessibilityValue`` getter will be read again and the next value will be vocalised. + @Steps { + @Step { + Accessible element can be marked by ``UIAccessibilityTraits_/adjustable`` trait to make ``Book/accessibilityValue`` dynamic. + + @Code(name: "", file: "AdjustableTutorialStep_1.swift") + } - > Note: `AccessibilityLabel wouldn't be read again after swipe` + @Step { + Accessible element can be marked by ``UIAccessibilityTraits_/adjustable`` trait to make ``Book/accessibilityValue`` dynamic. + + @Code(name: "", file: "AdjustableTutorialStep_2.swift") + } - @Code(name: "", file: "AdjustableTutorialStep_3.swift") + @Step {` + As a result the element will react on a vertical swipe by calling ``Book/accessibilityIncrement()`` and ``Book/accessibilityDecrement()``. + + After each swipe the ``Book/accessibilityValue`` getter will be read again and the next value will be vocalised. + + > Note: `AccessibilityLabel wouldn't be read again after swipe` + + @Code(name: "", file: "AdjustableTutorialStep_3.swift") + } } } - } - - @Section(title: "Backward Compatibility") { - @ContentAndMedia { - Voice Control and Switch Control work with separate *buttons* instead of *adjustable elements*. - } - - @Steps { - @Step { - > Important: Adjustable elements are only used for VoiceOver and will break the behaviour of Voice Control and Switch Control. - - Distinguish their behaviour in code by a dynamic getter: - - @Code(name: "", file: "AdjustableTutorialStep_4.swift") + + @Section(title: "Backward Compatibility") { + @ContentAndMedia { + Voice Control and Switch Control work with separate *buttons* instead of *adjustable elements*. } - - @Step { - Switch Control requires grouping: firstly focus will be placed on the group itself, afterwards the selection will be moved between elements of this group. It simulates navigation by reducing the number of elements on each level. - - > Note: Watch video [How Grouping Simplifies Navigation](https://youtube.com/shorts/1l8H615EkV0?si=tKyhIGjBbR9XG9HP) + + @Steps { + @Step { + > Important: Adjustable elements are only used for VoiceOver and will break the behaviour of Voice Control and Switch Control. + + Distinguish their behaviour in code by a dynamic getter: + + @Code(name: "", file: "AdjustableTutorialStep_4.swift") + } - @Code(name: "", file: "AdjustableTutorialStep_5.swift") + @Step { + Switch Control requires grouping: firstly focus will be placed on the group itself, afterwards the selection will be moved between elements of this group. It simulates navigation by reducing the number of elements on each level. + + > Note: Watch video [How Grouping Simplifies Navigation](https://youtube.com/shorts/1l8H615EkV0?si=tKyhIGjBbR9XG9HP) + + @Code(name: "", file: "AdjustableTutorialStep_5.swift") + } } } - } - - @Assessments { - @MultipleChoice { - What **Accessibility Features** use adjustable trait? - - @Choice(isCorrect: false) { - Switch Control - + + @Assessments { + @MultipleChoice { + What **Accessibility Features** use adjustable trait? - @Justification(reaction: "Try again!") { - Switch Control indeed requires grouping to simplify navigation, but uses ``Book/accessibilityNavigationStyle`` for that. - } - } - - @Choice(isCorrect: true) { - VoiceOver - - - @Justification(reaction: "That's right!") { - Blind people would like to have a reduced number of elements on the screen and simplified interactions by vertical swipes to adjust the value of the element. + @Choice(isCorrect: false) { + Switch Control + + + @Justification(reaction: "Try again!") { + Switch Control indeed requires grouping to simplify navigation, but uses ``Book/accessibilityNavigationStyle`` for that. + } } - } + + @Choice(isCorrect: true) { + VoiceOver - @Choice(isCorrect: false) { - Voice Control - + + @Justification(reaction: "That's right!") { + Blind people would like to have a reduced number of elements on the screen and simplified interactions by vertical swipes to adjust the value of the element. + } + } - @Justification(reaction: "Try again!") { - Voice Control is mostly used by people who are able to see. In such case percieving elements as separate buttons is preferred. + @Choice(isCorrect: false) { + Voice Control + + + @Justification(reaction: "Try again!") { + Voice Control is mostly used by people who are able to see. In such case percieving elements as separate buttons is preferred. + } } } } diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Advanced/VerticalSwipes/aAdjustableElements.md b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Advanced/VerticalSwipes/aAdjustableElements.md index b4cb2a6..6445edd 100644 --- a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Advanced/VerticalSwipes/aAdjustableElements.md +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Advanced/VerticalSwipes/aAdjustableElements.md @@ -1,64 +1,65 @@ # Adjustable Elements -Simplifies interactions with complex elements for VoiceOver. - -> Tip: -> - Best for VoiceOver, is changed by vertical swipe -> - Avoid at Voice Control -> - Replace by ``Book/accessibilityNavigationStyle`` for Switch Control +@Comment { + Simplifies interactions with complex elements for VoiceOver. -## Overview + > Tip: + > - Best for VoiceOver, is changed by vertical swipe + > - Avoid at Voice Control + > - Replace by ``Book/accessibilityNavigationStyle`` for Switch Control -By default any element can contain ``UIAccessibilityTraits_/adjustable`` trait to expose additional data for user. Some elements come complicated and can contain dynamic value, controlled by vertical swipe. Examples: -- Slider -- Stepper -- Any horizontal carousel + ## Overview -> Note: After vertical swipe reads only the new value, a label is omitted to avoid repeatness. + By default any element can contain ``UIAccessibilityTraits_/adjustable`` trait to expose additional data for user. Some elements come complicated and can contain dynamic value, controlled by vertical swipe. Examples: + - Slider + - Stepper + - Any horizontal carousel -Tutorial for detailed explanation. + > Note: After vertical swipe reads only the new value, a label is omitted to avoid repeatness. -### How to setup + Tutorial for detailed explanation. -- Accessible element can be marked by ``UIAccessibilityTraits_/adjustable`` trait to make ``Book/accessibilityValue`` dynamic. -- As a result the element will react on vertical swipe by calling ``Book/accessibilityIncrement()`` and ``Book/accessibilityDecrement()``. -- After each swipe the ``Book/accessibilityValue`` getter will be reread and the new value will be spoken out. + ### How to setup -### Enable adjustable only for VoiceOver + - Accessible element can be marked by ``UIAccessibilityTraits_/adjustable`` trait to make ``Book/accessibilityValue`` dynamic. + - As a result the element will react on vertical swipe by calling ``Book/accessibilityIncrement()`` and ``Book/accessibilityDecrement()``. + - After each swipe the ``Book/accessibilityValue`` getter will be reread and the new value will be spoken out. -> Important: Adjustable elements is useful only for VoiceOver and will brake behaviour for Voice Control and Switch Control. + ### Enable adjustable only for VoiceOver -Distinguish behaviour in code by dynamic getter: + > Important: Adjustable elements is useful only for VoiceOver and will brake behaviour for Voice Control and Switch Control. -``` -var isAccessibilityElement: Bool { - UIAccessibility.isVoiceOverRunning -} + Distinguish behaviour in code by dynamic getter: -var accessibilityTraits: UIAccessibilityTraits { - if UIAccessibility.isVoiceOverRunning { - return [.adjustable] - } else { - return .none + ``` + var isAccessibilityElement: Bool { + UIAccessibility.isVoiceOverRunning } -} -``` -### Selection follow focus + var accessibilityTraits: UIAccessibilityTraits { + if UIAccessibility.isVoiceOverRunning { + return [.adjustable] + } else { + return .none + } + } + ``` -@Comment { -// TODO: Selection follow focus -// TODO: Visual Samples -} + ### Selection follow focus -### `button` and `adjustable` + @Comment { + // TODO: Selection follow focus + // TODO: Visual Samples + } -@Comment { -// TODO: Stories sample -} + ### `button` and `adjustable` -### Tutorial + @Comment { + // TODO: Stories sample + } -See tutorial + ### Tutorial + See tutorial +} diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Essentials/1.Description/DescribeElements.tutorial b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Essentials/1.Description/DescribeElements.tutorial index 253be66..b2f82c1 100644 --- a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Essentials/1.Description/DescribeElements.tutorial +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Essentials/1.Description/DescribeElements.tutorial @@ -114,7 +114,7 @@ } @Step { - Pay attention that *action buttons* should have **short and comrehensible labels that describe what this button does**. Do not use the word "button" in its label: if spoken by [`VoiceOver`](), it is doubled since having `Trait` specified causes the screenreader to tell the user that the element is a button. + Pay attention that *action buttons* should have **short and comrehensible labels that describe what this button does**. Do not use the word "button" in its label: if spoken by [`VoiceOver`](), it is doubled since having `Trait` specified causes the screenreader to tell the user that the element is a button. @Image(source: placeholder-image.png, alt: "") @@ -147,9 +147,7 @@ @Step { Breaking the provided information into categories, pizza's name will serve as `Label` and everything else will go to `Value`. - Notice that if both stated, `Label` and `Value` are separated by a *comma* in speech — [`VoiceOver`]() will put a *pause* between them on its own. - - But everything that happens inside the properties in terms of **pronunciation** is *our* responsibility. **Don't forget to use *punctuation marks* to help `VoiceOver` read texts *easier* for humans to listen to**. + Notice that if both stated, `Label` and `Value` are separated by a *comma* in speech — [`VoiceOver`]() will put a *pause* between them on its own. But everything that happens inside the properties in terms of **pronunciation** is *our* responsibility. **Don't forget to use *punctuation marks* to help `VoiceOver` read texts *easier* for humans to listen to**. @Image(source: chapter-placeholder.png, alt: "") @@ -208,7 +206,7 @@ } } - @Section(title: "What Now?") { + @Section(title: "What now") { @ContentAndMedia { Congratulations! Now you know everything needed to fully **describe elements for *both* users and assistive technology** they use. @@ -217,7 +215,6 @@ @Image(source: chapter-placeholder.png, alt: "") } } - @Assessments { @MultipleChoice { Is this item accessible? diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Essentials/2.Reduce/AdaptCells.tutorial b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Essentials/2.Reduce/AdaptCells.tutorial index 22eb466..b9b55fa 100644 --- a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Essentials/2.Reduce/AdaptCells.tutorial +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Essentials/2.Reduce/AdaptCells.tutorial @@ -11,292 +11,295 @@ } - @Section(title: "What Is Wrong With The «Normal» Layout") { - @ContentAndMedia { - Even though the cell looks simple it is not enough — such layout would lead to several *accessibility issues*. Let's see **how exactly different Accessibility Features *struggle* with that**. - - @Image(source: "Chicken BBQ", alt: "Cell of Chicken BBQ containing an image, a title, ingredients and a price.") - } - - @Steps { - @Step { - Firstly, **there is a definite problem for *VoiceOver* to adapt such interfaces**. - - The thing is that **the focus works such way so it outlines *every* single element of a cell starting from *the title***. - - > Note: Pay attention that **images are hidden from VoiceOver *by default***, therefore are *inaccessible* to be focused on. - - @Image(source: "DescribeCell_1", alt: "Focus outlines the title of the cell first.") - } - - @Step { - After a swipe to the right (which triggers **moving to the next element**) the focus moves to **the list of ingredients**. - - @Image(source: "DescribeCell_2", alt: "In our case, secondly the focus outlines the ingredients' list.") - } - - @Step { - Same way the consequent swipe will move the focus to **the price button**. - - > Note: The *only* possibility **for a user to understand that this element is interactive by hearing VoiceOver say that's it's a *button***. It can be made possible by **specifying its `.button` *trait***. + @Comment { + + @Section(title: "What Is Wrong With The "Normal" Layout") { + @ContentAndMedia { + Even though the cell looks simple it is not enough — such layout would lead to several *accessibility issues*. Let's see **how exactly different Accessibility Features *struggle* with that**. - @Image(source: "DescribeCell_3", alt: "Consequently the focus outlines the button with the price.") + @Image(source: "Chicken BBQ", alt: "Cell of Chicken BBQ containing an image, a title, ingredients and a price.") } - @Step { - Overall the number of the swipes needed to go through a single cell is three. This is way *too* many: never forget that we're talking about a list of pizzas and **each pizza is an *independent* cell**. + @Steps { + @Step { + Firstly, **there is a definite problem for *VoiceOver* to adapt such interfaces**. + + The thing is that **the focus works such way so it outlines *every* single element of a cell starting from *the title***. + + > Note: Pay attention that **images are hidden from VoiceOver *by default***, therefore are *inaccessible* to be focused on. + + @Image(source: "DescribeCell_1", alt: "Focus outlines the title of the cell first.") + } - @Code(name: "Several Cells, Wrong Rhyme", file: "DescribeCell_3_0.swift") - } - - @Step { - Moreover such discretion leads to a decrease in *comrehensibility*: users can easily **lose track of what pizza in particular they are going through at the moment**. + @Step { + After a swipe to the right (which triggers **moving to the next element**) the focus moves to **the list of ingredients**. + + @Image(source: "DescribeCell_2", alt: "In our case, secondly the focus outlines the ingredients' list.") + } - @Code(name: "Several Cells, Wrong Rhyme", file: "DescribeCell_3_1.swift") { - @Image(source: "DescribeCell_3_3", alt: "Focus outlines the button with the price.") + @Step { + Same way the consequent swipe will move the focus to **the price button**. + + > Note: The *only* possibility **for a user to understand that this element is interactive by hearing VoiceOver say that's it's a *button***. It can be made possible by **specifying its `.button` *trait***. + + @Image(source: "DescribeCell_3", alt: "Consequently the focus outlines the button with the price.") } - } - - @Step { - For example, **the price button* may be percieved connected to the next title** which is something we really don't want to have. Normally prices are playing a critical role in choice-making. - @Code(name: "Several Cells, Wrong Rhyme", file: "DescribeCell_3_2.swift") { - @Image(source: "DescribeCell_3_3", alt: "Focus outlines the button with the price.") + @Step { + Overall the number of the swipes needed to go through a single cell is three. This is way *too* many: never forget that we're talking about a list of pizzas and **each pizza is an *independent* cell**. + + @Code(name: "Several Cells, Wrong Rhyme", file: "DescribeCell_3_0.swift") } - } - - @Step { - Talking about *price buttons*, there are ***Voice Control* and *Switch Control* that prioritise *interactive buttons*** and thus *struggle* with such layout too. As a result of their adapting behaviour **the only label shown will be the price button's *label***. To press the whole cell users would have to, for example, pronounce *«Tap From AED thirty»* — which is a nonsense. + @Step { + Moreover such discretion leads to a decrease in *comrehensibility*: users can easily **lose track of what pizza in particular they are going through at the moment**. + + @Code(name: "Several Cells, Wrong Rhyme", file: "DescribeCell_3_1.swift") { + @Image(source: "DescribeCell_3_3", alt: "Focus outlines the button with the price.") + } + } - > Tip: The solution here is to **use *the title* as the cell's *label***. + @Step { + For example, **the price button* may be percieved connected to the next title** which is something we really don't want to have. Normally prices are playing a critical role in choice-making. + + @Code(name: "Several Cells, Wrong Rhyme", file: "DescribeCell_3_2.swift") { + @Image(source: "DescribeCell_3_3", alt: "Focus outlines the button with the price.") + } + } - @Image(source: "DescribeCell_4", alt: "Voice Control shows the badge over the button with the price") + @Step { + + Talking about *price buttons*, there are ***Voice Control* and *Switch Control* that prioritise *interactive buttons*** and thus *struggle* with such layout too. As a result of their adapting behaviour **the only label shown will be the price button's *label***. To press the whole cell users would have to, for example, pronounce *"Tap From AED thirty"* — which is a nonsense. + + > Tip: The solution here is to **use *the title* as the cell's *label***. + + @Image(source: "DescribeCell_4", alt: "Voice Control shows the badge over the button with the price") + } } } - } - - @Section(title: "What Can Be Done: Cell's Description") { - @ContentAndMedia { - *VoiceOver's adaption* is all about **telling the user what's happening on the screen**. - - In order to **properly *describe* the cell so VoiceOver can read it correctly** we have to transfer the text from *labels* to the *accessibility description* of the cell in a *correct order* and with a *correct type*. Let's try to do so. - - @Image(source: "DescribeCell_9_preview", alt: "Order in which elements are read is controlled by designers' vision.") - } - @Steps { - @Step { - We will start with a simple cell with an *explicit* `ViewModel`. - - @Code(name: "Cell and VoiceOver.swift", file: "DescribeCell_6.swift") - } - - @Step { - First of all we have to **specify that the cell will be a *focusable element***. By doing that we ***reduce* the number of elements available on the screen**, which is, as you remember from the previous section, really helpful for *adaption*. - - There is no need to *explicitly* hide other elements - setting the cell with `accessibleElements` property is enough. - - To see **how it works *exactly*** take a look at where everything is explained in *greater* detail than we can afford in *tutorials*. + @Section(title: "What Can Be Done: Cell's Description") { + @ContentAndMedia { + *VoiceOver's adaption* is all about **telling the user what's happening on the screen**. - @Comment { - // TODO: why the cell's button is visible at pizza? - } + In order to **properly *describe* the cell so VoiceOver can read it correctly** we have to transfer the text from *labels* to the *accessibility description* of the cell in a *correct order* and with a *correct type*. Let's try to do so. - @Code(name: "Cell and VoiceOver.swift", file: "DescribeCell_7.swift") + @Image(source: "DescribeCell_9_preview", alt: "Order in which elements are read is controlled by designers' vision.") } - @Step { - As mentioned previously **the title** will take place in `accessibilityLabel`. **Ingredients** go to the `accessibilityValue` property. - - @Code(name: "Cell and VoiceOver.swift", file: "DescribeCell_8.swift") - - @Comment { - // TODO: Add Voice Control screenshot + @Steps { + @Step { + We will start with a simple cell with an *explicit* `ViewModel`. + + @Code(name: "Cell and VoiceOver.swift", file: "DescribeCell_6.swift") } - } - - @Step { - - Not to forget there is also *the price* which is **an *essential* part of cells with a *product offer***. - - To adapt it *correctly* we need to follow the strategy controlled by *the cell's design* whose concept is to make users *notice* the product. - - Its **image is what *attracts the attention***, then **title is read and understood *loud and clear*** - it's on top and visually distinguished by a *bolder* font used. - Furtherly the attention may be *interrupted* by a **bright coloured button**. - - **Ingredients are least prior** to the attention and this is in their nature: this elements is of an *informative matter*, therefore not about *attention attraction*. - - Logically **we place the price *after* the title**. Pay attention that **to keep label simple the price has to be put in the beginning of `accesibilityValue`**. + @Step { + First of all we have to **specify that the cell will be a *focusable element***. By doing that we ***reduce* the number of elements available on the screen**, which is, as you remember from the previous section, really helpful for *adaption*. + + There is no need to *explicitly* hide other elements - setting the cell with `accessibleElements` property is enough. + + To see **how it works *exactly*** take a look at where everything is explained in *greater* detail than we can afford in *tutorials*. + + @Comment { + // TODO: why the cell's button is visible at pizza? + } + + @Code(name: "Cell and VoiceOver.swift", file: "DescribeCell_7.swift") + } - @Code(name: "Cell and VoiceOver.swift", file: "DescribeCell_9.swift") { - @Image(source: "DescribeCell_9_preview", alt: "Reading order is controlled by people who want to sell this pizza to you.") + @Step { + As mentioned previously **the title** will take place in `accessibilityLabel`. **Ingredients** go to the `accessibilityValue` property. + + @Code(name: "Cell and VoiceOver.swift", file: "DescribeCell_8.swift") + + @Comment { + // TODO: Add Voice Control screenshot + } } - } - - @Step { - Everything is *described* and VoiceOver is happy, but *most importantly* we shouldn't forget to **mark the interactive element with `.button` trait*. - After that *specifying* we are done and did great! + @Step { + + Not to forget there is also *the price* which is **an *essential* part of cells with a *product offer***. + + To adapt it *correctly* we need to follow the strategy controlled by *the cell's design* whose concept is to make users *notice* the product. + + Its **image is what *attracts the attention***, then **title is read and understood *loud and clear*** - it's on top and visually distinguished by a *bolder* font used. + + Furtherly the attention may be *interrupted* by a **bright coloured button**. + + **Ingredients are least prior** to the attention and this is in their nature: this elements is of an *informative matter*, therefore not about *attention attraction*. + + Logically **we place the price *after* the title**. Pay attention that **to keep label simple the price has to be put in the beginning of `accesibilityValue`**. + + @Code(name: "Cell and VoiceOver.swift", file: "DescribeCell_9.swift") { + @Image(source: "DescribeCell_9_preview", alt: "Reading order is controlled by people who want to sell this pizza to you.") + } + } - @Code(name: "Cell and VoiceOver.swift", file: "DescribeCell_10.swift") + @Step { + Everything is *described* and VoiceOver is happy, but *most importantly* we shouldn't forget to **mark the interactive element with `.button` trait*. + + After that *specifying* we are done and did great! + + @Code(name: "Cell and VoiceOver.swift", file: "DescribeCell_10.swift") + } } } - } - - @Section(title: "What Can Be Done: Ease Scrolling") { - @ContentAndMedia { - In VoiceOver the **default *scrolling* is implemented by a *three-finger swipe***. The gesture will announce where the user currectly is, i.e. VoiceOver will **read the number of the *visible* page**. For example, *«4 out of 20*». - - **Going through *tables* of cells functions *exactly* the same way**. For example, *«from 25 to 40 out of 120»* will be said during going over the rows. - - Seemingly there is not much we can do to **simplify the scrolling**, but in reality technologies win. People who are responsible of these inventions are indeed smart, aren't they? So: - - **Providing *description* for *visible* area allows to use *commands* that increase the *precision* of actions desired to be done**. Like, for example, *asking to read all titles* of the products which would result in hearing *«Chicken BBQ, Meat King Supreme, Hawaii»*. - - @Image(source: "DescribeCell_11", alt: "Describe the screen after a scroll.") - } - @Steps { - @Step { - To **implement *comfortable* user experience** regardless of the fact that the interface is *adapted*, let's start with `MenuViewController` extension. + @Section(title: "What Can Be Done: Ease Scrolling") { + @ContentAndMedia { + In VoiceOver the **default *scrolling* is implemented by a *three-finger swipe***. The gesture will announce where the user currectly is, i.e. VoiceOver will **read the number of the *visible* page**. For example, *"4 out of 20*". - @Code(name: "Describe screen after scroll.swift", file: "DescribeCell_11_0.swift") - } - - @Step { - We will use `UIScrollViewAccessibilityDelegate` to **add *description* that can be used by any `firstResponder`**. + **Going through *tables* of cells functions *exactly* the same way**. For example, *"from 25 to 40 out of 120"* will be said during going over the rows. - @Code(name: "Describe screen after scroll.swift", file: "DescribeCell_11.swift") - } - - @Step { - Which means we will **provide description for *all* visible cells**. Sounds exhausting, but is it so in reality? Let's try and see. + Seemingly there is not much we can do to **simplify the scrolling**, but in reality technologies win. People who are responsible of these inventions are indeed smart, aren't they? So: - @Code(name: "Describe screen after scroll.swift", file: "DescribeCell_12.swift") - } - - @Step { - To start we **convert *cells* to *models***. + **Providing *description* for *visible* area allows to use *commands* that increase the *precision* of actions desired to be done**. Like, for example, *asking to read all titles* of the products which would result in hearing *"Chicken BBQ, Meat King Supreme, Hawaii"*. - @Code(name: "Describe screen after scroll.swift", file: "DescribeCell_13.swift") + @Image(source: "DescribeCell_11", alt: "Describe the screen after a scroll.") } - @Step { - From models **the *titles* can be easily extracted** — we do so. + @Steps { + @Step { + To **implement *comfortable* user experience** regardless of the fact that the interface is *adapted*, let's start with `MenuViewController` extension. + + @Code(name: "Describe screen after scroll.swift", file: "DescribeCell_11_0.swift") + } - @Code(name: "Describe screen after scroll.swift", file: "DescribeCell_14.swift") - } - - @Step { - Once we get the titles we join them in *a single row*, separated by *commas*. + @Step { + We will use `UIScrollViewAccessibilityDelegate` to **add *description* that can be used by any `firstResponder`**. + + @Code(name: "Describe screen after scroll.swift", file: "DescribeCell_11.swift") + } - @Code(name: "Describe screen after scroll.swift", file: "DescribeCell_15.swift") - } - - @Step { - And, as a result, **three-finger swipe will cause the *titles* to be listed outloud**. + @Step { + Which means we will **provide description for *all* visible cells**. Sounds exhausting, but is it so in reality? Let's try and see. + + @Code(name: "Describe screen after scroll.swift", file: "DescribeCell_12.swift") + } - We are happy, VoiceOver is happy, but, most importantly, the user would not have to do anything unnecessary to see what's available on the menu. Congratulations! - - @Comment { - // Additionally you can add some quantity expectation after everything described above is done. - // TODO: михаил рубанов что ты делаешь. что ты хочешь сказать строкой сверху. + @Step { + To start we **convert *cells* to *models***. + + @Code(name: "Describe screen after scroll.swift", file: "DescribeCell_13.swift") } - - @Code(name: "Describe screen after scroll.swift", file: "DescribeCell_16.swift") - @Comment { - // TODO: Add preview + @Step { + From models **the *titles* can be easily extracted** — we do so. + + @Code(name: "Describe screen after scroll.swift", file: "DescribeCell_14.swift") } - } - } - } - - @Assessments { - @MultipleChoice { - Choose the *most* fitting location for a *price* in a cell. - - @Image(source: "Chicken BBQ", alt: "Cell of Chicken BBQ with image, title, ingredients and price") - - @Choice(isCorrect: false) { - ``` - Label: Chicken BBQ, from 30 AED - Value: pizza sauce, mushrooms... - ``` - @Justification(reaction: "Try again!") { - **VoiceOver *doesn't* distinguish such pieces of data**, but **Voice Control *has to have* price as a value element** in order to use it correctly (as a button). + @Step { + Once we get the titles we join them in *a single row*, separated by *commas*. + + @Code(name: "Describe screen after scroll.swift", file: "DescribeCell_15.swift") } - } + + @Step { + And, as a result, **three-finger swipe will cause the *titles* to be listed outloud**. + We are happy, VoiceOver is happy, but, most importantly, the user would not have to do anything unnecessary to see what's available on the menu. Congratulations! + + @Comment { + // Additionally you can add some quantity expectation after everything described above is done. + // TODO: михаил рубанов что ты делаешь. что ты хочешь сказать строкой сверху. + } + + @Code(name: "Describe screen after scroll.swift", file: "DescribeCell_16.swift") - @Choice(isCorrect: true) { - ``` - Label: Chicken BBQ, - Value: from 30 AED, pizza sauce, mushrooms... - ``` - - - @Justification(reaction: "That's right!") { - Voice Control has a *simple label* it wants, VoiceOver reads the price *before* the ingredients just as it should. Good job! + @Comment { + // TODO: Add preview + } } } - - - @Choice(isCorrect: false) { - ``` - Label: Chicken BBQ, - Value: pizza sauce, mushrooms..., from 30 AED - ``` - - @Justification(reaction: "That's right!") { - Almost there, but **such case would be a *wrong* ordered showcase strategy**. One has to know the price *before* the ingredients. Imagine having to listen to an endless list of mushrooms and only then be informed that it doesn't quite fit the budget. - } - } } - @MultipleChoice { - What is **the default gesture for scrolling through a table** with VoiceOver? - - @Choice(isCorrect: false) { - A regular swipe + @Assessments { + @MultipleChoice { + Choose the *most* fitting location for a *price* in a cell. + + @Image(source: "Chicken BBQ", alt: "Cell of Chicken BBQ with image, title, ingredients and price") - @Justification(reaction: "Try again!") { - Nope, ***vertical swipes* are used for *adjustable elements* and other operations**. + @Choice(isCorrect: false) { + ``` + Label: Chicken BBQ, from 30 AED + Value: pizza sauce, mushrooms... + ``` - For example, **swipe from the *bottom* will close the current application**, the one **from the *top* will open Notifications Screen or Control Center**. + @Justification(reaction: "Try again!") { + **VoiceOver *doesn't* distinguish such pieces of data**, but **Voice Control *has to have* price as a value element** in order to use it correctly (as a button). + } } - } - - - @Choice(isCorrect: false) { - Two-fingers swipe - @Justification(reaction: "Try again!") { - **Two-finger swipe *up* describes the entire screen *from the top***. - **Two-finger swipe *down* describes the entire screen *from the selected item***. - } - } + + @Choice(isCorrect: true) { + ``` + Label: Chicken BBQ, + Value: from 30 AED, pizza sauce, mushrooms... + ``` - @Choice(isCorrect: true) { - Three-fingers swipe + @Justification(reaction: "That's right!") { + Voice Control has a *simple label* it wants, VoiceOver reads the price *before* the ingredients just as it should. Good job! + } + } + - @Justification(reaction: "That's right!") { - Yep, this is it! - - If adapted *correctly*, the user will hear what is in the table without unnecessery for the moment information specified. - } + @Choice(isCorrect: false) { + ``` + Label: Chicken BBQ, + Value: pizza sauce, mushrooms..., from 30 AED + ``` + + @Justification(reaction: "That's right!") { + Almost there, but **such case would be a *wrong* ordered showcase strategy**. One has to know the price *before* the ingredients. Imagine having to listen to an endless list of mushrooms and only then be informed that it doesn't quite fit the budget. + } + } } - @Choice(isCorrect: false) { - Four-fingers swipe + @MultipleChoice { + What is **the default gesture for scrolling through a table** with VoiceOver? - @Justification(reaction: "Try again!") { - Unfortunately, this is not the answer. Horizontal **four-fingers swipe switches beetwen applications opened**. - } + @Choice(isCorrect: false) { + A regular swipe + + @Justification(reaction: "Try again!") { + Nope, ***vertical swipes* are used for *adjustable elements* and other operations**. + + For example, **swipe from the *bottom* will close the current application**, the one **from the *top* will open Notifications Screen or Control Center**. + } + } + + + @Choice(isCorrect: false) { + Two-fingers swipe + + @Justification(reaction: "Try again!") { + **Two-finger swipe *up* describes the entire screen *from the top***. + **Two-finger swipe *down* describes the entire screen *from the selected item***. + } + } + + + @Choice(isCorrect: true) { + Three-fingers swipe + + @Justification(reaction: "That's right!") { + Yep, this is it! + + If adapted *correctly*, the user will hear what is in the table without unnecessery for the moment information specified. + } + } + + @Choice(isCorrect: false) { + Four-fingers swipe + + @Justification(reaction: "Try again!") { + Unfortunately, this is not the answer. Horizontal **four-fingers swipe switches beetwen applications opened**. + } + } } } } diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Essentials/3..Navigation/aControlHierarchy.md b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Essentials/3..Navigation/aControlHierarchy.md index 8bd0266..992631a 100644 --- a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Essentials/3..Navigation/aControlHierarchy.md +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/AdaptionTechniques/Essentials/3..Navigation/aControlHierarchy.md @@ -1,81 +1,83 @@ # ControlHierarchy -## Overview - -**Accessibility Features** take description of elements to provide different way of communications. The core part of this process is providing information about hierarchy of elements, what element should be focusable and what should be hidden from focus. - -### View hierarchy vs Accessibility Tree - -Regular screen we can describe like tree of Views with parent-child relation. Example: - -Screen with pizza: -``` -- Image -- Title -- Description container - - Size label - - Size segmented control wrapper - - Small size button - - Medium size button - - Large size button -- Purchase button - - Text inside button -``` - -VoiceOver needs another representation: -``` -- Title -- Size label -- Size segmented control as adjustable element -- Purchase button with text from the inside label -``` - -Voice Control and Switch Control place focus on buttons and tree should be different: -``` -- Small size button -- Medium size button -- Large size button -- Purchase button -``` - -As a result you can control what elements from your layout will be exposed to different technologies for better user experience. - -### Containers, nodes and leaf - -Visual hierarchy is based on child-parent relation and accessibility tree use the same paradigm. You have two main operations to control the tree: -- Hide *branch* of element at all. Use ``Book/accessibilityElementsHidden`` to hide the branch. -- Set element node (leaf or any parent) to be focusable. - -> Important: Setting ``Book/isAccessibilityElement`` to `false` has different meaning according to type of a node: -> - **Leaf of the tree** will be hidden -> - **Node of the tree** will be *not focusable*: hierarchy will be traversed for any focusable leaf, when ``Book/isAccessibilityElement`` is set to `true` to them. If there is no such leaf, entire subtree will be hidden. - -> Note: Some container can have additional name that prefixed first focused element's description. Supports only by VoiceOver, read more at ``AccessibilityContainer/accessibilityContainerType`` with type ``UIAccessibilityContainerType/semanticGroup`` - @Comment { - // TODO: Container can has a label when use .semantic -} + ## Overview -### Focus order -``AccessibilityContainer/accessibilityElements`` + **Accessibility Features** take description of elements to provide different way of communications. The core part of this process is providing information about hierarchy of elements, what element should be focusable and what should be hidden from focus. -@Comment { - // TODO: It should be part of -} + ### View hierarchy vs Accessibility Tree + + Regular screen we can describe like tree of Views with parent-child relation. Example: + + Screen with pizza: + ``` + - Image + - Title + - Description container + - Size label + - Size segmented control wrapper + - Small size button + - Medium size button + - Large size button + - Purchase button + - Text inside button + ``` + + VoiceOver needs another representation: + ``` + - Title + - Size label + - Size segmented control as adjustable element + - Purchase button with text from the inside label + ``` + + Voice Control and Switch Control place focus on buttons and tree should be different: + ``` + - Small size button + - Medium size button + - Large size button + - Purchase button + ``` + + As a result you can control what elements from your layout will be exposed to different technologies for better user experience. -#### Dynamic number of elements -https://github.com/akaDuality/RotorHeaders + ### Containers, nodes and leaf -### Tutorial + Visual hierarchy is based on child-parent relation and accessibility tree use the same paradigm. You have two main operations to control the tree: + - Hide *branch* of element at all. Use ``Book/accessibilityElementsHidden`` to hide the branch. + - Set element node (leaf or any parent) to be focusable. -Read for example + > Important: Setting ``Book/isAccessibilityElement`` to `false` has different meaning according to type of a node: + > - **Leaf of the tree** will be hidden + > - **Node of the tree** will be *not focusable*: hierarchy will be traversed for any focusable leaf, when ``Book/isAccessibilityElement`` is set to `true` to them. If there is no such leaf, entire subtree will be hidden. + > Note: Some container can have additional name that prefixed first focused element's description. Supports only by VoiceOver, read more at ``AccessibilityContainer/accessibilityContainerType`` with type ``UIAccessibilityContainerType/semanticGroup`` + @Comment { + // TODO: Container can has a label when use .semantic + } -## Topics + ### Focus order + ``AccessibilityContainer/accessibilityElements`` -- ``Book/isAccessibilityElement`` -- ``Book/accessibilityElementsHidden`` -- ``Book/accessibilityViewIsModal`` -- ``Book/shouldGroupAccessibilityChildren`` -- ``AccessibilityContainer`` + @Comment { + // TODO: It should be part of + } + + #### Dynamic number of elements + https://github.com/akaDuality/RotorHeaders + + ### Tutorial + + Read for example + + + + ## Topics + + - ``Book/isAccessibilityElement`` + - ``Book/accessibilityElementsHidden`` + - ``Book/accessibilityViewIsModal`` + - ``Book/shouldGroupAccessibilityChildren`` + - ``AccessibilityContainer`` +} diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/iOSAccessibilityHandbook.md b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/iOSAccessibilityHandbook.md index 24a7ea0..8fae2c5 100644 --- a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/iOSAccessibilityHandbook.md +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/iOSAccessibilityHandbook.md @@ -48,7 +48,7 @@ At the moment the project's form is defined by being a *documentation catalog* ( To contribute to the project visit its [GitHub page](https://github.com/VODGroup/AccessibilityDocumentation) and see the instruction of how one may help. ### Contributors -The resources are provided by **Mikhail Rubanov**, Head of Mobile Development at [Dodo Brands](https://dodobrands.io), accesisibility activist and the author of [«About Accesibility on iOS»]( https://rubanov.dev/a11y-book) book. Examplary and illustrative materials are based on his *working experience*. +The resources are provided by **Mikhail Rubanov**, Head of Mobile Development at [Dodo Brands](https://dodobrands.io), accesisibility activist and the author of ["About Accesibility on iOS"]( https://rubanov.dev/a11y-book) book. Examplary and illustrative materials are based on his *working experience*. @Image(source: "aboutAccessibility-sample", alt: "-") ### VoiceOver Designer