fix(ui): resolve toast icon inside the toast component (#34874)
This commit is contained in:
@@ -0,0 +1,26 @@
|
|||||||
|
import { describe, expect, test } from "bun:test"
|
||||||
|
import { createSignal, type JSX } from "solid-js"
|
||||||
|
import { showToastV2, toasterV2 } from "@opencode-ai/ui/v2/toast-v2"
|
||||||
|
|
||||||
|
describe("showToastV2", () => {
|
||||||
|
test("creates no reactive computations at call time", () => {
|
||||||
|
const [tick, setTick] = createSignal(0)
|
||||||
|
let reads = 0
|
||||||
|
const icon = (() => {
|
||||||
|
reads++
|
||||||
|
tick()
|
||||||
|
return undefined
|
||||||
|
}) as unknown as JSX.Element
|
||||||
|
|
||||||
|
const id = showToastV2({ description: "test", icon })
|
||||||
|
|
||||||
|
// Resolving the icon at call time creates an ownerless computation that is
|
||||||
|
// never disposed and tracks its dependencies forever; it must only resolve
|
||||||
|
// once the toast component renders.
|
||||||
|
expect(reads).toBe(0)
|
||||||
|
setTick(1)
|
||||||
|
expect(reads).toBe(0)
|
||||||
|
|
||||||
|
toasterV2.dismiss(id)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -97,44 +97,46 @@ export interface ToastV2Options {
|
|||||||
|
|
||||||
export function showToastV2(options: ToastV2Options | string) {
|
export function showToastV2(options: ToastV2Options | string) {
|
||||||
const opts = typeof options === "string" ? { description: options } : options
|
const opts = typeof options === "string" ? { description: options } : options
|
||||||
const resolvedIcon = children(() => opts.icon)
|
return toaster.show((props) => {
|
||||||
return toaster.show((props) => (
|
const resolvedIcon = children(() => opts.icon)
|
||||||
<ToastV2 toastId={props.toastId} duration={opts.duration} persistent={opts.persistent}>
|
return (
|
||||||
<div data-slot="toast-v2-header">
|
<ToastV2 toastId={props.toastId} duration={opts.duration} persistent={opts.persistent}>
|
||||||
<Show when={resolvedIcon()}>
|
<div data-slot="toast-v2-header">
|
||||||
<ToastV2.Icon>{resolvedIcon()}</ToastV2.Icon>
|
<Show when={resolvedIcon()}>
|
||||||
|
<ToastV2.Icon>{resolvedIcon()}</ToastV2.Icon>
|
||||||
|
</Show>
|
||||||
|
<ToastV2.Content>
|
||||||
|
<Show when={opts.title}>
|
||||||
|
<ToastV2.Title>{opts.title}</ToastV2.Title>
|
||||||
|
</Show>
|
||||||
|
<Show when={opts.description}>
|
||||||
|
<ToastV2.Description>{opts.description}</ToastV2.Description>
|
||||||
|
</Show>
|
||||||
|
</ToastV2.Content>
|
||||||
|
<ToastV2.CloseButton />
|
||||||
|
</div>
|
||||||
|
<Show when={opts.actions?.length}>
|
||||||
|
<ToastV2.Actions>
|
||||||
|
{opts.actions!.map((action) => (
|
||||||
|
<ButtonV2
|
||||||
|
variant={action.variant === "secondary" ? "ghost" : "neutral"}
|
||||||
|
size="small"
|
||||||
|
data-action-variant={action.variant ?? "primary"}
|
||||||
|
onClick={() => {
|
||||||
|
if (typeof action.onClick === "function") {
|
||||||
|
action.onClick()
|
||||||
|
}
|
||||||
|
toaster.dismiss(props.toastId)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{action.label}
|
||||||
|
</ButtonV2>
|
||||||
|
))}
|
||||||
|
</ToastV2.Actions>
|
||||||
</Show>
|
</Show>
|
||||||
<ToastV2.Content>
|
</ToastV2>
|
||||||
<Show when={opts.title}>
|
)
|
||||||
<ToastV2.Title>{opts.title}</ToastV2.Title>
|
})
|
||||||
</Show>
|
|
||||||
<Show when={opts.description}>
|
|
||||||
<ToastV2.Description>{opts.description}</ToastV2.Description>
|
|
||||||
</Show>
|
|
||||||
</ToastV2.Content>
|
|
||||||
<ToastV2.CloseButton />
|
|
||||||
</div>
|
|
||||||
<Show when={opts.actions?.length}>
|
|
||||||
<ToastV2.Actions>
|
|
||||||
{opts.actions!.map((action) => (
|
|
||||||
<ButtonV2
|
|
||||||
variant={action.variant === "secondary" ? "ghost" : "neutral"}
|
|
||||||
size="small"
|
|
||||||
data-action-variant={action.variant ?? "primary"}
|
|
||||||
onClick={() => {
|
|
||||||
if (typeof action.onClick === "function") {
|
|
||||||
action.onClick()
|
|
||||||
}
|
|
||||||
toaster.dismiss(props.toastId)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{action.label}
|
|
||||||
</ButtonV2>
|
|
||||||
))}
|
|
||||||
</ToastV2.Actions>
|
|
||||||
</Show>
|
|
||||||
</ToastV2>
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ToastV2PromiseOptions<T, U = unknown> {
|
export interface ToastV2PromiseOptions<T, U = unknown> {
|
||||||
|
|||||||
Reference in New Issue
Block a user