Extract reusable clipboard hook and standardize media queries#1006
Extract reusable clipboard hook and standardize media queries#1006juliusmarminge merged 6 commits intomainfrom
Conversation
- add `useCopyToClipboard` and adopt it in plan, sidebar, and message copy UI - extend `useMediaQuery` with breakpoint-aware queries and add `useIsMobile` - switch chat diff layout and sidebar mobile checks to semantic breakpoint queries
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Comment |
Co-authored-by: macroscopeapp[bot] <170038800+macroscopeapp[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Autofix Details
Bugbot Autofix prepared fixes for both issues found in the latest run.
- ✅ Fixed: Breakpoint mismatch between JS hook and Tailwind CSS
- Changed BREAKPOINTS.md from 800 to 768 to match Tailwind CSS v4's default md breakpoint (48rem = 768px), eliminating the 768-799px gap where the sidebar trigger was hidden but the sidebar was in mobile sheet mode.
- ✅ Fixed: Unstable
copyToClipboardreference defeats downstream memoization- Wrapped copyToClipboard in useCallback with stable refs for onCopy, onError, and timeout, ensuring the returned function identity is stable across renders and downstream useCallback hooks are not needlessly re-created.
Or push these changes by commenting:
@cursor push 152076a0b5
Preview (152076a0b5)
diff --git a/apps/web/src/hooks/useCopyToClipboard.ts b/apps/web/src/hooks/useCopyToClipboard.ts
--- a/apps/web/src/hooks/useCopyToClipboard.ts
+++ b/apps/web/src/hooks/useCopyToClipboard.ts
@@ -11,8 +11,15 @@
} = {}): { copyToClipboard: (value: string, ctx: TContext) => void; isCopied: boolean } {
const [isCopied, setIsCopied] = React.useState(false);
const timeoutIdRef = React.useRef<NodeJS.Timeout | null>(null);
+ const onCopyRef = React.useRef(onCopy);
+ const onErrorRef = React.useRef(onError);
+ const timeoutRef = React.useRef(timeout);
- const copyToClipboard = (value: string, ctx: TContext): void => {
+ onCopyRef.current = onCopy;
+ onErrorRef.current = onError;
+ timeoutRef.current = timeout;
+
+ const copyToClipboard = React.useCallback((value: string, ctx: TContext): void => {
if (typeof window === "undefined" || !navigator.clipboard?.writeText) {
return;
}
@@ -26,26 +33,24 @@
}
setIsCopied(true);
- if (onCopy) {
- onCopy(ctx);
- }
+ onCopyRef.current?.(ctx);
- if (timeout !== 0) {
+ if (timeoutRef.current !== 0) {
timeoutIdRef.current = setTimeout(() => {
setIsCopied(false);
timeoutIdRef.current = null;
- }, timeout);
+ }, timeoutRef.current);
}
},
(error) => {
- if (onError) {
- onError(error, ctx);
+ if (onErrorRef.current) {
+ onErrorRef.current(error, ctx);
} else {
console.error(error);
}
},
);
- };
+ }, []);
// Cleanup timeout on unmount
React.useEffect(() => {
diff --git a/apps/web/src/hooks/useMediaQuery.ts b/apps/web/src/hooks/useMediaQuery.ts
--- a/apps/web/src/hooks/useMediaQuery.ts
+++ b/apps/web/src/hooks/useMediaQuery.ts
@@ -5,7 +5,7 @@
"3xl": 1600,
"4xl": 2000,
lg: 1024,
- md: 800,
+ md: 768,
sm: 640,
xl: 1280,
} as const;- Change BREAKPOINTS.md from 800 to 768 to match Tailwind CSS v4's default md breakpoint, fixing the 768-799px gap where the sidebar trigger was hidden but the sidebar was in mobile sheet mode. - Wrap copyToClipboard in useCallback with refs for onCopy/onError/timeout so the returned function identity is stable across renders, preventing unnecessary re-creation of downstream useCallback hooks. Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com> Applied via @cursor push command
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Clipboard unavailability silently swallowed,
onErrorcallback bypassed- Added
onErrorRef.current?.(new Error("Clipboard API unavailable."), ctx)before the early return so the onError callback is invoked when the Clipboard API is unavailable.
- Added
Or push these changes by commenting:
@cursor push 6b03ce9bea
Preview (6b03ce9bea)
diff --git a/apps/web/src/hooks/useCopyToClipboard.ts b/apps/web/src/hooks/useCopyToClipboard.ts
--- a/apps/web/src/hooks/useCopyToClipboard.ts
+++ b/apps/web/src/hooks/useCopyToClipboard.ts
@@ -21,6 +21,7 @@
const copyToClipboard = React.useCallback((value: string, ctx: TContext): void => {
if (typeof window === "undefined" || !navigator.clipboard?.writeText) {
+ onErrorRef.current?.(new Error("Clipboard API unavailable."), ctx);
return;
}Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com> Applied via @cursor push command


Note
Medium Risk
Replaces clipboard and media-query logic used across UI, so regressions could affect copy interactions and responsive layout behavior despite limited surface-area changes.
Overview
Centralizes clipboard behavior by adding
useCopyToClipboard(with timeout-drivenisCopiedstate plusonCopy/onErrorcallbacks) and migrating plan/message copy actions and the thread context-menu “Copy Thread ID” flow to use it.Standardizes responsive queries by rewriting
useMediaQueryto useuseSyncExternalStoreand support breakpoint-based query strings/objects, then updating the sidebar to use a newuseIsMobile()helper. Also includes a tiny className whitespace tweak in_chat.$threadId.tsxand lockfile metadata adjustments.Written by Cursor Bugbot for commit b28cdbf. This will update automatically on new commits. Configure here.
Note
Extract reusable
useCopyToClipboardhook and rewriteuseMediaQuerywith SSR safetyuseCopyToClipboard, a shared hook that writes to the clipboard, tracks transientisCopiedstate, and accepts optionalonCopy/onErrorcallbacks with configurable timeout.PlanSidebar,Sidebar, andMessageCopyButtonwith the new hook.useMediaQueryusinguseSyncExternalStorefor SSR safety and adds support for semantic breakpoint strings (e.g.'max-md'); adds auseIsMobile()convenience hook.Macroscope summarized b28cdbf.