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

@joecodesallday/accessible-react-ui-kit

v1.12.0

Published

Accessible-first, timeless UI blocks for React projects.

Readme

UI Component Library

Live Demo Star on GitHub ⭐ PRs Welcome

A modern, accessible, and customizable React component library for rapid MVP development. ⭐️ If you find this project useful, please consider starring it on GitHub!

→ Accessibility Audit


Table of Contents


What's New (v1.12.0)

  • Demo site fully working!
    • React and ReactDOM are now bundled, so all playgrounds load without errors.
  • Asset paths fixed: No more MIME type errors or missing modules.
  • Version bump: Package and repo are now at v1.12.0.

Features

  • MVP-first: Fast, production-ready React components for quick prototyping and real apps.
  • Accessible: WCAG-compliant, keyboard-friendly, screen-reader support. All components are tested with jest-axe and React Testing Library.
  • Customizable: Theme everything via CSS variables or utility classes.
  • Documented: Clear prop tables and usage examples. Per-component docs for every component.
  • Robust Help Text: All components support always-rendered help text for accessibility.
  • Custom className: All components accept a custom className on the outermost element.
  • TypeScript Support: Type definitions included for all components via .d.ts files.
  • Lightweight: Minimal dependencies, tree-shakable.
  • Composable: Easy to integrate and extend.

Theming

All components are fully customizable via CSS variables for dark mode, branding, or any custom theme.

Override variables in your app’s CSS:

:root {
  --ui-button-primary-bg: #1976d2;
  --ui-modal-bg: #222c35;
  /* See src/theme.css for all variables */
}

You can also scope them to a class or selector for alternate themes.


Installation

npm install accessible-react-ui-kit
# or
yarn add accessible-react-ui-kit

Usage

import {
  Button,
  Input,
  Textarea,
  Select,
  Checkbox,
  RadioGroup,
  Alert,
  Card,
  Modal,
  Spinner,
  Tooltip,
  Dropdown,
  Tabs,
  Toast,
  Pagination,
} from 'your-ui-library'

function App() {
  return <Button variant="primary">Hello World</Button>
}

Components

Button

A versatile button with size, variant, full width, loading, and accessibility.

<Button variant="primary" size="md">Primary</Button>
<Button variant="secondary" size="sm">Small Secondary</Button>
<Button variant="danger" loading>Deleting…</Button>
<Button fullWidth>Full Width</Button>
<Button disabled>Disabled</Button>

| Prop | Type | Default | Description | | ----------- | --------------------------------------------------- | ----------- | ------------------------------ | | children | ReactNode | — | Button content | | variant | "primary" \| "secondary" \| "neutral" \| "danger" | "primary" | Button style | | size | "sm" \| "md" \| "lg" | "md" | Button size | | fullWidth | boolean | false | Make button fill parent width | | loading | boolean | false | Show loader and disable button | | disabled | boolean | false | Disable button | | type | "button" \| "submit" \| "reset" | "button" | Button type | | className | string | — | Extra CSS classes | | ...rest | any | — | Any native button props |

Accessibility:

  • Uses aria-disabled and aria-busy for loading/disabled states.
  • Standard keyboard/tab navigation.
  • Focus ring visible.

Input

A modern, accessible input component with size, state, and help/error message support.

<Input
  label="Username"
  id="username"
  value={username}
  onChange={handleChange}component: usage + props + accessibility
  placeholder="Enter your username"
  required
  size="md"
  help="Use 4–16 letters or numbers"
  error={error}
  success={success}
/>

| Prop | Type | Default | Description | | ------------- | ---------------------- | ------- | ---------------------------------- | | label | string | — | Optional label text | | id | string | — | Input id (required if using label) | | value | string | — | Input value | | onChange | function(e) | — | Input change handler | | placeholder | string | — | Placeholder text | | required | boolean | false | Mark as required | | disabled | boolean | false | Disable input | | readOnly | boolean | false | Read only | | size | "sm" \| "md" \| "lg" | "md" | Input size | | fullWidth | boolean | false | Make input full width | | error | string | — | Show error state/message | | success | string | — | Show success state/message | | help | string | — | Show help/hint text | | className | string | — | Extra CSS classes | | ...rest | any | — | Any native input props |

Accessibility:

  • Label and input are linked for screen readers.
  • Error/help/success messages are read out via aria-describedby.
  • aria-invalid and aria-disabled set as needed.
  • Focus ring visible.

Textarea

A modern, accessible textarea with size, state, help/error messages, and optional character counter.

<Textarea
  label="Bio"
  id="bio"
  value={bio}
  onChange={handleBioChange}
  placeholder="Tell us about yourself"
  required
  size="md"
  help="Max 150 characters"
  error={error}
  success={success}
  maxLength={150}
  showCount
/>

| Prop | Type | Default | Description | | ------------- | ---------------------- | ------- | ------------------------------------- | ---------------------------------------- | | label | string | — | Optional label text | | id | string | — | Textarea id (required if using label) | | value | string | — | Textarea value | | onChange | function(e) | — | Change handler | | placeholder | string | — | Placeholder text | | required | boolean | false | Mark as required | | disabled | boolean | false | Disable textarea | | readOnly | boolean | false | Read only | | size | "sm" \| "md" \| "lg" | "md" | Textarea size | | fullWidth | boolean | false | Make textarea full width | | error | string | — | Show error state/message | | success | string | — | Show success state/message | | help | string | — | Show help/hint text | | maxLength | number | — | Maximum allowed character count | component: usage + props + accessibility | | showCount | boolean | false | Show the character counter | | className | string | — | Extra CSS classes | | ...rest | any | — | Any native textarea props |

Accessibility:

  • Label and textarea are linked for screen readers.
  • Error/help/success messages are read out via aria-describedby.
  • aria-invalid and aria-disabled set as needed.
  • Focus ring visible.

Select

A modern, accessible select field with size, state, placeholder, and help/error message support.

<Select
  label="Favorite Fruit"
  id="fruit"
  options={[
    { label: 'Apple', value: 'apple' },
    { label: 'Banana', value: 'banana' },
    { label: 'Cherry', value: 'cherry' },
  ]}
  value={fruit}
  onChange={handleFruitChange}
  required
  size="md"
  help="Pick your favorite fruit"
  error={error}
  success={success}
  placeholder="Choose a fruit"
/>

| Prop | Type | Default | Description | | ------------- | ------------------------------------ | ------- | ----------------------------------- | | label | string | — | Optional label text | | id | string | — | Select id (required if using label) | | value | string | — | Select value | | onChange | function(e) | — | Change handler | | options | Array<{ label, value, disabled? }> | [] | List of options | | placeholder | string | — | Placeholder shown as first option | | required | boolean | false | Mark as required | | disabled | boolean | false | Disable select | | readOnly | boolean | false | Read only | | size | "sm" \| "md" \| "lg" | "md" | Select size | | fullWidth | boolean | false | Make select full width | | error | string | — | Show error state/message | | success | string | — | Show success state/message | | help | string | — | Show help/hint text | | className | string | — | Extra CSS classes | | ...rest | any | — | Any native select props |

Accessibility:

  • Label and select are linked for screen readers.
  • Error/help/success messages are read out via aria-describedby.
  • aria-invalid and aria-disabled set as needed.
  • Focus ring and keyboard friendly.

Checkbox

A modern, accessible checkbox with size, state, help/error message support.

<Checkbox
  label="I agree to the terms"
  id="terms"
  checked={checked}
  onChange={handleCheckChange}
  required
  size="md"
  help="You must agree to continue"
  error={error}
  success={success}
/>

| Prop | Type | Default | Description | | ----------- | ---------------------- | ------- | ---------------------------------- | | label | string | — | Optional label text (right of box) | | id | string | — | Checkbox id (required if label) | | checked | boolean | — | Checkbox checked state | | onChange | function(e) | — | Change handler | | required | boolean | false | Mark as required | | disabled | boolean | false | Disable checkbox | | readOnly | boolean | false | Read only | | size | "sm" \| "md" \| "lg" | "md" | Checkbox size | | error | string | — | Show error state/message | | success | string | — | Show success state/message | | help | string | — | Show help/hint text | | className | string | — | Extra CSS classes | | ...rest | any | — | Any native checkbox props |

Accessibility:

  • Label and checkbox are linked via htmlFor
  • Error/help/success messages are read out via aria-describedby
  • aria-invalid, aria-disabled set as needed
  • Keyboard/focus ring visible

RadioGroup

A modern, accessible radio button group with size, state, help/error message support.

<RadioGroup
  label="Favorite Color"
  name="color"
  options={[
    { label: 'Red', value: 'red' },
    { label: 'Green', value: 'green' },
    { label: 'Blue', value: 'blue', disabled: true },
  ]}
  value={selectedColor}
  onChange={handleColorChange}
  required
  size="md"
  help="Pick your favorite color"
  error={error}
  success={success}
/>

| Prop | Type | Default | Description | | ----------- | ------------------------------------ | ------- | ------------------------------ | | label | string | — | Optional group label | | name | string | — | All radios in group share this | | value | string | — | Selected radio value | | onChange | function(e) | — | Change handler | | options | Array<{ label, value, disabled? }> | [] | List of options | | required | boolean | false | Mark as required | | disabled | boolean | false | Disable all radios | | readOnly | boolean | false | Read only | | size | "sm" \| "md" \| "lg" | "md" | Radio size | | error | string | — | Show error state/message | | success | string | — | Show success state/message | | help | string | — | Show help/hint text | | className | string | — | Extra CSS classes |

Accessibility:

  • Group and radios use proper roles and aria- attributes
  • Error/help/success messages are read via aria-describedby
  • Keyboard/focus ring visible
  • Radios are keyboard navigable

Alert

A visually distinct alert box for feedback messages, warnings, errors, and more.

<Alert variant="success" title="Success!">
  Your profile was updated.
</Alert>
<Alert
  variant="error"
  title="Error"
  onClose={() => setShow(false)}
>
  Something went wrong.
</Alert>

| ----------- | --------------------------------------------- | -------- | ------------------------------- | | Prop | Type | Default | Description | | ----------- | --------------------------------------------- | -------- | ------------------------------- |


Tooltip

Accessible tooltip for hints and descriptions.

<Tooltip label="Helpful info">Hover or focus me</Tooltip>

| Prop | Type | Default | Description | | ----------- | ----------- | ------- | --------------------------------- | ------- | ------- | ---------------- | | children | ReactNode | — | Element that triggers the tooltip | | label | string | — | Tooltip text | | placement | "top" | "right" | "bottom" | "left" | "top" | Tooltip position |

Accessibility:

  • Uses aria-describedby to link trigger and tooltip
  • Keyboard and mouse accessible (focus, hover, Escape to close)
  • Uses role="tooltip"

Dropdown

Accessible dropdown/select menu for options.

<Dropdown
  label="Choose an option"
  options={[
    { label: 'One', value: '1' },
    { label: 'Two', value: '2' },
  ]}
  value={value}
  onChange={setValue}
/>

| Prop | Type | Default | Description | | ---------- | ----------------------------------------- | ------- | --------------- | | label | string | — | Dropdown label | | options | Array<{ label: string, value: string }> | — | List of options | | value | string | — | Selected value | | onChange | function(value: string) | — | Change handler |

Accessibility:

  • Uses aria-haspopup, aria-expanded, aria-controls, role="listbox"
  • Keyboard navigation and focus management
  • Screen reader friendly

Tabs

Accessible tabbed navigation for content panels.

<Tabs
  tabs={[
    { label: 'Tab 1', content: <div>One</div> },
    { label: 'Tab 2', content: <div>Two</div> },
  ]}
/>

| Prop | Type | Default | Description | | -------------- | ---------------------------------------------- | ------- | ---------------------------- | | tabs | Array<{ label: string, content: ReactNode }> | — | Tab labels and content | | defaultIndex | number | 0 | Initially selected tab index |

Accessibility:

  • Uses role="tablist", role="tab", role="tabpanel"
  • Keyboard navigation (Arrow keys)
  • Focus ring and screen reader support

Toast

Accessible toast notification for feedback messages.

<Toast message="Saved!" open={open} onClose={closeToast} variant="success" />

| Prop | Type | Default | Description | | ---------- | ------------ | ------- | ------------------- | ---------- | -------- | ----------- | | message | string | — | Toast message | | open | boolean | — | Show/hide toast | | onClose | function() | — | Close handler | | duration | number | 4000 | Auto-close after ms | | variant | "success" | "error" | "info" | "warning" | "info" | Toast style |

Accessibility:

  • Uses role="status" and aria-live for announcements
  • Keyboard and screen reader friendly
  • Close button is focusable and labeled

Pagination

Accessible pagination controls for navigation.

<Pagination page={2} pageCount={5} onPageChange={setPage} />

| Prop | Type | Default | Description | | -------------- | ------------------------ | ------- | ---------------------- | | page | number | — | Current page (1-based) | | pageCount | number | — | Total number of pages | | onPageChange | function(page: number) | — | Page change handler |

Accessibility:

  • Uses aria-label, aria-current, and labeled buttons
  • Keyboard and screen reader friendly
  • Focus ring visible | variant | "info" \| "success" \| "warning" \| "error" | "info" | Visual style and icon | | title | string | — | Optional bold title | | children | node | — | Main alert content | | onClose | function | — | Shows close button if present | | inline | boolean | false | Display inline (not full width) | | className | string | — | Extra CSS classes |

Accessibility:

  • Uses role="alert" (for error/warning) or role="status" (for info/success) and aria-live for screen reader announcements, matching the variant prop.
  • Dismiss button is accessible and focusable

Card

A visually distinct container for grouping related content.

<Card header="User Profile">
  <p>This is the main content of the card.</p>
</Card>

<Card
  header={<span><b>Project:</b> SuperApp</span>}
  footer="Last updated 2025-09-17"
  shadow
  size="lg"
>
  <p>SuperApp is a productivity tool...</p>
</Card>

| Prop | Type | Default | Description | | ------------ | -------------------- | ------- | ------------------------------ | | header | string | ReactNode | — | Top section of card | | footer | string | ReactNode | — | Bottom section of card | | children | node | — | Main card content | | shadow | boolean | false | Adds deeper shadow | | borderless | boolean | false | Removes card border | | size | "sm" | "md" | "lg" | "md" | Card padding/radius size | | center | boolean | false | Center text/content | | as | string | section | HTML element (section/article) | | className | string | — | Extra CSS classes |

Accessibility:

  • By default, uses <section>; for stand-alone content, use as="article" or add ARIA labels as needed.
  • Header and footer are semantic and accessible if provided.

Spinner

A simple animated indicator for loading states.

<Spinner />
<Spinner size="sm" />
<Spinner size="lg" color="danger" />
<Spinner color="muted" ariaLabel="Please wait…" />

| Prop | Type | Default | Description | | ----------- | ---------------------------- | --------- | ------------------- | | size | "sm"|"md"|"lg" | "md" | Spinner size | | color | "primary"|"muted"|"danger" | "primary" | Spinner color | | ariaLabel | string | "Loading" | Screen reader label | | className | string | — | Extra CSS classes |

Accessibility:

  • Uses role="status" and aria-label for assistive tech.
  • Use an informative ariaLabel for context.

Modal

A dialog overlay for focused content or actions.

const [open, setOpen] = useState(false)

;<Modal
  open={open}
  onClose={() => setOpen(false)}
  header="Dialog Title"
  footer={<Button onClick={() => setOpen(false)}>Close</Button>}
>
  <p>This is the modal’s content.</p>
</Modal>

| Prop | Type | Default | Description | | ------------- | ---------------- | ------- | ---------------------------- | | open | boolean | — | Modal visibility | | onClose | function | — | Called on close (esc, click) | | header | ReactNode | — | Modal title/header | | footer | ReactNode | — | Modal footer (actions) | | children | node | — | Modal content | | size | "sm"|"md"|"lg" | "md" | Modal width | | center | boolean | true | Center content | | closeButton | boolean | true | Show close (×) button | | className | string | — | Extra CSS classes |

Accessibility:

  • Uses role="dialog" and aria-modal
  • ESC key closes modal
  • Backdrop click closes modal
  • Focus is trapped and returned

Component Status

| Component | Status | Docs | Themeable | | ---------- | ------ | ---- | --------- | | Button | ✅ | ✅ | ✅ | | Input | ✅ | ✅ | ✅ | | Textarea | ✅ | ✅ | ✅ | | Select | ✅ | ✅ | ✅ | | Checkbox | ✅ | ✅ | ✅ | | RadioGroup | ✅ | ✅ | ✅ | | Alert | ✅ | ✅ | ✅ | | Card | ✅ | ✅ | ✅ | | Modal | ✅ | ✅ | ✅ | | Spinner | ✅ | ✅ | ✅ | | Tooltip | ✅ | ✅ | ✅ | | Dropdown | ✅ | ✅ | ✅ | | Tabs | ✅ | ✅ | ✅ | | Toast | ✅ | ✅ | ✅ | | Pagination | ✅ | ✅ | ✅ |


Roadmap

  • Advanced components: ~~Tooltip~~, ~~Dropdown~~, Tabs, Toast, Pagination, etc.
  • TypeScript types and support
  • Automated testing (Jest, Testing Library)
  • Improved documentation and demo site
  • Community & contribution guidelines

Example App

Try all components in the included main.jsx demo.


Development

  1. Clone the repo
  2. Run npm install
  3. Start the dev preview: npm start or yarn start
  4. Edit components and see live reload

Testing

All components are covered by professional, accessibility-first automated tests (Jest, React Testing Library, jest-axe). Every component robustly supports help text and custom className props, and all accessibility features are verified.

To try the components in a real project, install the package from npm and import as shown above.


Contribution

Contributions are very welcome!
Please see the CONTRIBUTING.md for guidelines and our Code of Conduct.


License

Copyright (c) 2025 Hermit-commits-code


Credits

Inspired by Radix UI, Reach UI, and the open-source community.