Skip to content

Instantly share code, notes, and snippets.

@azaek
Last active September 25, 2022 09:23
Show Gist options
  • Save azaek/22a1133ac2b991d2533bc883533bd7c0 to your computer and use it in GitHub Desktop.
Save azaek/22a1133ac2b991d2533bc883533bd7c0 to your computer and use it in GitHub Desktop.
This is a simple hook to move indicator element related to any tab<HTMLButtonElement> it will give current selected tab position, width and height then you can apply that to animate any HTMLDivElement accordingly
const [selected, setSelected] = useState(0);
const { w, h, indicatorRef, refs } = useTabIndicator({ selected, center: false });
return (
<div className="flex items-center gap-8 absolute inset-0 m-auto w-max t-all">
<div className="relative flex items-center gap-4">
{
["Home", "Explore", "Profile"].map((item, i) => (
<>
<button onClick={() => setSelected(i)} ref={el => refs.current[i] = el} className="p-2">
<p className="text-1214 t-lp font-bold">{item}</p>
</button>
</>
))
}
<div ref={indicatorRef} style={{ width: `${w}px`, height: `4px` }} className="w-2 h-2 t-all bg-black absolute bottom-0 left-0" />
</div>
</div>
);
import { useEffect, useRef, useState } from "react";
interface Props {
selected: number;
center?: boolean;
}
const useTabIndicator = ({ selected, center = false }: Props) => {
const refs = useRef<Array<HTMLButtonElement | null>>([]);
const indicatorRef = useRef<HTMLDivElement>(null);
const [w, setW] = useState(0);
const [h, setH] = useState(0);
// const [offL, setOffL] = useState(0);
useEffect(() => {
if (indicatorRef.current) {
setW(refs.current[selected]?.clientWidth!);
setH(refs.current[selected]?.clientHeight!);
let ol = center ? refs.current[selected]?.offsetLeft! + (refs.current[selected]?.clientWidth! / 2) : refs.current[selected]?.offsetLeft!;
indicatorRef.current.style.transform = `translateX(${ol}px)`;
}
}, [])
useEffect(() => {
if (indicatorRef.current) {
setW(refs.current[selected]?.clientWidth!);
setH(refs.current[selected]?.clientHeight!);
let ol = center ? refs.current[selected]?.offsetLeft! + (refs.current[selected]?.clientWidth! / 2) : refs.current[selected]?.offsetLeft!;
indicatorRef.current.style.transform = `translateX(${ol}px)`;
}
},[selected])
return { w, h, indicatorRef, refs };
}
export default useTabIndicator;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment