Comprehensive accessibility pass across PHP, iOS, and Android#4
Merged
Conversation
…roid PHP API: - New HasA11y trait (a11yLabel/a11yHint via Element::setProp) adopted by every element — kills the copy-pasted per-element methods and gives the 9 elements that had no a11y support (Icon, ListItem, Radio, Carousel, ListSection, NativeList, NativeVirtualList, NativeDrawer, Tab) the full API. Tab gains the fluent methods it was missing. - ListItem: trailing_a11y_label prop labels the trailing icon_button. - Boost guidelines rewritten with real accessibility guidance; README Accessibility section; Pest coverage for a11y serialization. iOS renderers: - Dynamic Type everywhere: @ScaledMetric-backed nuiScaledFont() replaces every fixed .font(.system(size:)) — text now tracks the user's preferred content size. - 44pt minimum touch targets (nuiMinTapTarget) on checkbox, radio, chip, tabs, modal close, list icon buttons, top-bar/back/hamburger buttons, clickable icons. - VoiceOver: checkbox .isToggle (iOS 17) + Checked/Unchecked value, chip selected value, select current-option value, button loading announced, Back/Open menu/bottom-nav labels + .isSelected, list rows combined into one focus stop, skeleton rows hidden, modal .isModal trait, text-input label/error exposure, carousel + gesture-area label plumbing. - Icons decorative-by-default (hidden without a11y_label; labeled and .isButton when clickable). Image renderer honors new alt prop. - Reduce Motion respected in drawer animations and screen transitions. Android renderers: - stateDescription misuse fixed: a11y_hint no longer clobbers the state channel; shared Modifier.nuiA11y merges label+hint into contentDescription. Only remaining stateDescription use is the legitimate one (button loading). - Toggle/Checkbox/Radio rows use toggleable/selectable with proper Roles: one merged TalkBack focus stop, label taps activate the control, radio double tap-target removed. - Roles + labels on hand-rolled clickables (icons, top-bar back/actions, bottom-nav tabs with selected state), 48dp targets on the same. - Icons stop announcing machine names; image renderer honors alt; activity indicator announces Loading politely. - Dark-mode-hostile hardcoded grays/white replaced with theme tokens. Theme: default secondary/destructive/accent tokens (config + Swift fallbacks) now meet WCAG AA 4.5:1 against their white on-colors — visible change: accent #FB923C -> #C2410C, destructive #DC2626 -> #B91C1C, secondary #64748B -> #475569. Wire contract additions: alt (image), trailing_a11y_label (list_item). Pairs with mobile-air 57079e9 (Image element alt prop). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The trait now lives on the base Edge Element (mobile-air 8797c71), so every element inherits a11yLabel()/a11yHint()/applyA11yAttributes() without per-element adoption — the plugin-local trait and its 24 use statements are gone. The applyAttributes() hydration calls stay for paths that bypass the collector's central attr pass. Wire output is unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…derer Companion comment for 2913a0c — records WHY the non-lazy chunked grid exists (Compose lazy grids throw under infinite max-height constraints where SwiftUI's LazyVGrid sizes to content). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…bset) Auto-fetched from Google's metadata endpoint; verified against the previous font-extracted set: 112 stale names removed, ZERO added — every remaining name still renders with the bundled ligature font. Re-added the provenance caution to _meta: web refreshes are only safe as a subset of the font's ligature names unless the bundled font upgrades in the same change. Apps regenerate enums via native-ui:generate-icons; removed names surface as compile errors at their call sites (the intended failure mode). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds phpunit.xml and a GitHub Actions tests workflow, and ignores the .phpunit.cache/ directory. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
nativephp/mobile pulls in endroid/qr-code ^6.1.3, which requires PHP ^8.4, so the dependency chain could not resolve on 8.3. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A comprehensive accessibility pass across the native-ui element library and both native renderers, plus supporting test/CI scaffolding.
HasA11ytrait wired through the element library (Button, Checkbox, Radio, Slider, Toggle, Select, Chip, ListItem, TabRow, ProgressBar, and more), so every interactive element can carry accessibility labels/roles/state.HasA11yitself lives innativephp/mobilecore.contentDescription/Modifier.semanticsacross the renderer set (Button, Checkbox, Radio, Slider, Toggle, List/ListItem, Nav, Icon, …).A11yTestsuite,phpunit.xml, and a GitHub Actions tests workflow.Test plan
A11yTestcovers the PHP-side accessibility API surface.🤖 Generated with Claude Code