feat: carousel keyboard keys
This commit is contained in:
parent
10f1fc2fb3
commit
63f82c3c18
2 changed files with 51 additions and 1 deletions
|
|
@ -15,6 +15,7 @@ export default function Carousel({ images, className }: Props) {
|
||||||
const [emblaRef, emblaApi] = useEmblaCarousel();
|
const [emblaRef, emblaApi] = useEmblaCarousel();
|
||||||
const [selectedIndex, setSelectedIndex] = useState(0);
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
||||||
const [scrollSnaps, setScrollSnaps] = useState<number[]>([]);
|
const [scrollSnaps, setScrollSnaps] = useState<number[]>([]);
|
||||||
|
const [isFocused, setIsFocused] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!emblaApi) return;
|
if (!emblaApi) return;
|
||||||
|
|
@ -22,8 +23,31 @@ export default function Carousel({ images, className }: Props) {
|
||||||
emblaApi.on("select", () => setSelectedIndex(emblaApi.selectedScrollSnap()));
|
emblaApi.on("select", () => setSelectedIndex(emblaApi.selectedScrollSnap()));
|
||||||
}, [emblaApi]);
|
}, [emblaApi]);
|
||||||
|
|
||||||
|
// Handle keyboard events
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isFocused || !emblaApi) return;
|
||||||
|
|
||||||
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
|
switch (event.key) {
|
||||||
|
case "ArrowLeft":
|
||||||
|
emblaApi.scrollPrev();
|
||||||
|
break;
|
||||||
|
case "ArrowRight":
|
||||||
|
emblaApi.scrollNext();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener("keydown", handleKeyDown);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("keydown", handleKeyDown);
|
||||||
|
};
|
||||||
|
}, [isFocused, emblaApi]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative w-full h-fit">
|
<div className="relative w-full h-fit" tabIndex={0} onMouseEnter={() => setIsFocused(true)} onMouseLeave={() => setIsFocused(false)}>
|
||||||
<div className={`overflow-hidden rounded-xl bg-zinc-300 border-2 border-zinc-300 ${className ?? ""}`} ref={emblaRef}>
|
<div className={`overflow-hidden rounded-xl bg-zinc-300 border-2 border-zinc-300 ${className ?? ""}`} ref={emblaRef}>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{images.map((src, index) => (
|
{images.map((src, index) => (
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,32 @@ export default function ImageViewer({ src, alt, width, height, className, images
|
||||||
emblaApi.on("select", () => setSelectedIndex(emblaApi.selectedScrollSnap()));
|
emblaApi.on("select", () => setSelectedIndex(emblaApi.selectedScrollSnap()));
|
||||||
}, [emblaApi, images, src]);
|
}, [emblaApi, images, src]);
|
||||||
|
|
||||||
|
// Handle keyboard events
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isOpen || !emblaApi) return;
|
||||||
|
|
||||||
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
|
switch (event.key) {
|
||||||
|
case "ArrowLeft":
|
||||||
|
emblaApi.scrollPrev();
|
||||||
|
break;
|
||||||
|
case "ArrowRight":
|
||||||
|
emblaApi.scrollNext();
|
||||||
|
break;
|
||||||
|
case "Escape":
|
||||||
|
close();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener("keydown", handleKeyDown);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("keydown", handleKeyDown);
|
||||||
|
};
|
||||||
|
}, [isOpen, emblaApi]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Image src={src} alt={alt} width={width} height={height} className={`cursor-pointer ${className}`} onClick={() => setIsOpen(true)} />
|
<Image src={src} alt={alt} width={width} height={height} className={`cursor-pointer ${className}`} onClick={() => setIsOpen(true)} />
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue