|
1 | 1 | "use client"; |
2 | 2 |
|
3 | | -import { useEffect, useState } from "react"; |
| 3 | +import { useSyncExternalStore } from "react"; |
4 | 4 |
|
5 | 5 | const DISMISSED_KEY = "desktop-tip-dismissed"; |
6 | 6 |
|
7 | | -export function DesktopTipModal() { |
8 | | - const [visible, setVisible] = useState(false); |
| 7 | +let listeners: Array<() => void> = []; |
| 8 | +function emitChange() { |
| 9 | + listeners.forEach((l) => l()); |
| 10 | +} |
9 | 11 |
|
10 | | - useEffect(() => { |
11 | | - // Only show on narrow viewports and if not previously dismissed |
12 | | - const mq = window.matchMedia("(max-width: 768px)"); |
13 | | - if (mq.matches && !sessionStorage.getItem(DISMISSED_KEY)) { |
14 | | - setVisible(true); |
15 | | - } |
16 | | - }, []); |
| 12 | +export function DesktopTipModal() { |
| 13 | + const notDismissed = useSyncExternalStore( |
| 14 | + (listener) => { |
| 15 | + listeners.push(listener); |
| 16 | + return () => { |
| 17 | + listeners = listeners.filter((l) => l !== listener); |
| 18 | + }; |
| 19 | + }, |
| 20 | + () => !sessionStorage.getItem(DISMISSED_KEY), |
| 21 | + () => false, |
| 22 | + ); |
17 | 23 |
|
18 | | - if (!visible) return null; |
| 24 | + if (!notDismissed) return null; |
19 | 25 |
|
20 | 26 | const dismiss = () => { |
21 | 27 | sessionStorage.setItem(DISMISSED_KEY, "1"); |
22 | | - setVisible(false); |
| 28 | + emitChange(); |
23 | 29 | }; |
24 | 30 |
|
25 | 31 | return ( |
26 | 32 | <div |
27 | 33 | onClick={dismiss} |
| 34 | + className="fixed inset-0 z-[9999] flex items-center justify-center p-6 md:hidden" |
28 | 35 | style={{ |
29 | | - position: "fixed", |
30 | | - inset: 0, |
31 | | - zIndex: 9999, |
32 | | - display: "flex", |
33 | | - alignItems: "center", |
34 | | - justifyContent: "center", |
35 | 36 | background: "rgba(0,0,0,0.45)", |
36 | 37 | backdropFilter: "blur(6px)", |
37 | 38 | WebkitBackdropFilter: "blur(6px)", |
38 | | - padding: 24, |
39 | 39 | }} |
40 | 40 | > |
41 | 41 | <div |
|
0 commit comments