From xonovex-skill-android-wcag
Use when making Android Jetpack Compose UI accessible or meeting WCAG 2.2 AA — labelling for TalkBack, focus / reading order, headings, state and live-region announcements, color contrast, text scaling, touch-target size, and accessibility testing. Triggers on contentDescription, semantics / clearAndSetSemantics / mergeDescendants, traversalIndex / isTraversalGroup / heading(), stateDescription / liveRegion / announceForAccessibility, Role, CustomAccessibilityAction, TalkBack, screen reader, contrast, font scaling, tap target, or @Composable accessibility tests — even when the user doesn't say "WCAG" or "accessibility".
How this skill is triggered — by the user, by Claude, or both
Slash command
/xonovex-skill-android-wcag:android-wcag-guideThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Platform-level accessibility for Jetpack Compose: the `androidx.compose.ui.semantics` APIs and the AA criteria they satisfy. Framework-agnostic — a design system layered on top may bake some of this in, but the techniques here are the platform baseline.
Platform-level accessibility for Jetpack Compose: the androidx.compose.ui.semantics APIs and the AA criteria they satisfy. Framework-agnostic — a design system layered on top may bake some of this in, but the techniques here are the platform baseline.
When this skill fires:
stringResource, never a literal.references/*.md file matching the question, not everything upfront.contentDescription; decorative ones get null, see references/labelling.mdtraversalIndex, isTraversalGroup, heading(), collection semantics, see references/focus-order.mdstateDescription, liveRegion, announceForAccessibility, CustomAccessibilityAction, onClickLabel, see references/state-and-announcements.mdsp text that honors fontScale, ≥48dp targets via minimumInteractiveComponentSize, see references/text-and-targets.mdcontentDescription is a localized user-facing string — source it from stringResource, never a literal. testTag is a separate dev-facing concern; never reuse one as the other.semantics(mergeDescendants = true) { } with no contentDescription collapses children into raw concatenated order and drops the intended label — always set the consolidated description.contentDescription has an accumulating merge policy: setting it on a mergeDescendants parent does not replace children, it appends to whatever the children already expose (badge counts, labelled icons). When children carry their own descriptions, use clearAndSetSemantics { } to get one clean label instead of a doubled-up one.graphicsLayer { alpha = 0f } (or any fade) hides a node visually but leaves it in the accessibility tree, so TalkBack still reads it — common cause of a collapsing header announcing its title twice. Gate the hidden copy with Modifier.semantics { hideFromAccessibility() } (older Compose: invisibleToUser()).liveRegion and a contentDescription makes TalkBack read it twice — pick one.clickable { } on a Row/Box/Card exposes no role by default, so TalkBack does not announce it as actionable — pass clickable(role = Role.Button) { } (or set role in semantics). Without onClickLabel it also announces only a generic "double tap to activate" — name the action verb.heading() is not implied by text size or font weight — set it explicitly on screen titles and section headers, or heading navigation finds nothing.heading() is for content sections only; tabs already carry Role.Tab. Conversely, in a list of cards, mark each item a heading so users skim with the heading gesture instead of swiping every card and its button.val recap = stringResource(R.string.event_recap, eventTitle, date) // localized, prebuilt
val newLabel = stringResource(R.string.badge_new)
Row(
modifier = Modifier
.clickable(onClickLabel = stringResource(R.string.action_open_event)) { onOpen() }
.clearAndSetSemantics { // replace children: announce as ONE node
role = Role.Button
contentDescription = recap
if (isNew) stateDescription = newLabel
},
) {
Icon(painterResource(R.drawable.ic_calendar), contentDescription = null) // decorative
Column {
Text(text = eventTitle)
Text(text = date, style = MaterialTheme.typography.bodySmall)
}
}
Each reference is a trigger — read it only when the user's intent matches; do not preload everything.
contentDescription, deciding decorative vs meaningful, or consolidating a composite control with clearAndSetSemantics / mergeDescendants (WCAG 1.1.1, 4.1.2).Guides collaborative design exploration before implementation: explores context, asks clarifying questions, proposes approaches, and writes a design doc for user approval.
Creates structured, bite-sized implementation plans from specs or requirements before writing code. Useful for breaking down multi-step tasks into testable steps with file structure and task boundaries.
Resolves in-progress git merge or rebase conflicts by analyzing history, understanding intent, and preserving both changes where possible. Runs automated checks after resolution.
npx claudepluginhub xonovex/platform --plugin xonovex-skill-android-wcag