flexcord
v0.1.1
Published
Flexible, ARIA-first accordions which work with your existing CSS, markup, and code
Downloads
22
Maintainers
Readme
flexcord
- NAME
- INSTALLATION
- SYNOPSIS
- DESCRIPTION
- WHY?
- TERMINOLOGY
- TYPES
- EXPORTS
- Options
- Events
- DEVELOPMENT
- COMPATIBILITY
- SEE ALSO
- VERSION
- AUTHOR
- COPYRIGHT AND LICENSE
NAME
flexcord - flexible ARIA-first accordions which work with your existing CSS, markup, and code
INSTALLATION
$ npm install flexcord
SYNOPSIS
JavaScript
import { Accordion, MultiAccordion } from 'flexcord'
for (const el of document.querySelectorAll('.accordion')) {
const klass = el.hasAttribute('data-multi-select') ? MultiAccordion : Accordion
klass.mount(el, options)
}
CSS
/* hide closed panels (the default) */
.accordion [aria-hidden="true"] {
display: none;
}
HTML
before:
<div class="accordion">
<div role="heading">
<button aria-controls="foo-panel">Foo</button>
</div>
<section id="foo-panel">...</section>
<div role="heading">
<button aria-controls="bar-panel" aria-expanded="true">Bar</button>
</div>
<section id="bar-panel">...</section>
<div role="heading">
<button aria-controls="baz-panel">Baz</button>
</div>
<section id="baz-panel">...</section>
</div>
after:
<div role="presentation" class="accordion">
<div role="heading">
<button
id="header-abc"
aria-controls="foo-panel"
aria-expanded="false">Foo</button>
</div>
<section
id="foo-panel"
role="region"
aria-labelledby="header-abc"
aria-hidden="true">...</section>
<div role="heading">
<button
id="header-def"
aria-controls="bar-panel"
aria-expanded="true">Bar</button>
</div>
<section
id="bar-panel"
role="region"
aria-labelledby="header-def"
aria-hidden="false">...</section>
<div role="heading">
<button
id="header-ghi"
aria-controls="baz-panel"
aria-expanded="false">Baz</button>
</div>
<section
id="baz-panel"
role="region"
aria-labelledby="header-ghi"
aria-hidden="true">...</section>
</div>
DESCRIPTION
flexcord is a library which implements flexible, ARIA-first accordions which work with your markup, CSS and code rather than the other way round.
WHY?
There are many accordion implementations on NPM, but most of them bake into their APIs the specific use case for which they were conceived, usually in the form of classes and/or data attributes that must be defined in the HTML and overridden in the CSS to take advantage of their functionality.
This makes them perfect for anyone who has exactly the same use case, and inconvenient for anyone who doesn't. flexcord is designed to adapt to the conventions your app or framework already uses, while also supporting zero-configuration usage out of the box by leveraging the conventions established in the WAI-ARIA accordion design-pattern.
TERMINOLOGY
The following terms are used in the description below:
header
A header-like element (e.g. H1, H2 etc.) which typically contains a button-like element which triggers the opening/closing of its corresponding accordion panel.
button
A clickable element within a header which triggers the opening/closing of its corresponding accordion panel.
panel
A section which is displayed when an accordion header is activated/expanded and hidden when it is de-activated/collapsed.
TYPES
The following types are referenced in the descriptions below:
AccordionItem
An object representing a header/panel pair in an accordion:
type AccordionItem = {
accordion: HTMLElement;
button: HTMLElement;
header: HTMLElement;
index: number;
isOpen: boolean;
panel: HTMLElement;
}
Options
Optional hooks to configure an accordion's HTML bindings and behavior.
type Options = {
header?: string | (accordion: HTMLElement) => Iterable<HTMLElement>;
button?: string | ({ accordion: HTMLElement, header: HTMLElement }) => HTMLElement;
disabled?: (item: AccordionItem, next: () => boolean) => boolean;
panel?: ({ accordion: HTMLElement, button: HTMLElement, header: HTMLElement }) => HTMLElement;
}
EXPORTS
Accordion
An accordion in which no more than one panel can be open at a time.
METHODS
Accordion.mount
Type: (el: HTMLElement, options?: Options) → Accordion
An alternative way to call the accordion class's constructor i.e.:
Accordion.mount(el, options)
is equivalent to:
new Accordion(el, options)
close
Type: () → this
Closes the currently open panel, if any.
Type: (index: number) → this
Closes the panel at the specified (0-based) index.
open
Type: (index: number) → this
Opens the panel at the specified (0-based) index.
toggle
Type: (index: number, open?: boolean) → this
Toggles the panel at the specified (0-based) index i.e. opens it if it's closed or closes it if it's open. Can take an optional boolean state to set the panel to.
MultiAccordion
An accordion in which mupltiple panels can be open at the same time.
METHODS
MultiAccordion.mount
Type: (el: HTMLElement, options?: Options) → MultiAccordion
An alternative way to call the accordion class's constructor. See Accordion.mount
for more details.
close
Type: () → this
Closes all open panels.
Type: (index: number) → this
Closes the panel at the specified (0-based) index.
Type: (index: Array<number>) → this
Closes the panel at the specified (0-based) indices.
open
Type: () → this
Opens all open panels.
Type: (index: number) → this
Opens the panel at the specified (0-based) index.
Type: (index: Array<number>) → this
Opens the panel at the specified (0-based) indices.
toggle
Type: () → this
Toggles the open state of all panels i.e. opens all closed panels and closes all open panels.
Type: (index: number) → this
Toggles the open state of the panel at the specified (0-based) index.
Type: (indices: Array<number>) → this
Toggles the open state of the panels at the specified (0-based) indices.
Options
The constructor takes an optional Options object with the following (optional) fields.
header
Type: string | (accordion: HTMLElement) → Iterable<HTMLElement>
Default: "[role='heading']"
A selector which returns a collection (e.g. NodeList, Array, jQuery instance etc.) of DOM elements representing the header-like elements inside the accordion. Headers are elements which contain (or are) an element which triggers the opening/closing of the corresponding panel.
The default value matches elements with a heading
role.
If supplied as a string, it is interepeted as a CSS3 selector and converted into a function which
returns a NodeList resulting from the evaluation of the selector against the accordion with querySelectorAll
.
button
Type: string | ({ accordion: HTMLElement, header: HTMLElement }) → HTMLElement
Default: "[aria-controls]"
A selector (string) or function which returns an element in the header which functions like a button.
An onclick
event handler is attached to this element which triggers the opening/closing of the
associated panel.
The default value selects the first element in the header with a non-empty aria-controls
attribute.
Typically, the button element is the child/descendant of an element which functions like a header
element (e.g. H1, H2 etc.). By default, this is an element with a heading
role e.g.:
<div class="accordion">
<div role="heading">
<button aria-controls="foo-panel">Foo</button>
</div>
<section id="foo-panel">...</section>
<div role="heading">
<button aria-controls="bar-panel">Bar</button>
</div>
<section id="bar-panel">...</section>
</div>
- but they can easily be the same element if a suitable selector is supplied e.g.:
<div class="accordion">
<button aria-controls="foo-panel">Foo</button>
<section id="foo-panel">...</section>
<button aria-controls="bar-panel">Bar</button>
<section id="bar-panel">...</section>
</div>
Accordion.mount(el, {
header: '[aria-controls]',
button: ({ accordion, header }) => header,
})
disabled
Type: (item: AccordionItem, next: () → boolean) → boolean
A callback used to determine whether an item is disabled. Disabled items don't respond to open or close (or toggle) actions.
The next
parameter is a function which calls the default disabled
implementation with the same AccordionItem object.
The default implementation returns true if the item's button element has an aria-disabled="true"
attribute, or false otherwise.
Can be used e.g. to avoid opening/closing items with a disabled button:
// disable <button disabled>...</button> as well as <button aria-disabled="true">...</button>
function disabled ({ button }, next) {
return button.hasAttribute('disabled') || next()
}
const accordion = new Accordion(el, { disabled })
- or to disable every item in an accordion:
<div class="accordion" data-disabled="true">
...
</div>
function disabled ({ accordion }) {
return accordion.getAttribute('data-disabled') === 'true'
}
const accordion = new Accordion(el, { disabled })
panel
Type: string | ({ accordion: HTMLElement, button: HTMLElement, header: HTMLElement }) → HTMLElement
The container of the content to display/hide when the corresponding header is activated/de-activated.
The default value is a function which selects the element whose ID corresponds to the button's aria-controls
ID.
Events
Accordions implement the EventEmitter interface and support the following events.
before:change
Type: (item: AccordionItem, type: string, accordion: Accordion) → void
Fired after a button is clicked and before its corresponding panel is opened or closed. Passed the action (i.e. "open" or "close") as a parameter.
before:close
Type: (item: AccordionItem, accordion: Accordion) → void
Fired after a button is clicked and before its corresponding panel is closed.
before:open
Type: (item: AccordionItem, accordion: Accordion) → void
Fired after a button is clicked and before its corresponding panel is opened.
change
Type: (item: AccordionItem, type: string, accordion: Accordion) → void
Fired after a panel is opened or closed. Passed the action (i.e. "open" or "close") as a parameter.
close
Type: (item: AccordionItem, accordion: Accordion) → void
Fired after a panel is closed.
open
Type: (item: AccordionItem, accordion: Accordion) → void
Fired after a panel is opened.
DEVELOPMENT
NPM Scripts
The following NPM scripts are available:
- build - compile and bundle the library for testing and release
- clean - remove temporary files and build artifacts
- test - run the test suite
COMPATIBILITY
- > 1% of browsers
- IE 11
- not Opera Mini
SEE ALSO
- @accede-web/accordion - a dependency-free WAI-ARIA accordion plugin
- @accede-web/tablist - a dependency-free WAI-ARIA tab plugin
- element-scope-ids - scope IDs to an element by rewriting them to be globally unique
- posthtml-aria-tabs - a PostHTML plugin for creating accessible tabs with minimal markup
VERSION
0.1.1
AUTHOR
COPYRIGHT AND LICENSE
Copyright © 2018-2019 by chocolateboy.
This is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0.