This report is our own app, published unedited — verify the bundle digest yourself. It was
measured on 16 August 2026. The crawl has changed since: it no longer attempts to pass
through a system permission sheet, so the engine running today reaches fewer screens on this
same build. A re-audit with the current engine is in progress and will replace this report.
SuppLab on the App Store, and
how to check the digest: download the build, run
readyaudit-package verify over it, and compare the hash with the one printed above.
This report previously carried a line reading “This report is what two independent audits of that artifact agreed on.”
That line was wrong. A defect in our convergence mechanism let one audit's measurement be read twice instead of two audits being performed. The run directory was keyed on part of the audit id rather than all of it, so the second complete audit inherited the first one's directory, could not start its test runner at all, and read the first one's accessibility dumps as its own.The claim was withdrawn from the document the same day it was found, the mechanism now requires each run to name the dumps it read, and a re-audit is in progress. Found 2026-08-25. Every report this engine produced with a convergence block. It affected 4 of
our reports. Every number below was measured
3 times per condition, which is unaffected — see
the method.
20
findings at 84.2% coverage20 findings, at 84.2% coverage
No category median on this report. That row appears once a category
has at least 20 completed audits, and the projection
always excludes the audit being reported — otherwise the first
customer in a category would be shown their own result as the bar.
While the readiness score is in shadow (Karar 81) this row does not
appear at all: a median is a score belonging to other apps, and we do
not put a number in front of a customer that we decline to print for
the app in front of us.
ExposureNot legal advice
1 unresolved critical findings map to obligations under:
WCAG 1.4.4
EN 11.1.4.4
Scope was not declared for this audit, so no EU penalty range is shown as a figure for this app. Whether the Act reaches it turns on two facts nobody has stated: a service in an Article 2(2) sector sold to EU consumers, from a company above the microenterprise threshold.
If both hold, the maxima reported by member states are Germany €100,000 (per non-compliant product); France €50,000 (plus repeat / additional obligations); Italy up to 5% of turnover (proportionate to revenue).
United States · ADA$25k–$75k+reported per-suit settlement range
Reported figures, subject to national implementation and change. This is a technical readiness perspective, not legal advice — confirm exposure with counsel.
Coverage
Every active rule, on every screen the crawl reached, with the result.
Published beside the finding count on purpose — one number is what we
found, the other is how much of the target we actually reached.
84.2%
Checks
499
Pass
257
Fail
53
Not applicable
110
Not testable
79
Rules active
21 / 74
Coverage matrix: 21 rules by 18 screens, each cell a verdict.
Rule
Onboarding step
Onboarding step 2
Onboarding step 3
Your Baseline
Permission prompt
Today
Settings
Library
Stack
Analytics
Paywall
Omega-3 (Fish Oil)
Log Supplement
Compact phone screen
Scenario T1 · Onboarding
Scenario T2 · Core navigation
Scenario T3 · Sign-in
Scenario T4 · Conversion
AP-LBL-001Interactive element has no accessibility labelWCAG 4.1.2 AEN 11.4.1.2
✓ Pass
✓ Pass
✕ Fail
✓ Pass
✓ Pass
✓ Pass
✕ Fail
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
? Not testable
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
AP-LBL-002Decorative image exposed to assistive technologyWCAG 1.1.1 AEN 11.1.1.1
✓ Pass
✓ Pass
✓ Pass
✓ Pass
— Not applicable
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
? Not testable
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
AP-LBL-004Visible label text is not contained in the accessibility nameWCAG 2.5.3 AEN 11.2.5.3
? Not testable
? Not testable
? Not testable
? Not testable
? Not testable
✓ Pass
✓ Pass
✓ Pass
? Not testable
— Not applicable
✓ Pass
? Not testable
? Not testable
? Not testable
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
AP-LBL-005Accessibility label repeats the element's rolenot scored
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
? Not testable
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
AP-LBL-006Link or button purpose is not determinable from its nameWCAG 2.4.4 AEN 11.2.4.4
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
? Not testable
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
AP-STA-001Interactive element exposes no role or traitWCAG 4.1.2 AEN 11.4.1.2
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
? Not testable
? Not testable
? Not testable
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
AP-STA-004Disabled control does not expose its disabled stateWCAG 4.1.2 AEN 11.4.1.2
? Not testable
? Not testable
? Not testable
? Not testable
? Not testable
? Not testable
? Not testable
? Not testable
? Not testable
? Not testable
? Not testable
? Not testable
? Not testable
? Not testable
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
AP-STA-005Adjustable control exposes no value or adjustment actionsWCAG 4.1.2 AEN 11.4.1.2
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
✕ Fail
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
? Not testable
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
AP-STR-002Accessibility reading order does not match the meaningful sequenceWCAG 1.3.2 AEN 11.1.3.2
✕ Fail
✕ Fail
✕ Fail
✓ Pass
✓ Pass
✓ Pass
✕ Fail
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✕ Fail
✕ Fail
? Not testable
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
AP-STR-007Screen exposes no accessibility elements at allWCAG 1.3.1 AEN 11.1.3.1
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
? Not testable
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
AP-DYN-001Content clipped or truncated at large Dynamic TypeWCAG 1.4.4 AAEN 11.1.4.4
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
? Not testable
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
AP-TGT-001Touch target smaller than 44ptWCAG 2.5.8 AA
✓ Pass
✕ Fail
✕ Fail
✕ Fail
✓ Pass
✕ Fail
✕ Fail
✕ Fail
✕ Fail
✓ Pass
✕ Fail
✓ Pass
✕ Fail
? Not testable
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
AP-TGT-006Adjacent targets overlap or sit inside each other's spacing allowanceWCAG 2.5.8 AA
— Not applicable
✓ Pass
✓ Pass
✓ Pass
— Not applicable
✓ Pass
✕ Fail
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
✓ Pass
? Not testable
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
AP-FRM-001Input field has no label or instructionWCAG 3.3.2 AEN 11.3.3.2
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
— Not applicable
✕ Fail
✓ Pass
— Not applicable
— Not applicable
— Not applicable
— Not applicable
✓ Pass
? Not testable
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
AP-TRP-002Task cannot be completed with VoiceOvervoiceover
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
✓ Pass
· Not evaluated
· Not evaluated
· Not evaluated
AP-TRP-001Interaction trap: element cannot be dismissed or escaped with assistive techWCAG 2.1.2 AEN 11.2.1.2voiceover
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
✓ Pass
✓ Pass
· Not evaluated
✓ Pass
AP-NAV-001Repeated navigation is not in a consistent orderWCAG 3.2.3 AAEN 11.3.2.3voiceover
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
✓ Pass
· Not evaluated
· Not evaluated
AP-NAV-002The same function is identified differently on different screensWCAG 3.2.4 AAEN 11.3.2.4voiceover
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
✓ Pass
· Not evaluated
· Not evaluated
AP-FRM-006Previously entered information must be entered againWCAG 3.3.7 Avoiceover
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
— Not applicable
· Not evaluated
AP-FRM-007Authentication requires a cognitive function test with no alternativeWCAG 3.3.8 AAvoiceover
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
— Not applicable
· Not evaluated
AP-FRM-008Irreversible action has no confirmation, reversal or reviewWCAG 3.3.4 AAEN 11.3.3.4voiceover
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
· Not evaluated
✓ Pass
✓ Pass — evaluated, threshold met
✕ Fail — evaluated, threshold missed; see findings
— Not applicable — the rule's condition was not present
? Not testable — we could not reach it; this is the only verdict that lowers coverage
The four tasks, one at a time
Each task is a different walk through the app, not one crawl counted
four times. Reached says whether the walk got to the thing the
task promises: a first-run-only flow, a second screen, a surface behind
sign-in, the last step before a purchase. A task that did not get there
says so — and says what it did establish instead.
Rows is how many checks in the table above were measured
during that walk, so a task cannot claim it was reached without
evidence that says the same.
Per-task coverage: runs completed, surfaces recorded,
check rows measured, and whether the task was
reached.
Task
Runs
Surfaces
Rows
Reached
T2Crawl
15 / 24
13
479
Yes
This flow requires a system permission sheet; the automated crawl does not pass through it — the recorded device pass covers it.
These runs are not part of the coverage percentage above. Coverage is
arithmetic over the check rows; a second denominator mixed into it would
make checking less the cheapest way to score higher.
What we could not reach, and what opens it
These rows are subtracted from coverage rather than quietly dropped: a
report that hides the screens it never opened is worth less than one
that names them. A named gap with no way past it is still no use — the
reader cannot tell a locked door from an engine that opens none — so
each one below carries the thing that removes it. The counts are
recounted from the matrix above, not asserted here.
The controls on this surface paint their own text and iOS publishes no field carrying it, so the name cannot be compared against what is drawn on the control. Re-running cannot change this; a human pass on a physical device answers it.
No element on this surface was proven interactive by a tap, and XCUITest publishes no handler list, so a missing control trait cannot be distinguished from a plain label. Re-running cannot change this; a human pass on a physical device answers it.
XCUITest derives isEnabled from the notEnabled trait rather than from the view, so the announcement cannot be checked against the state it is meant to describe. Re-running cannot change this; a human pass on a physical device answers it.
Nothing to send — this row is answered by the human verification pass
The screen was reached, captured and measured; the rule needs a property that iOS does not publish to an automated test at all. XCUITest reports no isAccessibilityElement of its own, its isEnabled is read back from the notEnabled trait rather than from the view, and text a control paints on itself never appears in the tree. Checking those against themselves would manufacture a pass on every app ever built, so the row stays open and goes to a person with the app in their hand and a screen reader running. The criterion still applies to your build — this says which pass answers it, not that nobody will.
Outside automated instrument reach; covered by human verification on physical device. No re-run is offered for this cause, because no re-run could move it: the field is absent from every dump of every app, so sending the build again would return the identical blank.
This audit ran on a machine with no compact phone simulator installed, so the layout of this app at that screen size was not measured — it was not measured on a different screen and labelled as this one. Installing the missing simulator and re-running closes this at no cost to you.
Invite audits@readyaudit.dev as a TestFlight tester
iOS Simulator does not run VoiceOver and cannot be network-throttled by simctl, so these variants have no honest reading here. A TestFlight invite is one click — no UDID registration, no provisioning profile, no re-signing — and the same checks are measured on real hardware with a screen reader actually running.
No extra charge: the device pass is part of the human-verification step already included in the audit.
Every action above needs the build again, except the one that asks for nothing because no second run could change its answer. For the rest: we hold your build for the retention window published in the privacy policy, so a re-measure asked for inside that window has nothing to re-send — send the audit id and the item above from the contact box in the app. Once the window has passed, submit the build again from the app, which is the only channel that carries one. The run is treated as a re-measure of this report rather than a new audit: the blocked checks are re-read and the coverage figure reissued. Never e-mail a build — a message can carry the id, not the bundle.
What a pass asserts, rule by rule
A pass is a bounded claim, not a clean bill of health. Each line below is
the exact assertion the tick marks in that row make — and nothing wider.
AP-LBL-001 · Interactive element has no accessibility label
Every interactive element in this surface's accessibility tree carries a non-empty name. It does not assert the names are good ones — see AP-LBL-006.
Onboarding step 1/1 interactive elements named
Onboarding step 2 2/2 interactive elements named
Your Baseline 3/3 interactive elements named
Permission prompt 1/1 interactive elements named
Today 8/8 interactive elements named
Library 15/15 interactive elements named
Stack 7/7 interactive elements named
Analytics 6/6 interactive elements named
Paywall 3/3 interactive elements named
Omega-3 (Fish Oil) 7/7 interactive elements named
Log Supplement 24/24 interactive elements named
AP-LBL-002 · Decorative image exposed to assistive technology
No image judged decorative is announced by the screen reader on this surface.
Onboarding step 1/1 exposed images named
Onboarding step 2 5/5 exposed images named
Onboarding step 3 2/2 exposed images named
Your Baseline 1/1 exposed images named
Today 9/9 exposed images named
Settings 10/10 exposed images named
Library 11/11 exposed images named
Stack 6/6 exposed images named
Analytics 6/6 exposed images named
Paywall 8/8 exposed images named
Omega-3 (Fish Oil) 11/11 exposed images named
Log Supplement 1/1 exposed images named
AP-LBL-004 · Visible label text is not contained in the accessibility name
Every control on this surface can be activated by Voice Control using the words a sighted user can read on it.
Today 1/1 controls match their visible text
Settings 2/2 controls match their visible text
Library 4/4 controls match their visible text
Paywall 2/2 controls match their visible text
AP-LBL-005 · Accessibility label repeats the element's role
No label on this surface duplicates the role the trait already announces.
Onboarding step 1/1 labels free of a repeated role
Onboarding step 2 2/2 labels free of a repeated role
Onboarding step 3 2/2 labels free of a repeated role
Your Baseline 3/3 labels free of a repeated role
Permission prompt 1/1 labels free of a repeated role
Today 8/8 labels free of a repeated role
Settings 11/11 labels free of a repeated role
Library 15/15 labels free of a repeated role
Stack 7/7 labels free of a repeated role
Analytics 6/6 labels free of a repeated role
Paywall 3/3 labels free of a repeated role
Omega-3 (Fish Oil) 7/7 labels free of a repeated role
Log Supplement 24/24 labels free of a repeated role
AP-LBL-006 · Link or button purpose is not determinable from its name
No control on this surface is named with a word that carries no destination or outcome.
AP-STA-001 · Interactive element exposes no role or trait
Every tappable element on this surface tells the screen reader what kind of control it is.
Onboarding step 1/1 tappable elements expose a role
Onboarding step 2 1/1 tappable elements expose a role
Onboarding step 3 1/1 tappable elements expose a role
Your Baseline 1/1 tappable elements expose a role
Permission prompt 1/1 tappable elements expose a role
Today 1/1 tappable elements expose a role
Settings 2/2 tappable elements expose a role
Library 1/1 tappable elements expose a role
Stack 1/1 tappable elements expose a role
Analytics 2/2 tappable elements expose a role
Paywall 1/1 tappable elements expose a role
AP-STR-002 · Accessibility reading order does not match the meaningful sequence
Swiping through this surface reads it in the order it is laid out.
Your Baseline 8/8 elements in visual reading order · passed in 3 of 3 attempts
Permission prompt 3/3 elements in visual reading order · passed in 2 of 2 attempts
Today 14/14 elements in visual reading order · passed in 2 of 2 attempts
Library 16/16 elements in visual reading order · passed in 2 of 2 attempts
Stack 11/11 elements in visual reading order · passed in 2 of 2 attempts
Analytics 16/16 elements in visual reading order · passed in 2 of 2 attempts
Paywall 21/21 elements in visual reading order · passed in 2 of 2 attempts
AP-STR-007 · Screen exposes no accessibility elements at all
A screen reader reaches at least one element on this surface instead of finding nothing to announce.
Onboarding step 7 elements reachable by a screen reader · passed in 3 of 3 attempts
Onboarding step 2 16 elements reachable by a screen reader · passed in 3 of 3 attempts
Onboarding step 3 10 elements reachable by a screen reader · passed in 3 of 3 attempts
Your Baseline 8 elements reachable by a screen reader · passed in 3 of 3 attempts
Permission prompt 3 elements reachable by a screen reader · passed in 2 of 2 attempts
Today 14 elements reachable by a screen reader · passed in 2 of 2 attempts
Settings 25 elements reachable by a screen reader · passed in 2 of 2 attempts
Library 17 elements reachable by a screen reader · passed in 2 of 2 attempts
Stack 11 elements reachable by a screen reader · passed in 2 of 2 attempts
Analytics 16 elements reachable by a screen reader · passed in 2 of 2 attempts
Paywall 21 elements reachable by a screen reader · passed in 2 of 2 attempts
Omega-3 (Fish Oil) 32 elements reachable by a screen reader · passed in 2 of 2 attempts
Log Supplement 47 elements reachable by a screen reader · passed in 2 of 2 attempts
AP-TGT-001 · Touch target smaller than 44pt
Every interactive frame measured on this surface is at least 44×44pt. Measured from the accessibility tree, not from the drawn glyph — the tappable area is what matters, and the two are often different.
Onboarding step smallest target 52pt · required 44pt · 1 measured · passed in 3 of 3 attempts
Permission prompt smallest target 48pt · required 44pt · 1 measured · passed in 2 of 2 attempts
Analytics smallest target 52pt · required 44pt · 6 measured · passed in 2 of 2 attempts
Omega-3 (Fish Oil) smallest target 44pt · required 44pt · 7 measured · passed in 2 of 2 attempts
AP-TGT-006 · Adjacent targets overlap or sit inside each other's spacing allowance
No two targets on this surface are close enough that the spacing exception in SC 2.5.8 is breached.
Onboarding step 2 closest pair 56.2px apart · required 24px · passed in 3 of 3 attempts
Onboarding step 3 closest pair 56.2px apart · required 24px · passed in 3 of 3 attempts
Your Baseline closest pair 225px apart · required 24px · passed in 3 of 3 attempts
Today closest pair 28.3px apart · required 24px · passed in 2 of 2 attempts
Library closest pair 68.1px apart · required 24px · passed in 2 of 2 attempts
Stack closest pair 68.1px apart · required 24px · passed in 2 of 2 attempts
Analytics closest pair 68.1px apart · required 24px · passed in 2 of 2 attempts
Paywall closest pair 129.3px apart · required 24px · passed in 2 of 2 attempts
Omega-3 (Fish Oil) closest pair 68.1px apart · required 24px · passed in 2 of 2 attempts
Log Supplement closest pair 66.5px apart · required 24px · passed in 2 of 2 attempts
AP-FRM-001 · Input field has no label or instruction
Every input on this surface has a label that survives once the user starts typing.
AP-TRP-002 · Task cannot be completed with VoiceOver
The task named in the check row was completed end to end with VoiceOver on. This is the only rule in the catalog that measures an outcome rather than a property.
Scenario T1 · Onboarding The task was completed end to end with VoiceOver on · passed in 1 of 1 attempts
AP-TRP-001 · Interaction trap: element cannot be dismissed or escaped with assistive tech
Every overlay reached on this surface was exited using only assistive technology, within the step budget stated in the check row.
Scenario T1 · Onboarding Every screen this scenario reached could be dismissed or left with VoiceOver · passed in 1 of 1 attempts
Scenario T2 · Core navigation Every screen this scenario reached could be dismissed or left with VoiceOver · passed in 1 of 1 attempts
Scenario T4 · Conversion Every screen this scenario reached could be dismissed or left with VoiceOver · passed in 1 of 1 attempts
AP-NAV-001 · Repeated navigation is not in a consistent order
The shared navigation was in the same order everywhere the crawl saw it.
Scenario T2 · Core navigation Repeated navigation appeared in the same order on every screen this scenario reached · passed in 1 of 1 attempts
AP-NAV-002 · The same function is identified differently on different screens
No function seen twice in the crawl was called two different things.
Scenario T2 · Core navigation The same function was named the same way on every screen this scenario reached · passed in 1 of 1 attempts
AP-FRM-008 · Irreversible action has no confirmation, reversal or review
Every destructive or committing action on this surface could be undone, reviewed or confirmed first.
Scenario T4 · Conversion The irreversible action offered a confirmation or a way back · passed in 1 of 1 attempts
Rule catalog v2.5.0 · 21 of 74 rules active in this engine release
· 53 defined but not yet evaluated, and therefore not counted above
20 findings
Sorted critical first · catalog v2.5.0
AP-DYN-001CRITICALCritical severity
1 control is drawn off the screen at the largest text size
Raised from majorAt the largest accessibility text size this control is drawn past the end of a screen that does not scroll, so there is no gesture that reaches it: the function it performs is unavailable to the people this text size exists for.
Screenshot from the audited build, unedited. SuppLab is our own app — see the build digest above to check the artifact this frame came out of.
bottom_pt
1046.3
clipped
4
elements
'Get Started'
fixed_elements
7
screen_height_pt
874
Reproduced in 3 of 3 attempts
Seen on 1 of 1 recorded states of this screen
Suggested fix
Put this screen's content in a ScrollView, so that what does not fit at the largest text size can still be reached. Fixed-height layouts sized for the default text size lose their bottom rows at the accessibility sizes.
ScrollView {
VStack(spacing: 24) { … }
.frame(maxWidth: .infinity)
.padding()
}
// and stop pinning heights that the text has to fit inside
AP-LBL-001MAJORMajor severity
1 interactive element has no accessibility label
Settings
unnamed date picker at 300,583
dark
iPhone 17 Pro (simulator)
T2 · Crawl
Evidence
dark · Settingsruns/bd1bf437/t2/dark/iphone-17-pro/r1/step-09.png
Screenshot from the audited build, unedited. SuppLab is our own app — see the build digest above to check the artifact this frame came out of.
elements
'unnamed date picker at 300,583'
interactive_elements
12
unnamed
1
Reproduced in 2 of 2 attempts
Seen on 2 of 2 recorded states of this screen
Suggested fix
Give each control a name that says what it does. VoiceOver announces the trait already, so the label is the verb, not the widget.
Screenshot from the audited build, unedited. SuppLab is our own app — see the build digest above to check the artifact this frame came out of.
drawn_at_position
1
element
Step 1 of 3
elements
7
out_of_order
1
reached_at_position
7
Reproduced in 3 of 3 attempts
Seen on 4 of 4 recorded states of this screen
Suggested fix
Swiping reaches 'Step 1 of 3' at position 7 of 7, and the screen draws it at position 1. 1 element is out of place on this surface. Reorder the views, or state the order explicitly, so swiping follows the way the screen reads.
// Example pattern — adapt it to the view that draws this element.
container
.accessibilityElement(children: .contain)
.accessibilitySortPriority(1)
AP-STR-002MAJORMajor severity
Accessibility order does not match the layout order
Screenshot from the audited build, unedited. SuppLab is our own app — see the build digest above to check the artifact this frame came out of.
drawn_at_position
1
element
Step 2 of 3
elements
16
out_of_order
1
reached_at_position
16
Reproduced in 3 of 3 attempts
Seen on 6 of 6 recorded states of this screen
Suggested fix
Swiping reaches 'Step 2 of 3' at position 16 of 16, and the screen draws it at position 1. 1 element is out of place on this surface. Reorder the views, or state the order explicitly, so swiping follows the way the screen reads.
// Example pattern — adapt it to the view that draws this element.
container
.accessibilityElement(children: .contain)
.accessibilitySortPriority(1)
AP-STR-002MAJORMajor severity
Accessibility order does not match the layout order
Screenshot from the audited build, unedited. SuppLab is our own app — see the build digest above to check the artifact this frame came out of.
drawn_at_position
1
element
Step 3 of 3
elements
10
out_of_order
3
reached_at_position
10
Reproduced in 3 of 3 attempts
Seen on 5 of 5 recorded states of this screen
Suggested fix
Swiping reaches 'Step 3 of 3' at position 10 of 10, and the screen draws it at position 1. 3 elements are out of place on this surface. Reorder the views, or state the order explicitly, so swiping follows the way the screen reads.
// Example pattern — adapt it to the view that draws this element.
container
.accessibilityElement(children: .contain)
.accessibilitySortPriority(1)
AP-STR-002MAJORMajor severity
Accessibility order does not match the layout order
Settings
Terms of Use
dark
iPhone 17 Pro (simulator)
T2 · Crawl
Evidence
dark · Settingsruns/bd1bf437/t2/dark/iphone-17-pro/r1/step-09.png
Screenshot from the audited build, unedited. SuppLab is our own app — see the build digest above to check the artifact this frame came out of.
drawn_at_position
22
element
Terms of Use
elements
25
out_of_order
4
reached_at_position
17
Reproduced in 2 of 2 attempts
Seen on 2 of 2 recorded states of this screen
Suggested fix
Swiping reaches 'Terms of Use' at position 17 of 25, and the screen draws it at position 22. 4 elements are out of place on this surface. Reorder the views, or state the order explicitly, so swiping follows the way the screen reads.
// Example pattern — adapt it to the view that draws this element.
container
.accessibilityElement(children: .contain)
.accessibilitySortPriority(1)
AP-STR-002MAJORMajor severity
Accessibility order does not match the layout order
Omega-3 (Fish Oil)
lock.fill
dark
iPhone 17 Pro (simulator)
T2 · Crawl
Evidence
dark · Omega-3 (Fish Oil)runs/bd1bf437/t2/dark/iphone-17-pro/r1/step-17.png
Screenshot from the audited build, unedited. SuppLab is our own app — see the build digest above to check the artifact this frame came out of.
background_layers_excluded
1
drawn_at_position
24
element
lock.fill
elements
31
out_of_order
2
reached_at_position
26
Reproduced in 2 of 2 attempts
Seen on 2 of 2 recorded states of this screen
Suggested fix
Swiping reaches 'lock.fill' at position 26 of 31, and the screen draws it at position 24. 2 elements are out of place on this surface. Reorder the views, or state the order explicitly, so swiping follows the way the screen reads.
// A decorative image has no place in the sequence at all:
Image("hero")
.accessibilityHidden(true)
AP-STR-002MAJORMajor severity
Accessibility order does not match the layout order
Log Supplement
Search supplements
dark
iPhone 17 Pro (simulator)
T2 · Crawl
Evidence
dark · Log Supplementruns/bd1bf437/t2/dark/iphone-17-pro/r1/step-18.png
Screenshot from the audited build, unedited. SuppLab is our own app — see the build digest above to check the artifact this frame came out of.
drawn_at_position
43
element
Search supplements
elements
47
out_of_order
12
reached_at_position
47
Reproduced in 2 of 2 attempts
Seen on 2 of 2 recorded states of this screen
Suggested fix
Swiping reaches 'Search supplements' at position 47 of 47, and the screen draws it at position 43. 12 elements are out of place on this surface. Reorder the views, or state the order explicitly, so swiping follows the way the screen reads.
// Example pattern — adapt it to the view that draws this element.
container
.accessibilityElement(children: .contain)
.accessibilitySortPriority(1)
AP-FRM-001MAJORMajor severity
1 input field has no persistent label
Settings
unnamed date picker at 300,583
dark
iPhone 17 Pro (simulator)
T2 · Crawl
Evidence
dark · Settingsruns/bd1bf437/t2/dark/iphone-17-pro/r1/step-09.png
Screenshot from the audited build, unedited. SuppLab is our own app — see the build digest above to check the artifact this frame came out of.
elements
'unnamed date picker at 300,583'
inputs
1
placeholder_only
0
without_label
1
Reproduced in 2 of 2 attempts
Seen on 2 of 2 recorded states of this screen
Suggested fix
Attach a label that survives typing. A placeholder vanishes at the first keystroke, taking the only description of the field with it.
// The placeholder disappears as soon as a date is chosen.
DatePicker("Start date", selection: $startDate, displayedComponents: .date)
AP-STA-005MINORMinor severity
1 adjustable control exposes no value or adjustment action
Settings
unnamed date picker at 300,583
dark
iPhone 17 Pro (simulator)
T2 · Crawl
Evidence
dark · Settingsruns/bd1bf437/t2/dark/iphone-17-pro/r1/step-09.png
Screenshot from the audited build, unedited. SuppLab is our own app — see the build digest above to check the artifact this frame came out of.
adjustable_controls
1
elements
'unnamed date picker at 300,583'
incomplete
1
Reproduced in 2 of 2 attempts
Seen on 2 of 2 recorded states of this screen
Suggested fix
Publish the current value and the adjustable trait, so the rotor can read the control and change it with a swipe.
dark · Settingsruns/bd1bf437/t2/dark/iphone-17-pro/r1/step-09.png
Screenshot from the audited build, unedited. SuppLab is our own app — see the build digest above to check the artifact this frame came out of.
elements
'unnamed date picker at 300,583' / 'Time Picker' 0px apart; 'Terms of Use' / 'books.vertical.fill' 19px apart; 'Privacy Policy' / 'chart.bar.xaxis' 20px apart
min_center_distance_px
0
pairs_below_threshold
3
required_center_distance_px
24
Reproduced in 2 of 2 attempts
Seen on 2 of 2 recorded states of this screen
Suggested fix
Space adjacent targets at least 24px centre to centre, or enlarge them. Targets this close are mistapped by anyone whose hands are not steady.
// Example pattern — adapt it to the view that draws this element.
HStack(spacing: 16) {
first.frame(width: 44, height: 44)
second.frame(width: 44, height: 44)
}