From d70a7930b5e74199eaf0c548154e1223474a2caf Mon Sep 17 00:00:00 2001 From: "C." Date: Sun, 3 Mar 2024 13:03:58 +0300 Subject: [PATCH] traits --- .../AccessibilityAttributes.tutorial} | 0 .../Frame/Frame.tutorial | 29 + .../Traits/Code/SwiftUI/addTraits.swift | 13 + .../Code/SwiftUI/allowsDirectTouch.swift | 14 + .../Traits/Code/SwiftUI/budgetSlider.swift | 12 + .../Traits/Code/SwiftUI/isToggle.swift | 13 + .../Traits/Code/UIKit/directTouch.swift | 15 + .../Traits/Code/UIKit/hiddenTraits.swift | 29 + .../Traits/Code/UIKit/optionSet.swift | 8 + .../Traits/Code/UIKit/toggleButton.swift | 15 + .../Traits/Traits.tutorial | 542 ++++++++++++++++++ .../Adaption/Basic/Describe/Traits.tutorial | 515 ----------------- 12 files changed, 690 insertions(+), 515 deletions(-) rename Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/{DescribeInterface.tutorial => AccessibilityAttributes/AccessibilityAttributes.tutorial} (100%) create mode 100644 Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Frame/Frame.tutorial create mode 100644 Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/addTraits.swift create mode 100644 Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/allowsDirectTouch.swift create mode 100644 Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/budgetSlider.swift create mode 100644 Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/isToggle.swift create mode 100644 Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/directTouch.swift create mode 100644 Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/hiddenTraits.swift create mode 100644 Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/optionSet.swift create mode 100644 Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/toggleButton.swift create mode 100644 Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Traits.tutorial delete mode 100644 Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/Traits.tutorial diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/DescribeInterface.tutorial b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/AccessibilityAttributes.tutorial similarity index 100% rename from Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/DescribeInterface.tutorial rename to Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/AccessibilityAttributes.tutorial diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Frame/Frame.tutorial b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Frame/Frame.tutorial new file mode 100644 index 0000000..a6db784 --- /dev/null +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Frame/Frame.tutorial @@ -0,0 +1,29 @@ +@Tutorial(time: <#number#>) { + @Intro(title: "<#text#>") { + <#text#> + + @Image(source: <#file#>, alt: "<#accessible description#>") + } + + @Section(title: "<#text#>") { + @ContentAndMedia { + <#text#> + + @Image(source: <#file#>, alt: "<#accessible description#>") + } + + @Steps { + @Step { + <#text#> + + @Image(source: <#file#>, alt: "<#accessible description#>") + } + + @Step { + <#text#> + + @Code(name: "<#display name#>", file: <#filename.swift#>) + } + } + } +} diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/addTraits.swift b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/addTraits.swift new file mode 100644 index 0000000..8391c63 --- /dev/null +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/addTraits.swift @@ -0,0 +1,13 @@ +struct ContentView: View { + var body: some View { + VStack { + Text("WWDC 2021") + .accessibilityAddTraits(.isHeader) + + Text("SwiftUI Accessibility") + Text("Beyond the Basics") + + Image(systemName: "checkmark.seal.fill") + } + } +} diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/allowsDirectTouch.swift b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/allowsDirectTouch.swift new file mode 100644 index 0000000..444779e --- /dev/null +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/allowsDirectTouch.swift @@ -0,0 +1,14 @@ +import SwiftUI + +struct KeyboardKeyView: View { + var soundFile: String + var body: some View { + Rectangle() + .fill(.white) + .frame(width: 35, height: 80) + .onTapGesture(count: 1) { + playSound(sound: soundFile, type: "mp3") + } + .accessibilityDirectTouch(options: .silentOnTouch) + } +} diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/budgetSlider.swift b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/budgetSlider.swift new file mode 100644 index 0000000..d309ff5 --- /dev/null +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/budgetSlider.swift @@ -0,0 +1,12 @@ +import SwiftUI + +var body: some View { + VStack { + SliderTrack(...) // Custom slider implementation. + } + .accessibilityRepresentation { + Slider(value: $value, in: 0...100) { + Text("Label") + } + } +} diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/isToggle.swift b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/isToggle.swift new file mode 100644 index 0000000..b2a67ac --- /dev/null +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/SwiftUI/isToggle.swift @@ -0,0 +1,13 @@ +import SwiftUI + +struct FilterButton: View { + @State var filter: Bool = false + + var body: some View { + Button(action: { filter.toggle() }) { + Text("Filter") + } + .background(filter ? darkGreen : lightGreen) + .accessibilityAddTraits(.isToggle) + } +} diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/directTouch.swift b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/directTouch.swift new file mode 100644 index 0000000..6caf754 --- /dev/null +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/directTouch.swift @@ -0,0 +1,15 @@ +import UIKit + +class ViewController: UIViewController { + let waveformButton = UIButton(type: .custom) + + override func viewDidLoad() { + super.viewDidLoad() + + waveformButton.accessibilityTraits = .allowsDirectInteraction + waveformButton.accessibilityDirectTouchOptions = .silentOnTouch + waveformButton.addTarget(self, action: #selector(playTone), for: .touchUpInside) + + view.addSubview(waveformButton) + } +} diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/hiddenTraits.swift b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/hiddenTraits.swift new file mode 100644 index 0000000..c9d7dc8 --- /dev/null +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/hiddenTraits.swift @@ -0,0 +1,29 @@ +import UIKit + +private func getHiddenTrait( + forIndex index: UInt64) -> UIAccessibilityTraits { + let traitRaw: UInt64 = 1 << index + return UIAccessibilityTraits( + rawValue: traitRaw) +} + +let hiddenTraits = [ + 19: "pickeritem", + 20: "radio button", + 23: "status bar item", + 25: "inactive", + 26: "footer", + 28: "tab", + 32: "visited", + 35: "tap and hold, then move up and down to select index", + 38: "draggable", + 39: "learning", + 40: "pop-up button", + 42: "maths", + 45: "hide from focus", + 50: "folder", + 52: "menu item", + 53: "double tap to toggle settings", + 59: "video playback", + 60: "icon", +] diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/optionSet.swift b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/optionSet.swift new file mode 100644 index 0000000..e077ede --- /dev/null +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/optionSet.swift @@ -0,0 +1,8 @@ +// +// optionSet.swift +// +// +// Created by admin on 03.03.2024. +// + +import Foundation diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/toggleButton.swift b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/toggleButton.swift new file mode 100644 index 0000000..617d35b --- /dev/null +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Code/UIKit/toggleButton.swift @@ -0,0 +1,15 @@ +import UIKit + +class ViewController: UIViewController { + override func viewDidLoad() { + super.viewDidLoad() + + let filterButton = UIButton(type: .custom) + + setupButtonView() + + filterButton.accessibilityTraits = [.toggleButton] + + view.addSubview(filterButton) + } +} diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Traits.tutorial b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Traits.tutorial new file mode 100644 index 0000000..b403b21 --- /dev/null +++ b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/AccessibilityAttributes/Traits/Traits.tutorial @@ -0,0 +1,542 @@ +@Tutorial(time: 15) { + + @Comment { + https://developer.apple.com/documentation/swiftui/accessibilitytraits swiftui cyka + } + + @Intro(title: "All Traits Explained") { + In tutorial we learnt how to provide everything needed about an element to assistive technology but we didn't go into details on traits. + + Overall there are 18 traits + + @Video(source: traits-scroll) + } + + @Section(title: "Setting Traits") { + @ContentAndMedia { + + The default value for this property is none unless the element is a UIKit control, in which case, the value is the standard set of traits for the control. + If you implement a custom control or view, you need to select all the accessibility traits that best characterize the object, and combine them with its superclass’s traits (that is, with super.accessibilityTraits) by performing an OR operation. See Accessibility Traits for a complete list of traits. + + } + + @Steps { + @Step { + jepa + + + @Code(name: "isToggle", file: addTraits.swift) + } + + @Step { + jepa + + + @Code(name: "toggleButton", file: optionSet.swift) + } + } + } + + @Section(title: "Interactive Elements Traits") { + @ContentAndMedia { + The elements of user interface that can be activated are called interactive. Interactive elements trigger different events but regardlessly of their role it is our responsibility to make sure that both the user and assistive technology know that the element has a functionality. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + VoiceOver example + + @Image(source: placeholder-image, alt: "") + } + + @Step { + Voice Control example + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Button") { + @ContentAndMedia { + Button trait adds the word "button" to the spoken description so the user knows that the element is, well, a button. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .button + + @Image(source: placeholder-image, alt: "") + } + + @Step { + isButton + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Toggle Button") { + @ContentAndMedia { + Toggle Button trait is used for buttons that behave like toggles. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .toggleButton + + @Code(name: "UIKit Toggle Button", file: toggleButton.swift) + } + + @Step { + isToggle + + @Code(name: "SwiftUI Toggle Button", file: isToggle.swift) + } + } + } + + @Section(title: "Adjustable") { + @ContentAndMedia { + Adjustable element is a setter that allows to increment and decrement a value by vertical swipes (up and down accordingly). + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .adjustable + + @Image(source: placeholder-image, alt: "") + } + + @Step { + Sliders in SwiftUi support vertical swipes by default. + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Link") { + @ContentAndMedia { + A link is a button that contains an URL. Pressing such button will either open a browser or an appropriate app. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .link + + @Image(source: placeholder-image, alt: "") + } + + @Step { + isLink + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Search Field") { + @ContentAndMedia { + Search Field trait points that the element is a search field. Stating this trait allows navigating to the element by default rotor (or Tab key on a external keyboard). + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .searchField + + @Image(source: placeholder-image, alt: "") + } + + @Step { + isSearchField + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Keyboard Key") { + @ContentAndMedia { + Keyboard Key is a button that has no "button" word in its description. The word is omitted to speed up the usage of the interface. Used for keys representation, such as any keyboard keys displayed on the screen. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .keyboardKey + + @Image(source: placeholder-image, alt: "") + } + + @Step { + isKeyboardKey + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Tab") { + @ContentAndMedia { + Tab is a... tab in a collection of tabs. Adds "Tab, X out of Y" to the description where X is the number of the focused tab and Y is how many tabs there are. The element which represent the collection of tabs is a tab bar. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + + .tab and .tabBar + @Image(source: placeholder-image, alt: "") + } + + @Step { + Tab items in SwiftUI are recognised correctly by default. + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Selected") { + @ContentAndMedia { + Selected trait shows that the focused element is chosen, i.e. in a selected state. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .selected + + @Image(source: placeholder-image, alt: "") + } + + @Step { + isSelected + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Not Enabled") { + @ContentAndMedia { + Not Enabled trait adds "Not Enabled" to the description. Perceive this trait as a fact that tells the user that the element doesn't respond to interaction. + + >Important: + Don't use this trait to hide the element from Accessibility Features - because it doesn't. Use isAccessibilityElement = false instead. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .notEnabled + + @Image(source: placeholder-image, alt: "") + } + + @Step { + Has to be put in Value. + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Allows Direct Interaction") { + @ContentAndMedia { + An element that is said to allow direct interaction requires Direct Touch to be used. For example, such element is typically found in application that have drawing or signing mechanics implemented. Adds "Use Rotor to enable Direct Touch for this application" instruction to the element's description. + https://developer.apple.com/wwdc23/10036?time=480 + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .allowsDirectInteraction + + @Image(source: placeholder-image, alt: "") + } + + @Step { + allowsDirectInteraction + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Plays Sound") { + @ContentAndMedia { + Plays Sounds trait should be stated for the elements that produce sounds when activated so VoiceOver will be muted for the duration of the sound. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .playsSound + + @Image(source: placeholder-image, alt: "") + } + + @Step { + playsSound + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Starts Media Session") { + @ContentAndMedia { + An element that starts media session according to its traits causes VoiceOver to be muted until the end of the session. So the screen reader doesn't interrupt any media playing or recording. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .startsMediaSession + + @Image(source: placeholder-image, alt: "") + } + + @Step { + startsMediaSession + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Causes Page Turn") { + @ContentAndMedia { + Causes Page Turn trait triggers an automatic page turn when VoiceOver finishes reading the content of the element with this trait stated. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .causesPageTurn + + @Image(source: placeholder-image, alt: "") + } + + @Step { + causesPageTurn + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Modal") { + @ContentAndMedia { + Modal element in SwiftUI has to be marked explicitly so non-modal elements are ignored when a modal view is visible. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .isModal + + @Image(source: placeholder-image, alt: "") + } + } + } + + + @Section(title: "Static Elements Traits") { + @ContentAndMedia { + jepa + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + jepa + + @Image(source: placeholder-image, alt: "") + } + + @Step { + jepa + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Static Text") { + @ContentAndMedia { + Static Text element is an element that is just a text and has possible interactions. Use it to explicitly state that the item cannot be activated and is purely decorative. Moreover, setting this trait tells that there is no need to check on the element afterwards: it won't change. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .staticText + + @Image(source: placeholder-image, alt: "") + } + + @Step { + isStaticText + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Header") { + @ContentAndMedia { + Header trait should be applied to elements that are essentially dividers, so the user knows that the content is divided into sections. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .header + + @Image(source: placeholder-image, alt: "") + } + + @Step { + isHeader + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Summary Element") { + @ContentAndMedia { + Summary Element trait is a curious one. There can be only one summary element on the screen and its description is spoken every time the application is opened, even from a collapsed state. It is a great option to implement notifying users about the state of something important: for example, if you have a delivery application reading the summary item will tell the current status of their order. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .summaryElement + + @Image(source: placeholder-image, alt: "") + } + + @Step { + isSummaryElement + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Updates Frequently") { + @ContentAndMedia { + An element that updates frequently if focused causes VoiceOver to read its description each time it updates. So if you have, for example, a timer app and you really don't want the user to hear VoiceOver speaking each second aloud use Updated Frequently trait - it limits VoiceOver to once-in-5-seconds check-ups. + + In cases of application that are purposed to monitor updates, good to be paired with the previous trait, Summary Element. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .updatesFrequently + + @Image(source: placeholder-image, alt: "") + } + + @Step { + updatesFrequently + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Image") { + @ContentAndMedia { + Image trait should be stated when you want to tell the user that there is an image. Users won't hear a thing about images without this trait stated because they are hidden from VoiceOver by default. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + .image + + @Image(source: placeholder-image, alt: "") + } + + @Step { + isImage + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Section(title: "Hidden Traits") { + @ContentAndMedia { + It is known that there are UIAccessibilityTraits not mentioned in UIKit documentation, but they are present in the code. + + @Image(source: placeholder-image, alt: "") + } + + @Steps { + @Step { + jep + + @Image(source: placeholder-image, alt: "") + } + + @Step { + jep + + @Image(source: placeholder-image, alt: "") + } + } + } + + @Resources { + Explore more resources for learning about sloths. + + + @Videos(destination: "https://www.example.com/sloth-videos/") { + Watch cute videos of sloths climbing, eating, and sleeping. + + + - [Treetop Breakfast](https://www.example.com/sloth-videos/breakfast/) + - [Slow Ascent](https://www.example.com/sloth-videos/climb/) + - [Rest Time](https://www.example.com/sloth-videos/snoozing/) + } + + + @Downloads(destination: "https://www.example.com/images/sloth-wallpaper/") { + Download the cutest sloth wallpaper for your iPhone, iPad, or Mac. + } + } +} diff --git a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/Traits.tutorial b/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/Traits.tutorial deleted file mode 100644 index 811eb0f..0000000 --- a/Sources/iOSAccessibilityHandbook/iOSAccessibilityHandbook.docc/Pages/Adaption/Basic/Describe/Traits.tutorial +++ /dev/null @@ -1,515 +0,0 @@ -@Tutorial(time: 15) { - - @Comment { - https://developer.apple.com/documentation/swiftui/accessibilitytraits swiftui cyka - } - - @Intro(title: "All Traits Explained") { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Section(title: "Setting Traits") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Interactive Elements Traits") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Button") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Adjustable") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Link") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Search Field") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Keyboard Key") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Tab") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Selected") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Not Enabled") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Allows Direct Interaction") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Plays Sound") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Starts Media Session") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Causes Page Turn") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Adjustable") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Static Elements Traits") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Static Text") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Header") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Summary Element") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Updates Frequently") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Image") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Section(title: "Hidden Traits") { - @ContentAndMedia { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Steps { - @Step { - <#text#> - - @Image(source: <#file#>, alt: "<#accessible description#>") - } - - @Step { - <#text#> - - @Code(name: "<#display name#>", file: <#filename.swift#>) - } - } - } - - @Resources { - Explore more resources for learning about sloths. - - - @Videos(destination: "https://www.example.com/sloth-videos/") { - Watch cute videos of sloths climbing, eating, and sleeping. - - - - [Treetop Breakfast](https://www.example.com/sloth-videos/breakfast/) - - [Slow Ascent](https://www.example.com/sloth-videos/climb/) - - [Rest Time](https://www.example.com/sloth-videos/snoozing/) - } - - - @Downloads(destination: "https://www.example.com/images/sloth-wallpaper/") { - Download the cutest sloth wallpaper for your iPhone, iPad, or Mac. - } - } -}