Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@joecodesallday/accessible-react-ui-kit) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
UI Component Library
A modern, accessible, and customizable React component library for rapid MVP development. ⭐️ If you find this project useful, please consider starring it on GitHub!
Table of Contents
- Features
- Theming
- Installation
- Usage
- Components
- Component Status
- Roadmap
- Example App
- Development
- Testing
- Contribution
- License
- Credits
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
andaria-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
andaria-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
andaria-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
andaria-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"
andaria-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) orrole="status"
(for info/success) andaria-live
for screen reader announcements, matching thevariant
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, useas="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"
andaria-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"
andaria-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
- Clone the repo
- Run
npm install
- Start the dev preview:
npm start
oryarn start
- 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.