Skip to content

Commit 5524d64

Browse files
committed
add isInitialized check
1 parent 799d48b commit 5524d64

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

packages/ui/src/components/devPrompts/KeylessPrompt/index.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ function withLastActiveFallback(cb: () => string): string {
4343
const KeylessPromptInternal = (_props: KeylessPromptProps) => {
4444
const { isSignedIn } = useUser();
4545
const [isExpanded, setIsExpanded] = useState(false);
46-
const { isDragging, cornerStyle, containerRef, onPointerDown, preventClick } = useDragToCorner();
46+
const { isDragging, cornerStyle, containerRef, onPointerDown, preventClick, isInitialized } = useDragToCorner();
4747

4848
useEffect(() => {
4949
if (isSignedIn) {
@@ -122,6 +122,7 @@ const KeylessPromptInternal = (_props: KeylessPromptProps) => {
122122
style={{
123123
...cornerStyle,
124124
position: 'fixed',
125+
opacity: isInitialized ? undefined : 0,
125126
}}
126127
sx={t => ({
127128
height: `${t.sizes.$10}`,
@@ -133,8 +134,8 @@ const KeylessPromptInternal = (_props: KeylessPromptProps) => {
133134
transition: isDragging
134135
? 'none'
135136
: isForcedExpanded
136-
? 'height 230ms cubic-bezier(0.28, 1, 0.32, 1), width 230ms cubic-bezier(0.28, 1, 0.32, 1), padding 230ms cubic-bezier(0.28, 1, 0.32, 1), border-radius 230ms cubic-bezier(0.28, 1, 0.32, 1)'
137-
: 'height 195ms cubic-bezier(0.2, 0.61, 0.1, 1), width 195ms cubic-bezier(0.2, 0.61, 0.1, 1), padding 195ms cubic-bezier(0.2, 0.61, 0.1, 1), border-radius 195ms cubic-bezier(0.2, 0.61, 0.1, 1)',
137+
? 'opacity 150ms ease-out, height 230ms cubic-bezier(0.28, 1, 0.32, 1), width 230ms cubic-bezier(0.28, 1, 0.32, 1), padding 230ms cubic-bezier(0.28, 1, 0.32, 1), border-radius 230ms cubic-bezier(0.28, 1, 0.32, 1)'
138+
: 'opacity 150ms ease-out, height 195ms cubic-bezier(0.2, 0.61, 0.1, 1), width 195ms cubic-bezier(0.2, 0.61, 0.1, 1), padding 195ms cubic-bezier(0.2, 0.61, 0.1, 1), border-radius 195ms cubic-bezier(0.2, 0.61, 0.1, 1)',
138139

139140
'&[data-expanded="false"]:hover': {
140141
background: 'linear-gradient(180deg, rgba(255, 255, 255, 0.20) 0%, rgba(255, 255, 255, 0) 100%), #1f1f1f',

packages/ui/src/components/devPrompts/KeylessPrompt/use-drag-to-corner.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { PointerEventHandler } from 'react';
2-
import { useCallback, useLayoutEffect, useRef, useState } from 'react';
2+
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
33

44
type Corner = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
55

@@ -33,6 +33,7 @@ interface UseDragToCornerResult {
3333
containerRef: React.RefObject<HTMLDivElement>;
3434
onPointerDown: PointerEventHandler;
3535
preventClick: boolean;
36+
isInitialized: boolean;
3637
}
3738

3839
const getCornerFromPosition = (x: number, y: number): Corner => {
@@ -119,11 +120,34 @@ const calculateVelocity = (history: Velocity[]): Point => {
119120
};
120121

121122
export const useDragToCorner = (): UseDragToCornerResult => {
122-
const [corner, setCorner] = useState<Corner>(loadCornerPreference);
123+
// Initialize with deterministic server-safe value to avoid SSR/hydration mismatch
124+
const [corner, setCorner] = useState<Corner>('bottom-right');
123125
const [isDragging, setIsDragging] = useState(false);
124126
const [preventClick, setPreventClick] = useState(false);
127+
const [isInitialized, setIsInitialized] = useState(false);
125128
const pendingCornerUpdate = useRef<Corner | null>(null);
126129

130+
// Defer localStorage read to client-side only after mount
131+
useEffect(() => {
132+
if (typeof window === 'undefined') {
133+
setIsInitialized(true);
134+
return;
135+
}
136+
try {
137+
const stored = localStorage.getItem(STORAGE_KEY);
138+
if (stored && ['top-left', 'top-right', 'bottom-left', 'bottom-right'].includes(stored)) {
139+
const storedCorner = stored as Corner;
140+
// Set corner before making visible to prevent flash
141+
setCorner(storedCorner);
142+
}
143+
} catch {
144+
// Ignore localStorage errors
145+
} finally {
146+
// Mark as initialized after reading localStorage (or if it fails)
147+
setIsInitialized(true);
148+
}
149+
}, []);
150+
127151
const containerRef = useRef<HTMLDivElement | null>(null);
128152
const machine = useRef<{ state: 'idle' | 'press' | 'animating' } | { state: 'drag'; pointerId: number }>({
129153
state: 'idle',
@@ -386,5 +410,6 @@ export const useDragToCorner = (): UseDragToCornerResult => {
386410
containerRef,
387411
onPointerDown: handlePointerDown,
388412
preventClick,
413+
isInitialized,
389414
};
390415
};

0 commit comments

Comments
 (0)