Files
next-tjwater-drainage-frontend/features/map/core/components/draw-toolbar.tsx
T

137 lines
4.5 KiB
TypeScript

"use client";
import type { LucideIcon } from "lucide-react";
import { cn } from "@/lib/utils";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger
} from "@/shared/ui/tooltip";
import {
MAP_COMPACT_RADIUS_CLASS_NAME,
MAP_CONTROL_SURFACE_CLASS_NAME,
MAP_ICON_CELL_RADIUS_CLASS_NAME,
MAP_READABLE_SURFACE_CLASS_NAME
} from "./map-control-styles";
export type MapDrawTool = {
id: string;
label: string;
icon: LucideIcon;
active?: boolean;
disabled?: boolean;
tone?: "default" | "danger";
onClick?: () => void;
};
export type MapDrawToolbarProps = {
items: MapDrawTool[];
label?: string;
className?: string;
variant?: "compact" | "panel";
};
export function MapDrawToolbar({ items, label = "绘制工具", className = "", variant = "compact" }: MapDrawToolbarProps) {
if (variant === "panel") {
return (
<div
role="toolbar"
aria-label={label}
className={cn("pointer-events-auto grid grid-cols-2 gap-1.5", className)}
>
{items.map((item) => {
const Icon = item.icon;
const isDanger = item.tone === "danger";
return (
<button
key={item.id}
type="button"
aria-pressed={item.active}
disabled={item.disabled}
onClick={item.onClick}
className={cn(
"flex min-h-10 items-center gap-2 border px-2.5 py-2 text-left text-xs font-semibold transition duration-150",
MAP_COMPACT_RADIUS_CLASS_NAME,
item.active
? "border-blue-600 bg-blue-600 text-white shadow-md shadow-blue-600/20"
: "text-slate-700 hover:border-blue-100 hover:bg-white hover:text-blue-700",
!item.active && MAP_READABLE_SURFACE_CLASS_NAME,
isDanger && "hover:border-red-100 hover:text-red-700",
item.disabled &&
"cursor-not-allowed opacity-55 hover:border-white/70 hover:bg-white/95 hover:text-slate-700"
)}
>
<span
className={cn(
"grid h-7 w-7 shrink-0 place-items-center",
MAP_ICON_CELL_RADIUS_CLASS_NAME,
item.active ? "bg-white/16 text-white" : "bg-slate-100 text-slate-500",
isDanger && "bg-red-50 text-red-600"
)}
>
<Icon size={15} aria-hidden="true" />
</span>
<span className="min-w-0 truncate">{item.label}</span>
</button>
);
})}
</div>
);
}
return (
<TooltipProvider delayDuration={180}>
<div
role="toolbar"
aria-label={label}
className={cn(
"pointer-events-auto inline-flex p-1",
MAP_COMPACT_RADIUS_CLASS_NAME,
MAP_CONTROL_SURFACE_CLASS_NAME,
className
)}
>
{items.map((item) => {
const Icon = item.icon;
const isDanger = item.tone === "danger";
return (
<Tooltip key={item.id}>
<TooltipTrigger asChild>
<button
type="button"
aria-label={item.label}
aria-pressed={item.active}
disabled={item.disabled}
onClick={item.onClick}
className={cn(
"grid h-8 w-8 shrink-0 place-items-center text-slate-600 transition duration-150",
MAP_ICON_CELL_RADIUS_CLASS_NAME,
"focus-visible:outline focus-visible:outline-2 focus-visible:outline-slate-900 focus-visible:outline-offset-2",
item.active
? "bg-blue-600 text-white shadow-sm"
: "hover:bg-blue-50 hover:text-blue-700",
isDanger && "hover:bg-red-50 hover:text-red-700",
item.disabled && "cursor-not-allowed opacity-45 hover:bg-transparent hover:text-slate-600"
)}
>
<Icon size={16} aria-hidden="true" />
</button>
</TooltipTrigger>
<TooltipContent
side="top"
sideOffset={7}
className="border border-slate-200 bg-white px-2.5 py-1.5 text-xs font-medium text-slate-800 shadow-lg"
>
{item.label}
</TooltipContent>
</Tooltip>
);
})}
</div>
</TooltipProvider>
);
}