Aether JS AetherJS

Accordion

The accordion components below are built with AetherJS state management. Triggers and panels grouped within the data-aether-ui="accordion-group" container automatically operate in accordance with accessibility (ARIA) standards.


01 Simple Accordion

A standard accordion structure. If the data-aether-allow-multiple attribute is not present in the container, one item closes automatically when another opens. data-aether-default-open can be added to the item intended to be open by default.

AetherUI is a headless, utility-first interaction controller designed to handle complex UI states without imposing any specific styling.
Simply include the script in your project. It initializes automatically on DOM content loaded for elements with the auto-init attribute.
Yes! AetherUI automatically manages ARIA attributes like aria-expanded, aria-hidden, and aria-controls for you.
index.html
<!-- Wrapper -->
<div class="w-full max-w-lg space-y-4" data-aether-ui="accordion-group">

    <!-- Item 1 -->
    <div class="border border-primary rounded-xl overflow-hidden">
        <button class="w-full flex items-center justify-between p-4 bg-primary/20 hover:bg-primary/40 text-secondary hover:text-primary transition-colors group text-left"
            data-aether-trigger="accordion"
            data-aether-target="acc-item-1"
            data-aether-default-open
            data-aether-active-class="bg-primary/60 text-primary"
            data-aether-inactive-class="bg-primary/20 text-secondary">
            <span class="font-medium">What is AetherUI?</span>
            <svg class="size-5 transition-transform duration-300 group-aria-expanded:rotate-180 opacity-70" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
            </svg>
        </button>
        <div id="acc-item-1" class="bg-secondary" data-aether-ui="accordion-panel">
            <div class="p-4 text-sm text-secondary leading-relaxed border-t border-primary">
                AetherUI is a headless, utility-first interaction controller designed to handle complex UI states without imposing any specific styling.
            </div>
        </div>
    </div>

    <!-- Item 2 -->
    <div class="border border-primary rounded-xl overflow-hidden">
        <button class="w-full flex items-center justify-between p-4 bg-primary/20 hover:bg-primary/40 text-secondary hover:text-primary transition-colors group text-left"
            data-aether-trigger="accordion"
            data-aether-target="acc-item-2"
            data-aether-active-class="bg-primary/60 text-primary"
            data-aether-inactive-class="bg-primary/20 text-secondary">
            <span class="font-medium">How do I install it?</span>
            <svg class="size-5 transition-transform duration-300 group-aria-expanded:rotate-180 opacity-70" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
            </svg>
        </button>
        <div id="acc-item-2" class="bg-secondary" data-aether-ui="accordion-panel">
            <div class="p-4 text-sm text-secondary leading-relaxed border-t border-primary">
                Simply include the script in your project. It initializes automatically on DOM content loaded for elements with the auto-init attribute.
            </div>
        </div>
    </div>

    <!-- Item 3 -->
    <div class="border border-primary rounded-xl overflow-hidden">
        <button class="w-full flex items-center justify-between p-4 bg-primary/20 hover:bg-primary/40 text-secondary hover:text-primary transition-colors group text-left"
            data-aether-trigger="accordion"
            data-aether-target="acc-item-3"
            data-aether-active-class="bg-primary/60 text-primary"
            data-aether-inactive-class="bg-primary/20 text-secondary">
            <span class="font-medium">Is it accessible?</span>
            <svg class="size-5 transition-transform duration-300 group-aria-expanded:rotate-180 opacity-70" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
            </svg>
        </button>
        <div id="acc-item-3" class="bg-secondary" data-aether-ui="accordion-panel">
            <div class="p-4 text-sm text-secondary leading-relaxed border-t border-primary">
                Yes! AetherUI automatically manages ARIA attributes like aria-expanded, aria-hidden, and aria-controls for you.
            </div>
        </div>
    </div>

</div>

02 Nested Accordion

You can create multi-level hierarchical structures (file explorer, categories, etc.) by adding new accordion groups inside accordion panels.

Project Files

Button.vue
Modal.vue
App.vue
logo.png
index.html
<!-- Wrapper -->
<div class="w-full max-w-sm bg-primary/20 border border-primary rounded-2xl p-4" data-aether-ui="accordion-group">
    <h3 class="text-xs font-bold text-tertiary uppercase tracking-wider mb-3 ml-2">Project Files</h3>

    <!-- Folder: src -->
    <div class="mb-1">
        <button class="w-full flex items-center gap-2 p-2 rounded-lg text-sm group hover:bg-primary/30 transition-colors"
            data-aether-trigger="accordion"
            data-aether-target="folder-src"
            data-aether-default-open
            data-aether-active-class="text-primary"
            data-aether-inactive-class="text-secondary">
            <svg class="size-4 text-tertiary transition-transform duration-200 group-aria-expanded:rotate-90" fill="currentColor" viewBox="0 0 20 20">
                <path d="M6 6L14 10L6 14V6Z" />
            </svg>
            <svg class="size-5 text-accent opacity-80" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
            </svg>
            <span class="font-medium">src</span>
        </button>
        <div id="folder-src" class="pl-6 py-1" data-aether-ui="accordion-panel">
            
            <!-- Nested Group: Components -->
            <div class="border-l border-primary pl-2" data-aether-ui="accordion-group">
                <button class="w-full flex items-center gap-2 p-2 rounded-lg text-secondary text-sm group hover:bg-primary/30 transition-colors"
                    data-aether-trigger="accordion"
                    data-aether-target="folder-components"
                    data-aether-active-class="text-primary"
                    data-aether-inactive-class="text-secondary">
                    <svg class="size-4 text-tertiary transition-transform duration-200 group-aria-expanded:rotate-90" fill="currentColor" viewBox="0 0 20 20">
                        <path d="M6 6L14 10L6 14V6Z" />
                    </svg>
                    <svg class="size-5 text-accent opacity-60" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
                    </svg>
                    <span>components</span>
                </button>
                <div id="folder-components" class="pl-6" data-aether-ui="accordion-panel">
                    <div class="flex items-center gap-2 p-2 text-sm text-tertiary hover:text-primary cursor-pointer">
                        <svg class="size-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
                        </svg>
                        Button.vue
                    </div>
                    <div class="flex items-center gap-2 p-2 text-sm text-tertiary hover:text-primary cursor-pointer">
                        <svg class="size-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
                        </svg>
                        Modal.vue
                    </div>
                    <div class="flex items-center gap-2 p-2 text-sm text-tertiary hover:text-primary cursor-pointer">
                        <svg class="size-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
                        </svg>
                        App.vue
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- Folder: assets -->
    <div class="mb-1">
        <button class="w-full flex items-center gap-2 p-2 rounded-lg text-secondary text-sm group hover:bg-primary/30 transition-colors"
            data-aether-trigger="accordion"
            data-aether-target="folder-assets"
            data-aether-active-class="text-primary"
            data-aether-inactive-class="text-secondary">
            <svg class="size-4 text-tertiary transition-transform duration-200 group-aria-expanded:rotate-90" fill="currentColor" viewBox="0 0 20 20">
                <path d="M6 6L14 10L6 14V6Z" />
            </svg>
            <svg class="size-5 text-accent opacity-80" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
            </svg>
            <span class="font-medium">assets</span>
        </button>
        <div id="folder-assets" class="pl-6 py-1" data-aether-ui="accordion-panel">
            <div class="flex items-center gap-2 p-2 text-sm text-tertiary hover:text-primary cursor-pointer">
                <svg class="size-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
                </svg>
                logo.png
            </div>
        </div>
    </div>

</div>