layout-check
Skill: layout-check
On load: Read ../../.claude-plugin/plugin.json from this skill's base directory. Display layout-check v{version} before proceeding.
Verify visual layout against React Native's official Flexbox and style documentation.
Dependencies
| Skill / Resource | Why |
|---|---|
ios-sim |
capture.sh view captures the simulator screenshot; ui.sh describe-all provides element positions from the accessibility tree |
_shared (metro.sh, cdp-bridge.js) |
Optional Step 1.5 — reads computed style values from the React fiber tree via CDP when Metro is running |
Workflow
Step 1 — Capture and Analyze (subagent)
Dispatch a subagent to capture the screen and analyze layout. Never load screenshots or accessibility trees in main context.
Dispatch Agent:
subagent_type: general-purpose
model: haiku
description: "layout-check: capture and analyze layout"
prompt: |
You are analyzing an iOS Simulator screen for React Native layout issues.
1. Run: ${CLAUDE_SKILL_DIR}/../ios-sim/scripts/capture.sh view
Read the output file path to see the screenshot.
2. Run: ${CLAUDE_SKILL_DIR}/../ios-sim/scripts/ui.sh describe-all
Parse the full accessibility tree JSON.
If this fails (e.g., "AXe is not installed" error), skip the accessibility tree
and proceed with screenshot-only analysis. Note in your report that element
positions are estimated from visual inspection, not the accessibility tree.
3. Analyze and return a structured report:
ELEMENT POSITIONS:
- List each visible element with its frame (x, y, width, height)
- Note parent-child nesting where relevant
SPACING ANALYSIS:
- Gaps between sibling elements
- Padding/margin indicators (distance from element edge to content)
- Alignment within rows/columns
POTENTIAL ISSUES:
- Elements clipped or extending beyond parent bounds (overflow)
- Unexpected sizing (zero-width, zero-height, stretched beyond screen)
- Misaligned elements that should share an axis
- Overlapping elements that likely should not overlap
- Text truncation or elements pushed off-screen
Return text only. Be concise but precise with coordinates.
USER CONCERN: [insert user's layout question here]
Step 1.5 — Computed Styles (optional)
If Metro/Hermes debugger is available, extract actual computed style values from the React fiber tree to compare against visual observations.
Guard: Run ${CLAUDE_SKILL_DIR}/../_shared/scripts/metro.sh status. If exit code is 1 (Metro not running), skip silently to Step 2.
If Metro is running:
Run ${CLAUDE_SKILL_DIR}/../_shared/scripts/cdp-bridge.js eval with an inline JS expression that:
- Accesses
__REACT_DEVTOOLS_GLOBAL_HOOK__ - Iterates
hook.renderersto find all registered renderer IDs, then callshook.getFiberRoots(id)for each (do NOT hardcode renderer ID 1 — it varies with new architecture) - Walks the fiber tree starting from
root.current - For each fiber node:
- Gets the component name (
type.displayNameortype.name) - Reads
memoizedProps.style - Filters to target props only:
flexDirection,justifyContent,alignItems,flex,alignSelf,flexWrap,backgroundColor,borderWidth,borderColor,borderRadius - Skips nodes with no style props or empty filtered result
- Gets the component name (
- Returns array of
{name, styles}objects - Limits output by only including components with non-empty filtered styles
Save the output as "computed styles" for use in Step 2.
The expression handles both resolved style objects and StyleSheet numeric IDs (fiber stores resolved values in dev mode). Output is compact (~1-3 KB) so it stays in main context (no subagent needed).
Step 2 — Search docs for relevant properties
In the main context, grep the docs for layout properties related to the subagent's findings. If computed styles are available from Step 1.5, compare visual observations against actual flex/style values to confirm or refine the diagnosis.
Docs path: ${CLAUDE_SKILL_DIR}/../../refs/react-native-docs/
Key files to check:
- flexbox.md — flex, flexDirection, justifyContent, alignItems, flexWrap
- style.md — style composition, transforms
- layout-props.md — position, overflow, zIndex, aspect ratio, insets
- dimensions.md — window vs screen, onLayout
Use Grep against the docs directory to find specific property docs relevant to the reported issue.
Step 3 — Diagnose and recommend
Match the subagent findings against documentation to identify root cause. Return:
- Visual assessment — what the subagent observed
- Suspected issue — the layout property or combination causing the problem
- Fix — concrete code change with cited Flexbox/style property from docs
Context Efficiency
| Item | Size | Location |
|---|---|---|
| Screenshot JPEG | ~100-300 KB | Subagent only |
| Accessibility tree JSON | ~10-100 KB | Subagent only |
| Subagent layout summary | ~500-1500 chars | Main context |
| Computed styles JSON | ~1-3 KB | Main context |
| Doc snippets from Grep | ~200-800 chars | Main context |
Common Layout Issues Reference
| Symptom | Likely Cause | Key Property | Doc File |
|---|---|---|---|
| Children overflow container | Missing overflow: 'hidden' or unbounded flex |
overflow, flex |
layout-props.md, flexbox.md |
| Items won't wrap to next line | flexWrap defaults to 'nowrap' |
flexWrap: 'wrap' |
flexbox.md |
| Item ignores width/height | Flex basis or flex overriding explicit size | flex, flexBasis |
flexbox.md |
| Absolute element mispositioned | Wrong position: 'absolute' anchor or missing parent size |
position, top/left/right/bottom |
layout-props.md |
| Element has zero size | No children, no explicit dimensions, flex: 0 |
width, height, flex |
layout-props.md, dimensions.md |
| Uneven spacing between items | Using margins vs gap; wrong justifyContent |
gap, justifyContent |
flexbox.md |
| Text truncated unexpectedly | Container has fixed width without flexShrink |
flexShrink, numberOfLines |
flexbox.md |
| Items not centering | Wrong axis — justifyContent vs alignItems |
justifyContent, alignItems |
flexbox.md |
Tips
- RN defaults:
flexDirection: 'column',alignItems: 'stretch',position: 'relative'— different from CSS defaults. flex: 1in RN is shorthand forflexGrow: 1, flexShrink: 1, flexBasis: 0— not the same as CSSflex: 1.overflowdefaults to'hidden'on Android,'visible'on iOS.- Percentage dimensions require the parent to have a defined size in that axis.