["class"]
classList?: ComponentProps<"div">["classList"]
}
-function DialogRoot(props: DialogProps) {
- let trigger!: HTMLElement
- const [local, others] = splitProps(props, ["trigger", "class", "classList", "children"])
-
- const resetTabIndex = () => {
- trigger.tabIndex = 0
- }
-
- const handleTriggerFocus = (e: FocusEvent & { currentTarget: HTMLElement | null }) => {
- const firstChild = e.currentTarget?.firstElementChild as HTMLElement
- if (!firstChild) return
-
- firstChild.focus()
- trigger.tabIndex = -1
-
- firstChild.addEventListener("focusout", resetTabIndex)
- onCleanup(() => {
- firstChild.removeEventListener("focusout", resetTabIndex)
- })
- }
-
- onMount(() => {
- // @ts-ignore
- document?.activeElement?.blur?.()
- })
-
+export function Dialog(props: DialogProps) {
return (
-
-
-
- {props.trigger}
-
-
-
-
-
-
-
- {local.children}
-
-
-
-
-
+
+
+
+
+
+
+ {props.title}
+
+
+ {props.action}
+
+
+
+
+
+
+
+ {props.description}
+
+ {props.children}
+
+
+
)
}
-
-function DialogHeader(props: ComponentProps<"div">) {
- return
-}
-
-function DialogBody(props: ComponentProps<"div">) {
- return
-}
-
-function DialogTitle(props: DialogTitleProps & ComponentProps<"h2">) {
- return
-}
-
-function DialogDescription(props: DialogDescriptionProps & ComponentProps<"p">) {
- return
-}
-
-function DialogCloseButton(props: DialogCloseButtonProps & ComponentProps<"button">) {
- return
-}
-
-export const Dialog = Object.assign(DialogRoot, {
- Header: DialogHeader,
- Title: DialogTitle,
- Description: DialogDescription,
- CloseButton: DialogCloseButton,
- Body: DialogBody,
-})
diff --git a/packages/ui/src/context/dialog.tsx b/packages/ui/src/context/dialog.tsx
new file mode 100644
index 000000000..af5da06f9
--- /dev/null
+++ b/packages/ui/src/context/dialog.tsx
@@ -0,0 +1,79 @@
+import { For, Show, type JSX } from "solid-js"
+import { createStore } from "solid-js/store"
+import { createSimpleContext } from "@opencode-ai/ui/context"
+
+type DialogElement = JSX.Element | (() => JSX.Element)
+
+export const { use: useDialog, provider: DialogProvider } = createSimpleContext({
+ name: "Dialog",
+ init: () => {
+ const [store, setStore] = createStore({
+ stack: [] as {
+ element: DialogElement
+ onClose?: () => void
+ }[],
+ })
+
+ return {
+ get stack() {
+ return store.stack
+ },
+ push(element: DialogElement, onClose?: () => void) {
+ setStore("stack", (s) => [...s, { element, onClose }])
+ },
+ pop() {
+ const current = store.stack.at(-1)
+ current?.onClose?.()
+ setStore("stack", store.stack.slice(0, -1))
+ },
+ replace(element: DialogElement, onClose?: () => void) {
+ for (const item of store.stack) {
+ item.onClose?.()
+ }
+ setStore("stack", [{ element, onClose }])
+ },
+ clear() {
+ for (const item of store.stack) {
+ item.onClose?.()
+ }
+ setStore("stack", [])
+ },
+ }
+ },
+})
+
+import { Dialog as Kobalte } from "@kobalte/core/dialog"
+
+export function DialogRoot(props: { children?: JSX.Element }) {
+ const dialog = useDialog()
+ return (
+ <>
+ {props.children}
+
0}>
+
+
+ {(item, index) => (
+
+ {
+ if (!open) {
+ item.onClose?.()
+ dialog.pop()
+ }
+ }}
+ >
+
+
+ {typeof item.element === "function" ? item.element() : item.element}
+
+
+
+ )}
+
+
+
+ >
+ )
+}
diff --git a/packages/ui/src/context/index.ts b/packages/ui/src/context/index.ts
index 3e0f5de74..499cb74d4 100644
--- a/packages/ui/src/context/index.ts
+++ b/packages/ui/src/context/index.ts
@@ -1,3 +1,4 @@
export * from "./helper"
export * from "./data"
export * from "./diff"
+export * from "./dialog"
--
cgit v1.2.3