mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-08 18:30:00 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f77f5a343e |
@@ -88,7 +88,7 @@ export const DialogSelectModelUnpaidV2: Component<{ model?: ModelState }> = (pro
|
|||||||
class="w-full"
|
class="w-full"
|
||||||
placement="right-start"
|
placement="right-start"
|
||||||
gutter={6}
|
gutter={6}
|
||||||
openDelay={0}
|
delay="intent"
|
||||||
contentStyle={{ "font-family": "var(--v2-font-family-sans)" }}
|
contentStyle={{ "font-family": "var(--v2-font-family-sans)" }}
|
||||||
value={
|
value={
|
||||||
<ModelTooltip
|
<ModelTooltip
|
||||||
|
|||||||
@@ -452,7 +452,7 @@ export function ModelSelectorPopoverV2(props: {
|
|||||||
class="w-full"
|
class="w-full"
|
||||||
placement="right-start"
|
placement="right-start"
|
||||||
gutter={6}
|
gutter={6}
|
||||||
openDelay={0}
|
delay="intent"
|
||||||
value={
|
value={
|
||||||
<ModelTooltip
|
<ModelTooltip
|
||||||
model={item}
|
model={item}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export const PromptContextItems: Component<ContextItemsProps> = (props) => {
|
|||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
placement="top"
|
placement="top"
|
||||||
openDelay={800}
|
{...(!props.newLayoutDesigns ? { openDelay: 800 } : {})}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
classList={{
|
classList={{
|
||||||
|
|||||||
@@ -52,12 +52,7 @@ export const PromptImageAttachments: Component<PromptImageAttachmentsProps> = (p
|
|||||||
<For each={props.comments ?? []}>
|
<For each={props.comments ?? []}>
|
||||||
{(item) => (
|
{(item) => (
|
||||||
<div class="relative group shrink-0">
|
<div class="relative group shrink-0">
|
||||||
<TooltipV2
|
<TooltipV2 value={item.comment} placement="top" contentClass="max-w-[300px] break-words">
|
||||||
value={item.comment}
|
|
||||||
placement="top"
|
|
||||||
openDelay={800}
|
|
||||||
contentClass="max-w-[300px] break-words"
|
|
||||||
>
|
|
||||||
<CommentCardV2
|
<CommentCardV2
|
||||||
comment={item.comment ?? ""}
|
comment={item.comment ?? ""}
|
||||||
path={item.path}
|
path={item.path}
|
||||||
|
|||||||
@@ -263,7 +263,6 @@ function ProviderTip(props: { ready: () => boolean; connected: () => boolean; op
|
|||||||
<TooltipV2
|
<TooltipV2
|
||||||
class="hover-reveal absolute left-full top-0 flex h-6 w-7 items-center justify-end delay-0 duration-0 group-hover/provider-tip:delay-[250ms] group-hover/provider-tip:duration-150 group-hover/provider-tip:opacity-100 focus-within:delay-0 focus-within:duration-0 focus-within:opacity-100"
|
class="hover-reveal absolute left-full top-0 flex h-6 w-7 items-center justify-end delay-0 duration-0 group-hover/provider-tip:delay-[250ms] group-hover/provider-tip:duration-150 group-hover/provider-tip:opacity-100 focus-within:delay-0 focus-within:duration-0 focus-within:opacity-100"
|
||||||
placement="top"
|
placement="top"
|
||||||
openDelay={1000}
|
|
||||||
value={language.t("common.dismiss")}
|
value={language.t("common.dismiss")}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ export function CommentCardV2(props: {
|
|||||||
return (
|
return (
|
||||||
<TooltipV2
|
<TooltipV2
|
||||||
placement="top"
|
placement="top"
|
||||||
openDelay={1000}
|
|
||||||
value={props.title ?? props.comment}
|
value={props.title ?? props.comment}
|
||||||
disabled={!props.tooltip || !truncated()}
|
disabled={!props.tooltip || !truncated()}
|
||||||
class={props.wide ? "w-full" : undefined}
|
class={props.wide ? "w-full" : undefined}
|
||||||
|
|||||||
@@ -385,12 +385,7 @@ export function PromptInputV2Attachments(props: {
|
|||||||
<For each={props.comments ?? []}>
|
<For each={props.comments ?? []}>
|
||||||
{(comment) => (
|
{(comment) => (
|
||||||
<div class="relative group shrink-0">
|
<div class="relative group shrink-0">
|
||||||
<TooltipV2
|
<TooltipV2 value={comment.comment} placement="top" contentClass="max-w-[300px] break-words">
|
||||||
value={comment.comment}
|
|
||||||
placement="top"
|
|
||||||
openDelay={800}
|
|
||||||
contentClass="max-w-[300px] break-words"
|
|
||||||
>
|
|
||||||
<CommentCardV2
|
<CommentCardV2
|
||||||
comment={comment.comment ?? ""}
|
comment={comment.comment ?? ""}
|
||||||
path={comment.path}
|
path={comment.path}
|
||||||
|
|||||||
@@ -214,7 +214,6 @@ export function SessionReviewV2(props: SessionReviewV2Props) {
|
|||||||
</Show>
|
</Show>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<TooltipV2
|
<TooltipV2
|
||||||
openDelay={2000}
|
|
||||||
inactive={!prev()}
|
inactive={!prev()}
|
||||||
value={
|
value={
|
||||||
<>
|
<>
|
||||||
@@ -234,7 +233,6 @@ export function SessionReviewV2(props: SessionReviewV2Props) {
|
|||||||
/>
|
/>
|
||||||
</TooltipV2>
|
</TooltipV2>
|
||||||
<TooltipV2
|
<TooltipV2
|
||||||
openDelay={2000}
|
|
||||||
inactive={!next()}
|
inactive={!next()}
|
||||||
value={
|
value={
|
||||||
<>
|
<>
|
||||||
@@ -268,12 +266,12 @@ export function SessionReviewV2(props: SessionReviewV2Props) {
|
|||||||
class="session-review-v2-segmented-control session-review-v2-segmented-control--icon"
|
class="session-review-v2-segmented-control session-review-v2-segmented-control--icon"
|
||||||
aria-label={i18n.t("ui.sessionReviewV2.expandMode")}
|
aria-label={i18n.t("ui.sessionReviewV2.expandMode")}
|
||||||
>
|
>
|
||||||
<TooltipV2 openDelay={2000} value={i18n.t("ui.sessionReviewV2.showAllLines")}>
|
<TooltipV2 value={i18n.t("ui.sessionReviewV2.showAllLines")}>
|
||||||
<SegmentedControlItemV2 value="expand" aria-label={i18n.t("ui.sessionReviewV2.showAllLines")}>
|
<SegmentedControlItemV2 value="expand" aria-label={i18n.t("ui.sessionReviewV2.showAllLines")}>
|
||||||
<Icon name="expand" />
|
<Icon name="expand" />
|
||||||
</SegmentedControlItemV2>
|
</SegmentedControlItemV2>
|
||||||
</TooltipV2>
|
</TooltipV2>
|
||||||
<TooltipV2 openDelay={2000} value={i18n.t("ui.sessionReviewV2.hideNonDiffLines")}>
|
<TooltipV2 value={i18n.t("ui.sessionReviewV2.hideNonDiffLines")}>
|
||||||
<SegmentedControlItemV2 value="collapse" aria-label={i18n.t("ui.sessionReviewV2.hideNonDiffLines")}>
|
<SegmentedControlItemV2 value="collapse" aria-label={i18n.t("ui.sessionReviewV2.hideNonDiffLines")}>
|
||||||
<Icon name="collapse" />
|
<Icon name="collapse" />
|
||||||
</SegmentedControlItemV2>
|
</SegmentedControlItemV2>
|
||||||
@@ -289,12 +287,12 @@ export function SessionReviewV2(props: SessionReviewV2Props) {
|
|||||||
class="session-review-v2-segmented-control session-review-v2-segmented-control--icon"
|
class="session-review-v2-segmented-control session-review-v2-segmented-control--icon"
|
||||||
aria-label={i18n.t("ui.sessionReviewV2.diffView")}
|
aria-label={i18n.t("ui.sessionReviewV2.diffView")}
|
||||||
>
|
>
|
||||||
<TooltipV2 openDelay={2000} value={i18n.t("ui.sessionReviewV2.unifiedDiff")}>
|
<TooltipV2 value={i18n.t("ui.sessionReviewV2.unifiedDiff")}>
|
||||||
<SegmentedControlItemV2 value="unified" aria-label={i18n.t("ui.sessionReviewV2.unifiedDiff")}>
|
<SegmentedControlItemV2 value="unified" aria-label={i18n.t("ui.sessionReviewV2.unifiedDiff")}>
|
||||||
<Icon name="unified" />
|
<Icon name="unified" />
|
||||||
</SegmentedControlItemV2>
|
</SegmentedControlItemV2>
|
||||||
</TooltipV2>
|
</TooltipV2>
|
||||||
<TooltipV2 openDelay={2000} value={i18n.t("ui.sessionReviewV2.splitDiff")}>
|
<TooltipV2 value={i18n.t("ui.sessionReviewV2.splitDiff")}>
|
||||||
<SegmentedControlItemV2 value="split" aria-label={i18n.t("ui.sessionReviewV2.splitDiff")}>
|
<SegmentedControlItemV2 value="split" aria-label={i18n.t("ui.sessionReviewV2.splitDiff")}>
|
||||||
<Icon name="split" />
|
<Icon name="split" />
|
||||||
</SegmentedControlItemV2>
|
</SegmentedControlItemV2>
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
const OPEN_DELAY = 1_000
|
||||||
|
|
||||||
|
// Kobalte warms every tooltip globally. Keep intent previews isolated so opening
|
||||||
|
// a model picker never inherits warm state from an unrelated tooltip.
|
||||||
|
let warm = false
|
||||||
|
let reset: ReturnType<typeof setTimeout> | undefined
|
||||||
|
|
||||||
|
export function openTooltipIntent(open: () => void) {
|
||||||
|
clearTimeout(reset)
|
||||||
|
reset = undefined
|
||||||
|
if (warm) {
|
||||||
|
open()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
warm = true
|
||||||
|
open()
|
||||||
|
}, OPEN_DELAY)
|
||||||
|
return () => clearTimeout(timer)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function closeTooltipIntent() {
|
||||||
|
clearTimeout(reset)
|
||||||
|
// Adjacent triggers enter before the next task; leaving the group does not.
|
||||||
|
reset = setTimeout(() => {
|
||||||
|
warm = false
|
||||||
|
reset = undefined
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resetTooltipIntent() {
|
||||||
|
clearTimeout(reset)
|
||||||
|
reset = undefined
|
||||||
|
warm = false
|
||||||
|
}
|
||||||
@@ -2,19 +2,22 @@ import { Tooltip as KobalteTooltip } from "@kobalte/core/tooltip"
|
|||||||
import { createEffect, Match, onCleanup, splitProps, Switch, type JSX } from "solid-js"
|
import { createEffect, Match, onCleanup, splitProps, Switch, type JSX } from "solid-js"
|
||||||
import type { ComponentProps } from "solid-js"
|
import type { ComponentProps } from "solid-js"
|
||||||
import { createStore } from "solid-js/store"
|
import { createStore } from "solid-js/store"
|
||||||
|
import { closeTooltipIntent, openTooltipIntent, resetTooltipIntent } from "./tooltip-intent"
|
||||||
import "./tooltip-v2.css"
|
import "./tooltip-v2.css"
|
||||||
|
|
||||||
export interface TooltipV2Props extends ComponentProps<typeof KobalteTooltip> {
|
export interface TooltipV2Props extends Omit<ComponentProps<typeof KobalteTooltip>, "openDelay"> {
|
||||||
value: JSX.Element
|
value: JSX.Element
|
||||||
class?: string
|
class?: string
|
||||||
contentClass?: string
|
contentClass?: string
|
||||||
contentStyle?: JSX.CSSProperties
|
contentStyle?: JSX.CSSProperties
|
||||||
inactive?: boolean
|
inactive?: boolean
|
||||||
|
delay?: "standard" | "intent"
|
||||||
forceOpen?: boolean
|
forceOpen?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TooltipV2(props: TooltipV2Props) {
|
export function TooltipV2(props: TooltipV2Props) {
|
||||||
let ref: HTMLDivElement | undefined
|
let ref: HTMLDivElement | undefined
|
||||||
|
let cancelIntent: (() => void) | undefined
|
||||||
const [state, setState] = createStore({
|
const [state, setState] = createStore({
|
||||||
open: false,
|
open: false,
|
||||||
block: false,
|
block: false,
|
||||||
@@ -26,19 +29,37 @@ export function TooltipV2(props: TooltipV2Props) {
|
|||||||
"contentClass",
|
"contentClass",
|
||||||
"contentStyle",
|
"contentStyle",
|
||||||
"inactive",
|
"inactive",
|
||||||
|
"delay",
|
||||||
"forceOpen",
|
"forceOpen",
|
||||||
"ignoreSafeArea",
|
"ignoreSafeArea",
|
||||||
"value",
|
"value",
|
||||||
])
|
])
|
||||||
|
|
||||||
const close = () => setState("open", false)
|
|
||||||
|
|
||||||
const inside = () => {
|
const inside = () => {
|
||||||
const active = document.activeElement
|
const active = document.activeElement
|
||||||
if (!ref || !active) return false
|
if (!ref || !active) return false
|
||||||
return ref.contains(active)
|
return ref.contains(active)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
cancelIntent?.()
|
||||||
|
cancelIntent = undefined
|
||||||
|
if (local.delay === "intent") closeTooltipIntent()
|
||||||
|
setState("open", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const show = () => {
|
||||||
|
if (local.delay !== "intent" || inside()) {
|
||||||
|
setState("open", true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (cancelIntent) return
|
||||||
|
cancelIntent = openTooltipIntent(() => {
|
||||||
|
cancelIntent = undefined
|
||||||
|
setState("open", true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const drop = (expand = state.expand) => {
|
const drop = (expand = state.expand) => {
|
||||||
if (expand) return
|
if (expand) return
|
||||||
if (ref?.matches(":hover")) return
|
if (ref?.matches(":hover")) return
|
||||||
@@ -80,6 +101,11 @@ export function TooltipV2(props: TooltipV2Props) {
|
|||||||
onCleanup(() => obs.disconnect())
|
onCleanup(() => obs.disconnect())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onCleanup(() => {
|
||||||
|
cancelIntent?.()
|
||||||
|
if (local.delay === "intent") resetTooltipIntent()
|
||||||
|
})
|
||||||
|
|
||||||
let justClickedTrigger = false
|
let justClickedTrigger = false
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -88,8 +114,8 @@ export function TooltipV2(props: TooltipV2Props) {
|
|||||||
<Match when={true}>
|
<Match when={true}>
|
||||||
<KobalteTooltip
|
<KobalteTooltip
|
||||||
gutter={4}
|
gutter={4}
|
||||||
openDelay={400}
|
openDelay={local.delay === "intent" ? 0 : 400}
|
||||||
skipDelayDuration={300}
|
skipDelayDuration={local.delay === "intent" ? 0 : 300}
|
||||||
{...others}
|
{...others}
|
||||||
closeDelay={0}
|
closeDelay={0}
|
||||||
ignoreSafeArea={local.ignoreSafeArea ?? true}
|
ignoreSafeArea={local.ignoreSafeArea ?? true}
|
||||||
@@ -101,7 +127,11 @@ export function TooltipV2(props: TooltipV2Props) {
|
|||||||
justClickedTrigger = false
|
justClickedTrigger = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setState("open", open)
|
if (open) {
|
||||||
|
show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
close()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<KobalteTooltip.Trigger
|
<KobalteTooltip.Trigger
|
||||||
|
|||||||
Reference in New Issue
Block a user