summaryrefslogtreecommitdiffhomepage
path: root/packages/ui/src/context
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-12-15 18:14:30 -0500
committerDax Raad <[email protected]>2025-12-15 18:14:33 -0500
commitdbbcf0b8d041245a8b8feeff159d0bb9801b9924 (patch)
tree714e316b5f6af31518a4243317a0c3293de5a10f /packages/ui/src/context
parentefac8cebb3e3b5abb9672d7973aa508e9d9ef0d4 (diff)
downloadopencode-dbbcf0b8d041245a8b8feeff159d0bb9801b9924.tar.gz
opencode-dbbcf0b8d041245a8b8feeff159d0bb9801b9924.zip
tui: fix model selection dialog to properly replace current dialog instead of creating nested dialogs
Diffstat (limited to 'packages/ui/src/context')
-rw-r--r--packages/ui/src/context/dialog.tsx70
1 files changed, 37 insertions, 33 deletions
diff --git a/packages/ui/src/context/dialog.tsx b/packages/ui/src/context/dialog.tsx
index fae0c57b4..50e41c596 100644
--- a/packages/ui/src/context/dialog.tsx
+++ b/packages/ui/src/context/dialog.tsx
@@ -1,7 +1,9 @@
import {
createContext,
+ createEffect,
createMemo,
createSignal,
+ For,
getOwner,
Owner,
ParentProps,
@@ -11,6 +13,7 @@ import {
type JSX,
} from "solid-js"
import { Dialog as Kobalte } from "@kobalte/core/dialog"
+import { iife } from "@opencode-ai/util/iife"
type DialogElement = () => JSX.Element
@@ -25,23 +28,49 @@ function init() {
}[]
>([])
- return {
+ const result = {
get stack() {
return store()
},
- push(element: DialogElement, owner: Owner, onClose?: () => void) {
- setStore((s) => [...s, { element, onClose, owner }])
- },
pop() {
const current = store().at(-1)
+ if (!current) return
current?.onClose?.()
- setStore((stack) => stack.slice(0, -1))
+ setStore((stack) => {
+ stack.pop()
+ return [...stack]
+ })
},
replace(element: DialogElement, owner: Owner, onClose?: () => void) {
for (const item of store()) {
item.onClose?.()
}
- setStore([{ element, onClose, owner }])
+ setStore([
+ {
+ element: () =>
+ runWithOwner(owner, () => (
+ <Show when={result.stack.at(-1)?.owner === owner}>
+ <Kobalte
+ modal
+ defaultOpen
+ onOpenChange={(open) => {
+ if (!open) {
+ onClose?.()
+ result.pop()
+ }
+ }}
+ >
+ <Kobalte.Portal>
+ <Kobalte.Overlay data-component="dialog-overlay" />
+ {element()}
+ </Kobalte.Portal>
+ </Kobalte>
+ </Show>
+ )),
+ onClose,
+ owner,
+ },
+ ])
},
clear() {
for (const item of store()) {
@@ -50,38 +79,16 @@ function init() {
setStore([])
},
}
+ return result
}
export function DialogProvider(props: ParentProps) {
const ctx = init()
- const last = createMemo(() => ctx.stack.at(-1))
return (
<Context.Provider value={ctx}>
{props.children}
<div data-component="dialog-stack">
- <Show when={last()}>
- {(item) =>
- runWithOwner(item().owner, () => {
- return (
- <Kobalte
- modal
- defaultOpen
- onOpenChange={(open) => {
- if (!open) {
- item().onClose?.()
- ctx.pop()
- }
- }}
- >
- <Kobalte.Portal>
- <Kobalte.Overlay data-component="dialog-overlay" />
- {item().element()}
- </Kobalte.Portal>
- </Kobalte>
- )
- })
- }
- </Show>
+ <For each={ctx.stack}>{(item) => <>{item.element()}</>}</For>
</div>
</Context.Provider>
)
@@ -103,9 +110,6 @@ export function useDialog() {
replace(element: DialogElement, onClose?: () => void) {
ctx.replace(element, owner, onClose)
},
- push(element: DialogElement, onClose?: () => void) {
- ctx.push(element, owner, onClose)
- },
pop() {
ctx.pop()
},