Files
Webklar/src/components/WischReihe.tsx
T

57 lines
2.0 KiB
TypeScript

import { Children, useEffect, useRef, useState, type ReactNode } from "react";
import "./wisch-reihe.css";
type WischReiheProps = {
/** Beschreibung für Screenreader, z. B. „Vier Leistungen, seitlich wischen“ */
ariaLabel: string;
children: ReactNode;
className?: string;
/** Zähler „2 / 4“ unter der Reihe anzeigen (Standard: ja) */
zaehler?: boolean;
};
/**
* Horizontale Wisch-Reihe für Handys (Spezifikation 9.4): natives Scroll-Snap ohne Bibliothek,
* die nächste Karte ist angeschnitten sichtbar, darunter ein Zähler. Keine automatische Bewegung.
* Ab 900 px entscheidet der Abschnitt selbst, ob er die Reihe überhaupt zeigt.
*/
const WischReihe = ({ ariaLabel, children, className, zaehler = true }: WischReiheProps) => {
const karten = Children.toArray(children);
const reiheRef = useRef<HTMLUListElement>(null);
const [aktiv, setAktiv] = useState(0);
useEffect(() => {
const reihe = reiheRef.current;
if (!reihe || typeof IntersectionObserver === "undefined") return;
const beobachter = new IntersectionObserver(
(eintraege) => {
for (const e of eintraege) {
if (e.isIntersecting) setAktiv(Number((e.target as HTMLElement).dataset.index));
}
},
{ root: reihe, threshold: 0.6 },
);
reihe.querySelectorAll<HTMLElement>(":scope > li").forEach((li) => beobachter.observe(li));
return () => beobachter.disconnect();
}, [karten.length]);
return (
<div className={`wk-wisch${className ? ` ${className}` : ""}`}>
<ul ref={reiheRef} className="wk-wisch__reihe" role="list" tabIndex={0} aria-label={ariaLabel}>
{karten.map((karte, i) => (
<li key={i} className="wk-wisch__karte" data-index={i}>
{karte}
</li>
))}
</ul>
{zaehler && karten.length > 1 && (
<p className="wk-wisch__zaehler wk-num" aria-hidden>
{aktiv + 1} / {karten.length}
</p>
)}
</div>
);
};
export default WischReihe;