From 3c1399b44adaabcd889b5746cd3631432579bd46 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Fri, 25 Jul 2025 12:48:57 -0400 Subject: [PATCH] Changed position of theme button, hiding tooltip after set time. (#735) * fix: changed position of theme button, hiding tooltip after set time. * feat: added usevisibility hook * updating paths --- .../web/src/components/DeviceInfoPanel.tsx | 13 ++++---- packages/web/src/components/ThemeSwitcher.tsx | 19 ++++++++--- .../src/core/hooks/useToggleVisiblility.ts | 32 +++++++++++++++++++ 3 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 packages/web/src/core/hooks/useToggleVisiblility.ts diff --git a/packages/web/src/components/DeviceInfoPanel.tsx b/packages/web/src/components/DeviceInfoPanel.tsx index 6e89a4db..6480cb39 100644 --- a/packages/web/src/components/DeviceInfoPanel.tsx +++ b/packages/web/src/components/DeviceInfoPanel.tsx @@ -85,6 +85,12 @@ export const DeviceInfoPanel = ({ ]; const actionButtons: ActionButtonConfig[] = [ + { + id: "theme", + label: t("theme.changeTheme"), + icon: Palette, + render: () => , + }, { id: "changeName", label: t("sidebar.deviceInfo.deviceName.changeName"), @@ -97,12 +103,7 @@ export const DeviceInfoPanel = ({ icon: SearchIcon, onClick: setCommandPaletteOpen, }, - { - id: "theme", - label: t("theme.changeTheme"), - icon: Palette, - render: () => , - }, + { id: "language", label: t("language.changeLanguage"), diff --git a/packages/web/src/components/ThemeSwitcher.tsx b/packages/web/src/components/ThemeSwitcher.tsx index f0900279..a4595079 100644 --- a/packages/web/src/components/ThemeSwitcher.tsx +++ b/packages/web/src/components/ThemeSwitcher.tsx @@ -1,7 +1,8 @@ -import { useTheme } from "@core/hooks/useTheme.ts"; -import { cn } from "@core/utils/cn.ts"; import { Monitor, Moon, Sun } from "lucide-react"; import { useTranslation } from "react-i18next"; +import { useTheme } from "../core/hooks/useTheme.ts"; +import { useToggleVisibility } from "../core/hooks/useToggleVisiblility.ts"; +import { cn } from "../core/utils/cn.ts"; import { Button } from "./UI/Button.tsx"; import { Subtle } from "./UI/Typography/Subtle.tsx"; @@ -12,10 +13,16 @@ interface ThemeSwitcherProps { disableHover?: boolean; } +const TOOLTIP_TIMEOUT = 2000; // 2 seconds + export default function ThemeSwitcher({ className: passedClassName = "", disableHover = false, }: ThemeSwitcherProps) { + const [showTooltip, toggleShowTooltip] = useToggleVisibility({ + timeout: TOOLTIP_TIMEOUT, + }); + const { preference, setPreference } = useTheme(); const { t } = useTranslation("ui"); @@ -35,8 +42,10 @@ export default function ThemeSwitcher({ const toggleTheme = () => { const preferences: ThemePreference[] = ["light", "dark", "system"]; const currentIndex = preferences.indexOf(preference); - const nextPreference = preferences[(currentIndex + 1) % preferences.length]; + const nextPreference = + preferences[(currentIndex + 1) % preferences.length] ?? "system"; setPreference(nextPreference); + toggleShowTooltip(); }; const preferenceDisplayMap: Record = { @@ -65,12 +74,12 @@ export default function ThemeSwitcher({ {currentDisplayPreference} diff --git a/packages/web/src/core/hooks/useToggleVisiblility.ts b/packages/web/src/core/hooks/useToggleVisiblility.ts new file mode 100644 index 00000000..5f83800e --- /dev/null +++ b/packages/web/src/core/hooks/useToggleVisiblility.ts @@ -0,0 +1,32 @@ +import { useCallback, useEffect, useRef, useState } from "react"; + +export function useToggleVisibility({ timeout }: { timeout?: number } = {}) { + const [isVisible, setIsVisible] = useState(false); + const timeoutRef = useRef | null>(null); + + const show = useCallback(() => { + setIsVisible(true); + + if (timeout) { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + + timeoutRef.current = setTimeout(() => { + setIsVisible(false); + timeoutRef.current = null; + }, timeout); + } + }, [timeout]); + + // Clear timeout on unmount + useEffect(() => { + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + }; + }, []); + + return [isVisible, show] as const; +}