Collapsible
This library is a work-in-progress. We are releasing it early to gather feedback, but it is not ready for production.
A collapsible is a standalone component that allows users to show and hide a single section of content. Unlike accordions which manage multiple items, collapsibles work independently and are ideal for revealing optional information, FAQs, or additional details on demand.
Examples
Live Preview
Basic Collapsible (Default)
By default, the Collapsible provides a chevron which points down when closed, then rotates 180° to point up when open. See below for how to opt out or use different indicators.
This is the collapsible content that can be shown or hidden. The default chevron indicator rotates smoothly when toggled.
X Indicator
Plus rotated 180° (upside down) when closed, rotates to 45° forming an X when open.
Plus transforms into X when opened. This provides a modern, dynamic visual indicator.
Plus/Minus Indicator
Plus transitions to minus when open with smooth animation.
Plus changes to minus when opened. Classic expand/collapse indicator style.
No Indicator
Collapsible without any visual indicator.
Clean header without indicator icon. Minimal design focused on content.
Indicator Comparison
Toggle each collapsible to see how the different indicators behave.
The chevron points down when closed and up when open via rotation.
Starts as an upside-down plus sign and rotates 45° to form an X when open.
Shows a plus icon when closed and swaps to a minus icon when open.
No indicator is shown at all.
Bordered
This collapsible has a border around it for visual separation.
With Shadow
This collapsible has a box-shadow applied for depth.
Combined Features
This collapsible combines both border and shadow styling for maximum visual impact.
Open by Default
This collapsible starts in an open state using the open prop.
Rich Content
Technical Specifications
- Processor: Octa-core 2.8 GHz
- Memory: 8GB RAM
- Storage: 256GB SSD
- Display: 15.6" Full HD
Warranty: 2 years manufacturer warranty with optional extended coverage available.
FAQ Example
AgnosticUI is a framework-agnostic component library built with web components. It works seamlessly with React, Vue, Svelte, Angular, and vanilla JavaScript.
You can install AgnosticUI via npm:
npm install agnosticui-core
Yes! All AgnosticUI components are built with accessibility in mind, following WAI-ARIA best practices and ensuring keyboard navigation and screen reader support.
Absolutely! AgnosticUI uses CSS Shadow Parts to allow deep customization of component internals while maintaining encapsulation. You can also use design tokens for consistent theming across your application.
Nested Collapsibles
This is the main content area.
Nested collapsible content for subtopic A. Note the different indicator style.
Nested collapsible content for subtopic B.
Interactive with Event Handling
The collapsible dispatches a toggle event when opened or closed.
Current state: Collapsed
CSS Parts Customization
Customize collapsible appearance using CSS Shadow Parts without breaking encapsulation.
This collapsible uses a gradient background with white text and custom styling.
View Vue Code
<template>
<section>
<div class="mbe4">
<h2>Basic Collapsible (Default)</h2>
<p
class="mbe2"
style="color: var(--ag-text-secondary); font-size: 0.875rem;"
>
By default, the Collapsible provides a chevron which points down when closed, then rotates 180° to point up when open. See below for how to opt out or use different indicators.
</p>
</div>
<div class="stacked mbe4">
<VueCollapsible use-chevron>
<template #summary>
<span>Click to expand</span>
</template>
<p>This is the collapsible content that can be shown or hidden. The default chevron indicator rotates smoothly when toggled.</p>
</VueCollapsible>
</div>
<div class="mbe4">
<h2>X Indicator</h2>
<p
class="mbe2"
style="color: var(--ag-text-secondary); font-size: 0.875rem;"
>
Plus rotated 180° (upside down) when closed, rotates to 45° forming an X when open.
</p>
</div>
<div class="stacked mbe4">
<VueCollapsible use-x>
<template #summary>
<span>X Indicator</span>
</template>
<p>Plus transforms into X when opened. This provides a modern, dynamic visual indicator.</p>
</VueCollapsible>
</div>
<div class="mbe4">
<h2>Plus/Minus Indicator</h2>
<p
class="mbe2"
style="color: var(--ag-text-secondary); font-size: 0.875rem;"
>
Plus transitions to minus when open with smooth animation.
</p>
</div>
<div class="stacked mbe4">
<VueCollapsible use-minus>
<template #summary>
<span>Plus/Minus Indicator</span>
</template>
<p>Plus changes to minus when opened. Classic expand/collapse indicator style.</p>
</VueCollapsible>
</div>
<div class="mbe4">
<h2>No Indicator</h2>
<p
class="mbe2"
style="color: var(--ag-text-secondary); font-size: 0.875rem;"
>
Collapsible without any visual indicator.
</p>
</div>
<div class="stacked mbe4">
<VueCollapsible no-indicator>
<template #summary>
<span>No Indicator</span>
</template>
<p>Clean header without indicator icon. Minimal design focused on content.</p>
</VueCollapsible>
</div>
<div class="mbe4">
<h2>Indicator Comparison</h2>
<p
class="mbe2"
style="color: var(--ag-text-secondary); font-size: 0.875rem;"
>
Toggle each collapsible to see how the different indicators behave.
</p>
</div>
<div class="stacked mbe4">
<VueCollapsible
bordered
use-chevron
>
<template #summary>
<span>Chevron (default) - Rotates 180°</span>
</template>
<p>The chevron points down when closed and up when open via rotation.</p>
</VueCollapsible>
<VueCollapsible
bordered
use-x
>
<template #summary>
<span>X Indicator - Rotates from upside-down plus to X</span>
</template>
<p>Starts as an upside-down plus sign and rotates 45° to form an X when open.</p>
</VueCollapsible>
<VueCollapsible
bordered
use-minus
>
<template #summary>
<span>Plus/Minus - Swaps icons</span>
</template>
<p>Shows a plus icon when closed and swaps to a minus icon when open.</p>
</VueCollapsible>
<VueCollapsible
bordered
no-indicator
>
<template #summary>
<span>No Indicator - Completely hidden</span>
</template>
<p>No indicator is shown at all.</p>
</VueCollapsible>
</div>
<div class="mbe4">
<h2>Bordered</h2>
</div>
<div class="stacked mbe4">
<VueCollapsible bordered>
<template #summary>
<span>Bordered collapsible</span>
</template>
<p>This collapsible has a border around it for visual separation.</p>
</VueCollapsible>
</div>
<div class="mbe4">
<h2>With Shadow</h2>
</div>
<div class="stacked mbe4">
<VueCollapsible shadow>
<template #summary>
<span>Collapsible with shadow</span>
</template>
<p>This collapsible has a box-shadow applied for depth.</p>
</VueCollapsible>
</div>
<div class="mbe4">
<h2>Combined Features</h2>
</div>
<div class="stacked mbe4">
<VueCollapsible
bordered
shadow
>
<template #summary>
<span>Bordered with shadow</span>
</template>
<p>This collapsible combines both border and shadow styling for maximum visual impact.</p>
</VueCollapsible>
</div>
<div class="mbe4">
<h2>Open by Default</h2>
</div>
<div class="stacked mbe4">
<VueCollapsible
bordered
open
>
<template #summary>
<span>Already expanded</span>
</template>
<p>This collapsible starts in an open state using the <code>open</code> prop.</p>
</VueCollapsible>
</div>
<div class="mbe4">
<h2>Rich Content</h2>
</div>
<div class="stacked mbe4">
<VueCollapsible
bordered
shadow
>
<template #summary>
<div class="flex-inline items-center">
<Info
color="var(--ag-primary)"
:size="18"
class="mie2"
/>
<strong>Product Details</strong>
</div>
</template>
<div>
<h4 style="margin-top: 0;">Technical Specifications</h4>
<ul>
<li>Processor: Octa-core 2.8 GHz</li>
<li>Memory: 8GB RAM</li>
<li>Storage: 256GB SSD</li>
<li>Display: 15.6" Full HD</li>
</ul>
<p>
<strong>Warranty:</strong> 2 years manufacturer warranty with optional
extended coverage available.
</p>
</div>
</VueCollapsible>
</div>
<div class="mbe4">
<h2>FAQ Example</h2>
</div>
<div class="stacked mbe4">
<VueCollapsible bordered>
<template #summary>
<span>What is AgnosticUI?</span>
</template>
<p>
AgnosticUI is a framework-agnostic component library built with web
components. It works seamlessly with React, Vue, Svelte, Angular, and
vanilla JavaScript.
</p>
</VueCollapsible>
<VueCollapsible bordered>
<template #summary>
<span>How do I install it?</span>
</template>
<p>You can install AgnosticUI via npm:</p>
<pre style="background: var(--ag-background-secondary); padding: 1rem; border-radius: 4px; overflow-x: auto;">npm install agnosticui-core</pre>
</VueCollapsible>
<VueCollapsible bordered>
<template #summary>
<span>Is it accessible?</span>
</template>
<p>
Yes! All AgnosticUI components are built with accessibility in mind,
following WAI-ARIA best practices and ensuring keyboard navigation and
screen reader support.
</p>
</VueCollapsible>
<VueCollapsible bordered>
<template #summary>
<span>Can I customize the styling?</span>
</template>
<p>
Absolutely! AgnosticUI uses CSS Shadow Parts to allow deep customization
of component internals while maintaining encapsulation. You can also use
design tokens for consistent theming across your application.
</p>
</VueCollapsible>
</div>
<div class="mbe4">
<h2>Nested Collapsibles</h2>
</div>
<div class="stacked mbe4">
<VueCollapsible bordered>
<template #summary>
<span>Level 1 - Main Topic</span>
</template>
<div>
<p>This is the main content area.</p>
<VueCollapsible
:bordered="true"
:use-minus="true"
style="margin-top: 1rem;"
>
<template #summary>
<span>Level 2 - Subtopic A</span>
</template>
<p>Nested collapsible content for subtopic A. Note the different indicator style.</p>
</VueCollapsible>
<VueCollapsible
:bordered="true"
:use-minus="true"
style="margin-top: 0.5rem;"
>
<template #summary>
<span>Level 2 - Subtopic B</span>
</template>
<p>Nested collapsible content for subtopic B.</p>
</VueCollapsible>
</div>
</VueCollapsible>
</div>
<div class="mbe4">
<h2>Interactive with Event Handling</h2>
</div>
<div class="stacked mbe4">
<VueCollapsible
bordered
shadow
@toggle="handleToggle"
>
<template #summary>
<span>Click to toggle (watch console)</span>
</template>
<div>
<p>The collapsible dispatches a <code>toggle</code> event when opened or closed.</p>
</div>
</VueCollapsible>
<p style="margin-top: 1rem;">
Current state: <strong>{{ isExpanded ? 'Expanded' : 'Collapsed' }}</strong>
</p>
</div>
<div class="mbe4">
<h2>CSS Parts Customization</h2>
<p
class="mbe2"
style="color: var(--ag-text-secondary); font-size: 0.875rem;"
>
Customize collapsible appearance using CSS Shadow Parts without breaking encapsulation.
</p>
</div>
<div class="stacked mbe4">
<VueCollapsible class="custom-gradient">
<template #summary>
<span>Gaudy Gradient</span>
</template>
<p>This collapsible uses a gradient background with white text and custom styling.</p>
</VueCollapsible>
</div>
</section>
</template>
<script>
import { VueCollapsible } from "agnosticui-core/collapsible/vue";
import { Info } from "lucide-vue-next";
export default {
name: "CollapsibleExamples",
components: {
VueCollapsible,
Info,
},
data() {
return {
isExpanded: false,
};
},
methods: {
handleToggle(event) {
this.isExpanded = event.target.open;
console.log("Collapsible toggled. New state:", this.isExpanded);
},
},
};
</script>
<style scoped>
/* CSS Parts customization examples */
.custom-gradient::part(ag-collapsible-details) {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 12px;
overflow: hidden;
}
.custom-gradient::part(ag-collapsible-summary) {
color: white;
font-weight: 600;
padding: 1.5rem;
}
.custom-gradient::part(ag-collapsible-indicator) {
filter: brightness(0) invert(1);
}
.custom-gradient::part(ag-collapsible-content) {
color: white;
background: rgba(0, 0, 0, 0.1);
}
</style>
Live Preview
View Lit / Web Component Code
import { LitElement, html } from 'lit';
import 'agnosticui-core/collapsible';
export class CollapsibleLitExamples extends LitElement {
// Render in light DOM to access global utility classes
createRenderRoot() {
return this;
}
constructor() {
super();
this.isExpanded = false;
}
handleToggle(event) {
this.isExpanded = event.target.open;
console.log('Collapsible toggled. New state:', this.isExpanded);
this.requestUpdate();
}
render() {
return html`
<section>
<!-- Basic Collapsible (Default) -->
<div class="mbe4">
<h2>Basic Collapsible (Default)</h2>
<p class="mbe2" style="color: var(--ag-text-secondary); font-size: 0.875rem;">
By default, the Collapsible provides a chevron which points down when closed, then rotates 180° to point up when open. See below for how to opt out or use different indicators.
</p>
</div>
<div class="stacked mbe4">
<ag-collapsible use-chevron>
<span slot="summary">Click to expand</span>
<p>This is the collapsible content that can be shown or hidden. The default chevron indicator rotates smoothly when toggled.</p>
</ag-collapsible>
</div>
<!-- X Indicator -->
<div class="mbe4">
<h2>X Indicator</h2>
<p class="mbe2" style="color: var(--ag-text-secondary); font-size: 0.875rem;">
Plus rotated 180° (upside down) when closed, rotates to 45° forming an X when open.
</p>
</div>
<div class="stacked mbe4">
<ag-collapsible use-x>
<span slot="summary">X Indicator</span>
<p>Plus transforms into X when opened. This provides a modern, dynamic visual indicator.</p>
</ag-collapsible>
</div>
<!-- Plus/Minus Indicator -->
<div class="mbe4">
<h2>Plus/Minus Indicator</h2>
<p class="mbe2" style="color: var(--ag-text-secondary); font-size: 0.875rem;">
Plus transitions to minus when open with smooth animation.
</p>
</div>
<div class="stacked mbe4">
<ag-collapsible use-minus>
<span slot="summary">Plus/Minus Indicator</span>
<p>Plus changes to minus when opened. Classic expand/collapse indicator style.</p>
</ag-collapsible>
</div>
<!-- No Indicator -->
<div class="mbe4">
<h2>No Indicator</h2>
<p class="mbe2" style="color: var(--ag-text-secondary); font-size: 0.875rem;">
Collapsible without any visual indicator.
</p>
</div>
<div class="stacked mbe4">
<ag-collapsible no-indicator>
<span slot="summary">No Indicator</span>
<p>Clean header without indicator icon. Minimal design focused on content.</p>
</ag-collapsible>
</div>
<!-- Indicator Comparison -->
<div class="mbe4">
<h2>Indicator Comparison</h2>
<p class="mbe2" style="color: var(--ag-text-secondary); font-size: 0.875rem;">
Toggle each collapsible to see how the different indicators behave.
</p>
</div>
<div class="stacked mbe4">
<ag-collapsible bordered use-chevron>
<span slot="summary">Chevron (default) - Rotates 180°</span>
<p>The chevron points down when closed and up when open via rotation.</p>
</ag-collapsible>
<ag-collapsible bordered use-x>
<span slot="summary">X Indicator - Rotates from upside-down plus to X</span>
<p>Starts as an upside-down plus sign and rotates 45° to form an X when open.</p>
</ag-collapsible>
<ag-collapsible bordered use-minus>
<span slot="summary">Plus/Minus - Swaps icons</span>
<p>Shows a plus icon when closed and swaps to a minus icon when open.</p>
</ag-collapsible>
<ag-collapsible bordered no-indicator>
<span slot="summary">No Indicator - Completely hidden</span>
<p>No indicator is shown at all.</p>
</ag-collapsible>
</div>
<!-- Bordered -->
<div class="mbe4">
<h2>Bordered</h2>
</div>
<div class="stacked mbe4">
<ag-collapsible bordered>
<span slot="summary">Bordered collapsible</span>
<p>This collapsible has a border around it for visual separation.</p>
</ag-collapsible>
</div>
<!-- With Shadow -->
<div class="mbe4">
<h2>With Shadow</h2>
</div>
<div class="stacked mbe4">
<ag-collapsible shadow>
<span slot="summary">Collapsible with shadow</span>
<p>This collapsible has a box-shadow applied for depth.</p>
</ag-collapsible>
</div>
<!-- Combined Features -->
<div class="mbe4">
<h2>Combined Features</h2>
</div>
<div class="stacked mbe4">
<ag-collapsible bordered shadow>
<span slot="summary">Bordered with shadow</span>
<p>This collapsible combines both border and shadow styling for maximum visual impact.</p>
</ag-collapsible>
</div>
<!-- Open by Default -->
<div class="mbe4">
<h2>Open by Default</h2>
</div>
<div class="stacked mbe4">
<ag-collapsible bordered open>
<span slot="summary">Already expanded</span>
<p>This collapsible starts in an open state using the <code>open</code> attribute.</p>
</ag-collapsible>
</div>
<!-- Rich Content -->
<div class="mbe4">
<h2>Rich Content</h2>
</div>
<div class="stacked mbe4">
<ag-collapsible bordered shadow>
<div slot="summary" class="flex-inline items-center">
<svg viewBox="0 0 24 24" fill="none" stroke="var(--ag-primary)" stroke-width="2" width="18" height="18" class="mie2" aria-hidden="true">
<circle cx="12" cy="12" r="10"/>
<path d="M12 16v-4m0-4h.01"/>
</svg>
<strong>Product Details</strong>
</div>
<div>
<h4 style="margin-top: 0;">Technical Specifications</h4>
<ul>
<li>Processor: Octa-core 2.8 GHz</li>
<li>Memory: 8GB RAM</li>
<li>Storage: 256GB SSD</li>
<li>Display: 15.6" Full HD</li>
</ul>
<p>
<strong>Warranty:</strong> 2 years manufacturer warranty with optional
extended coverage available.
</p>
</div>
</ag-collapsible>
</div>
<!-- FAQ Example -->
<div class="mbe4">
<h2>FAQ Example</h2>
</div>
<div class="stacked mbe4">
<ag-collapsible bordered>
<span slot="summary">What is AgnosticUI?</span>
<p>
AgnosticUI is a framework-agnostic component library built with web
components. It works seamlessly with React, Vue, Svelte, Angular, and
vanilla JavaScript.
</p>
</ag-collapsible>
<ag-collapsible bordered>
<span slot="summary">How do I install it?</span>
<p>You can install AgnosticUI via npm:</p>
<pre style="background: var(--ag-background-secondary); padding: 1rem; border-radius: 4px; overflow-x: auto;">npm install agnosticui-core</pre>
</ag-collapsible>
<ag-collapsible bordered>
<span slot="summary">Is it accessible?</span>
<p>
Yes! All AgnosticUI components are built with accessibility in mind,
following WAI-ARIA best practices and ensuring keyboard navigation and
screen reader support.
</p>
</ag-collapsible>
<ag-collapsible bordered>
<span slot="summary">Can I customize the styling?</span>
<p>
Absolutely! AgnosticUI uses CSS Shadow Parts to allow deep customization
of component internals while maintaining encapsulation. You can also use
design tokens for consistent theming across your application.
</p>
</ag-collapsible>
</div>
<!-- Nested Collapsibles -->
<div class="mbe4">
<h2>Nested Collapsibles</h2>
</div>
<div class="stacked mbe4">
<ag-collapsible bordered>
<span slot="summary">Level 1 - Main Topic</span>
<div>
<p>This is the main content area.</p>
<ag-collapsible bordered use-minus style="margin-top: 1rem;">
<span slot="summary">Level 2 - Subtopic A</span>
<p>Nested collapsible content for subtopic A. Note the different indicator style.</p>
</ag-collapsible>
<ag-collapsible bordered use-minus style="margin-top: 0.5rem;">
<span slot="summary">Level 2 - Subtopic B</span>
<p>Nested collapsible content for subtopic B.</p>
</ag-collapsible>
</div>
</ag-collapsible>
</div>
<!-- Interactive with Event Handling -->
<div class="mbe4">
<h2>Interactive with Event Handling</h2>
</div>
<div class="stacked mbe4">
<ag-collapsible bordered shadow @toggle=${this.handleToggle}>
<span slot="summary">Click to toggle (watch console)</span>
<div>
<p>The collapsible dispatches a <code>toggle</code> event when opened or closed.</p>
</div>
</ag-collapsible>
<p style="margin-top: 1rem;">
Current state: <strong>${this.isExpanded ? 'Expanded' : 'Collapsed'}</strong>
</p>
</div>
<!-- CSS Parts Customization -->
<div class="mbe4">
<h2>CSS Parts Customization</h2>
<p class="mbe2" style="color: var(--ag-text-secondary); font-size: 0.875rem;">
Customize collapsible appearance using CSS Shadow Parts without breaking encapsulation.
</p>
</div>
<div class="stacked mbe4">
<ag-collapsible class="custom-gradient">
<span slot="summary">Gaudy Gradient</span>
<p>This collapsible uses a gradient background with white text and custom styling.</p>
</ag-collapsible>
</div>
</section>
`;
}
}
// Register the custom element
customElements.define('collapsible-lit-examples', CollapsibleLitExamples);
Interactive Preview: Click the "Open in StackBlitz" button below to see this example running live in an interactive playground.
View React Code
import { useState } from "react";
import { ReactCollapsible } from "agnosticui-core/collapsible/react";
import { Info } from "lucide-react";
export default function CollapsibleReactExamples() {
const [isExpanded, setIsExpanded] = useState(false);
const handleToggle = (event) => {
setIsExpanded(event.target.open);
console.log("Collapsible toggled. New state:", event.target.open);
};
return (
<section>
{/* Basic Collapsible (Default) */}
<div className="mbe4">
<h2>Basic Collapsible (Default)</h2>
<p className="mbe2" style={{ color: "var(--ag-text-secondary)", fontSize: "0.875rem" }}>
By default, the Collapsible provides a chevron which points down when closed, then rotates 180° to point up when open. See below for how to opt out or use different indicators.
</p>
</div>
<div className="stacked mbe4">
<ReactCollapsible useChevron>
<span slot="summary">Click to expand</span>
<p>This is the collapsible content that can be shown or hidden. The default chevron indicator rotates smoothly when toggled.</p>
</ReactCollapsible>
</div>
{/* X Indicator */}
<div className="mbe4">
<h2>X Indicator</h2>
<p className="mbe2" style={{ color: "var(--ag-text-secondary)", fontSize: "0.875rem" }}>
Plus rotated 180° (upside down) when closed, rotates to 45° forming an X when open.
</p>
</div>
<div className="stacked mbe4">
<ReactCollapsible useX>
<span slot="summary">X Indicator</span>
<p>Plus transforms into X when opened. This provides a modern, dynamic visual indicator.</p>
</ReactCollapsible>
</div>
{/* Plus/Minus Indicator */}
<div className="mbe4">
<h2>Plus/Minus Indicator</h2>
<p className="mbe2" style={{ color: "var(--ag-text-secondary)", fontSize: "0.875rem" }}>
Plus transitions to minus when open with smooth animation.
</p>
</div>
<div className="stacked mbe4">
<ReactCollapsible useMinus>
<span slot="summary">Plus/Minus Indicator</span>
<p>Plus changes to minus when opened. Classic expand/collapse indicator style.</p>
</ReactCollapsible>
</div>
{/* No Indicator */}
<div className="mbe4">
<h2>No Indicator</h2>
<p className="mbe2" style={{ color: "var(--ag-text-secondary)", fontSize: "0.875rem" }}>
Collapsible without any visual indicator.
</p>
</div>
<div className="stacked mbe4">
<ReactCollapsible noIndicator>
<span slot="summary">No Indicator</span>
<p>Clean header without indicator icon. Minimal design focused on content.</p>
</ReactCollapsible>
</div>
{/* Indicator Comparison */}
<div className="mbe4">
<h2>Indicator Comparison</h2>
<p className="mbe2" style={{ color: "var(--ag-text-secondary)", fontSize: "0.875rem" }}>
Toggle each collapsible to see how the different indicators behave.
</p>
</div>
<div className="stacked mbe4">
<ReactCollapsible bordered useChevron>
<span slot="summary">Chevron (default) - Rotates 180°</span>
<p>The chevron points down when closed and up when open via rotation.</p>
</ReactCollapsible>
<ReactCollapsible bordered useX>
<span slot="summary">X Indicator - Rotates from upside-down plus to X</span>
<p>Starts as an upside-down plus sign and rotates 45° to form an X when open.</p>
</ReactCollapsible>
<ReactCollapsible bordered useMinus>
<span slot="summary">Plus/Minus - Swaps icons</span>
<p>Shows a plus icon when closed and swaps to a minus icon when open.</p>
</ReactCollapsible>
<ReactCollapsible bordered noIndicator>
<span slot="summary">No Indicator - Completely hidden</span>
<p>No indicator is shown at all.</p>
</ReactCollapsible>
</div>
{/* Bordered */}
<div className="mbe4">
<h2>Bordered</h2>
</div>
<div className="stacked mbe4">
<ReactCollapsible bordered>
<span slot="summary">Bordered collapsible</span>
<p>This collapsible has a border around it for visual separation.</p>
</ReactCollapsible>
</div>
{/* With Shadow */}
<div className="mbe4">
<h2>With Shadow</h2>
</div>
<div className="stacked mbe4">
<ReactCollapsible shadow>
<span slot="summary">Collapsible with shadow</span>
<p>This collapsible has a box-shadow applied for depth.</p>
</ReactCollapsible>
</div>
{/* Combined Features */}
<div className="mbe4">
<h2>Combined Features</h2>
</div>
<div className="stacked mbe4">
<ReactCollapsible bordered shadow>
<span slot="summary">Bordered with shadow</span>
<p>This collapsible combines both border and shadow styling for maximum visual impact.</p>
</ReactCollapsible>
</div>
{/* Open by Default */}
<div className="mbe4">
<h2>Open by Default</h2>
</div>
<div className="stacked mbe4">
<ReactCollapsible bordered open>
<span slot="summary">Already expanded</span>
<p>This collapsible starts in an open state using the <code>open</code> prop.</p>
</ReactCollapsible>
</div>
{/* Rich Content */}
<div className="mbe4">
<h2>Rich Content</h2>
</div>
<div className="stacked mbe4">
<ReactCollapsible bordered shadow>
<div slot="summary" className="flex-inline items-center">
<Info color="var(--ag-primary)" size={18} className="mie2" />
<strong>Product Details</strong>
</div>
<div>
<h4 style={{ marginTop: 0 }}>Technical Specifications</h4>
<ul>
<li>Processor: Octa-core 2.8 GHz</li>
<li>Memory: 8GB RAM</li>
<li>Storage: 256GB SSD</li>
<li>Display: 15.6" Full HD</li>
</ul>
<p>
<strong>Warranty:</strong> 2 years manufacturer warranty with optional
extended coverage available.
</p>
</div>
</ReactCollapsible>
</div>
{/* FAQ Example */}
<div className="mbe4">
<h2>FAQ Example</h2>
</div>
<div className="stacked mbe4">
<ReactCollapsible bordered>
<span slot="summary">What is AgnosticUI?</span>
<p>
AgnosticUI is a framework-agnostic component library built with web
components. It works seamlessly with React, Vue, Svelte, Angular, and
vanilla JavaScript.
</p>
</ReactCollapsible>
<ReactCollapsible bordered>
<span slot="summary">How do I install it?</span>
<p>You can install AgnosticUI via npm:</p>
<pre style={{ background: "var(--ag-background-secondary)", padding: "1rem", borderRadius: "4px", overflowX: "auto" }}>npm install agnosticui-core</pre>
</ReactCollapsible>
<ReactCollapsible bordered>
<span slot="summary">Is it accessible?</span>
<p>
Yes! All AgnosticUI components are built with accessibility in mind,
following WAI-ARIA best practices and ensuring keyboard navigation and
screen reader support.
</p>
</ReactCollapsible>
<ReactCollapsible bordered>
<span slot="summary">Can I customize the styling?</span>
<p>
Absolutely! AgnosticUI uses CSS Shadow Parts to allow deep customization
of component internals while maintaining encapsulation. You can also use
design tokens for consistent theming across your application.
</p>
</ReactCollapsible>
</div>
{/* Nested Collapsibles */}
<div className="mbe4">
<h2>Nested Collapsibles</h2>
</div>
<div className="stacked mbe4">
<ReactCollapsible bordered>
<span slot="summary">Level 1 - Main Topic</span>
<div>
<p>This is the main content area.</p>
<ReactCollapsible bordered useMinus style={{ marginTop: "1rem" }}>
<span slot="summary">Level 2 - Subtopic A</span>
<p>Nested collapsible content for subtopic A. Note the different indicator style.</p>
</ReactCollapsible>
<ReactCollapsible bordered useMinus style={{ marginTop: "0.5rem" }}>
<span slot="summary">Level 2 - Subtopic B</span>
<p>Nested collapsible content for subtopic B.</p>
</ReactCollapsible>
</div>
</ReactCollapsible>
</div>
{/* Interactive with Event Handling */}
<div className="mbe4">
<h2>Interactive with Event Handling</h2>
</div>
<div className="stacked mbe4">
<ReactCollapsible bordered shadow onToggle={handleToggle}>
<span slot="summary">Click to toggle (watch console)</span>
<div>
<p>The collapsible dispatches a <code>toggle</code> event when opened or closed.</p>
</div>
</ReactCollapsible>
<p style={{ marginTop: "1rem" }}>
Current state: <strong>{isExpanded ? 'Expanded' : 'Collapsed'}</strong>
</p>
</div>
{/* CSS Parts Customization */}
<div className="mbe4">
<h2>CSS Parts Customization</h2>
<p className="mbe2" style={{ color: "var(--ag-text-secondary)", fontSize: "0.875rem" }}>
Customize collapsible appearance using CSS Shadow Parts without breaking encapsulation.
</p>
</div>
<div className="stacked mbe4">
<ReactCollapsible className="custom-gradient">
<span slot="summary">Gaudy Gradient</span>
<p>This collapsible uses a gradient background with white text and custom styling.</p>
</ReactCollapsible>
</div>
</section>
);
}
Usage
TIP
The framework examples below import AgnosticUI as an npm package. Alternatively, you can use the CLI for complete control, AI/LLM visibility, and full code ownership:
npx ag init --framework FRAMEWORK # react, vue, lit, svelte, etc.
npx ag add CollapsibleThe CLI copies source code directly into your project, giving you full visibility and control. After running npx ag add, you'll receive exact import instructions.
Vue
<template>
<section>
<VueCollapsible>
<template #summary>
<span>Click to expand</span>
</template>
<p>This is the collapsible content that can be shown or hidden.</p>
</VueCollapsible>
<VueCollapsible open>
<template #summary>
<span>Already expanded</span>
</template>
<p>This collapsible starts in an open state.</p>
</VueCollapsible>
<VueCollapsible
bordered
shadow
>
<template #summary>
<span>Bordered with shadow</span>
</template>
<p>This collapsible has both border and shadow styling.</p>
</VueCollapsible>
<VueCollapsible
use-x
@toggle="handleToggle"
>
<template #summary>
<span>X Indicator</span>
</template>
<p>Plus icon that transforms into an X when opened</p>
</VueCollapsible>
<VueCollapsible
use-minus
@toggle="handleToggle"
>
<template #summary>
<span>Plus/Minus Indicator</span>
</template>
<p>Plus icon that changes to minus when opened</p>
</VueCollapsible>
<VueCollapsible no-indicator>
<template #summary>
<span>No indicator</span>
</template>
<p>This collapsible has no indicator icon at all.</p>
</VueCollapsible>
</section>
</template>
<script>
import { VueCollapsible } from "agnosticui-core/collapsible/vue";
export default {
components: { VueCollapsible },
methods: {
handleToggle(event) {
const newOpenState = event.detail.open;
console.log("Collapsible toggled:", newOpenState);
},
},
};
</script>React
import { ReactCollapsible } from "agnosticui-core/collapsible/react";
export default function CollapsibleExample() {
const handleToggle = (event: CustomEvent<{ open: boolean }>) => {
console.log("Collapsible toggled:", event.detail.open);
};
return (
<section>
<ReactCollapsible>
<span slot="summary">Click to expand</span>
<p>This is the collapsible content that can be shown or hidden.</p>
</ReactCollapsible>
<ReactCollapsible open={true}>
<span slot="summary">Already expanded</span>
<p>This collapsible starts in an open state.</p>
</ReactCollapsible>
<ReactCollapsible bordered shadow>
<span slot="summary">Bordered with shadow</span>
<p>This collapsible has both border and shadow styling.</p>
</ReactCollapsible>
<ReactCollapsible useX onToggle={handleToggle}>
<span slot="summary">X Indicator</span>
<p>Plus icon that transforms into an X when opened</p>
</ReactCollapsible>
<ReactCollapsible useMinus onToggle={handleToggle}>
<span slot="summary">Plus/Minus Indicator</span>
<p>Plus icon that changes to minus when opened</p>
</ReactCollapsible>
<ReactCollapsible noIndicator>
<span slot="summary">No indicator</span>
<p>This collapsible has no indicator icon at all.</p>
</ReactCollapsible>
</section>
);
}Lit (Web Components)
import { LitElement, html, css } from 'lit';
import { customElement } from 'lit/decorators.js';
import 'agnosticui-core/collapsible';
@customElement('collapsible-example')
export class CollapsibleExample extends LitElement {
static styles = css`
:host {
display: block;
}
section {
display: flex;
flex-direction: column;
gap: 1rem;
}
`;
firstUpdated() {
// Set up event listeners for collapsible elements in the shadow DOM
const collapsibles = this.shadowRoot?.querySelectorAll('ag-collapsible');
collapsibles?.forEach((el) => {
el.addEventListener('toggle', (event: Event) => {
const customEvent = event as CustomEvent;
console.log('Collapsible toggled:', customEvent.detail.open);
});
});
}
render() {
return html`
<section>
<ag-collapsible>
<span slot="summary">Click to expand</span>
<p>This is the collapsible content that can be shown or hidden.</p>
</ag-collapsible>
<ag-collapsible open>
<span slot="summary">Already expanded</span>
<p>This collapsible starts in an open state.</p>
</ag-collapsible>
<ag-collapsible bordered shadow>
<span slot="summary">Bordered with shadow</span>
<p>This collapsible has both border and shadow styling.</p>
</ag-collapsible>
<ag-collapsible use-x>
<span slot="summary">X Indicator</span>
<p>Plus icon that transforms into an X when opened</p>
</ag-collapsible>
<ag-collapsible use-minus>
<span slot="summary">Plus/Minus Indicator</span>
<p>Plus icon that changes to minus when opened</p>
</ag-collapsible>
<ag-collapsible no-indicator>
<span slot="summary">No indicator</span>
<p>This collapsible has no indicator icon at all.</p>
</ag-collapsible>
</section>
`;
}
}Note: When using collapsible components within a custom element's shadow DOM, set up event listeners in the component's lifecycle (e.g., firstUpdated()) rather than using DOMContentLoaded, as document.querySelector() cannot access elements inside shadow DOM. Use this.shadowRoot.querySelector() instead.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | false | Whether the collapsible is expanded |
bordered | boolean | false | Whether to apply border styling |
shadow | boolean | false | Whether to apply box-shadow styling |
useChevron | boolean | true | Use chevron indicator (default) — rotates 180° when open |
useX | boolean | false | Use X indicator — plus rotates to form an X when open |
useMinus | boolean | false | Use plus/minus indicator — plus transitions to minus when open |
noIndicator | boolean | false | Hide the indicator completely |
Note: Indicator props are mutually exclusive with priority: noIndicator > useX > useMinus > useChevron (default)
Events
| Event | Framework | Detail | Description |
|---|---|---|---|
toggle | Vue: @toggleReact: onToggleLit: @toggle | { open: boolean } | Fired when the collapsible opens or closes. The event detail contains the new open state. |
Type:
export type CollapsibleToggleEvent = CustomEvent<{ open: boolean }>;CSS Shadow Parts
| Part | Description | Element |
|---|---|---|
ag-collapsible-details | The main details element container | <details> |
ag-collapsible-summary | The interactive summary/trigger element | <summary> |
ag-collapsible-indicator | The expand/collapse indicator icon wrapper | <span> |
ag-collapsible-content | The collapsible content region | <div> |
Example Usage
ag-collapsible::part(ag-collapsible-details) {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 12px;
overflow: hidden;
}
ag-collapsible::part(ag-collapsible-summary) {
color: white;
font-weight: 600;
padding: 1.5rem;
cursor: pointer;
}
ag-collapsible::part(ag-collapsible-indicator) {
filter: brightness(0) invert(1);
}
ag-collapsible::part(ag-collapsible-content) {
color: white;
background: rgba(0, 0, 0, 0.1);
padding: 1.5rem;
}
ag-collapsible.minimal::part(ag-collapsible-summary) {
background: #f9fafb;
border-left: 4px solid #3b82f6;
padding: 1rem 1rem 1rem 1.5rem;
}
ag-collapsible.minimal::part(ag-collapsible-content) {
background: #ffffff;
padding: 1rem 1rem 1rem 1.5rem;
}Accessibility
The Collapsible is built on the native HTML <details> and <summary> elements, providing excellent accessibility by default:
Uses semantic HTML
<details>and<summary>elementsNative keyboard support:
- Space/Enter: Toggle the collapsible
The
openattribute communicates state to assistive technologiesScreen readers can interact with it naturally
Focus indicators are clearly visible for keyboard navigation
No additional ARIA attributes are needed due to native semantics
Progressive Enhancement
The Collapsible is designed with progressive enhancement in mind:
- Built on native
<details>and<summary>HTML elements - Content is accessible even if JavaScript fails to load
- Core expand/collapse functionality works without JavaScript
- JavaScript enhancement adds custom indicators and smoother animations
- Gracefully degrades to native browser behavior