Accordion Components
Beautiful, responsive accordion components built with TailwindCSS and AlpineJS. Perfect for FAQs, collapsible content, and expandable sections.
1. Basic Accordion
A simple, clean accordion perfect for FAQs or basic content organization.
TailwindCSS is a utility-first CSS framework that provides low-level utility classes to build custom designs directly in your markup.
Start by installing TailwindCSS via npm or including it via CDN. Then begin using utility classes in your HTML.
Yes! TailwindCSS includes responsive variants for almost every utility class, making it easy to build responsive designs.
<div x-data="{ open: null }" class="space-y-2">
<div class="bg-white border border-gray-200 shadow-sm rounded-lg">
<button @click="open = open === 1 ? null : 1" class="w-full px-6 py-4 text-left font-semibold flex justify-between items-center hover:bg-gray-50 transition-colors">
<span>What is TailwindCSS?</span>
<svg class="w-5 h-5 transform transition-transform" :class="{'rotate-180': open === 1}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open === 1" x-collapse>
<div class="px-6 py-4 border-t border-gray-200 bg-gray-50">
<p class="text-gray-700">TailwindCSS is a utility-first CSS framework that provides low-level utility classes to build custom designs directly in your markup.</p>
</div>
</div>
</div>
<div class="bg-white border border-gray-200 shadow-sm rounded-lg">
<button @click="open = open === 2 ? null : 2" class="w-full px-6 py-4 text-left font-semibold flex justify-between items-center hover:bg-gray-50 transition-colors">
<span>How do I get started?</span>
<svg class="w-5 h-5 transform transition-transform" :class="{'rotate-180': open === 2}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open === 2" x-collapse>
<div class="px-6 py-4 border-t border-gray-200 bg-gray-50">
<p class="text-gray-700">Start by installing TailwindCSS via npm or including it via CDN. Then begin using utility classes in your HTML.</p>
</div>
</div>
</div>
<div class="bg-white border border-gray-200 shadow-sm rounded-lg">
<button @click="open = open === 3 ? null : 3" class="w-full px-6 py-4 text-left font-semibold flex justify-between items-center hover:bg-gray-50 transition-colors">
<span>Is it responsive by default?</span>
<svg class="w-5 h-5 transform transition-transform" :class="{'rotate-180': open === 3}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open === 3" x-collapse>
<div class="px-6 py-4 border-t border-gray-200 bg-gray-50">
<p class="text-gray-700">Yes! TailwindCSS includes responsive variants for almost every utility class, making it easy to build responsive designs.</p>
</div>
</div>
</div>
</div>
<template>
<div class="space-y-2">
<div class="bg-white border border-gray-200 shadow-sm rounded-lg">
<button
@click="toggleAccordion(1)"
class="w-full px-6 py-4 text-left font-semibold flex justify-between items-center hover:bg-gray-50 transition-colors">
<span>What is TailwindCSS?</span>
<ChevronDownIcon
:class="{ 'rotate-180': openItem === 1 }"
class="w-5 h-5 transform transition-transform"
/>
</button>
<Transition name="accordion">
<div v-show="openItem === 1" class="px-6 py-4 border-t border-gray-200 bg-gray-50">
<p class="text-gray-700">TailwindCSS is a utility-first CSS framework...</p>
</div>
</Transition>
</div>
<div class="bg-white border border-gray-200 shadow-sm rounded-lg">
<button
@click="toggleAccordion(2)"
class="w-full px-6 py-4 text-left font-semibold flex justify-between items-center hover:bg-gray-50 transition-colors">
<span>How do I get started?</span>
<ChevronDownIcon
:class="{ 'rotate-180': openItem === 2 }"
class="w-5 h-5 transform transition-transform"
/>
</button>
<Transition name="accordion">
<div v-show="openItem === 2" class="px-6 py-4 border-t border-gray-200 bg-gray-50">
<p class="text-gray-700">Start by installing TailwindCSS via npm...</p>
</div>
</Transition>
</div>
<div class="bg-white border border-gray-200 shadow-sm rounded-lg">
<button
@click="toggleAccordion(3)"
class="w-full px-6 py-4 text-left font-semibold flex justify-between items-center hover:bg-gray-50 transition-colors">
<span>Is it responsive by default?</span>
<ChevronDownIcon
:class="{ 'rotate-180': openItem === 3 }"
class="w-5 h-5 transform transition-transform"
/>
</button>
<Transition name="accordion">
<div v-show="openItem === 3" class="px-6 py-4 border-t border-gray-200 bg-gray-50">
<p class="text-gray-700">Yes! TailwindCSS includes responsive variants...</p>
</div>
</Transition>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ChevronDownIcon } from '@heroicons/vue/24/outline'
const openItem = ref(null)
const toggleAccordion = (item) => {
openItem.value = openItem.value === item ? null : item
}
</script>
import React, { useState } from 'react'
import { ChevronDownIcon } from '@heroicons/react/24/outline'
const BasicAccordion = () => {
const [openItem, setOpenItem] = useState(null)
const toggleAccordion = (item) => {
setOpenItem(openItem === item ? null : item)
}
const accordionItems = [
{
id: 1,
question: "What is TailwindCSS?",
answer: "TailwindCSS is a utility-first CSS framework that provides low-level utility classes to build custom designs directly in your markup."
},
{
id: 2,
question: "How do I get started?",
answer: "Start by installing TailwindCSS via npm or including it via CDN. Then begin using utility classes in your HTML."
},
{
id: 3,
question: "Is it responsive by default?",
answer: "Yes! TailwindCSS includes responsive variants for almost every utility class, making it easy to build responsive designs."
}
]
return (
<div className="space-y-2">
{accordionItems.map((item) => (
<div key={item.id} className="bg-white border border-gray-200 shadow-sm rounded-lg">
<button
onClick={() => toggleAccordion(item.id)}
className="w-full px-6 py-4 text-left font-semibold flex justify-between items-center hover:bg-gray-50 transition-colors"
>
<span>{item.question}</span>
<ChevronDownIcon
className={`w-5 h-5 transform transition-transform ${openItem === item.id ? 'rotate-180' : ''}`}
/>
</button>
{openItem === item.id && (
<div className="px-6 py-4 border-t border-gray-200 bg-gray-50">
<p className="text-gray-700">{item.answer}</p>
</div>
)}
</div>
))}
</div>
)
}
export default BasicAccordion
2. Plus/Minus Accordion
Clean accordion with plus/minus icons that smoothly animate between states.
We support React, Vue, Angular, and vanilla JavaScript. All components are built with TailwindCSS for easy customization.
Absolutely! Since we use TailwindCSS, you can easily modify colors, spacing, and styling by changing the utility classes.
Yes! Each component comes with detailed documentation, code examples, and usage guidelines to help you get started quickly.
<div x-data="{ open: null }" class="space-y-3">
<div class="border border-gray-300 rounded-lg">
<button @click="open = open === 1 ? null : 1" class="w-full px-6 py-4 text-left font-medium flex justify-between items-center hover:bg-gray-50 transition-colors">
<span>What frameworks do you support?</span>
<div class="flex items-center justify-center w-6 h-6 text-gray-500">
<svg x-show="open !== 1" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
</svg>
<svg x-show="open === 1" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 12h14" />
</svg>
</div>
</button>
<div x-show="open === 1" x-collapse>
<div class="px-6 py-4 border-t border-gray-200 text-gray-700">
<p>We support React, Vue, Angular, and vanilla JavaScript. All components are built with TailwindCSS for easy customization.</p>
</div>
</div>
</div>
</div>
<template>
<div class="space-y-3">
<div v-for="item in accordionItems" :key="item.id" class="border border-gray-300 rounded-lg">
<button @click="toggleAccordion(item.id)" class="w-full px-6 py-4 text-left font-medium flex justify-between items-center hover:bg-gray-50 transition-colors">
<span>{{ item.question }}</span>
<div class="flex items-center justify-center w-6 h-6 text-gray-500">
<PlusIcon v-show="openItem !== item.id" class="w-5 h-5" />
<MinusIcon v-show="openItem === item.id" class="w-5 h-5" />
</div>
</button>
<div v-show="openItem === item.id" class="px-6 py-4 border-t border-gray-200 text-gray-700">
<p>{{ item.answer }}</p>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { PlusIcon, MinusIcon } from '@heroicons/vue/24/outline'
const openItem = ref(null)
const toggleAccordion = (itemId) => {
openItem.value = openItem.value === itemId ? null : itemId
}
const accordionItems = [
{ id: 1, question: "What frameworks do you support?", answer: "We support React, Vue, Angular, and vanilla JavaScript." },
{ id: 2, question: "Can I customize the colors?", answer: "Absolutely! Since we use TailwindCSS, you can easily modify colors." },
{ id: 3, question: "Do you provide documentation?", answer: "Yes! Each component comes with detailed documentation." }
]
</script>
import React, { useState } from 'react'
import { PlusIcon, MinusIcon } from '@heroicons/react/24/outline'
const PlusMinusAccordion = () => {
const [openItem, setOpenItem] = useState(null)
const toggleAccordion = (itemId) => {
setOpenItem(openItem === itemId ? null : itemId)
}
const accordionItems = [
{ id: 1, question: "What frameworks do you support?", answer: "We support React, Vue, Angular, and vanilla JavaScript." },
{ id: 2, question: "Can I customize the colors?", answer: "Absolutely! Since we use TailwindCSS, you can easily modify colors." },
{ id: 3, question: "Do you provide documentation?", answer: "Yes! Each component comes with detailed documentation." }
]
return (
<div className="space-y-3">
{accordionItems.map((item) => (
<div key={item.id} className="border border-gray-300 rounded-lg">
<button onClick={() => toggleAccordion(item.id)} className="w-full px-6 py-4 text-left font-medium flex justify-between items-center hover:bg-gray-50 transition-colors">
<span>{item.question}</span>
<div className="flex items-center justify-center w-6 h-6 text-gray-500">
{openItem !== item.id ? <PlusIcon className="w-5 h-5" /> : <MinusIcon className="w-5 h-5" />}
</div>
</button>
{openItem === item.id && (
<div className="px-6 py-4 border-t border-gray-200 text-gray-700">
<p>{item.answer}</p>
</div>
)}
</div>
))}
</div>
)
}
export default PlusMinusAccordion
3. Gradient Card Accordion
Colorful gradient cards with icons, shadow animations, and smooth slide effects.
Our components are built with performance in mind, utilizing modern CSS techniques and minimal JavaScript for maximum speed.
Change colors, spacing, and styles instantly with Tailwind's utility classes. No complex CSS required.
All components are battle-tested in real applications, with comprehensive documentation and support.
<div x-data="{ open: null }" class="space-y-4">
<div class="bg-gradient-to-r from-blue-500 to-purple-600 rounded-xl shadow-lg hover:shadow-xl transition-all duration-300">
<button @click="open = open === 1 ? null : 1" class="w-full px-6 py-5 text-left flex items-center gap-4 text-white">
<div class="flex-shrink-0 w-12 h-12 bg-white/20 rounded-lg flex items-center justify-center backdrop-blur-sm">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
</svg>
</div>
<div class="flex-grow">
<h3 class="font-bold text-lg">Lightning Fast Performance</h3>
<p class="text-blue-100 text-sm">Optimized for speed and efficiency</p>
</div>
<div class="flex-shrink-0">
<svg class="w-6 h-6 transform transition-transform duration-300" :class="{'rotate-180': open === 1}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</div>
</button>
<div x-show="open === 1" x-transition:enter="transition ease-out duration-300" x-transition:enter-start="opacity-0 -translate-y-2" x-transition:enter-end="opacity-100 translate-y-0" x-transition:leave="transition ease-in duration-200" x-transition:leave-start="opacity-100 translate-y-0" x-transition:leave-end="opacity-0 -translate-y-2">
<div class="px-6 pb-5 ml-16">
<div class="bg-white/10 backdrop-blur-sm rounded-lg p-4 text-white">
<p class="leading-relaxed">Our components are built with performance in mind, utilizing modern CSS techniques and minimal JavaScript for maximum speed.</p>
</div>
</div>
</div>
</div>
</div>
<template>
<div class="space-y-4">
<div v-for="card in cardItems" :key="card.id" :class="card.gradient" class="rounded-xl shadow-lg hover:shadow-xl transition-all duration-300">
<button @click="toggleAccordion(card.id)" class="w-full px-6 py-5 text-left flex items-center gap-4 text-white">
<div class="flex-shrink-0 w-12 h-12 bg-white/20 rounded-lg flex items-center justify-center backdrop-blur-sm">
<component :is="card.icon" class="w-6 h-6" />
</div>
<div class="flex-grow">
<h3 class="font-bold text-lg">{{ card.title }}</h3>
<p :class="card.textColor" class="text-sm">{{ card.subtitle }}</p>
</div>
<div class="flex-shrink-0">
<ChevronDownIcon :class="{ 'rotate-180': openItem === card.id }" class="w-6 h-6 transform transition-transform duration-300" />
</div>
</button>
<div v-show="openItem === card.id" class="px-6 pb-5 ml-16">
<div class="bg-white/10 backdrop-blur-sm rounded-lg p-4 text-white">
<p class="leading-relaxed">{{ card.content }}</p>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ChevronDownIcon, BoltIcon, HeartIcon, ShieldCheckIcon } from '@heroicons/vue/24/outline'
const openItem = ref(null)
const toggleAccordion = (itemId) => {
openItem.value = openItem.value === itemId ? null : itemId
}
const cardItems = [
{ id: 1, title: "Lightning Fast Performance", subtitle: "Optimized for speed", content: "Built with performance in mind.", icon: BoltIcon, gradient: "bg-gradient-to-r from-blue-500 to-purple-600", textColor: "text-blue-100" },
{ id: 2, title: "Easy to Customize", subtitle: "Tailwind utility classes", content: "Change colors and styles instantly.", icon: HeartIcon, gradient: "bg-gradient-to-r from-green-500 to-emerald-600", textColor: "text-green-100" },
{ id: 3, title: "Production Ready", subtitle: "Thoroughly tested", content: "Battle-tested in real applications.", icon: ShieldCheckIcon, gradient: "bg-gradient-to-r from-orange-500 to-red-500", textColor: "text-orange-100" }
]
</script>
import React, { useState } from 'react'
import { ChevronDownIcon, BoltIcon, HeartIcon, ShieldCheckIcon } from '@heroicons/react/24/outline'
const GradientCardAccordion = () => {
const [openItem, setOpenItem] = useState(null)
const toggleAccordion = (itemId) => {
setOpenItem(openItem === itemId ? null : itemId)
}
const cardItems = [
{ id: 1, title: "Lightning Fast Performance", subtitle: "Optimized for speed", content: "Built with performance in mind.", icon: BoltIcon, gradient: "bg-gradient-to-r from-blue-500 to-purple-600", textColor: "text-blue-100" },
{ id: 2, title: "Easy to Customize", subtitle: "Tailwind utility classes", content: "Change colors and styles instantly.", icon: HeartIcon, gradient: "bg-gradient-to-r from-green-500 to-emerald-600", textColor: "text-green-100" },
{ id: 3, title: "Production Ready", subtitle: "Thoroughly tested", content: "Battle-tested in real applications.", icon: ShieldCheckIcon, gradient: "bg-gradient-to-r from-orange-500 to-red-500", textColor: "text-orange-100" }
]
return (
<div className="space-y-4">
{cardItems.map((card) => {
const IconComponent = card.icon
return (
<div key={card.id} className={`${card.gradient} rounded-xl shadow-lg hover:shadow-xl transition-all duration-300`}>
<button onClick={() => toggleAccordion(card.id)} className="w-full px-6 py-5 text-left flex items-center gap-4 text-white">
<div className="flex-shrink-0 w-12 h-12 bg-white/20 rounded-lg flex items-center justify-center backdrop-blur-sm">
<IconComponent className="w-6 h-6" />
</div>
<div className="flex-grow">
<h3 className="font-bold text-lg">{card.title}</h3>
<p className={`${card.textColor} text-sm`}>{card.subtitle}</p>
</div>
<div className="flex-shrink-0">
<ChevronDownIcon className={`w-6 h-6 transform transition-transform duration-300 ${openItem === card.id ? 'rotate-180' : ''}`} />
</div>
</button>
{openItem === card.id && (
<div className="px-6 pb-5 ml-16">
<div className="bg-white/10 backdrop-blur-sm rounded-lg p-4 text-white">
<p className="leading-relaxed">{card.content}</p>
</div>
</div>
)}
</div>
)
})}
</div>
)
}
export default GradientCardAccordion
4. Apple Liquid Glass Accordion
Premium glass morphism design inspired by Apple's design language with smooth animations and depth effects.
Apple-style glass uses layered transparency, ultra-soft blur, and minimal shadow depth to give a floating-UI effect.
Animations use native GPU-accelerated transforms for 120Hz-ready smooth interaction feel.
Adjust backdrop-blur, opacity layers, and shadow spreads in Tailwind to match your brand's aesthetic perfectly.
<div x-data="{ open: null }" class="space-y-5">
<!-- Item 1 -->
<div class="rounded-3xl overflow-hidden border border-white/20 backdrop-blur-2xl bg-white/[0.07] shadow-[0_8px_40px_rgba(255,255,255,0.08)] hover:shadow-[0_15px_60px_rgba(255,255,255,0.12)] transition-all duration-300"
:class="{ 'scale-[1.015] bg-white/[0.12] border-white/30 shadow-[0_15px_80px_rgba(255,255,255,0.2)]': open === 1 }">
<button @click="open = open === 1 ? null : 1" class="w-full px-6 py-6 flex justify-between items-center">
<div class="flex items-center gap-4">
<div class="w-12 h-12 rounded-xl bg-white/20 border border-white/30 backdrop-blur-md shadow-inner flex items-center justify-center">
<svg class="h-6 w-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
</svg>
</div>
<h3 class="text-white text-xl font-semibold">What Makes Apple Glass UI?</h3>
</div>
<svg class="w-6 h-6 text-white transition-transform duration-300" :class="{'rotate-180': open === 1}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</button>
<div x-show="open === 1" x-transition:enter="transition ease-out duration-400" x-transition:enter-start="opacity-0 -translate-y-3" x-transition:enter-end="opacity-100 translate-y-0" class="px-6 py-6 border-t border-white/20 bg-white/[0.04] backdrop-blur-sm">
<p class="text-gray-300 leading-relaxed">Apple-style glass uses layered transparency, ultra-soft blur, and minimal shadow depth to give a floating-UI effect.</p>
</div>
</div>
<!-- Item 2 -->
<div class="rounded-3xl overflow-hidden border border-white/20 backdrop-blur-2xl bg-white/[0.07] shadow-[0_8px_40px_rgba(255,255,255,0.08)] hover:shadow-[0_15px_60px_rgba(255,255,255,0.12)] transition-all duration-300"
:class="{ 'scale-[1.015] bg-white/[0.12] border-white/30 shadow-[0_15px_80px_rgba(255,255,255,0.2)]': open === 2 }">
<button @click="open = open === 2 ? null : 2" class="w-full px-6 py-6 flex justify-between items-center">
<div class="flex items-center gap-4">
<div class="w-12 h-12 rounded-xl bg-white/20 border border-white/30 backdrop-blur-md shadow-inner flex items-center justify-center">
<svg class="h-6 w-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/>
</svg>
</div>
<h3 class="text-white text-xl font-semibold">Why is it so smooth?</h3>
</div>
<svg class="w-6 h-6 text-white transition-transform duration-300" :class="{'rotate-180': open === 2}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</button>
<div x-show="open === 2" x-transition:enter="transition ease-out duration-400" x-transition:enter-start="opacity-0 -translate-y-3" x-transition:enter-end="opacity-100 translate-y-0" class="px-6 py-6 border-t border-white/20 bg-white/[0.04] backdrop-blur-sm">
<p class="text-gray-300 leading-relaxed">Animations use native GPU-accelerated transforms for 120Hz-ready smooth interaction feel.</p>
</div>
</div>
<!-- Item 3 -->
<div class="rounded-3xl overflow-hidden border border-white/20 backdrop-blur-2xl bg-white/[0.07] shadow-[0_8px_40px_rgba(255,255,255,0.08)] hover:shadow-[0_15px_60px_rgba(255,255,255,0.12)] transition-all duration-300"
:class="{ 'scale-[1.015] bg-white/[0.12] border-white/30 shadow-[0_15px_80px_rgba(255,255,255,0.2)]': open === 3 }">
<button @click="open = open === 3 ? null : 3" class="w-full px-6 py-6 flex justify-between items-center">
<div class="flex items-center gap-4">
<div class="w-12 h-12 rounded-xl bg-white/20 border border-white/30 backdrop-blur-md shadow-inner flex items-center justify-center">
<svg class="h-6 w-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4"/>
</svg>
</div>
<h3 class="text-white text-xl font-semibold">How do I customize it?</h3>
</div>
<svg class="w-6 h-6 text-white transition-transform duration-300" :class="{'rotate-180': open === 3}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</button>
<div x-show="open === 3" x-transition:enter="transition ease-out duration-400" x-transition:enter-start="opacity-0 -translate-y-3" x-transition:enter-end="opacity-100 translate-y-0" class="px-6 py-6 border-t border-white/20 bg-white/[0.04] backdrop-blur-sm">
<p class="text-gray-300 leading-relaxed">Adjust backdrop-blur, opacity layers, and shadow spreads in Tailwind to match your brand's aesthetic perfectly.</p>
</div>
</div>
</div>
<template>
<div class="space-y-5">
<div v-for="item in items" :key="item.id"
class="rounded-3xl overflow-hidden border border-white/20 backdrop-blur-2xl bg-white/[0.07] shadow-[0_8px_40px_rgba(255,255,255,0.08)] hover:shadow-[0_15px_60px_rgba(255,255,255,0.12)] transition-all duration-300"
:class="{ 'scale-[1.015] bg-white/[0.12] border-white/30 shadow-[0_15px_80px_rgba(255,255,255,0.2)]': open === item.id }">
<button @click="toggle(item.id)" class="w-full px-6 py-6 flex justify-between items-center">
<div class="flex items-center gap-4">
<div class="w-12 h-12 rounded-xl bg-white/20 border border-white/30 backdrop-blur-md shadow-inner flex items-center justify-center">
<component :is="item.icon" class="h-6 w-6 text-white" />
</div>
<h3 class="text-white text-xl font-semibold">{{ item.title }}</h3>
</div>
<ChevronDownIcon :class="{'rotate-180': open === item.id}" class="w-6 h-6 text-white transition-transform duration-300" />
</button>
<Transition enter-active-class="transition ease-out duration-400" enter-from-class="opacity-0 -translate-y-3" enter-to-class="opacity-100 translate-y-0">
<div v-show="open === item.id" class="px-6 py-6 border-t border-white/20 bg-white/[0.04] backdrop-blur-sm">
<p class="text-gray-300 leading-relaxed">{{ item.content }}</p>
</div>
</Transition>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ChevronDownIcon, BoltIcon, LightBulbIcon, AdjustmentsHorizontalIcon } from '@heroicons/vue/24/outline'
const open = ref(null)
const toggle = (id) => open.value = open.value === id ? null : id
const items = [
{ id: 1, icon: BoltIcon, title: 'What Makes Apple Glass UI?', content: 'Apple-style glass uses layered transparency, ultra-soft blur, and minimal shadow depth to give a floating-UI effect.' },
{ id: 2, icon: LightBulbIcon, title: 'Why is it so smooth?', content: 'Animations use native GPU-accelerated transforms for 120Hz-ready smooth interaction feel.' },
{ id: 3, icon: AdjustmentsHorizontalIcon, title: 'How do I customize it?', content: 'Adjust backdrop-blur, opacity layers, and shadow spreads in Tailwind to match your brand\'s aesthetic perfectly.' }
]
</script>
import React, { useState } from 'react'
import { ChevronDownIcon, BoltIcon, LightBulbIcon, AdjustmentsHorizontalIcon } from '@heroicons/react/24/outline'
const AppleGlassAccordion = () => {
const [open, setOpen] = useState(null)
const items = [
{ id: 1, icon: BoltIcon, title: 'What Makes Apple Glass UI?', content: 'Apple-style glass uses layered transparency, ultra-soft blur, and minimal shadow depth to give a floating-UI effect.' },
{ id: 2, icon: LightBulbIcon, title: 'Why is it so smooth?', content: 'Animations use native GPU-accelerated transforms for 120Hz-ready smooth interaction feel.' },
{ id: 3, icon: AdjustmentsHorizontalIcon, title: 'How do I customize it?', content: 'Adjust backdrop-blur, opacity layers, and shadow spreads in Tailwind to match your brand\'s aesthetic perfectly.' }
]
return (
<div className="space-y-5">
{items.map((item) => {
const Icon = item.icon
return (
<div key={item.id}
className={`rounded-3xl overflow-hidden border border-white/20 backdrop-blur-2xl bg-white/[0.07] shadow-[0_8px_40px_rgba(255,255,255,0.08)] hover:shadow-[0_15px_60px_rgba(255,255,255,0.12)] transition-all duration-300 ${
open === item.id ? 'scale-[1.015] bg-white/[0.12] border-white/30 shadow-[0_15px_80px_rgba(255,255,255,0.2)]' : ''
}`}>
<button onClick={() => setOpen(open === item.id ? null : item.id)} className="w-full px-6 py-6 flex justify-between items-center">
<div className="flex items-center gap-4">
<div className="w-12 h-12 rounded-xl bg-white/20 border border-white/30 backdrop-blur-md shadow-inner flex items-center justify-center">
<Icon className="h-6 w-6 text-white" />
</div>
<h3 className="text-white text-xl font-semibold">{item.title}</h3>
</div>
<ChevronDownIcon className={`w-6 h-6 text-white transition-transform duration-300 ${open === item.id ? 'rotate-180' : ''}`} />
</button>
{open === item.id && (
<div className="px-6 py-6 border-t border-white/20 bg-white/[0.04] backdrop-blur-sm animate-[slideDown_0.4s_ease-out]">
<p className="text-gray-300 leading-relaxed">{item.content}</p>
</div>
)}
</div>
)
})}
</div>
)
}
export default AppleGlassAccordion
🚀 How to Use These Components
Requirements
- TailwindCSS v4.0+ installed (Install Guide)
- AlpineJS for interactivity (HTML version)
-
Heroicons for icons (optional)
-
React:
npm install @heroicons/react -
Vue:
npm install @heroicons/vue
-
React:
Installation
Pro Tip: These accordions work great for FAQs, product features, documentation, and any collapsible content. Customize colors, spacing, and animations to match your brand.