Skip to content

Accessibility improvements#194

Draft
robmadole wants to merge 1 commit into1.xfrom
004-accessibility-support
Draft

Accessibility improvements#194
robmadole wants to merge 1 commit into1.xfrom
004-accessibility-support

Conversation

@robmadole
Copy link
Member

No description provided.

@robmadole
Copy link
Member Author

@claude please review this PR

@claude
Copy link

claude bot commented Feb 12, 2026

Claude finished @robmadole's task in 1m 40s —— View job


Code Review Complete

I've reviewed the accessibility improvements PR. Overall, this is a well-designed implementation with excellent test coverage. Below are my findings:


Summary

This PR successfully implements accessibility support and prop passthrough for FontAwesomeIcon, addressing requirements from the spec. The implementation allows:

  • All React Native accessibility props to be passed to the root SVG element
  • Arbitrary props (like nativeID, pointerEvents) to flow through
  • Full backward compatibility with existing usage

Key changes:

  • FontAwesomeIcon.tsx: Added restProps spread and SvgProps type integration
  • converter.ts: Added extraProps parameter to merge user-provided props
  • Tests: Added 10 new test cases covering accessibility and prop passthrough

Strengths

  1. Excellent type safety: The Props type correctly uses Omit<SvgProps, ...> to exclude conflicting props (width, height, color) while allowing all other SvgProps through
  2. Proper precedence: FontAwesome-specific props correctly take precedence over passthrough props (line 69 in converter.ts: { ...extraProps, ...mixins.attrs })
  3. Comprehensive test coverage: 10 new tests verify accessibility props, prop passthrough, and backward compatibility
  4. Backward compatibility: testID continues to work, existing usage unaffected (verified by test T016, T018)
  5. Clean implementation: Minimal changes to achieve the feature

Issues Found

1. Type Safety Issue: testID removed from interface but still used (Medium severity)

In src/FontAwesomeIcon.tsx:43, testID was removed from FontAwesomeIconOwnProps:

-  testID?: string;

However, testID is a standard prop from SvgProps, so it will still work through passthrough. But this creates a subtle issue:

Problem: testID is no longer listed in the Omit<> clause, which means:

  • If a user passes both testID (from SvgProps) and it happens to conflict with FA's internal handling, there's ambiguity
  • TypeScript users lose the explicit testID in autocomplete for FontAwesomeIcon props

Recommendation:
Since testID is used in examples and tests (line 669 in test file), and it's a common prop developers expect, consider explicitly keeping it in the type definition even though it passes through:

interface FontAwesomeIconOwnProps {
  icon: IconProp;
  // ... other props
  testID?: string;  // Explicitly support testID for discoverability
}

This ensures testID remains a first-class citizen in the API.

2. Converter extraProps applied to children comment is misleading (Low severity)

In src/converter.ts:34, the comment states:

// extraProps only apply to root element, not children
return convert(createElement, child);

Issue: This is correct behavior, but the comment placement suggests defensiveness against a problem that can't happen. The recursive call to convert() doesn't pass extraProps, so children will never receive them anyway.

Recommendation: Either remove the comment (the code is self-explanatory) or make it more informative:

// Recursively convert children without extraProps (only root element receives them)
return convert(createElement, child);

3. Missing TypeScript strict null checking consideration (Low severity)

In src/converter.ts:66-69:

const finalProps = extraProps
  ? { ...extraProps, ...mixins.attrs }
  : mixins.attrs;

Observation: With strict TypeScript enabled (as per CLAUDE.md), extraProps?: Record<string, unknown> means it can be undefined. The ternary check extraProps ? ... : ... treats empty objects {} as truthy, which is fine, but consider if extraProps could ever be an empty object that should be optimized away.

Recommendation: Current implementation is correct, but you could make it more explicit:

const finalProps = extraProps && Object.keys(extraProps).length > 0
  ? { ...extraProps, ...mixins.attrs }
  : mixins.attrs;

However, this is likely premature optimization. Current code is fine.

4. Test coverage gap: Multiple accessibility props simultaneously (Low severity)

The tests cover individual accessibility props well (T007-T021), but there's no test for combining multiple accessibility props at once, like:

<FontAwesomeIcon
  icon={faCoffee}
  accessibilityLabel="Delete"
  accessibilityRole="button"
  accessibilityHint="Removes item"
  accessibilityState={{ selected: true }}
  nativeID="my-icon"
/>

Recommendation: Add one comprehensive test (T022) that verifies multiple props work together without conflicts.


Questions/Clarifications

  1. ARIA props filtering: In converter.ts:52-56, ARIA props (aria-*) are explicitly deleted from the abstract element attributes. Is this intentional? The spec (FR-011) says ARIA props MUST be supported.

    Looking at the code flow:

    • User passes aria-hidden={true} via restProps
    • It goes into extraProps in converter
    • Gets merged into finalProps (line 69)
    • BUT FontAwesome abstract elements might have their own aria-* attributes that get deleted (line 52-56)

    Clarification needed: Are you intentionally filtering out FA's own ARIA attributes to prevent conflicts with user-provided ones? If so, this is correct. If not, you might want to preserve FA's ARIA attributes and let user props override them.

  2. Precedence behavior documentation: The spec says "passthrough props MUST NOT override explicitly defined FontAwesomeIcon props" (FR-013). The implementation correctly puts mixins.attrs after extraProps in the spread. However, is this behavior documented anywhere user-facing (README, docs)? Users might try to "override" FA props and be confused when it doesn't work.


Recommendations Summary

Must Fix:

  • None (implementation meets spec requirements)

Should Consider:

  1. Restore testID to FontAwesomeIconOwnProps for API discoverability
  2. Add test for multiple accessibility props used together

Nice to Have:

  1. Clarify converter comment about extraProps and children
  2. Document prop precedence behavior in user-facing docs

Conclusion

This is a solid implementation that successfully delivers the accessibility requirements with good type safety and backward compatibility. The issues found are minor and mostly about refinement rather than correctness. The test coverage is excellent.

Approval recommendation: ✅ Approve with minor suggestions for improvement


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant