npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gauravsinghss/rn-a11y-check

v1.0.3

Published

React Native Accessibility Code Validation & Duplication Checker CLI

Readme

React Native Accessibility Code Validation & Duplication Checker (rn-a11y-check)

A standalone TypeScript CLI tool and AST-based validation engine for React Native codebases.


Objective & Philosophy

When implementing accessibility in large enterprise applications, accessibility work must follow a strict principle:

Accessibility work should primarily add the required accessibility properties and helpers without unnecessarily altering existing business logic, UI layout, styling, architecture, or behavior.

rn-a11y-check automatically inspects your React Native codebase and Git changes to detect:

  1. Duplicate accessibility properties on JSX elements.
  2. Conflicting accessibility implementations (e.g. accessibilityElementsHidden combined with accessible).
  3. Duplicate accessibility values across equivalent properties.
  4. Duplicate accessibility logic and helper functions across components.
  5. Unauthorized modifications to existing non-accessibility code in Git pull requests / branches.
  6. Violations of project-configured accessibility rules.

🔒 Read-Only Safety Guarantee

rn-a11y-check is 100% read-only against your application code.

  • It never modifies .ts, .tsx, .js, or .jsx files.
  • It never executes automatic fixes, reformatting, Prettier, or ESLint fixes.
  • It never changes Git state, commits, stashes, or resets code.
  • It only reads files, parses ASTs, analyzes Git diffs, and reports findings.

Installation & Setup

# Clone or navigate to the project
cd rn-a11y-check

# Install dependencies
npm install

# Build the TypeScript project
npm run build

# Run tests
npm test

To run directly via CLI:

# Using npm script
npm run a11y-check

# Using npx (when linked or installed in a project)
npx rn-a11y-check

CLI Usage

1. Scan Entire Project

Scans all configured files in the current repository:

npx rn-a11y-check

2. Scan a Specific Directory or File

npx rn-a11y-check ./src/components
npx rn-a11y-check ./src/screens/AccountScreen.tsx

3. Git Diff Mode

Validates changes in your current branch against a base branch (e.g. origin/develop or main):

npx rn-a11y-check --diff origin/develop

In Diff mode, the tool:

  • Inspects git diff <base>...HEAD.
  • Verifies that all added/modified lines in JSX elements or statements are configured accessibility properties or helpers.
  • Flags any modifications or deletions of existing business logic, styles, or non-accessibility props (Rule A11Y005).
  • Runs AST accessibility rules on the modified files.

4. Baseline Mode

Generates .a11y-baseline.json recording the current accessibility state:

npx rn-a11y-check --baseline

The baseline records:

  • Files containing accessibility implementations
  • Configured accessibility properties used
  • Component counts

Privacy Guarantee: The baseline contains no sensitive application data (no proprietary strings, no mock data, no secrets). It is deterministic and designed to be committed to Git.

5. Custom Configuration File

Specify a custom path to a configuration file:

npx rn-a11y-check --config ./custom-rn-a11y.config.json

6. Output Formats

Human-readable terminal output (default):

npx rn-a11y-check --format text

Machine-readable JSON output for CI pipelines or tooling:

npx rn-a11y-check --format json

7. Interactive HTML Dashboard Report (index.html)

Every time rn-a11y-check completes, it automatically generates a modern, self-contained HTML dashboard report at ./a11y-report/index.html (and prints the full file path in the terminal):

# Generated automatically on every run
npx rn-a11y-check

# Customize the HTML report output path
npx rn-a11y-check --html-path ./custom-reports/index.html

# Disable HTML report generation if desired
npx rn-a11y-check --no-html

Dashboard Features:

  • 📊 Overview Stats: Total files scanned, total issues, errors, warnings, and overall status.
  • 🟡 Yellow Warning Cards: Prominently highlights accessibility warnings in yellow with exact filepath (path:line:col), copyable file path, rule badges, and suggestions.
  • 🔴 Red Error Cards: Highlights errors in bold red with filepath, rule badges, code diffs (+ / -), and remediation suggestions.
  • 🔍 Interactive Filters: Instant filtering by severity (All, Errors Only, Warnings Only), rule selection dropdown, and live text search across filepaths, rules, messages, and properties.
  • 🔒 100% Offline: Embedded CSS and JavaScript with zero external CDN dependencies.

Exit Codes

rn-a11y-check uses standard CI-friendly exit codes:

| Exit Code | Meaning | | :--- | :--- | | 0 | PASS — All checks passed without errors. | | 1 | FAIL — Validation errors detected (e.g. A11Y001, A11Y005, or rules configured as error). | | 2 | TOOL ERROR — Configuration error or file not found. |

Note: Rules configured as warning will report warnings in the console but will not fail CI (exit code 0), unless configured as error.


Rules Reference

Rule A11Y001 — Duplicate Accessibility Props

  • Severity: error
  • Description: Detects duplicate accessibility properties on the same JSX element.
  • Example violation:
    <View
      accessible
      accessibilityLabel="Account"
      accessibilityLabel="Account"
    />

Rule A11Y002 — Conflicting Accessibility Properties

  • Severity: warning (configurable)
  • Description: Detects accessibility properties that conflict with each other on the same element.
  • Default conflicting pairs:
    • accessibilityElementsHidden + accessible
    • importantForAccessibility + accessibilityElementsHidden
  • Example violation:
    <View
      accessible={true}
      accessibilityElementsHidden={true}
    />

Rule A11Y003 — Duplicate Accessibility Values

  • Severity: warning (configurable)
  • Description: Detects duplicate accessibility values across configured equivalent properties on the same JSX component.
  • Example violation:
    <XbText
      a11yLabel="Transaction amount"
      accessibilityLabel="Transaction amount"
    />

Rule A11Y004 — Duplicate Accessibility Logic

  • Severity: warning
  • Description: Detects duplicated accessibility helper logic across different files using AST normalization and structural similarity analysis.
  • Example violation:
    // AccountCard.tsx
    const getAccessibilityLabel = () => `${title}, ${value}`;
    
    // PortfolioCard.tsx
    const getAccountA11y = () => `${heading}, ${amount}`;

Rule A11Y005 — Non-Accessibility Code Modification

  • Severity: error
  • Description: Used in Git Diff mode (--diff). Ensures developers do not modify or delete existing non-accessibility code while implementing accessibility.
  • Scenarios:
    • Scenario 1 (PASS): Pure accessibility additions:
       <XbText
         style={styles.title}
         text={title}
      +  a11yLabel={title}
      +  accessibilityRole="text"
      />
    • Scenario 2 (FAIL): Existing non-accessibility property modified:
       <XbText
      -  style={styles.title}
      +  style={styles.headerTitle}
         text={title}
      +  a11yLabel={title}
      />
    • Scenario 3 (FAIL): Existing business logic modified:
      - const title = getAccountTitle(account);
      + const title = getFormattedAccountTitle(account);
    • Scenario 4 (PASS): Accessibility helper function modified.

Rule RN001 — No Inline Styling

  • Severity: warning (configurable)
  • Description: Prevents inline style objects on JSX elements (style={{ ... }} or style={[..., { ... }]}), which create new object references on every render and harm performance.
  • Example violation:
    <View style={{ margin: 16, padding: 12 }} />
  • Recommended fix: Extract styles to StyleSheet.create(...).

Rule RN002 — Safe Property & Array Access (Optional Chaining)

  • Severity: warning (configurable)
  • Description: Enforces null/undefined safety using optional chaining (?.) on data model objects and array index accesses to prevent runtime TypeError: Cannot read property of undefined crashes.
  • Example violation:
    const name = user.name;
    const first = items[0];
  • Recommended fix:
    const name = user?.name;
    const first = items?.[0];

Rule RN003 — No Static Text in JSX

  • Severity: warning (configurable)
  • Description: Detects hardcoded static text in JSX elements and text attributes, encouraging internationalization/localization (i18n) keys or variables.
  • Example violation:
    <Text>Total Portfolio Value</Text>
    <TextInput placeholder="Enter account number" />
  • Recommended fix: Use localized string functions or variables:
    <Text>{t('portfolio_value')}</Text>
    <TextInput placeholder={t('enter_account_number')} />

Configuration (rn-a11y.config.json)

Place rn-a11y.config.json at the root of your React Native project:

{
  "projectName": "My_App",
  "include": [
    "src/**/*.{ts,tsx,js,jsx}",
    "app/**/*.{ts,tsx,js,jsx}"
  ],
  "exclude": [
    "node_modules",
    "android",
    "ios",
    "build",
    "dist"
  ],
  "accessibilityProps": [
    "accessible",
    "accessibilityLabel",
    "accessibilityRole",
    "accessibilityState",
    "accessibilityValue",
    "accessibilityHint",
    "accessibilityActions",
    "onAccessibilityTap",
    "onAccessibilityMagicTap",
    "onAccessibilityEscape",
    "accessibilityViewIsModal",
    "accessibilityElementsHidden",
    "importantForAccessibility"
  ],
  "customProps": [
    "a11yLabel",
    "a11yRole",
    "a11yState",
    "disableA11yScaling"
  ],
  "equivalentProps": [
    ["a11yLabel", "accessibilityLabel"],
    ["a11yRole", "accessibilityRole"]
  ],
  "conflictingProps": [
    ["accessibilityElementsHidden", "accessible"]
  ],
  "rules": {
    "A11Y001": "error",
    "A11Y002": "warning",
    "A11Y003": "warning",
    "A11Y004": "warning",
    "A11Y005": "error"
  },
  "similarityThreshold": 0.85
}

CI / CD Integration Examples

GitHub Actions

name: Accessibility PR Check

on:
  pull_request:
    branches: [main, develop]

jobs:
  a11y-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0 # Full history needed for git diff

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Validate Accessibility Diff
        run: npx rn-a11y-check --diff origin/${{ github.base_ref }}

GitLab CI

stages:
  - test

a11y_validation:
  stage: test
  image: node:20
  before_script:
    - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
  script:
    - npm ci
    - npx rn-a11y-check --diff origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
  only:
    - merge_requests

Architecture & Future Extensibility

The tool decouples the CLI interface, AST parser, rule engine, Git analyzer, and reporter:

CLI (cli.ts)
 │
 ▼
Scanner (scanner.ts)
 ├── AST Parser (parser.ts - Babel)
 ├── Git Diff Engine (git/diffChecker.ts)
 ├── Rule Registry (rules/registry.ts)
 │    ├── A11Y001 (duplicateProps)
 │    ├── A11Y002 (conflictingProps)
 │    ├── A11Y003 (duplicateValues)
 │    ├── A11Y004 (duplicateLogic)
 │    └── A11Y005 (nonA11yChanges)
 └── Reporters
      ├── Text (reporter/textReporter.ts)
      └── JSON (reporter/jsonReporter.ts)

Adding New Rules

Future rules (such as A11Y006 Missing accessibilityLabel, A11Y007 Incorrect accessibilityRole, etc.) can be registered by creating a rule implementing the Rule interface:

import { Rule, RuleContext } from './types';

export const missingLabelRule: Rule = {
  id: 'A11Y006',
  name: 'Missing accessibilityLabel',
  description: 'Flags accessible touchable elements missing accessibilityLabel.',
  defaultSeverity: 'warning',
  runOnFile(context: RuleContext) {
    // AST traversal logic here
    return [];
  },
};

And registering it with registry.registerRule(missingLabelRule).