"use client"; import { type ReactNode, useRef, useState } from "react"; import { HINT_DELAY_MS, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { DIVE_TYPE_ABBREVIATIONS, DIVE_TYPE_LABELS, WATER_TYPE_ABBREVIATIONS, WATER_TYPE_LABELS, type Dive, } from "@/lib/api/dives"; import { labelOrFallback } from "@/lib/api/labels"; import { owedDeco } from "@/lib/dive-recordings"; // One chip, bordered in its text's colour, with what it stands for in full as // its hover hint and in a screen reader's words. Without the text's glow, as a // map's credit chip is: its fill lifts it. // // A finger has no hover, so a tap shows the hint, until a press elsewhere. Its // hit area grows to 44px up and down only, so two chips side by side keep their // own. function Chip({ text, label }: { text: string; label: string }) { const [hovered, setHovered] = useState(false); const [tapped, setTapped] = useState(false); const finger = useRef(false); return ( { setHovered(open); if (!open) setTapped(false); }} > {/* The name is already in the chip's words, so the hint describes nothing a screen reader has not heard: `IconTooltip`'s override. */} { finger.current = event.pointerType !== "mouse"; }} onClick={() => { if (finger.current) setTapped(true); }} render={ } > {text} {label} {label} ); } // One of the diver's tags, in the brand's teal, its words its own: there is // nothing shorter to show and nothing longer to hint at. A name too long for // the row ends in an ellipsis rather than overflowing it. function TagChip({ tag }: { tag: string }) { return ( {tag} ); } /** * The chips over a dive's title, on its card and its page's hero alike: the * water, then the kind of dive, then whether it owed decompression, then the * diver's tags in their order. Salt water, open circuit and a no-stop dive * have none - each goes without saying - and a dive with none of the four has * no row. Lifted over a card's link, so its hints are reachable by a mouse; on * a card a finger's tap goes through them to the link (`DiveCard`). */ export function diveChips(dive: Dive): ReactNode { const water = dive.water_type && WATER_TYPE_ABBREVIATIONS[dive.water_type]; const type = dive.type && DIVE_TYPE_ABBREVIATIONS[dive.type]; const deco = owedDeco(dive); const tags = dive.tags ?? []; if (!water && !type && !deco && tags.length === 0) return null; return (
{water && ( )} {type && ( )} {deco && } {tags.map((tag) => ( ))}
); }