@cakewalk/ngx-headlessui
v2.0.0
Published
headlessui for angular
Downloads
115
Readme
@cakewalk/ngx-headlessui
A set of completely unstyled, fully accessible UI components for Angular based on headlessui. Designed to integrate beautifully with Tailwind CSS.
New: Popover added
Installation
Tested with Angular 16.2.12 only.
# npm
npm install @cakewalk/ngx-headlessui
Components
This project is still in early development. So far, only Disclosure, Menu, Switch and Transition component is available. Also expect the API to change.
- Disclosure (Expandable and Collapsible Panel)
- Menu Button (Dropdown)
- Switch (Checkbox)
- Transition (Animation)
- Popover
Disclosure (Expandable and Collapsible Panel)
Disclosure are built using Button and Panel components which are warpped in Disclosure
Markup
<hux-disclosure>
<hux-disclosure-button>
<button class="flex w-full text-left mb-4">
<span class="flex-grow font-semibold">Header Text</span>
<svg class="text-indigo-600 w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
</hux-disclosure-button>
<hux-disclosure-panel>
panel content...
</hux-disclosure-panel>
</hux-disclosure>
Menu Button (Dropdown)
Basic example
Menu Buttons are built using the hlMenu
, hlMenuButton
, *hlMenuItems
, and *hlMenuItem
directives.
The menu button *hlMenuButton
will automatically open/close the *hlMenuItems
when clicked, and when the menu is open, the list of items receives focus and is automatically navigable via the keyboard.
<div hlMenu>
<button hlMenuButton class="w-full">More</button>
<div *hlMenuItems>
<a *hlMenuItem="let item" [class.bg-blue-500]="item.active" href="./#account-settings">
Account settings
</a>
<a *hlMenuItem="let item" [class.bg-blue-500]="item.active" href="./#documentation">
Documentation
</a>
<span *hlMenuItem="let item; disabled: true">
Invite a friend (coming soon!)
</span>
</div>
</div>
Styling the active item
This is a headless component so there are no styles included by default. Instead, the components expose useful information via let expressions that you can use to apply the styles you'd like to apply yourself.
To style the active hlMenuItem
you can read the active
state, which tells you whether or not that menu item is the item that is currently focused via the mouse or keyboard.
You can use this state to conditionally apply whatever active/focus styles you like, for instance a blue background like is typical in most operating systems.
<div hlMenu>
<button hlMenuButton>More</button>
<div *hlMenuItems>
<!-- Use the `active` state to conditionally style the active item. -->
<a *hlMenuItem="let item"
[class]="item.active ? 'bg-blue-500 text-white' : 'bg-white text-black'"
href="#settings">
Settings
</a>
</ul>
</div>
Switch (Checkbox)
The Switch
component and related child components are used to quickly build custom switch/toggle components that are fully accessible out of the box, including correct ARIA attribute management and robust keyboard support.
Switches are built using the Switch
component. Optionally you can also use the SwitchGroup
and SwitchLabel
components.
Markup:
<div SwitchGroup class="flex items-center space-x-4">
<button Switch (change)="onChange($event)" class="w-11 focus:outline-none focus:shadow-outline relative inline-flex flex-shrink-0 h-6 transition-colors duration-200 ease-in-out border-2 border-transparent rounded-full cursor-pointer" [ngClass]="{'bg-indigo-600': switchValue, 'bg-gray-200': !switchValue}">
<span class="inline-block w-5 h-5 transition duration-200 ease-in-out transform bg-white rounded-full" [ngClass]="{ 'translate-x-5': switchValue, 'translate-x-0': !switchValue }">
</span>
</button>
</div>
Using a custom label
By default the Switch will use the contents as the label for screenreaders. If you need more control, you can render a SwitchLabel outside of the Switch, as long as both the switch and label are within a parent SwitchGroup.
Clicking the label will toggle the switch state, like you'd expect from a native checkbox.
<div SwitchGroup class="flex items-center space-x-4">
<span class="flex flex-col">
<label SwitchLabel class="text-sm font-medium leading-5 text-gray-900">Enable notifications</label>
</span>
<button Switch (change)="onChange($event)" class="w-11 focus:outline-none focus:shadow-outline relative inline-flex flex-shrink-0 h-6 transition-colors duration-200 ease-in-out border-2 border-transparent rounded-full cursor-pointer" [ngClass]="{'bg-indigo-600': switchValue, 'bg-gray-200': !switchValue}">
<span class="inline-block w-5 h-5 transition duration-200 ease-in-out transform bg-white rounded-full" [ngClass]="{ 'translate-x-5': switchValue, 'translate-x-0': !switchValue }"></span>
</button>
</div>
Transition (Animation)
The Transition
component lets you add enter/leave transitions to conditionally rendered elements, using CSS classes to control the actual transition styles in the different stages of the transition.
Markup:
<transition
enter="transition-opacity duration-75"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity duration-150"
leaveFrom="opacity-100"
leaveTo="opacity-0">
<span>I will fade in and out</span>
</transition>
By default, a Transition
will enter and leave instantly, which is probably not what you're looking for if you're using this library.
To animate your enter/leave transitions, add classes that provide the styling for each phase of the transitions using these props:
enter
Applied the entire time an element is entering. Usually you define your duration and what properties you want to transition here, for example transition-opacity duration-75.enterFrom
The starting point to enter from, for example opacity-0 if something should fade in.enterTo
The ending point to enter to, for example opacity-100 after fading in.leave
Applied the entire time an element is leaving. Usually you define your duration and what properties you want to transition here, for example transition-opacity duration-75.leaveFrom
The starting point to leave from, for example opacity-100 if something should fade out.leaveTo
The ending point to leave to, for example opacity-0 after fading out.
Props
| Prop | Type | Description |
| ------------- |:-------------:|:-----|
| show
| Boolean | Whether the children should be shown or hidden. |
| enter
| String (Default: '') | Classes to add to the transitioning element during the entire enter phase. |
| enterFrom
| String (Default: '') | Classes to add to the transitioning element before the enter phase starts. |
| enterTo
| String (Default: '') | Classes to add to the transitioning element immediately after the enter phase starts. |
| leave
| String (Default: '') | Classes to add to the transitioning element during the entire leave phase. |
| leaveFrom
| String (Default: '') | Classes to add to the transitioning element before the leave phase starts. |
| leaveTo
| String (Default: '') | Classes to add to the transitioning element immediately after the leave phase starts. |
| beforeEnter
| Function | Callback which is called before we start the enter transition. |
| afterEnter
| Function | Callback which is called after we finished the enter transition. |
| beforeLeave
| Function |Callback which is called before we start the leave transition. |
| afterLeave
| Function | Callback which is called after we finished the leave transition. |
Popover
Popover are built using Button and Panel components which are wrapped in Popover
Markup
<hux-popover>
<hux-popover-button>
<button class="flex w-full text-left mb-4">
<span class="flex-grow font-semibold">Open Popover</span>
<svg class="text-indigo-600 w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
</hux-popover-button>
<hux-popover-panel>
panel content...
</hux-popover-panel>
</hux-popover>