Files

62 lines
1.8 KiB
TypeScript

"use client";
import { useEffect, useId, useState } from "react";
export default function OverlapChip(props: {
label: string;
tooltip?: string;
/** stable key so chip doesn't re-animate on trivial rerenders */
persistKey?: string;
className?: string;
}) {
const { label, tooltip, persistKey, className } = props;
// Animate only once per persistKey per session
const storageKey = persistKey ? `bb_overlapchip_seen:${persistKey}` : null;
const [animateIn, setAnimateIn] = useState(false);
const tooltipId = useId();
useEffect(() => {
if (!storageKey) {
// No key provided: animate once on mount
setAnimateIn(true);
return;
}
try {
const seen = sessionStorage.getItem(storageKey);
if (!seen) {
sessionStorage.setItem(storageKey, "1");
setAnimateIn(true);
}
} catch {
// sessionStorage blocked — still animate
setAnimateIn(true);
}
}, [storageKey]);
return (
<span className={`inline-flex items-center ${className ?? ""}`}>
<span
className={[
"inline-flex items-center gap-1.5 rounded-full border border-amber-400/50 bg-amber-400/10 px-2 py-1",
"text-[0.7rem] font-medium text-amber-200",
"transition-all duration-300 ease-out",
animateIn ? "opacity-100 translate-y-0" : "opacity-0 translate-y-1",
].join(" ")}
aria-describedby={tooltip ? tooltipId : undefined}
title={tooltip}
>
<span aria-hidden="true" className="text-amber-300">
</span>
<span>{label}</span>
</span>
{/* Optional: if you later want a real tooltip instead of title,
you can wire one here using tooltipId. */}
{tooltip ? <span id={tooltipId} className="sr-only">{tooltip}</span> : null}
</span>
);
}