Dapatkan diskon up to 40% untuk pembelian di bulan Ramadhan.

Membuat Accordion Dengan Pure Tailwind CSS

Dalam snippet kali ini saya akan menuntun Anda bagaimana sebenarnya membuat komponen yang bernama accordion, biasa digunakan untuk Frequently Asked Question (FAQ), atau bisa jadi yang lain seperti dropdown untuk sidebar.

5 min read

Published on 24 Oct, 2021 (updated: 23 Sep, 2022)

Written by Irsyad A. Panjaitan

Fill in Tailwind CSS

ArticlesMembuat Accordion Dengan Pure Tailwind CSS

Dalam snippet kali ini saya akan menuntun Anda bagaimana sebenarnya membuat komponen yang bernama accordion, biasa digunakan untuk Frequently Asked Question (FAQ), atau bisa jadi yang lain seperti dropdown untuk sidebar.

Nah, disini kita tidak akan mulai dari awal, yang artinya saya akan sudah menganggap bahwa Anda sudah mempersiapkan project yang Tailwind CSS nya sendiri sudah ready untuk digunakan.

Jika Anda belum tau bagaimana cara install nya, saya sudah membuat post tentang installasi Tailwind CSS didalam nextjs. Atau Anda bisa lihat installasi dibeberapa framework seperti reactjs, vuejs, atau pun laravel (Install Tailwind CSS 2 Di Beberapa Framework)

Jika sudah, silahkan buka file tailwind.config.js dan ganti mode nya menjadi Just In Time jit, atau jika Anda belum menggunakan mode, silahkan tambahkan seperti berikut.

module.exports = { purge: [], darkMode: false, // or 'media' or 'class' mode: 'jit', theme: { extend: {}, }, variants: { extend: {}, }, plugins: [], };
jsCopy

Dalam teknik yang akan kita lakukan ini sama sekali tidak menggunakan yang namanya javascript, jadi ini pure dengan Tailwind CSS, tapi saya berharap Anda menggunakan versi ^2.2, atau bisa lebih besar dari itulah, karena teknik yang akan kita gunakan ini adalah menggunakan peer, yang mana itu sendiri datang sejak v2.2.

Dalam post kali ini, saya menggunakan framework dari reactjs yaitu Nextjs. Tidak ada masalah sama sekali jika Anda menggunakan html, yang penting, jika nanti saya ketik className itu hanya karena saya pakai jsx. Jadi jika Anda menggunkan pure html, anda bisa ganti menjadi class saja.

<!-- HTML --> <div class="bg-red-500"></div> <!-- JSX --> <div className="bg-red-500"></div>
htmlCopy

Mari kita mulai dengan membuat wrappernya, seperti berikut.

<div className="relative overflow-hidden"> </div>
jsxCopy

Didalam nya, silahkan masukkan satu input dengan type checkbox dan beri class nya dengan peer seperti berikut.

<input type="checkbox" className="peer absolute top-0 inset-x-0 w-full h-12 opacity-0 z-10 cursor-pointer" />
jsxCopy

Jadi sekarang kira - kira komplitnya seperti ini.

<div className="relative overflow-hidden"> <input type="checkbox" className="peer absolute top-0 inset-x-0 w-full h-12 opacity-0 z-10 cursor-pointer" /> </div>
jsxCopy

Sekarang, silahkan tambahkan satu div tepat dibawah checkbox tersebut, bayangkan aja sekarang kita lagi buat FAQ, jadi div pertama akan jadi pertanyaan nya, div kedua akan menjadi jawabannya.

<div className="h-12 w-full pl-5 flex items-center"> <h1> Question 1 </h1> </div>
jsxCopy

Kemudian, tambah kan satu lagi div untuk jawabannya tepat dibawah penutup div nya seperti berikut.

<div className="overflow-hidden bg-white transition-all duration-500 max-h-0 peer-checked:max-h-40"> <div className="p-5 border-t">Answer 1</div> </div>
jsxCopy

Percaya atau tidak, itu semua sudah berhasil, cuma kita perlu sedikit visual icon untuk menandakan bahwa dia terbuka atau tertutup. Silahkan tambah tepat ditengah - tengah div tersebut.

<div className="..."> {/* Question */} </div> <div className="absolute top-3 right-3 transition-transform duration-500 rotate-0 peer-checked:-rotate-90"> <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" /> </svg> </div> <div className="..."> {/* Answer */} </div>
jsxCopy

Komplitnya kira - kira seperti ini.

<div className="relative overflow-hidden"> <input type="checkbox" className="peer absolute top-0 inset-x-0 w-full h-12 opacity-0 z-10 cursor-pointer" /> <div className="h-12 w-full pl-5 flex items-center"> <h1> Question 1 </h1> </div> <div className="absolute top-3 right-3 transition-transform duration-500 rotate-0 peer-checked:-rotate-90"> <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" /> </svg> </div> <div className="overflow-hidden bg-white transition-all duration-500 max-h-0 peer-checked:max-h-40"> <div className="p-5 border-t">Answer 1</div> </div> </div>
jsxCopy

Jika sudah, harusnya sekarang Anda sudah selesai, tapi jika Anda ingin membuatnya menjadi reusable component, itu sah - sah saja. Karena disini saya menggunakan next yang membawa react, pastinya itu sangat mudah, tapi bukan berarti Anda menggunakan vue atau laravel itu sulit.

Pertama, silakan cut semua markup tersebut dan extract kedalam satu komponen seperti berikut.

const Item = ({ q, a }) => ( <div className="relative overflow-hidden"> <input type="checkbox" className="peer absolute top-0 inset-x-0 w-full h-12 opacity-0 z-10 cursor-pointer" /> <div className="h-12 w-full pl-5 flex items-center"> <h1> {q} </h1> </div> <div className="absolute top-3 right-3 transition-transform duration-500 rotate-0 peer-checked:-rotate-90"> <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" /> </svg> </div> <div className="overflow-hidden bg-white transition-all duration-500 max-h-0 peer-checked:max-h-40"> <div className="p-5 border-t">{a}</div> </div> </div> );
jsxCopy

Jika sudah, sekarang Anda bisa pakai komponen tersebut dengan cara seperti ini.

export default function Home() { return ( <div className="p-10"> <div className="overflow-hidden divide-y border shadow-sm rounded-2xl"> <Item q="Question 1" a="Answer 1" /> <Item q="Question 2" a="Answer 2" /> <Item q="Question 3" a="Answer 3" /> </div> </div> ); }
jsxCopy

Kali ini step nya sudah selesai, jadi sekarang Anda tinggal buat satu array, terserah itu mau datang dari database atau tidak. Yang jelas, Anda bisa buat seperti ini sekarang.

export default function Home() { const faqs = [ { question: 'Apakah video gratis tersedia ?', answered: 'Tentu saja. Video yang berbayar bertanda icon rocket. Jika tidak ada tanda, video itu gratis.' }, { question: 'Seberapa sering Parsinta upload pelajaran baru ?', answered: ' Setiap hari akan ada video untuk setiap seri yang masih dalam persiapan, usahakan setiap hari Anda cek konten baru di parsinta. ', }, { question: 'Bagaimana cara nonton video gratis mau pun berbayar ?', answered: ' Dari kedua sisi baik gratis mau pun berbayar, Anda tetap harus login jika ingin menonton video. ', }, ]; return ( <div className="p-10"> <div className="overflow-hidden divide-y border shadow-sm rounded-2xl"> {faqs.map((item, key) => <Item q={item.question} a={item.answered} key={key} />)} </div> </div> ); }
jsxCopy

Oia, pertanyaan tersebut saya kopi dari Parsinta FAQ. Semoga bermanfaat, jangan lupa share jika menurut Anda ini bermanfaat ya. Saya irsyad. See on the other one 🙂

Irsyad A. Panjaitan

Let's start living like no one can help us in any event, so that when we are helped in certain times, it becomes a plus in itself.
2

Share on