81 lines
2.2 KiB
TypeScript
81 lines
2.2 KiB
TypeScript
"use client";
|
|
|
|
import { useTranslation } from "@/components/i18n/locale-provider";
|
|
import { InfoIcon } from "lucide-react";
|
|
import { useSyncExternalStore } from "react";
|
|
|
|
import {
|
|
Drawer,
|
|
DrawerContent,
|
|
DrawerDescription,
|
|
DrawerHeader,
|
|
DrawerTitle,
|
|
DrawerTrigger,
|
|
} from "@/components/ui/drawer";
|
|
import {
|
|
HoverCard,
|
|
HoverCardContent,
|
|
HoverCardTrigger,
|
|
} from "@/components/ui/hover-card";
|
|
|
|
const finePointerQuery = "(hover: hover) and (pointer: fine)";
|
|
|
|
function subscribe(callback: () => void) {
|
|
const query = window.matchMedia(finePointerQuery);
|
|
query.addEventListener("change", callback);
|
|
return () => query.removeEventListener("change", callback);
|
|
}
|
|
|
|
function getSnapshot() {
|
|
return window.matchMedia(finePointerQuery).matches;
|
|
}
|
|
|
|
function Trigger({ label }: { label: string }) {
|
|
return (
|
|
<span className="inline-flex min-h-11 cursor-help items-center gap-1 rounded-md text-left font-medium underline decoration-border underline-offset-4 outline-none hover:text-primary focus-visible:ring-2 focus-visible:ring-ring md:min-h-0">
|
|
{label}
|
|
<InfoIcon aria-hidden="true" className="size-3.5 text-muted-foreground" />
|
|
</span>
|
|
);
|
|
}
|
|
|
|
export function TermDetail({
|
|
label,
|
|
detail,
|
|
}: {
|
|
label: string;
|
|
detail: string;
|
|
}) {
|
|
const { t } = useTranslation();
|
|
const finePointer = useSyncExternalStore(subscribe, getSnapshot, () => false);
|
|
|
|
if (finePointer) {
|
|
return (
|
|
<HoverCard>
|
|
<HoverCardTrigger aria-label={t("ดูรายละเอียด {label}", { label: label })}>
|
|
<Trigger label={label} />
|
|
</HoverCardTrigger>
|
|
<HoverCardContent align="start">
|
|
<p className="font-medium">{label}</p>
|
|
<p className="mt-1 text-muted-foreground">{detail}</p>
|
|
</HoverCardContent>
|
|
</HoverCard>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Drawer showSwipeHandle>
|
|
<DrawerTrigger aria-label={t("เปิดรายละเอียด {label}", { label: label })}>
|
|
<Trigger label={label} />
|
|
</DrawerTrigger>
|
|
<DrawerContent>
|
|
<DrawerHeader>
|
|
<DrawerTitle>{label}</DrawerTitle>
|
|
<DrawerDescription>{detail}</DrawerDescription>
|
|
</DrawerHeader>
|
|
<div className="h-6" />
|
|
</DrawerContent>
|
|
</Drawer>
|
|
);
|
|
}
|