Component
Settings Accordion
Application settings accordion whose panels hold form controls, toggles, and a danger zone. Single-open sections grouped like a real settings page.
- Component
- Tailwind
- HTML
- MIT
Preview
Live component
9:41 100%
devsnips.dev/library/tailwind/components/accordions/settings-accordion/ fluid · no fixed width 100%
Install
Add to your project
npx devsnips add Tailwind/Components/Accordions/settings-accordion Tailwind/Components/Accordions/settings-accordion <!--
Snippet Name: Settings Accordion
Description: Application settings accordion whose panels contain form controls (toggles, selects). Section-grouped, single-open.
Author: DevSnips Contributors
Usage Example: Account/workspace settings pages where controls are grouped into collapsible sections.
-->
<div class="overflow-hidden rounded-xl border border-gray-200 bg-white" data-accordion="settings" data-single-open>
<div class="divide-y divide-gray-100">
<!-- Profile -->
<div data-accordion-item>
<h3>
<button type="button" id="settings-trigger-1" aria-controls="settings-panel-1" aria-expanded="false" class="accordion-trigger group flex w-full items-center gap-3 px-5 py-4 text-left focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-inset">
<span class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-blue-50 text-blue-600"><svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/></svg></span>
<span class="min-w-0 flex-1"><span class="block text-sm font-semibold text-gray-900">Profile</span><span class="block text-xs text-gray-500">Name, email, and display photo</span></span>
<svg class="accordion-chevron h-5 w-5 shrink-0 text-gray-400 transition-transform duration-300 ease-out" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</button>
</h3>
<div id="settings-panel-1" role="region" aria-labelledby="settings-trigger-1" class="accordion-panel grid grid-rows-[0fr] transition-[grid-template-rows] duration-300 ease-out">
<div class="overflow-hidden">
<div class="space-y-4 border-t border-gray-100 px-5 py-4">
<div>
<label for="settings-name" class="block text-xs font-medium text-gray-700">Full name</label>
<input id="settings-name" type="text" value="Jordan Avery" class="mt-1.5 w-full rounded-lg border border-gray-200 px-3 py-2 text-sm text-gray-900 focus:border-blue-400 focus:outline-none focus:ring-2 focus:ring-blue-100">
</div>
<div>
<label for="settings-email" class="block text-xs font-medium text-gray-700">Email</label>
<input id="settings-email" type="email" value="jordan@devsnips.dev" class="mt-1.5 w-full rounded-lg border border-gray-200 px-3 py-2 text-sm text-gray-900 focus:border-blue-400 focus:outline-none focus:ring-2 focus:ring-blue-100">
</div>
</div>
</div>
</div>
</div>
<!-- Notifications -->
<div data-accordion-item>
<h3>
<button type="button" id="settings-trigger-2" aria-controls="settings-panel-2" aria-expanded="false" class="accordion-trigger group flex w-full items-center gap-3 px-5 py-4 text-left focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-inset">
<span class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-amber-50 text-amber-600"><svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"/></svg></span>
<span class="min-w-0 flex-1"><span class="block text-sm font-semibold text-gray-900">Notifications</span><span class="block text-xs text-gray-500">Email and in-app alerts</span></span>
<svg class="accordion-chevron h-5 w-5 shrink-0 text-gray-400 transition-transform duration-300 ease-out" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</button>
</h3>
<div id="settings-panel-2" role="region" aria-labelledby="settings-trigger-2" class="accordion-panel grid grid-rows-[0fr] transition-[grid-template-rows] duration-300 ease-out">
<div class="overflow-hidden">
<ul class="divide-y divide-gray-100 border-t border-gray-100">
<li class="flex items-center justify-between gap-4 px-5 py-3.5">
<div><p class="text-sm font-medium text-gray-900">Product updates</p><p class="text-xs text-gray-500">New features and changelog</p></div>
<button role="switch" aria-checked="true" class="relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent bg-blue-600 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"><span class="pointer-events-none inline-block h-5 w-5 translate-x-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span></button>
</li>
<li class="flex items-center justify-between gap-4 px-5 py-3.5">
<div><p class="text-sm font-medium text-gray-900">Security alerts</p><p class="text-xs text-gray-500">Logins and suspicious activity</p></div>
<button role="switch" aria-checked="true" class="relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent bg-blue-600 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"><span class="pointer-events-none inline-block h-5 w-5 translate-x-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span></button>
</li>
<li class="flex items-center justify-between gap-4 px-5 py-3.5">
<div><p class="text-sm font-medium text-gray-900">Marketing</p><p class="text-xs text-gray-500">Tips, offers, and newsletters</p></div>
<button role="switch" aria-checked="false" class="relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent bg-gray-200 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"><span class="pointer-events-none inline-block h-5 w-5 translate-x-0 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span></button>
</li>
</ul>
</div>
</div>
</div>
<!-- Danger zone -->
<div data-accordion-item>
<h3>
<button type="button" id="settings-trigger-3" aria-controls="settings-panel-3" aria-expanded="false" class="accordion-trigger group flex w-full items-center gap-3 px-5 py-4 text-left focus:outline-none focus-visible:ring-2 focus-visible:ring-rose-500 focus-visible:ring-inset">
<span class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-rose-50 text-rose-600"><svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6M1 7h22M9 7V4a1 1 0 011-1h4a1 1 0 011 1v3"/></svg></span>
<span class="min-w-0 flex-1"><span class="block text-sm font-semibold text-gray-900">Danger zone</span><span class="block text-xs text-gray-500">Transfer or delete this workspace</span></span>
<svg class="accordion-chevron h-5 w-5 shrink-0 text-gray-400 transition-transform duration-300 ease-out" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</button>
</h3>
<div id="settings-panel-3" role="region" aria-labelledby="settings-trigger-3" class="accordion-panel grid grid-rows-[0fr] transition-[grid-template-rows] duration-300 ease-out">
<div class="overflow-hidden">
<div class="space-y-3 border-t border-gray-100 px-5 py-4">
<div class="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between"><div><p class="text-sm font-medium text-gray-900">Transfer ownership</p><p class="text-xs text-gray-500">Hand this workspace to another admin</p></div><button class="self-start rounded-lg border border-gray-200 px-3 py-1.5 text-sm font-medium text-gray-700 hover:bg-gray-50 sm:self-auto">Transfer</button></div>
<div class="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between"><div><p class="text-sm font-medium text-rose-600">Delete workspace</p><p class="text-xs text-gray-500">Permanent, cannot be undone</p></div><button class="self-start rounded-lg border border-rose-200 bg-rose-50 px-3 py-1.5 text-sm font-medium text-rose-600 hover:bg-rose-100 sm:self-auto">Delete</button></div>
</div>
</div>
</div>
</div>
</div>
<script>
(function () {
const root = document.currentScript.closest('[data-accordion]');
if (!root) return;
const singleOpen = root.hasAttribute('data-single-open');
const items = Array.from(root.querySelectorAll('[data-accordion-item]'));
items.forEach((item) => {
const trigger = item.querySelector('.accordion-trigger');
const panel = item.querySelector('.accordion-panel');
const chevron = item.querySelector('.accordion-chevron');
if (!trigger || !panel) return;
const close = () => { trigger.setAttribute('aria-expanded','false'); panel.classList.remove('grid-rows-[1fr]'); panel.classList.add('grid-rows-[0fr]'); if (chevron) chevron.style.transform=''; };
const open = () => { trigger.setAttribute('aria-expanded','true'); panel.classList.add('grid-rows-[1fr]'); panel.classList.remove('grid-rows-[0fr]'); if (chevron) chevron.style.transform='rotate(180deg)'; };
trigger.addEventListener('click', () => {
const isOpen = trigger.getAttribute('aria-expanded') === 'true';
if (singleOpen) items.forEach((o) => { if (o !== item) { const t=o.querySelector('.accordion-trigger'); const p=o.querySelector('.accordion-panel'); const c=o.querySelector('.accordion-chevron'); t.setAttribute('aria-expanded','false'); p.classList.remove('grid-rows-[1fr]'); p.classList.add('grid-rows-[0fr]'); if(c) c.style.transform=''; } });
isOpen ? close() : open();
});
});
// Toggle switches
root.querySelectorAll('[role="switch"]').forEach((sw) => {
sw.addEventListener('click', () => {
const on = sw.getAttribute('aria-checked') === 'true';
sw.setAttribute('aria-checked', String(!on));
sw.classList.toggle('bg-blue-600', !on);
sw.classList.toggle('bg-gray-200', on);
const knob = sw.querySelector('span');
if (knob) knob.classList.toggle('translate-x-5', !on);
if (knob) knob.classList.toggle('translate-x-0', on);
});
});
})();
</script>
</div> # Settings Accordion
Settings-oriented accordion with denser controls and sectioned preferences.
## Usage
```bash
npx devsnips add Tailwind/Components/Accordions/settings-accordion
```
Copy from `code.html`. Keep ARIA expanded/controls in sync if using the inline script.
## File Structure
`code.html` · `preview.html` · `metadata.json` · `README.md` 116 lines UTF-8 · LF · Spaces: 2
Continue browsing