Skip to content

QuesoCollapsible ​

A collapsible content component with smooth animations and comprehensive accessibility support. It provides a header that can be clicked to expand/collapse content with automatic ARIA attributes and keyboard navigation.

Basic Usage ​

vue
<template>
    <queso-collapsible>
        <template #headerText> Click to expand </template>
        <template #content>
            <p>This content can be expanded and collapsed.</p>
        </template>
    </queso-collapsible>
</template>

<script setup>
import { QuesoCollapsible } from "@allomambo/queso";
</script>

Props ​

expandOnMount ​

  • Type: boolean
  • Default: false
  • Description: When true, the collapsible content will be expanded when the component is first mounted.

Emits ​

collapsible:open ​

  • Payload: void
  • Description: Emitted when the collapsible is opened.

collapsible:close ​

  • Payload: void
  • Description: Emitted when the collapsible is closed.

collapsible:toggle ​

  • Payload: boolean
  • Description: Emitted when the collapsible state changes. The boolean indicates if it's now open.

Slots ​

  • Props: { isCollapsibleOpen: boolean }
  • Description: Completely replaces the entire header content.

headerPrefix ​

  • Description: Content to display before #headerText.

headerText ​

  • Props: { isCollapsibleOpen: boolean }
  • Description: The main text content of the header.

headerSuffix ​

  • Description: Content to display after #headerText.

headerIcon ​

  • Props: { isCollapsibleOpen: boolean }
  • Description: The icon displayed in the header. Defaults to "↓".

beforeHeader ​

  • Description: Content to display before the header.

afterHeader ​

  • Description: Content to display after the header.

content ​

  • Description: The collapsible content that will be shown/hidden.

beforeContent ​

  • Description: Content to display before the collapsible content.

afterContent ​

  • Description: Content to display after the collapsible content.

Examples ​

Basic Collapsible ​

vue
<template>
    <queso-collapsible>
        <template #headerText> Click to expand </template>
        <template #content>
            <p>This content can be expanded and collapsed.</p>
        </template>
    </queso-collapsible>
</template>
html
<div class="queso-collapsible is-collapsible-close">
    <div
        class="queso-collapsible__header"
        aria-expanded="false"
        aria-controls="queso-collapsible__abc123"
        tabindex="0"
    >
        <div class="queso-collapsible__header__text">Click to expand</div>
        <div class="queso-collapsible__header__icon">↓</div>
    </div>
    <div class="queso-collapsible__content" id="queso-collapsible__abc123">
        <div class="queso-collapsible__content__inner">
            <p>This content can be expanded and collapsed.</p>
        </div>
    </div>
</div>

Expanded on Mount ​

vue
<template>
    <queso-collapsible expand-on-mount>
        <template #headerText> Already expanded </template>
        <template #content>
            <p>This content starts expanded.</p>
        </template>
    </queso-collapsible>
</template>

Custom Header with Slots ​

vue
<template>
    <queso-collapsible>
        <template #headerPrefix>
            <span class="icon">📁</span>
        </template>
        <template #headerText="{ isCollapsibleOpen }">
            {{ isCollapsibleOpen ? "Hide details" : "Show details" }}
        </template>
        <template #headerSuffix>
            <span class="badge">3 items</span>
        </template>
        <template #headerIcon="{ isCollapsibleOpen }">
            {{ isCollapsibleOpen ? "↑" : "↓" }}
        </template>
        <template #content>
            <ul>
                <li>Item 1</li>
                <li>Item 2</li>
                <li>Item 3</li>
            </ul>
        </template>
    </queso-collapsible>
</template>
html
<div class="queso-collapsible is-collapsible-close">
    <div
        class="queso-collapsible__header"
        aria-expanded="false"
        aria-controls="queso-collapsible__abc123"
        tabindex="0"
    >
        <span class="icon">📁</span>
        <div class="queso-collapsible__header__text">Show details</div>
        <span class="badge">3 items</span>
        <div class="queso-collapsible__header__icon">↓</div>
    </div>
    <div class="queso-collapsible__content" id="queso-collapsible__abc123">
        <div class="queso-collapsible__content__inner">
            <ul>
                <li>Item 1</li>
                <li>Item 2</li>
                <li>Item 3</li>
            </ul>
        </div>
    </div>
</div>
html
<div class="queso-collapsible is-collapsible-open">
    <div
        class="queso-collapsible__header"
        aria-expanded="true"
        aria-controls="queso-collapsible__abc123"
        tabindex="0"
    >
        <span class="icon">📁</span>
        <div class="queso-collapsible__header__text">Hide details</div>
        <span class="badge">3 items</span>
        <div class="queso-collapsible__header__icon">↑</div>
    </div>
    <div class="queso-collapsible__content" id="queso-collapsible__abc123">
        <div class="queso-collapsible__content__inner">
            <ul>
                <li>Item 1</li>
                <li>Item 2</li>
                <li>Item 3</li>
            </ul>
        </div>
    </div>
</div>

With Event Handling ​

vue
<template>
    <queso-collapsible
        @collapsible:open="handleOpen"
        @collapsible:close="handleClose"
        @collapsible:toggle="handleToggle"
    >
        <template #headerText> Interactive collapsible </template>
        <template #content>
            <p>This collapsible triggers events when opened/closed.</p>
        </template>
    </queso-collapsible>
</template>

<script setup>
const handleOpen = () => {
    console.log("Collapsible opened");
};

const handleClose = () => {
    console.log("Collapsible closed");
};

const handleToggle = (isOpen) => {
    console.log("Collapsible toggled:", isOpen);
};
</script>

Exposed Methods ​

open() ​

Opens the collapsible content.

close() ​

Closes the collapsible content.

toggle() ​

Toggles the collapsible content between open and closed states.

isCollapsibleOpen ​

Reactive boolean indicating the current open state.

Behavior ​

  • Smooth Animation: Content expands/collapses with CSS transitions
  • Keyboard Navigation: Supports Space key to toggle
  • Accessibility: Automatic ARIA attributes (aria-expanded, aria-controls)
  • Height Calculation: Automatically calculates content height for smooth animations
  • CSS Customization: Uses CSS custom properties for timing and easing

Accessibility ​

The component automatically handles:

  • aria-expanded attribute for screen readers
  • aria-controls attribute linking to the content
  • tabindex="0" for keyboard navigation
  • Space key support for toggling
  • Proper semantic structure

CSS ​

Classes ​

The component applies the following CSS classes:

  • .queso-collapsible - Base class
  • .is-collapsible-open - Applied when content is expanded
  • .is-collapsible-close - Applied when content is collapsed
  • .queso-collapsible__header - Header container
  • .queso-collapsible__content - Content container
  • .queso-collapsible__content__inner - Inner content wrapper

Custom Properties ​

  • --queso-collapsible-duration - Animation duration (default: 0.5s)
  • --queso-collapsible-ease - Animation easing (default: ease)
  • --queso-collapsible-header-align - Header alignment (default: center)
  • --queso-collapsible-header-justify - Header justification (default: flex-start)

Type Declaration ​

ts
export interface QuesoCollapsibleProps {
    expandOnMount?: boolean;
}