Accessible UI Component Library for Vanilla JS & React – Monochrome

Accessible UI Component Library for Vanilla JS & React – Monochrome
Accessible UI Component Library for Vanilla JS & React – Monochrome
Monochrome is a lightweight, accessible UI component library that delivers keyboard navigation, ARIA attribute management, and focus handling through a single 2.2kB vanilla JavaScript runtime.

It currently includes 4 prebuilt UI components (accordion, collapsible, menu, and tabs) and works with any server-rendered stack, static site generator, or React application.

The library uses the DOM as its source of truth. It reads and writes ARIA attributes directly, with no per-component state and no framework dependency at runtime.

It’s ideal for teams building content-heavy or server-rendered pages who need real accessibility compliance at a near-zero runtime cost.

Features:

  • Event delegation: A small set of global listeners handles every component on the page. There are no per-component instances, no memory allocations per element, and zero DOM queries at initialization.
  • ARIA compliance: Every component follows WAI-ARIA Authoring Practices and targets WCAG 2.2 AA.
  • Keyboard navigation: Arrow keys, Home, End, Enter, Space, and Escape all work as specified by ARIA patterns across every component.
  • Framework-agnostic HTML API: Components activate via an ID naming convention. Any server-side framework — PHP, Rails, Django, or plain HTML — can render the markup and get full interactivity from a single script tag.
  • Optional React wrappers: The monochrome/react package provides React components that generate the correct HTML structure and IDs.
  • Headless styling: No CSS ships with the library. You apply your own styles.
  • Browser find-in-page preserved: The hidden="until-found" attribute keeps collapsed content discoverable via Cmd+F in the browser.
  • Modern browser baseline: The library relies on the Popover API and hidden="until-found". Supports all current major browsers.

How To Use It:

1. Install Monochrome with the package manager you prefer.

# Using npm
npm install monochrome

# Using pnpm
pnpm add monochrome

# Using bun
bun add monochrome

# Using yarn
yarn add monochrome

2. Import the runtime once at your application’s entry point.

// Entry point: index.js, main.js, or app.js
// This registers the global event listeners that power every component
import "monochrome";

3. For projects that have no build step, use the CDN script tag:

<!-- Add this to your <head> or before </body> -->
<!-- Works in PHP, Rails, Django, WordPress, or plain HTML files -->
<script defer src="https://unpkg.com/monochrome"></script>

4. Create your own UI components. Monochrome identifies which elements to coordinate using a structured ID prefix system. You do not call any initialization function. The library reads these IDs on interaction and responds accordingly.

Prefix Role Example ID
mct: Trigger (the button or clickable element) mct:collapsible:faq-1
mcc: Content (the panel that shows or hides) mcc:collapsible:faq-1
mcr: Root container (for grouped components) mcr:accordion:product-faq

The third segment of the ID (e.g., faq-1) is your unique identifier. It links the trigger to its content panel. You choose it; just keep it consistent within a component pair.

<!-- Accordion Component -->
<div id="mcr:accordion:faq" data-mode="single">
  <div>
    <h3>
      <button id="mct:accordion:q1" aria-expanded="false" aria-controls="mcc:accordion:q1">
        What is monochrome?
      </button>
    </h3>
    <div id="mcc:accordion:q1" role="region" aria-labelledby="mct:accordion:q1" aria-hidden="true" hidden="until-found">
      A minimal component library...
    </div>
  </div>
  <div>
    <h3>
      <button id="mct:accordion:q2" aria-expanded="false" aria-controls="mcc:accordion:q2">
        How does it work?
      </button>
    </h3>
    <div id="mcc:accordion:q2" role="region" aria-labelledby="mct:accordion:q2" aria-hidden="true" hidden="until-found">
      Components are server-rendered...
    </div>
  </div>
</div>
<!-- Collapsible Component -->
<button id="mct:collapsible:details" aria-expanded="false" aria-controls="mcc:collapsible:details">
  Show more details
</button>
<div id="mcc:collapsible:details" aria-labelledby="mct:collapsible:details" aria-hidden="true" hidden="until-found">
  This content is revealed when you click the trigger.
</div>
<!-- Menu Component -->
<div id="mcr:menu:account">
  <button type="button" id="mct:menu:account" aria-controls="mcc:menu:account" aria-expanded="false" aria-haspopup="menu">
    Account
  </button>
  <ul role="menu" id="mcc:menu:account" aria-labelledby="mct:menu:account" aria-hidden="true" popover="manual">
    <li role="presentation">Settings</li>
    <li role="none"><button role="menuitem" tabindex="-1">Profile</button></li>
    <li role="none"><button role="menuitem" tabindex="-1">Preferences</button></li>
    <li role="separator"></li>
    <li role="none"><button role="menuitem" tabindex="-1">Sign Out</button></li>
  </ul>
</div>
<!-- Tabs Component -->
<div id="mcr:tabs:demo" data-orientation="horizontal">
  <div role="tablist" aria-orientation="horizontal">
    <button
      role="tab"
      id="mct:tabs:t1"
      aria-selected="true"
      aria-controls="mcc:tabs:t1"
      tabindex="0"
    >
      Overview
    </button>
    <button
      role="tab"
      id="mct:tabs:t2"
      aria-selected="false"
      aria-controls="mcc:tabs:t2"
      tabindex="-1"
    >
      Features
    </button>
  </div>
  <div
    role="tabpanel"
    id="mcc:tabs:t1"
    aria-labelledby="mct:tabs:t1"
    aria-hidden="false"
    tabindex="0"
  >
    Overview content...
  </div>
  <div
    role="tabpanel"
    id="mcc:tabs:t2"
    aria-labelledby="mct:tabs:t2"
    aria-hidden="true"
    hidden="until-found"
    tabindex="-1"
  >
    Features content...
  </div>
</div>

5. If you use React, you can import the optional wrapper components. These components generate the correct HTML structure automatically.

// Accordion
import { Accordion } from "monochrome/react"
<Accordion.Root>
  <Accordion.Item>
    <Accordion.Header>
      <Accordion.Trigger>What is monochrome?</Accordion.Trigger>
    </Accordion.Header>
    <Accordion.Panel>A minimal component library...</Accordion.Panel>
  </Accordion.Item>
  <Accordion.Item>
    <Accordion.Header>
      <Accordion.Trigger>How does it work?</Accordion.Trigger>
    </Accordion.Header>
    <Accordion.Panel>Components are server-rendered...</Accordion.Panel>
  </Accordion.Item>
</Accordion.Root>
// Collapsible
import { Collapsible } from "monochrome/react"
<Collapsible.Root>
  <Collapsible.Trigger>Show more details</Collapsible.Trigger>
  <Collapsible.Panel>
    This content is revealed when you click the trigger.
  </Collapsible.Panel>
</Collapsible.Root>
// Menu
import { Menu } from "monochrome/react"
<Menu.Root>
  <Menu.Trigger>Account</Menu.Trigger>
  <Menu.Popover>
    <Menu.Label>Settings</Menu.Label>
    <Menu.Item>Profile</Menu.Item>
    <Menu.Item>Preferences</Menu.Item>
    <Menu.Separator />
    <Menu.Item>Sign Out</Menu.Item>
  </Menu.Popover>
</Menu.Root>
// Tabs
import { Tabs } from "monochrome/react"
<Tabs.Root defaultValue="overview">
  <Tabs.List>
    <Tabs.Tab value="overview">Overview</Tabs.Tab>
    <Tabs.Tab value="features">Features</Tabs.Tab>
  </Tabs.List>
  <Tabs.Panel value="overview">Overview content...</Tabs.Panel>
  <Tabs.Panel value="features">Features content...</Tabs.Panel>
</Tabs.Root>

The post Accessible UI Component Library for Vanilla JS & React – Monochrome appeared first on CSS Script.


Discover more from RSS Feeds Cloud

Subscribe to get the latest posts sent to your email.

Leave a Reply

Your email address will not be published. Required fields are marked *

Discover more from RSS Feeds Cloud

Subscribe now to keep reading and get access to the full archive.

Continue reading