+
{React.cloneElement(currentStyle.icon, {
className: "size-4",
})}
diff --git a/apps/v4/app/(create)/components/theme-picker.tsx b/apps/v4/app/(create)/components/theme-picker.tsx
index 532d2ecd1e..00a7f52eaf 100644
--- a/apps/v4/app/(create)/components/theme-picker.tsx
+++ b/apps/v4/app/(create)/components/theme-picker.tsx
@@ -64,7 +64,7 @@ export function ThemePicker({
],
} as React.CSSProperties
}
- className="pointer-events-none absolute top-1/2 right-4 size-4 -translate-y-1/2 rounded-full bg-(--color) select-none md:right-2"
+ className="pointer-events-none absolute top-1/2 right-4 size-4 -translate-y-1/2 rounded-full bg-(--color) select-none md:right-2.5"
/>
)}
diff --git a/apps/v4/app/(create)/hooks/use-iframe-sync.tsx b/apps/v4/app/(create)/hooks/use-iframe-sync.tsx
index b914f7c77b..ec0bc70ad3 100644
--- a/apps/v4/app/(create)/hooks/use-iframe-sync.tsx
+++ b/apps/v4/app/(create)/hooks/use-iframe-sync.tsx
@@ -23,6 +23,12 @@ export function useIframeMessageListener<
messageType: MessageType,
onMessage: (data: Extract["data"]) => void
) {
+ const onMessageRef = React.useRef(onMessage)
+
+ React.useEffect(() => {
+ onMessageRef.current = onMessage
+ }, [onMessage])
+
React.useEffect(() => {
if (!isInIframe()) {
return
@@ -30,7 +36,7 @@ export function useIframeMessageListener<
const handleMessage = (event: MessageEvent) => {
if (event.data.type === messageType) {
- onMessage(event.data.data)
+ onMessageRef.current(event.data.data)
}
}
@@ -38,7 +44,7 @@ export function useIframeMessageListener<
return () => {
window.removeEventListener("message", handleMessage)
}
- }, [messageType, onMessage])
+ }, [messageType])
}
export function sendToIframe<
diff --git a/apps/v4/app/(create)/hooks/use-random.tsx b/apps/v4/app/(create)/hooks/use-random.tsx
index 45a1f43986..b15d29140b 100644
--- a/apps/v4/app/(create)/hooks/use-random.tsx
+++ b/apps/v4/app/(create)/hooks/use-random.tsx
@@ -79,7 +79,7 @@ export function useRandom() {
context.font = selectedFont
context.radius = selectedRadius
- setParams({
+ const nextParams = {
style: selectedStyle,
baseColor,
theme: selectedTheme,
@@ -88,9 +88,23 @@ export function useRandom() {
menuAccent: selectedMenuAccent,
menuColor: selectedMenuColor,
radius: selectedRadius,
- })
+ }
+
+ // Keep the ref in sync so rapid repeats use the latest randomized state
+ // even before the URL state finishes committing.
+ paramsRef.current = {
+ ...paramsRef.current,
+ ...nextParams,
+ }
+
+ setParams(nextParams)
}, [setParams, locks])
+ const randomizeRef = React.useRef(randomize)
+ React.useEffect(() => {
+ randomizeRef.current = randomize
+ }, [randomize])
+
React.useEffect(() => {
const down = (e: KeyboardEvent) => {
if ((e.key === "r" || e.key === "R") && !e.metaKey && !e.ctrlKey) {
@@ -104,7 +118,7 @@ export function useRandom() {
}
e.preventDefault()
- randomize()
+ randomizeRef.current()
}
}
@@ -112,7 +126,7 @@ export function useRandom() {
return () => {
document.removeEventListener("keydown", down)
}
- }, [randomize])
+ }, [])
return { randomize }
}