refactor(ui): adopt useDismissable in ColorFilter and BulkActionBar
Replaces the hand-rolled outside-pointerdown listeners with the shared hook. Both popovers now also close on Escape, and listeners only attach while a panel is actually open.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { useGalleryStore } from "../store";
|
import { useGalleryStore } from "../store";
|
||||||
import { BulkTagPopover } from "./bulk/BulkTagPopover";
|
import { BulkTagPopover } from "./bulk/BulkTagPopover";
|
||||||
|
import { useDismissable } from "./menu";
|
||||||
import { Tooltip } from "./Tooltip"
|
import { Tooltip } from "./Tooltip"
|
||||||
|
|
||||||
type Panel = "tag" | "rating" | "album" | "delete" | null;
|
type Panel = "tag" | "rating" | "album" | "delete" | null;
|
||||||
@@ -28,15 +29,8 @@ export function BulkActionBar() {
|
|||||||
const [newAlbumName, setNewAlbumName] = useState("");
|
const [newAlbumName, setNewAlbumName] = useState("");
|
||||||
const barRef = useRef<HTMLDivElement>(null);
|
const barRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
// Close any open popover when clicking outside the bar.
|
// Close any open popover when clicking outside the bar or pressing Escape.
|
||||||
useEffect(() => {
|
useDismissable(barRef, () => setPanel(null), panel !== null);
|
||||||
const onPointerDown = (event: PointerEvent) => {
|
|
||||||
if (barRef.current?.contains(event.target as Node)) return;
|
|
||||||
setPanel(null);
|
|
||||||
};
|
|
||||||
window.addEventListener("pointerdown", onPointerDown);
|
|
||||||
return () => window.removeEventListener("pointerdown", onPointerDown);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Reset transient UI whenever the selection empties.
|
// Reset transient UI whenever the selection empties.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useEffect, useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
import { AnimatePresence, motion } from "framer-motion";
|
import { AnimatePresence, motion } from "framer-motion";
|
||||||
import { useGalleryStore } from "../store";
|
import { useGalleryStore } from "../store";
|
||||||
|
import { useDismissable } from "./menu";
|
||||||
import { Tooltip } from "./Tooltip";
|
import { Tooltip } from "./Tooltip";
|
||||||
|
|
||||||
type Rgb = [number, number, number];
|
type Rgb = [number, number, number];
|
||||||
@@ -45,15 +46,8 @@ export function ColorFilter() {
|
|||||||
const isActive = colorFilter !== null;
|
const isActive = colorFilter !== null;
|
||||||
const isCustom = isActive && !SWATCHES.some((swatch) => rgbEquals(colorFilter, swatch.rgb));
|
const isCustom = isActive && !SWATCHES.some((swatch) => rgbEquals(colorFilter, swatch.rgb));
|
||||||
|
|
||||||
// Collapse the panel when clicking elsewhere.
|
// Collapse the panel when clicking elsewhere or pressing Escape.
|
||||||
useEffect(() => {
|
useDismissable(ref, () => setOpen(false), open);
|
||||||
if (!open) return;
|
|
||||||
const onPointerDown = (event: PointerEvent) => {
|
|
||||||
if (ref.current && !ref.current.contains(event.target as Node)) setOpen(false);
|
|
||||||
};
|
|
||||||
window.addEventListener("pointerdown", onPointerDown);
|
|
||||||
return () => window.removeEventListener("pointerdown", onPointerDown);
|
|
||||||
}, [open]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="relative ml-1 flex shrink-0 items-center border-l border-white/6 pl-2">
|
<div ref={ref} className="relative ml-1 flex shrink-0 items-center border-l border-white/6 pl-2">
|
||||||
|
|||||||
Reference in New Issue
Block a user