summaryrefslogtreecommitdiffhomepage
path: root/packages/ui/src/components/tool-utils.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/ui/src/components/tool-utils.ts')
-rw-r--r--packages/ui/src/components/tool-utils.ts101
1 files changed, 56 insertions, 45 deletions
diff --git a/packages/ui/src/components/tool-utils.ts b/packages/ui/src/components/tool-utils.ts
index 171649e3d..4d57c626e 100644
--- a/packages/ui/src/components/tool-utils.ts
+++ b/packages/ui/src/components/tool-utils.ts
@@ -1,4 +1,6 @@
+import type { ToolPart } from "@opencode-ai/sdk/v2"
import { createEffect, createMemo, createSignal, on, onCleanup, onMount } from "solid-js"
+import { useReducedMotion } from "../hooks/use-reduced-motion"
import {
animate,
type AnimationPlaybackControls,
@@ -8,8 +10,6 @@ import {
GROW_SPRING,
WIPE_MASK,
} from "./motion"
-import { prefersReducedMotion } from "../hooks/use-reduced-motion"
-import type { ToolPart } from "@opencode-ai/sdk/v2"
export const TEXT_RENDER_THROTTLE_MS = 100
@@ -106,57 +106,67 @@ export function useCollapsible(options: {
measure?: () => number
onOpen?: () => void
}) {
+ const reduce = useReducedMotion()
let heightAnim: AnimationPlaybackControls | undefined
let fadeAnim: AnimationPlaybackControls | undefined
let gen = 0
createEffect(
- on(
- options.open,
- (isOpen) => {
- const content = options.content()
- const body = options.body()
- if (!content || !body) return
- heightAnim?.stop()
- fadeAnim?.stop()
- const id = ++gen
+ on(options.open, (isOpen) => {
+ const content = options.content()
+ const body = options.body()
+ if (!content || !body) return
+ heightAnim?.stop()
+ fadeAnim?.stop()
+ if (reduce()) {
+ body.style.opacity = ""
+ body.style.filter = ""
if (isOpen) {
content.style.display = ""
- content.style.height = "0px"
- body.style.opacity = "0"
- body.style.filter = "blur(2px)"
- fadeAnim = animate(body, { opacity: [0, 1], filter: ["blur(2px)", "blur(0px)"] }, COLLAPSIBLE_SPRING)
- queueMicrotask(() => {
- if (gen !== id) return
- const c = options.content()
- if (!c) return
- const h = options.measure?.() ?? Math.ceil(body.getBoundingClientRect().height)
- heightAnim = animate(c, { height: ["0px", `${h}px`] }, COLLAPSIBLE_SPRING)
- heightAnim.finished.then(
- () => {
- if (gen !== id) return
- c.style.height = "auto"
- options.onOpen?.()
- },
- () => {},
- )
- })
+ content.style.height = "auto"
+ options.onOpen?.()
return
}
+ content.style.height = "0px"
+ content.style.display = "none"
+ return
+ }
+ const id = ++gen
+ if (isOpen) {
+ content.style.display = ""
+ content.style.height = "0px"
+ body.style.opacity = "0"
+ body.style.filter = "blur(2px)"
+ fadeAnim = animate(body, { opacity: [0, 1], filter: ["blur(2px)", "blur(0px)"] }, COLLAPSIBLE_SPRING)
+ queueMicrotask(() => {
+ if (gen !== id) return
+ const c = options.content()
+ if (!c) return
+ const h = options.measure?.() ?? Math.ceil(body.getBoundingClientRect().height)
+ heightAnim = animate(c, { height: ["0px", `${h}px`] }, COLLAPSIBLE_SPRING)
+ heightAnim.finished.then(
+ () => {
+ if (gen !== id) return
+ c.style.height = "auto"
+ options.onOpen?.()
+ },
+ () => {},
+ )
+ })
+ return
+ }
- const h = content.getBoundingClientRect().height
- heightAnim = animate(content, { height: [`${h}px`, "0px"] }, COLLAPSIBLE_SPRING)
- fadeAnim = animate(body, { opacity: [1, 0], filter: ["blur(0px)", "blur(2px)"] }, COLLAPSIBLE_SPRING)
- heightAnim.finished.then(
- () => {
- if (gen !== id) return
- content.style.display = "none"
- },
- () => {},
- )
- },
- { defer: true },
- ),
+ const h = content.getBoundingClientRect().height
+ heightAnim = animate(content, { height: [`${h}px`, "0px"] }, COLLAPSIBLE_SPRING)
+ fadeAnim = animate(body, { opacity: [1, 0], filter: ["blur(0px)", "blur(2px)"] }, COLLAPSIBLE_SPRING)
+ heightAnim.finished.then(
+ () => {
+ if (gen !== id) return
+ content.style.display = "none"
+ },
+ () => {},
+ )
+ }),
)
onCleanup(() => {
@@ -181,7 +191,7 @@ export function useRowWipe(opts: {
ref: () => HTMLElement | undefined
seen: Set<string>
}) {
- const reduce = prefersReducedMotion
+ const reduce = useReducedMotion()
createEffect(() => {
const id = opts.id()
@@ -265,13 +275,14 @@ export function useToolFade(
const delay = options?.delay ?? 0
const wipe = options?.wipe ?? false
const active = options?.animate !== false
+ const reduce = useReducedMotion()
onMount(() => {
if (!active) return
const el = ref()
if (!el || typeof window === "undefined") return
- if (prefersReducedMotion()) return
+ if (reduce()) return
const mask =
wipe &&