Accordion
Yig'iladigan bo'limlar: FAQ, sozlamalar va uzun formalarni ixcham ko'rsatish uchun.
'use client';
import { Accordion } from '@akhatmirzo/ui';
const faq = [
{
value: 'delivery',
title: 'Yetkazib berish qancha vaqt oladi?',
body: "Toshkent bo'ylab 1 kun, viloyatlarga 2–3 ish kuni.",
},
{
value: 'payment',
title: "Qanday to'lov usullari bor?",
body: "Click, Payme, Uzum va naqd pul. Karta orqali to'lov darhol tasdiqlanadi.",
},
{
value: 'return',
title: "Mahsulotni qaytarsa bo'ladimi?",
body: "Ha, 14 kun ichida, qadoq buzilmagan bo'lsa.",
},
];
export default function AccordionBasic() {
return (
<Accordion defaultValue="delivery" className="max-w-xl">
{faq.map((q) => (
<Accordion.Item key={q.value} value={q.value} title={q.title}>
{q.body}
</Accordion.Item>
))}
</Accordion>
);
}
Import
import { Accordion } from '@akhatmirzo/ui';Qachon ishlatish
- Ko'p savol-javob (FAQ) — foydalanuvchi faqat kerakli savolni ochadi, sahifa qisqa qoladi.
- Sozlamalar va uzun formalar — bo'limlarga bo'lib, hammasini birdan ko'rsatmaslik.
- Asosiy kontentni yashirmang. Foydalanuvchi albatta ko'rishi kerak bo'lgan ma'lumot ochiq tursin — accordion ichidagi matnni ko'pchilik o'qimaydi.
- Bir vaqtda faqat bitta bo'lim ko'rinsin desangiz va bo'limlar teng ahamiyatli bo'lsa,
Tabsham mos keladi.
Tuzilishi
Eng oddiy yo'l — Accordion.Item ga title berish: sarlavha va kontent avtomatik chiziladi,
children kontentga tushadi.
<Accordion defaultValue="delivery">
<Accordion.Item value="delivery" title="Yetkazib berish qancha vaqt oladi?">
Toshkent bo'ylab 1 kun, viloyatlarga 2–3 ish kuni.
</Accordion.Item>
</Accordion>Sarlavhaga o'z kontentingizni (badge, ikonka) qo'yish kerak bo'lsa, title bermang va
Accordion.Trigger + Accordion.Content ni o'zingiz yozing (pastda "Kompozitsiya").
Variantlar
| Variant | Ko'rinish |
|---|---|
separated | Har bir bo'lim alohida karta, orasida 8px (standart) |
bordered | Hammasi bitta kartada, bo'limlar chiziq bilan ajralgan |
ghost | Fonsiz, faqat ajratuvchi chiziqlar |
'use client';
import { Accordion } from '@akhatmirzo/ui';
export default function AccordionVariants() {
return (
<div className="grid w-full gap-6 md:grid-cols-3">
{(['separated', 'bordered', 'ghost'] as const).map((variant) => (
<div key={variant} className="flex flex-col gap-2">
<span className="text-xs font-medium text-text-muted">{variant}</span>
<Accordion variant={variant} defaultValue="a">
<Accordion.Item value="a" title="Yetkazib berish">
Toshkent bo'ylab 1 kun.
</Accordion.Item>
<Accordion.Item value="b" title="To'lov">
Click, Payme yoki naqd.
</Accordion.Item>
<Accordion.Item value="c" title="Qaytarish">
14 kun ichida.
</Accordion.Item>
</Accordion>
</div>
))}
</div>
);
}
Bir nechtasi ochiq
Standart holatda (type="single") bitta bo'lim ochiq turadi — boshqasi ochilsa, oldingisi
yopiladi. type="multiple" bilan bir nechtasini birga ochish mumkin; bunda value va
defaultValue — massiv.
'use client';
import { Accordion } from '@akhatmirzo/ui';
export default function AccordionMultiple() {
return (
<Accordion type="multiple" defaultValue={['delivery', 'payment']} className="max-w-xl">
<Accordion.Item value="delivery" title="Yetkazib berish qancha vaqt oladi?">
Toshkent bo'ylab 1 kun, viloyatlarga 2–3 ish kuni.
</Accordion.Item>
<Accordion.Item value="payment" title="Qanday to'lov usullari bor?">
Click, Payme, Uzum va naqd pul.
</Accordion.Item>
<Accordion.Item value="return" title="Mahsulotni qaytarsa bo'ladimi?">
Ha, 14 kun ichida, qadoq buzilmagan bo'lsa.
</Accordion.Item>
</Accordion>
);
}
Yopib bo'lmaydigan
type="single" da ochiq bo'limni qayta bosish uni yopadi (collapsible standart — true).
collapsible={false} bilan doim bitta bo'lim ochiq turadi — variantlar orasidan tanlashga
o'xshaydi.
'use client';
import { Accordion } from '@akhatmirzo/ui';
export default function AccordionNonCollapsible() {
return (
<Accordion collapsible={false} defaultValue="courier" variant="bordered" className="max-w-xl">
<Accordion.Item value="courier" title="Kuryer orqali">
Ertasi kuni eshigingizgacha. Narxi — 25 000 so'm.
</Accordion.Item>
<Accordion.Item value="pickup" title="Olib ketish punktidan">
Toshkentdagi 12 ta punktdan bepul olib ketasiz.
</Accordion.Item>
<Accordion.Item value="post" title="Pochta orqali">
Viloyatlarga 2–3 ish kuni. Narxi — 18 000 so'm.
</Accordion.Item>
</Accordion>
);
}
Kompozitsiya
Accordion.Item ichida Accordion.Trigger va Accordion.Content — sarlavhaga badge, ikonka
yoki ikkinchi qator qo'shish uchun. Bitta bo'limni disabled bilan o'chirish mumkin.
'use client';
import { Accordion, Badge } from '@akhatmirzo/ui';
export default function AccordionComposition() {
return (
<Accordion variant="bordered" className="max-w-xl">
<Accordion.Item value="notifications">
<Accordion.Trigger>
<span className="flex items-center gap-2">
Bildirishnomalar
<Badge color="primary" size="sm">
3 ta yangi
</Badge>
</span>
</Accordion.Trigger>
<Accordion.Content>
<ul className="m-0 flex list-disc flex-col gap-1 pl-5">
<li>Buyurtma #1042 yetkazildi</li>
<li>Yangi sharh qoldirildi</li>
<li>To'lov qabul qilindi</li>
</ul>
</Accordion.Content>
</Accordion.Item>
<Accordion.Item value="security">
<Accordion.Trigger>Xavfsizlik</Accordion.Trigger>
<Accordion.Content>Parolni oxirgi marta 3 oy oldin o'zgartirgansiz.</Accordion.Content>
</Accordion.Item>
<Accordion.Item value="billing" disabled>
<Accordion.Trigger>To'lov ma'lumotlari (tez orada)</Accordion.Trigger>
<Accordion.Content>—</Accordion.Content>
</Accordion.Item>
</Accordion>
);
}
Boshqariladigan rejim
value + onValueChange — qaysi bo'limlar ochiqligini o'zingiz boshqarasiz: "Hammasini ochish"
tugmasi, URL bilan sinxronlash va hokazo.
'use client';
import { Accordion, Button } from '@akhatmirzo/ui';
import { useState } from 'react';
const sections = [
{ value: 'profile', title: "Shaxsiy ma'lumotlar", body: "Ism, telefon va tug'ilgan sana." },
{ value: 'address', title: 'Manzillar', body: 'Uy: Toshkent, Chilonzor tumani, 9-mavze.' },
{ value: 'cards', title: "To'lov kartalari", body: 'Uzcard •• 4521, Humo •• 9087.' },
];
export default function AccordionControlled() {
const [open, setOpen] = useState<string[]>(['profile']);
return (
<div className="flex w-full max-w-xl flex-col gap-3">
<div className="flex flex-wrap gap-2">
<Button size="sm" variant="outline" onClick={() => setOpen(sections.map((s) => s.value))}>
Hammasini ochish
</Button>
<Button size="sm" variant="outline" onClick={() => setOpen([])}>
Hammasini yopish
</Button>
</div>
<Accordion type="multiple" value={open} onValueChange={setOpen}>
{sections.map((s) => (
<Accordion.Item key={s.value} value={s.value} title={s.title}>
{s.body}
</Accordion.Item>
))}
</Accordion>
</div>
);
}
Props
Accordion
Qolgan <div> atributlari ham qabul qilinadi.
| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
type | 'single' | 'multiple' | 'single' | Bitta yoki bir nechta bo'lim ochiq tura oladi |
value | string · string[] | — | Ochiq bo'lim(lar) — multiple da massiv |
defaultValue | string · string[] | — | Boshlang'ich ochiq bo'lim(lar) |
onValueChange | (value: string) => void · (value: string[]) => void | — | Ochilib-yopilganda |
collapsible | boolean | true | Faqat single: ochiq bo'limni qayta bosib yopish mumkinmi |
variant | 'separated' | 'bordered' | 'ghost' | 'separated' | Ko'rinish |
disabled | boolean | — | Barcha bo'limlarni o'chiradi |
orientation | 'horizontal' | 'vertical' | — | Klaviatura navigatsiyasi yo'nalishi (standart — vertical) |
dir | 'ltr' | 'rtl' | — | Yozuv yo'nalishi |
Accordion.Item
| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
valuemajburiy | string | — | Bo'lim qiymati |
title | ReactNode | — | Berilsa — Trigger va Content avtomatik, children kontentga tushadi |
disabled | boolean | — | Bo'limni o'chiradi |
Accordion.Trigger, Accordion.Content
Accordion.Trigger — <button> atributlarini oladi; matn yonida o'ngda chevron chiziladi.
Accordion.Content — <div> atributlari va forceMount (yopiq paytda ham DOM'da qoldirish).
Data atributlari
| Atribut | Qayerda | Qiymat |
|---|---|---|
data-variant | ildiz, bo'lim | separated · bordered · ghost |
data-state | bo'lim, sarlavha, kontent | open · closed |
data-disabled | bo'lim, sarlavha | o'chirilganda mavjud |
data-orientation | barcha qismlar | vertical · horizontal |
data-accordion-chevron | chevron ikonka | — |
Klaviatura
| Tugma | Harakat |
|---|---|
Enter / Space | Fokusdagi bo'limni ochadi yoki yopadi |
↓ / ↑ | Keyingi / oldingi sarlavhaga o'tish |
Home / End | Birinchi / oxirgi sarlavha |
Tab | Keyingi fokuslanadigan element |
Accessibility
- Tuzilma. Har bir sarlavha
<h3>ichidagi<button>; tugmaaria-expandedvaaria-controlsoladi, kontent —role="region"vaaria-labelledbybilan sarlavhaga ulanadi. Asosida Radix Accordion. - Chevron bezak —
aria-hidden, ochilganda 180° buriladi. - Animatsiya. Balandlik 200ms davomida o'zgaradi;
prefers-reduced-motionda faqat shaffoflik. - Fokus halqasi faqat klaviatura bilan kelganda ko'rinadi.