a11y(prediction): add aria-pressed + type=button to period presets

PredictionPanel's 3-segment 예측 기간 control (15일/30일/1년) was the last
segmented control without aria-pressed after slice (n)'s audit. It carried
the visual "pressed" state via className branch but no ARIA attribute, so
screen-reader users got no announcement of the current selection.

Also tighten type="button" to prevent default form submission semantics —
the buttons live outside <form> here, but explicit type is canonical for
non-submit buttons.

Visual styling kept as-is. The slightly heavier active token (bg-zinc-700
solid, px-3 py-1) vs the chart-toolbar canonical (border-zinc-600 bg-zinc-
800/80, px-2 py-0.5) is intentional: these presets live in the card body
next to a primary rose-600 execute button and need more visual weight than
toolbar toggles. Comment documents the reasoning.
This commit is contained in:
claude-owner
2026-06-01 11:17:11 +09:00
parent c172f244e3
commit 0a09540e9f

View File

@@ -94,19 +94,30 @@ export function PredictionPanel({ code, initial, onResult }: Props) {
<div className="mb-3 flex flex-wrap items-center gap-2 text-xs">
<span className="text-zinc-500"> :</span>
{PREDICT_PRESETS.map((p, i) => (
<button
key={p.id}
onClick={() => setPresetIdx(i)}
className={
presetIdx === i
? "rounded-full bg-zinc-700 px-3 py-1 font-medium text-zinc-50"
: "rounded-full border border-zinc-700 px-3 py-1 text-zinc-300 hover:border-zinc-500"
}
>
{p.label}
</button>
))}
{PREDICT_PRESETS.map((p, i) => {
const on = presetIdx === i;
return (
// segmented control — PeriodTabs / InvestorCumulative window / SMA·RSI·MACD 토글과
// 같은 패턴. type="button" 으로 폼 submit 기본값 사고 차단, aria-pressed 로 스크린
// 리더에 현재 선택 노출. 시각 토큰은 PredictionPanel 자체 톤(bg-zinc-700 solid)
// 유지 — 본문 카드 영역 안 primary 보조 컨트롤이라 툴바용 zinc-800/80 보다 한
// 단계 도드라지는 게 의도. 패딩(px-3 py-1) 도 옆 rose-600 실행 버튼과 시각
// 무게 균형을 위해 툴바 토글(px-2 py-0.5) 보다 큼.
<button
key={p.id}
type="button"
onClick={() => setPresetIdx(i)}
aria-pressed={on}
className={
on
? "rounded-full bg-zinc-700 px-3 py-1 font-medium text-zinc-50"
: "rounded-full border border-zinc-700 px-3 py-1 text-zinc-300 hover:border-zinc-500"
}
>
{p.label}
</button>
);
})}
{presetIdx === 2 && (
<span className="ml-1 text-[11px] text-amber-400">
30