Have ideas to improve npm?Join in the discussion! »

    flexcord
    TypeScript icon, indicating that this package has built-in type declarations

    0.1.1 • Public • Published

    flexcord

    Build Status NPM Version

    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

    VERSION

    0.1.1

    AUTHOR

    chocolateboy

    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.

    Install

    npm i flexcord

    DownloadsWeekly Downloads

    1

    Version

    0.1.1

    License

    Artistic-2.0

    Unpacked Size

    244 kB

    Total Files

    15

    Last publish

    Collaborators

    • avatar