From 370fd5e32753fbe6c7986b3a842050ccbc813f88 Mon Sep 17 00:00:00 2001 From: Moulik Aggarwal Date: Thu, 12 Mar 2026 17:06:09 +0530 Subject: [PATCH] Performance: Fix slow color picker (#1969) * Fix Performance issue when picking color Signed-off-by: Moulik Aggarwal * Fix any type in hook Signed-off-by: Moulik Aggarwal * Theme sidebar handleChange Signed-off-by: Moulik Aggarwal --------- Signed-off-by: Moulik Aggarwal --- .../src/components/themes/theme-sidebar.tsx | 22 ++++++++------ .../ui/src/hooks/use-debounce-callback.ts | 29 +++++++++++++++++++ 2 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 packages/ui/src/hooks/use-debounce-callback.ts diff --git a/apps/status-page/src/components/themes/theme-sidebar.tsx b/apps/status-page/src/components/themes/theme-sidebar.tsx index 4eeffea0..bc25de24 100644 --- a/apps/status-page/src/components/themes/theme-sidebar.tsx +++ b/apps/status-page/src/components/themes/theme-sidebar.tsx @@ -47,6 +47,7 @@ import { } from "@openstatus/ui/components/ui/tooltip"; import { useCopyToClipboard } from "@openstatus/ui/hooks/use-copy-to-clipboard"; import { useDebounce } from "@openstatus/ui/hooks/use-debounce"; +import { useDebounceCallback } from "@openstatus/ui/hooks/use-debounce-callback"; import { cn } from "@openstatus/ui/lib/utils"; import { Check, @@ -344,6 +345,17 @@ function ThemeValueSelector(props: { }) { const { resolvedTheme } = useTheme(); + const handleChange = useDebounceCallback((value: string) => { + const mode = resolvedTheme as "light" | "dark"; + props.setTheme({ + ...props.theme, + [mode]: { + ...props.theme[mode], + [props.id]: value, + }, + }); + }, 100); + if (!props.isMounted || !resolvedTheme) return ; @@ -362,15 +374,7 @@ function ThemeValueSelector(props: { name={props.id} value={value} className="sr-only" - onChange={(e) => - props.setTheme({ - ...props.theme, - [resolvedTheme as "light" | "dark"]: { - ...props.theme[resolvedTheme as "light" | "dark"], - [props.id]: e.target.value, - }, - }) - } + onChange={(e) => handleChange(e.target.value)} /> ); diff --git a/packages/ui/src/hooks/use-debounce-callback.ts b/packages/ui/src/hooks/use-debounce-callback.ts new file mode 100644 index 00000000..6b8e4ca1 --- /dev/null +++ b/packages/ui/src/hooks/use-debounce-callback.ts @@ -0,0 +1,29 @@ +import { useCallback, useEffect, useRef } from "react"; + +export function useDebounceCallback( + callback: (...args: Args) => void, + delay = 500, +) { + const timerRef = useRef | null>(null); + + const debounced = useCallback( + (...args: Args) => { + if (timerRef.current) { + clearTimeout(timerRef.current); + } + + timerRef.current = setTimeout(() => { + callback(...args); + }, delay); + }, + [callback, delay], + ); + + useEffect(() => { + return () => { + if (timerRef.current) clearTimeout(timerRef.current); + }; + }, []); + + return debounced; +} -- 2.51.2