Erişilebilir React accordion
WAI-ARIA uyumlu accordion bileşeni üretimi.

Prompt Metni
React ve TypeScript ile tek paneli açık tutan erişilebilir bir accordion oluştur. Gereksinimler: - Başlıklar gerçek button öğeleri olmalı. - aria-expanded ve aria-controls kullanılmalı. - Yukarı/Aşağı ok tuşları başlıklar arasında gezinmeli. - Enter ve Space, button öğesinin doğal davranışını kullanmalı. - Bileşen ile kısa kullanım örneğini tek dosyada göster.
Prompt Sonucu
'use client'
import { useRef, useState, type KeyboardEvent } from 'react'
type Item = { title: string; content: string }
export function Accordion({ items }: { items: Item[] }) {
const [openIndex, setOpenIndex] = useState<number | null>(0)
const buttons = useRef<Array<HTMLButtonElement | null>>([])
function moveFocus(event: KeyboardEvent, index: number) {
if (!['ArrowDown', 'ArrowUp'].includes(event.key)) return
event.preventDefault()
const offset = event.key === 'ArrowDown' ? 1 : -1
const next = (index + offset + items.length) % items.length
buttons.current[next]?.focus()
}
return (
<div>
{items.map((item, index) => {
const open = openIndex === index
const buttonId = 'accordion-button-' + index
const panelId = 'accordion-panel-' + index
return (
<section key={item.title}>
<h3>
<button
ref={(node) => { buttons.current[index] = node }}
id={buttonId}
aria-expanded={open}
aria-controls={panelId}
onClick={() => setOpenIndex(open ? null : index)}
onKeyDown={(event) => moveFocus(event, index)}
>
{item.title}
</button>
</h3>
<div
id={panelId}
role="region"
aria-labelledby={buttonId}
hidden={!open}
>
{item.content}
</div>
</section>
)
})}
</div>
)
}
// Kullanım:
// <Accordion items={[
// { title: 'Prompt nedir?', content: 'Modele verilen görev tanımıdır.' },
// { title: 'Nasıl yazılır?', content: 'Amaç, bağlam ve çıktı biçimi belirtilir.' },
// ]} />