Getting Started with HTML5 Web Components
Standard, framework-agnostic Custom Elements built for WCAG 2.1/2.2 AA & AAA compliance. Usable in plain HTML, Vue, Svelte, Angular, Astro, WordPress, Rails, and React.
Building a dedicated React application? Check out the Getting Started with React guide for idiomatic React props, forwardRefs, and hooks.
Why Standard Web Components?
Accessibility shouldn't be locked to a single UI framework. By providing standard HTML Custom Elements via @a11ypros/a11y-ui-elements, developers can drop accessible components into any stack:
- 100% Light DOM Accessibility: Unlike typical web components that hide markup inside a Shadow Root (breaking cross-boundary ARIA associations like
aria-labelledby,aria-describedby, and<label for="...">), our components render directly in the Light DOM. Screen readers navigate standard semantic HTML without barriers. - Zero External Runtime: Zero third-party dependencies. Ultra-lightweight footprint.
- Universal Styling: Reuses your existing design tokens and CSS custom properties without needing complex
::part()selectors.
1. Installation
Install via npm for module bundlers (Vite, Webpack, Next.js, Nuxt, SvelteKit):
npm install @a11ypros/a11y-ui-elements @a11ypros/a11y-ui-componentsImport into your app (recommended)
Just like CrowdStrike Glide Core, import the element once in your app or component entry point. The custom element is registered automatically:
import '@a11ypros/a11y-ui-elements/switch';
import '@a11ypros/a11y-ui-elements/button';
// Or import all elements:
import '@a11ypros/a11y-ui-elements';Then use the tag directly in your markup without any script tags:
<a11y-switch label="Notifications" checked></a11y-switch>
<a11y-button variant="primary">Submit</a11y-button>Without a bundler (Static HTML / CMS)
For static sites, WordPress, or Rails without an npm pipeline, load the standalone bundle:
<!-- Stylesheet with tokens & component styles -->
<link rel="stylesheet" href="path/to/@a11ypros/a11y-ui-components/styles/global.css">
<link rel="stylesheet" href="path/to/@a11ypros/a11y-ui-components/styles/components.css">
<!-- Self-contained Web Components bundle -->
<script src="path/to/@a11ypros/a11y-ui-elements/dist/bundle.js"></script>Interactive Switch Example
Toggle between React and Web Component / HTML syntax to see how the component behaves identically.
Interactive Button Example
Custom elements support all variants, keyboard navigation, and loading states.
Using with Your Favorite Framework
Vue 3
Tell Vite/Vue to recognize <a11y-*> tags as custom elements in your vite.config.ts:
import vue from '@vitejs/plugin-vue';
export default {
plugins: [
vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('a11y-'),
},
},
}),
],
};Then use it directly in any Vue template:
<template>
<a11y-switch :checked="isEnabled" @change="onToggle" label="Dark Mode" />
<a11y-button variant="primary" :loading="isSubmitting">Submit</a11y-button>
</template>Svelte
Svelte supports custom elements natively. Import the package once and use the tags:
<script>
import '@a11ypros/a11y-ui-elements';
let checked = false;
</script>
<a11y-switch label="Notifications" {checked} on:change={(e) => checked = e.detail.checked} />React 19
React 19 includes native custom element support, automatically passing properties, attributes, and listening to custom events:
import '@a11ypros/a11y-ui-elements';
export function Settings() {
return (
<a11y-switch
label="Sound Effects"
checked={true}
onChange={(e) => console.log(e.detail.checked)}
/>
);
}