mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-18 08:33:29 +00:00
fix(app): wait for connected project picker anchor (#36879)
This commit is contained in:
parent
e7e7a97648
commit
5f7091ab4e
1 changed files with 33 additions and 8 deletions
|
|
@ -1,6 +1,14 @@
|
|||
import { createEffect, For, onCleanup, Show, splitProps, type Accessor, type ComponentProps } from "solid-js"
|
||||
import {
|
||||
createEffect,
|
||||
createSignal,
|
||||
For,
|
||||
onCleanup,
|
||||
Show,
|
||||
splitProps,
|
||||
type Accessor,
|
||||
type ComponentProps,
|
||||
} from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { Dynamic } from "solid-js/web"
|
||||
import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
|
||||
import { Icon } from "@opencode-ai/ui/icon"
|
||||
import { Icon as IconV2 } from "@opencode-ai/ui/v2/icon"
|
||||
|
|
@ -185,9 +193,28 @@ export function PromptProjectSelector(props: {
|
|||
controller: PromptProjectController
|
||||
placement?: "bottom" | "bottom-start"
|
||||
}) {
|
||||
const [triggerReady, setTriggerReady] = createSignal(false)
|
||||
let contentRef: HTMLDivElement | undefined
|
||||
let triggerFrame: number | undefined
|
||||
let restoreTrigger = true
|
||||
|
||||
// Floating UI requires a connected anchor; route transitions can construct this trigger before adoption.
|
||||
const setTriggerRef = (element: HTMLButtonElement) => {
|
||||
const ready = () => {
|
||||
if (!element.isConnected) {
|
||||
triggerFrame = requestAnimationFrame(ready)
|
||||
return
|
||||
}
|
||||
triggerFrame = undefined
|
||||
setTriggerReady(true)
|
||||
}
|
||||
ready()
|
||||
}
|
||||
|
||||
onCleanup(() => {
|
||||
if (triggerFrame !== undefined) cancelAnimationFrame(triggerFrame)
|
||||
})
|
||||
|
||||
const activeItem = () =>
|
||||
props.controller.active()
|
||||
? contentRef?.querySelector<HTMLElement>(`[data-option-key="${CSS.escape(props.controller.active())}"]`)
|
||||
|
|
@ -258,13 +285,13 @@ export function PromptProjectSelector(props: {
|
|||
|
||||
return (
|
||||
<DropdownMenu
|
||||
open={props.controller.open()}
|
||||
open={triggerReady() && props.controller.open()}
|
||||
placement={props.placement ?? "bottom"}
|
||||
gutter={4}
|
||||
modal={false}
|
||||
onOpenChange={(open) => props.controller.setOpen(open)}
|
||||
>
|
||||
<DropdownMenu.Trigger as={ProjectTrigger} controller={props.controller} />
|
||||
<DropdownMenu.Trigger as={ProjectTrigger} ref={setTriggerRef} controller={props.controller} />
|
||||
<DropdownMenu.Portal>
|
||||
<DropdownMenu.Content
|
||||
ref={contentRef}
|
||||
|
|
@ -434,9 +461,7 @@ function ProjectTrigger(props: ComponentProps<"button"> & { controller: PromptPr
|
|||
const [local, rest] = splitProps(props, ["controller", "class", "classList", "onClick", "onKeyDown"])
|
||||
const project = () => local.controller.selected()
|
||||
return (
|
||||
// Avoid an inert template clone that Floating UI can measure before browser adoption.
|
||||
<Dynamic
|
||||
component="button"
|
||||
<button
|
||||
{...rest}
|
||||
data-action="prompt-project"
|
||||
type="button"
|
||||
|
|
@ -473,7 +498,7 @@ function ProjectTrigger(props: ComponentProps<"button"> & { controller: PromptPr
|
|||
{project() ? displayName(project()!) : local.controller.labels.new()}
|
||||
</span>
|
||||
<Icon name="chevron-down" size="small" class="shrink-0 text-v2-icon-icon-muted" />
|
||||
</Dynamic>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue