refactor(web): replace slideout panel window event with jotai atom (fixes #1358)

Replace the `SLIDEOUT_PANEL_OPENED_EVENT` window event with a
`slideoutOpenedTickAtom` jotai atom. The dispatcher in
`SidebarSlideOutPanel` now bumps the tick via `useSetAtom`, and the
listener in `Thread` reads it via `useAtomValue` and reacts on change
behind a ref guard that skips the initial render — preserving the
one-shot-per-open semantics of the previous event.

This removes the implicit cross-module string contract, makes the
signal traceable through React DevTools / jotai inspector, and lets
TypeScript catch typos that the string-based event API silently
swallowed.
This commit is contained in:
suryo12 2026-05-24 16:41:47 +07:00
parent d53866d87d
commit ddae506631
3 changed files with 26 additions and 13 deletions

View file

@ -1,9 +1,10 @@
"use client";
import { useSetAtom } from "jotai";
import { AnimatePresence, motion } from "motion/react";
import { useCallback, useEffect } from "react";
import { useIsMobile } from "@/hooks/use-mobile";
import { SLIDEOUT_PANEL_OPENED_EVENT } from "@/lib/layout-events";
import { slideoutOpenedTickAtom } from "@/lib/layout-events";
interface SidebarSlideOutPanelProps {
open: boolean;
@ -29,12 +30,13 @@ export function SidebarSlideOutPanel({
children,
}: SidebarSlideOutPanelProps) {
const isMobile = useIsMobile();
const bumpSlideoutOpenedTick = useSetAtom(slideoutOpenedTickAtom);
useEffect(() => {
if (open) {
window.dispatchEvent(new Event(SLIDEOUT_PANEL_OPENED_EVENT));
bumpSlideoutOpenedTick((tick) => tick + 1);
}
}, [open]);
}, [open, bumpSlideoutOpenedTick]);
const handleEscape = useCallback(
(e: KeyboardEvent) => {