Vanilla-headless Web Components
Completely un-styled, fully accessible UI Web Components library, with fully unopinionated css styling.
Installation
To use the TailwindCSS Stripes Plugin, you need to have TailwindCSS installed in your project. If you don't have it yet, you can follow the installation guide to set it up.
Once you have TailwindCSS installed, you can add the Stripes Plugin to your project using pnpm, npm or yarn:
Using pnpm
pnpm add vanilla-headless
Using npm
npm install vanilla-headless
Using yarn
yarn add vanilla-headless
Using cdn
https://unpkg.com/vanilla-headless@latest
https://cdn.jsdelivr.net/npm/vanilla-headless@latest
Use
import "vanilla-headless"
That's all, no other javascript required. Just wrap you aria compliant markup with the appropriate tag and attributes.
The example files is using TailwindCSS but is not required with TailwindUI
Web Components
The web component is basically a wrapper around your semantic html. At it's most basic it will even work without any css.
Popover with aria keyboard navigation
The popover element makes it easy to show and hide html elements on page. This work great for dropdown, menus and popover.
Events:
- Toggle dropdown on click event.
- Toggle dropdown on keyEvent Space and Enter keys
- Close dropdown keyEvent Esc key.
- Close dropdown on click outside of element.
Requirements:
- Button:
- must be typeof
button
- must have attributes of
aria-haspopup
andaria-expanded
-
ID
must have same value as dropdown labelledby
- must be typeof
- Dropdown
- must have attributes of
aria-labelledby
- must have attributes of
Unstyled popover component
<headless-popover class="relative">
<button aria-expanded="false" id="popover" aria-haspopup="true">Button</button>
<div aria-labelledby="popover">
Content
</div>
</headless-popover>
Styled popover component with tailwindcss
<headless-popover class="relative text-gray-700" offset="0 10" placement="bottom top" popper>
<button
aria-expanded="false"
aria-haspopup="true"
class="inline-flex justify-between w-full rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2
focus:ring-offset-gray-100 focus:ring-primary-500"
id="popover"
type="button"
>
Popover
<!-- Heroicon name: solid/chevron-down -->
<svg aria-hidden="true" class="-mr-1 ml-2 h-5 w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path clip-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" fill-rule="evenodd" />
</svg>
</button>
<div aria-labelledby="popover" class="absolute z-10 w-screen max-w-sm transform px-4 sm:px-0">
<div class="overflow-hidden rounded-lg shadow-lg ring-1 ring-black ring-opacity-5">
<div class="relative grid gap-8 bg-white p-7">
<a class="-m-3 flex items-center rounded-lg p-2 transition duration-150 ease-in-out hover:bg-gray-50 focus:outline-none focus-visible:ring focus-visible:ring-primary-500 focus-visible:ring-opacity-50" href="#">
<span>
<svg aria-hidden="true" fill="none" height="48" viewBox="0 0 48 48" width="48" xmlns="http://www.w3.org/2000/svg" class=text-primary-500>
<rect class="fill-primary-500/20" height="48" rx="8" width="48"></rect>
<path d="M24 11L35.2583 17.5V30.5L24 37L12.7417 30.5V17.5L24 11Z" stroke="currentColor" stroke-width="2"></path>
<path clip-rule="evenodd" d="M16.7417 19.8094V28.1906L24 32.3812L31.2584 28.1906V19.8094L24 15.6188L16.7417 19.8094Z" fill-rule="evenodd" stroke="currentColor" stroke-width="2"></path>
<path clip-rule="evenodd" d="M20.7417 22.1196V25.882L24 27.7632L27.2584 25.882V22.1196L24 20.2384L20.7417 22.1196Z" fill-rule="evenodd" stroke="currentColor" stroke-width="2"></path>
</svg>
</span>
<span class="ml-2 text-gray-600"> Lorem ipsum dolor sit amet, consectetur. </span>
</a>
<a class="-m-3 flex items-center rounded-lg p-2 transition duration-150 ease-in-out hover:bg-gray-50 focus:outline-none focus-visible:ring focus-visible:ring-primary-500 focus-visible:ring-opacity-50" href="#">
<span>
<svg aria-hidden="true" fill="none" height="48" viewBox="0 0 48 48" width="48" xmlns="http://www.w3.org/2000/svg" class=text-primary-500>
<rect class="fill-primary-500/20" height="48" rx="8" width="48"></rect>
<path d="M24 11L35.2583 17.5V30.5L24 37L12.7417 30.5V17.5L24 11Z" stroke="currentColor" stroke-width="2"></path>
<path clip-rule="evenodd" d="M16.7417 19.8094V28.1906L24 32.3812L31.2584 28.1906V19.8094L24 15.6188L16.7417 19.8094Z" fill-rule="evenodd" stroke="currentColor" stroke-width="2"></path>
<path clip-rule="evenodd" d="M20.7417 22.1196V25.882L24 27.7632L27.2584 25.882V22.1196L24 20.2384L20.7417 22.1196Z" fill-rule="evenodd" stroke="currentColor" stroke-width="2"></path>
</svg>
</span>
<span class="ml-2 text-gray-600"> Lorem ipsum dolor sit amet, consectetur. </span>
</a>
<a class="-m-3 flex items-center rounded-lg p-2 transition duration-150 ease-in-out hover:bg-gray-50 focus:outline-none focus-visible:ring focus-visible:ring-primary-500 focus-visible:ring-opacity-50" href="#">
<span>
<svg aria-hidden="true" fill="none" height="48" viewBox="0 0 48 48" width="48" xmlns="http://www.w3.org/2000/svg" class=text-primary-500>
<rect class="fill-primary-500/20" height="48" rx="8" width="48"></rect>
<path d="M24 11L35.2583 17.5V30.5L24 37L12.7417 30.5V17.5L24 11Z" stroke="currentColor" stroke-width="2"></path>
<path clip-rule="evenodd" d="M16.7417 19.8094V28.1906L24 32.3812L31.2584 28.1906V19.8094L24 15.6188L16.7417 19.8094Z" fill-rule="evenodd" stroke="currentColor" stroke-width="2"></path>
<path clip-rule="evenodd" d="M20.7417 22.1196V25.882L24 27.7632L27.2584 25.882V22.1196L24 20.2384L20.7417 22.1196Z" fill-rule="evenodd" stroke="currentColor" stroke-width="2"></path>
</svg>
</span>
<span class="ml-2 text-gray-600"> Lorem ipsum dolor sit amet, consectetur. </span>
</a>
</div>
</div>
</div>
</headless-popover>
Dropdown with aria keyboard navigation
The dropdown is at the core the same as the popover element with the only difference that it adds additional functionality to navigate menu elements via keyboard and adding aria-current attribute to track selected element
Events:
- Toggle dropdown on click event.
- Toggle dropdown on keyEvent Space and Enter keys
- Navigate up and down with Tab, Shift + Tab, DownArrow, UpArrow, RightArrow, LeftArrow keys
- Close dropdown keyEvent Esc key.
- Close dropdown on click outside of element.
Requirements:
- Button:
- must be typeof
button
- must have attributes of
aria-haspopup
andaria-expanded
-
ID
must have same value as dropdownlabelledby
- must be typeof
- Dropdown
- must have attributes of
aria-labelledby
- dropdown require at least 1 anchor or button tag with attribute
role="menuitem"
- must have attributes of
Unstyled Dropdown menu
<headless-dropdown>
<button aria-expanded="false" aria-haspopup="true" type="button" id="dropdown">Button</button>
<div aria-labelledby="dropdown">
<a href="#" role="menuitem">Link</a>
<a href="#" role="menuitem">Link</a>
<a href="#" role="menuitem">Link</a>
<a href="#" role="menuitem">Link</a>
</div>
</headless-dropdown>
Styled Dropdown menu with Tailwindcss
<headless-dropdown class="relative inline-block text-left" offset="0 10" placement="bottom-end top-end" popper>
<button
type="button"
class="inline-flex justify-center w-full rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-indigo-500"
id="menu-button"
aria-expanded="false"
aria-haspopup="true"
>
USE VANILLA HEADLESS
<svg class="-mr-1 ml-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</button>
<div class="w-56 absolute rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none shadow-2xl" role="menu" aria-orientation="vertical" aria-labelledby="menu-button" tabindex="-1">
<div class="py-1" role="none">
<a href="#" class="text-gray-700 block px-4 py-2 text-sm" role="menuitem" tabindex="-1" id="menu-item-0">GITHUB</a>
<a href="#" class="text-gray-700 block px-4 py-2 text-sm" role="menuitem" tabindex="-1" id="menu-item-1">NPM</a>
<a href="#" class="text-gray-700 block px-4 py-2 text-sm" role="menuitem" tabindex="-1" id="menu-item-2">YARN</a>
<a href="#" class="text-gray-700 block px-4 py-2 text-sm" role="menuitem" tabindex="-1" id="menu-item-2">UNPKG CDN</a>
</div>
</div>
</headless-dropdown>
Disclosure with aria keyboard navigation
The Disclosure element is ideal for hide and showing a list of elements. Best used for components like for Q&A's.
Events:
- Toggle panels on click event.
- Toggle panels on keyEvent Space and Enter
- Navigate up and down with Tab, Shift + Tab, DownArrow, UpArrow
Requirements:
- Button:
- must be typeof
button
- must have attributes of
aria-controls
andaria-expanded
- must be typeof
- Dropdown
- must have a
ID
matchingaria-controls
- must have a
Unstyled Disclosure
-
Park at the nearest available parking meter without paying the meter and call 999-999-9999 to report the problem. We will note and approve your alternate location and will investigate the cause of the shortage in your assigned facility.
-
You should come to the Parking office and report the loss. There is a fee to replace your lost permit. However, if your permit was stolen, a copy of a police report needs to be submitted along with a stolen parking permit form for a fee replacement exemption.
<headless-disclosure>
<dl>
<dt>
<button aria-controls="faq_1_desc" aria-expanded="false" type="button">
What do I do if I have a permit for an assigned lot, but can't find a space there? <span style="display: inline-flex;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5"><path
fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd" /></svg></span>
</button>
</dt>
<dd>
<div id="faq_1_desc">
Park at the nearest available parking meter without paying the meter and call 999-999-9999 to report the problem. We will note and approve your alternate location and will investigate the cause of the shortage in your assigned
facility.
</div>
</dd>
<dt>
<button aria-controls="faq_2_desc" aria-expanded="false" type="button">
What do I do if I lose my permit or if my permit is stolen?
<span style="display: inline-flex;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5">
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
clip-rule="evenodd" /></svg></span>
</button>
</dt>
<dd>
<div id="faq_2_desc">
You should come to the Parking office and report the loss. There is a fee to replace your lost permit. However, if your permit was stolen, a copy of a police report needs to be submitted along with a stolen parking permit form for a
fee replacement exemption.
</div>
</dd>
</dl>
</headless-disclosure>
Styled disclosure with Tailwindcss
-
Park at the nearest available parking meter without paying the meter and call 999-999-9999 to report the problem. We will note and approve your alternate location and will investigate the cause of the shortage in your assigned facility.
-
You should come to the Parking office and report the loss. There is a fee to replace your lost permit. However, if your permit was stolen, a copy of a police report needs to be submitted along with a stolen parking permit form for a fee replacement exemption.
-
All facilities are restricted from 2:00 am - 6:00 am on all days. No exceptions are made for any holiday or recess except those officially listed as a
Holidays
in the calendar. Please note: 24-hour rental spaces, 24-hour rental lots, and disabled parking is enforced at all times. -
Some parking facility restrictions differ from others. Be sure to take note of the signs at each lot entrance.
<headless-disclosure class="max-w-md block rounded-md bg-white p-2">
<dl class="faq">
<dt>
<button
aria-controls="faq1_desc"
aria-expanded="true"
class="flex w-full rounded-md bg-primary-100 px-4 py-2 text-left text-sm font-medium text-primary-900 hover:bg-primary-200 focus:outline-none focus-visible:ring focus-visible:ring-primary-500 focus-visible:ring-opacity-75 mb-2"
type="button"
>
What do I do if I have a permit for an assigned lot, but can't find a space there?
</button>
</dt>
<dd>
<div class="px-4 pt-4 pb-2 text-sm text-gray-500" id="faq1_desc">
Park at the nearest available parking meter without paying the meter and call 999-999-9999 to report the problem. We will note and approve your alternate location and will investigate the cause of the shortage in your assigned
facility.
</div>
</dd>
<dt>
<button
aria-controls="faq2_desc"
aria-expanded="false"
class="flex w-full rounded-md bg-primary-100 px-4 py-2 text-left text-sm font-medium text-primary-900 hover:bg-primary-200 focus:outline-none focus-visible:ring focus-visible:ring-primary-500 focus-visible:ring-opacity-75 mb-2"
type="button"
>
What do I do if I lose my permit or if my permit is stolen?
</button>
</dt>
<dd>
<div class="px-4 pt-4 pb-2 text-sm text-gray-500" id="faq2_desc">
You should come to the Parking office and report the loss. There is a fee to replace your lost permit. However, if your permit was stolen, a copy of a police report needs to be submitted along with a stolen parking permit form for a
fee replacement exemption.
</div>
</dd>
<dt>
<button
aria-controls="faq3_desc"
aria-expanded="false"
class="flex w-full rounded-md bg-primary-100 px-4 py-2 text-left text-sm font-medium text-primary-900 hover:bg-primary-200 focus:outline-none focus-visible:ring focus-visible:ring-primary-500 focus-visible:ring-opacity-75 mb-2"
type="button"
>
Is there free parking on holidays?
</button>
</dt>
<dd>
<div class="px-4 pt-4 pb-2 text-sm text-gray-500" id="faq3_desc">
All facilities are restricted from 2:00 am - 6:00 am on all days. No exceptions are made for any holiday or recess except those officially listed as a
<q> Holidays </q>
in the calendar. Please note: 24-hour rental spaces, 24-hour rental lots, and disabled parking is enforced at all times.
</div>
</dd>
<dt>
<button
aria-controls="faq4_desc"
aria-expanded="false"
class="flex w-full rounded-md bg-primary-100 px-4 py-2 text-left text-sm font-medium text-primary-900 hover:bg-primary-200 focus:outline-none focus-visible:ring focus-visible:ring-primary-500 focus-visible:ring-opacity-75 mb-2"
type="button"
>
Do all parking facilities have the same enforcement rules?
</button>
</dt>
<dd>
<div class="px-4 pt-4 pb-2 text-sm text-gray-500" id="faq4_desc">
Some parking facility restrictions differ from others. Be sure to take note of the signs at each lot entrance.
</div>
</dd>
</dl>
</headless-disclosure>
Tabs with aria keyboard navigation
The Tab element is ideal to show or hide content by use showing content on selected tab button.
Events:
- Toggle panels on click event.
- Toggle panels on keyEvent Space and Enter
- Navigate up and down with Tab, Shift + Tab, DownArrow, UpArrow
Requirements:
- Button:
- must be typeof
button
- must have attributes of
aria-controls
andaria-expanded
- must be typeof
- Dropdown
- must have a
ID
matchingaria-controls
- must have a
Important: To prevent content shift add hidden to corresponding aria-controlled element
Unstyled Tabs
Tab 1
lorem content for tab item 1
Tab 2
lorem content for tab item 2
Tab 3
lorem content for tab item 3
Tab 4
lorem content for tab item 4
<headless-tabs>
<div>
<button
aria-controls="tab-1-1"
aria-expanded="true"
type="button"
style="background-color: lightgray; padding: 2px 5px; border-radius: 4px; color: #111; font-size: 14px; "
>
Tab 1
</button>
<button
aria-controls="tab-2-1"
aria-expanded="false"
type="button"
style="background-color: lightgray; padding: 2px 5px; border-radius: 4px; color: #111; font-size: 14px; "
>
Tab 2
</button>
<button
aria-controls="tab-3-1"
aria-expanded="false"
type="button"
style="background-color: lightgray; padding: 2px 5px; border-radius: 4px; color: #111; font-size: 14px; "
>
Tab 3
</button>
<button
aria-controls="tab-4-1"
aria-expanded="false"
type="button"
style="background-color: lightgray; padding: 2px 5px; border-radius: 4px; color: #111; font-size: 14px; "
>
Tab 4
</button>
</div>
<div id="tab-1-1">
<h3>Tab 1</h3>
<p>
lorem content for tab item 1
</p>
</div>
<div hidden id="tab-2-1">
<h3>Tab 2</h3>
<p>
lorem content for tab item 2
</p>
</div>
<div hidden id="tab-3-1">
<h3>Tab 3</h3>
<p>
lorem content for tab item 3
</p>
</div>
<div hidden id="tab-4-1">
<h3>Tab 4</h3>
<p>
lorem content for tab item 4
</p>
</div>
</headless-tabs>
Styled tabs with Tailwindcss
Tab 1
lorem content for tab item 1
Tab 2
lorem content for tab item 2
Tab 3
lorem content for tab item 3
Tab 4
lorem content for tab item 4
<headless-tabs class="mx-auto my-20 block w-full max-w-md rounded-md bg-white p-2 shadow-2xl shadow-primary-500/25">
<div class="flex space-x-2">
<button
aria-controls="tab-1"
aria-expanded="true"
class="flex w-full rounded-md bg-blue-100 px-4 py-2 text-left text-sm font-medium text-blue-900 hover:bg-blue-200 focus:outline-none focus-visible:ring focus-visible:ring-blue-500 focus-visible:ring-opacity-75 mb-2"
type="button"
>
Tab 1
</button>
<button
aria-controls="tab-2"
aria-expanded="false"
class="flex w-full rounded-md bg-blue-100 px-4 py-2 text-left text-sm font-medium text-blue-900 hover:bg-blue-200 focus:outline-none focus-visible:ring focus-visible:ring-blue-500 focus-visible:ring-opacity-75 mb-2"
type="button"
>
Tab 2
</button>
<button
aria-controls="tab-3"
aria-expanded="false"
class="flex w-full rounded-md bg-blue-100 px-4 py-2 text-left text-sm font-medium text-blue-900 hover:bg-blue-200 focus:outline-none focus-visible:ring focus-visible:ring-blue-500 focus-visible:ring-opacity-75 mb-2"
type="button"
>
Tab 3
</button>
<button
aria-controls="tab-4"
aria-expanded="false"
class="flex w-full rounded-md bg-blue-100 px-4 py-2 text-left text-sm font-medium text-blue-900 hover:bg-blue-200 focus:outline-none focus-visible:ring focus-visible:ring-blue-500 focus-visible:ring-opacity-75 mb-2"
type="button"
>
Tab 4
</button>
</div>
<div class="px-4 text-sm text-gray-500" id="tab-1">
<h3 class="text-xl font-bold text-gray-900 mt-2">Tab 1</h3>
<p>
lorem content for tab item 1
</p>
</div>
<div hidden class="px-4 text-sm text-gray-500" id="tab-2">
<h3 class="text-xl font-bold text-gray-900 mt-2">Tab 2</h3>
<p>
lorem content for tab item 2
</p>
</div>
<div hidden class="px-4 text-sm text-gray-500" id="tab-3">
<h3 class="text-xl font-bold text-gray-900 mt-2">Tab 3</h3>
<p>
lorem content for tab item 3
</p>
</div>
<div hidden class="px-4 text-sm text-gray-500" id="tab-4">
<h3 class="text-xl font-bold text-gray-900 mt-2">Tab 4</h3>
<p>
lorem content for tab item 4
</p>
</div>
</headless-tabs>
Navigation with aria keyboard interactions
This component allow you to add hamburger toggle functionality to your navigation by adding aria labels to button
and the section you want to hide and show. The data attribute of data-state
can be used to style or hide element.
Events:
- Toggle mobile menu with mouse click events.
- Toggle mobile menu pressing down on Enter and Space keys.
- Close mobile menu pressing Esc Key.
- Close mobile menu by clicking outside menu.
- Add multiple data-state of open and close
- Support two-way binding on state change of data-state
Requirements:
- Button:
- must be typeof
button
- must add an attribute of
aria-expanded
aria-controls
- must be typeof
- Mobile Menu
- must have a html element with an
id
matchingaria-controls
- must have a html element with an
Unstyled navigation
<headless-navigation>
<button type="button" aria-expanded="false" aria-controls="menu">
menu
</button>
<div id="menu">
Dummy menu dropdown
</div>
</headless-navigation>
Styled navigation with tailwindcss
<headless-navigation class="relative z-50" popper>
<nav class="relative w-full bg-white rounded-md py-2 flex justify-end">
<button type="button" aria-expanded="false" aria-controls="menu" class="w-8 h-8 mr-10 border border-primary-900 flex justify-center items-center m-3 rounded-md">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
</svg>
</button>
<div id="menu" class="bg-white absolute inset-x-0 rounded-md p-4 w-full h-[400px]">
Dummy menu dropdown
</div>
</nav>
</headless-navigation>
Dark Mode Toggle button with keyboard interactions
The dark mode component will toggle between dark and light and save the result to localStorage.
Events:
- Toggle theme button with mouse click events.
- Toggle theme button pressing down on Enter and Space keys.
- Adds a
data-theme
to root component
Requirements:
- Button:
- must be typeof
button
- There must be at least 1
headless-darkmode
component on every page. It is recommended to use it with in a section that will be display on every page. Places like navigation or footer will work great.
- must be typeof
Dark mode toggle
<headless-darkmode class="inline-flex">
<button type="button" class="px-4 py-2 flex justify-center space-x-2 inline-block rounded-md dark:bg-white dark:text-gray-600 bg-gray-700 text-gray-100 shadow-md">
<svg style="width: 24px; height: 24px;" viewBox="0 0 24 24">
<path
fill="currentColor"
d="M7.5,2C5.71,3.15 4.5,5.18 4.5,7.5C4.5,9.82 5.71,11.85 7.53,13C4.46,13 2,10.54 2,7.5A5.5,5.5 0 0,1 7.5,2M19.07,3.5L20.5,4.93L4.93,20.5L3.5,19.07L19.07,3.5M12.89,5.93L11.41,5L9.97,6L10.39,4.3L9,3.24L10.75,3.12L11.33,1.47L12,3.1L13.73,3.13L12.38,4.26L12.89,5.93M9.59,9.54L8.43,8.81L7.31,9.59L7.65,8.27L6.56,7.44L7.92,7.35L8.37,6.06L8.88,7.33L10.24,7.36L9.19,8.23L9.59,9.54M19,13.5A5.5,5.5 0 0,1 13.5,19C12.28,19 11.15,18.6 10.24,17.93L17.93,10.24C18.6,11.15 19,12.28 19,13.5M14.6,20.08L17.37,18.93L17.13,22.28L14.6,20.08M18.93,17.38L20.08,14.61L22.28,17.15L18.93,17.38M20.08,12.42L18.94,9.64L22.28,9.88L20.08,12.42M9.63,18.93L12.4,20.08L9.87,22.27L9.63,18.93Z"
/>
</svg>
<span>Dark Mode</span>
</button>
</headless-darkmode>
Toggle Switch
The toggle component allow you to turn a button elements into toggle switch
Events
- Toggle switch with mouse click event
- Toggle switch by pressing down on Enter and Space keys.
Requirements
- Button element with type of button
<headless-toggle>
<headless-toggle class="flex items-center group">
<button
aria-checked="true"
class="group-data-switch-on:bg-primary-500 bg-gray-200 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
type="button"
>
<span class="sr-only">Use setting</span>
<span aria-hidden="true" class="group-data-switch-on:translate-x-5 translate-x-0 pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-50" data-switch></span>
</button>
</headless-toggle>
Styling toggle state
Markup the button the way you want and adding data-switch
to one or multiple elements. This will set the data
attribute to "on" or "off". Now you can style, hide or show elements by styling data attribute. By default, this
attribute will be added to the top level component.
headless-toggle[data-switch="on"] button[aria-checked] {
background: indigo;
}
headless-toggle[data-switch="on"] span[aria-hidden="true"] {
transform: translateX(20px);
}
Directives
Directives are markers on a DOM element to attach a specified behavior to that DOM element.
Button directive
The button directive just adds event listeners to set aria-pressed attributes to a button element. Just add
is="headless-button"
to button element. Use css to style button using css propery button[aria-pressed=true]
or button[aria-pressed=false]
Events
- Add
aria-pressed="true | false"
on keydown, keyup, mouse click
Requirements:
- Must be a
button
element. - Just add
is="headless-button"
to button elements
ScrollTop with aria keyboard interactions (Extends HeadlessButton)
The scroll-to-top button makes it super easy to add this feature to your website. Just add a button and add the
attribute of is="headless-scrolltop"
and that is it.
Events:
- Hide button on initial load.
- Hide and show button on scroll.
- Scroll to top on Mouse click.
- Scroll to top on Keydown for Space, Enter and Ctrl + Home.
Requirements:
- Button:
- must be typeof
button
- must add an attribute of
is="headless-scrolltop"
- must be typeof
<button type="button" is="headless-scrolltop">Scroll to top</button>
GoBack with aria keyboard interactions (Extends HeadlessButton)
The headless-goback
directive allow you to turn a button into go to previous page button using window.history
and adding the necessary aria indicators and events
Events:
- Trigger element on mouse click event
- Trigger element on keyboard event, when using Space or Enter
- Automatically set aria-pressed to true and false
<button type="button" is="headless-goback">Go Back</button>
PopperJs
PopperJs is already bundle in and only require an attribute of popper
to work. PopperJs only works on Popover,
DropDown and Navigation component.
Optional
- Popper.js
-
Required: Add attribute of
popper
orpopper="true"
to enable popper.js - Change placement with attribute
placement="bottom-end bottom-start"
- Change offset with attribute
offset="0 20"
-
Required: Add attribute of
Use with PopperJs
Attribute can be seperated by comma or empty space
<headless-dropdown popper placement="bottom-end bottom-start" ....
<headless-dropdown popper="true" placement="bottom-end,bottom-start" ....
<headless-dropdown popper offset="0 20" ....
<headless-dropdown popper="true" offset="0,20" ....
Contributing
Contributions to this plugin are welcome! If you encounter any issues, have feature requests, or want to improve the plugin, feel free to create a pull request or submit an issue on the GitHub repository.
Contributors
License
This project is licensed under the MIT License - see the LICENSE file for details.