Pretty isn't enough
Clickable <div>s can't be reached by keyboard, and screen readers don't know a row of buttons is a set of tabs. React makes it easy to keep ARIA attributes in sync with state — so let's build components everyone can use.
Roles, state and keyboard
import { useState } from "react";
const TABS = ["Menu", "Hours", "Contact"];
export default function Tabs() {
const [active, setActive] = useState(0);
return (
<div>
<div role="tablist" aria-label="Restaurant info">
{TABS.map((t, i) => (
<button
key={t}
role="tab"
id={"tab-" + i}
aria-selected={i === active}
aria-controls={"panel-" + i}
tabIndex={i === active ? 0 : -1}
onClick={() => setActive(i)}
>
{t}
</button>
))}
</div>
<div role="tabpanel" id={"panel-" + active} aria-labelledby={"tab-" + active}>
{TABS[active]} details…
</div>
</div>
);
}- Use real <button>s and <a>s — they're focusable and work with Enter/Space for free.
- Every input needs a <label>; every image an alt.
- Check your work with only the keyboard, and with a screen reader (VoiceOver, NVDA).