summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdam <[email protected]>2025-11-06 06:05:08 -0600
committerAdam <[email protected]>2025-11-06 09:48:50 -0600
commitab345cf0dac4378163292a5fb99b102bb2922ee1 (patch)
treeeaed6e9071897e97229477d61420200a00f519ef
parenta1836527ce75f2c1ba7c8d66ae9478c4444d8bfd (diff)
downloadopencode-ab345cf0dac4378163292a5fb99b102bb2922ee1.tar.gz
opencode-ab345cf0dac4378163292a5fb99b102bb2922ee1.zip
feat(desktop): better tooltips
-rw-r--r--packages/desktop/src/components/prompt-input.tsx36
-rw-r--r--packages/ui/src/components/icon.tsx1
-rw-r--r--packages/ui/src/components/tooltip.css69
-rw-r--r--packages/ui/src/components/tooltip.tsx8
4 files changed, 68 insertions, 46 deletions
diff --git a/packages/desktop/src/components/prompt-input.tsx b/packages/desktop/src/components/prompt-input.tsx
index 7dc67f6ae..cad1f2098 100644
--- a/packages/desktop/src/components/prompt-input.tsx
+++ b/packages/desktop/src/components/prompt-input.tsx
@@ -1,6 +1,6 @@
-import { Button, Icon, IconButton, Select, SelectDialog } from "@opencode-ai/ui"
+import { Button, Icon, IconButton, Select, SelectDialog, Tooltip } from "@opencode-ai/ui"
import { useFilteredList } from "@opencode-ai/ui/hooks"
-import { createEffect, on, Component, Show, For, onMount, onCleanup } from "solid-js"
+import { createEffect, on, Component, Show, For, onMount, onCleanup, Switch, Match } from "solid-js"
import { createStore } from "solid-js/store"
import { FileIcon } from "@/ui"
import { getDirectory, getFilename } from "@/utils"
@@ -519,12 +519,32 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
)}
</SelectDialog>
</div>
- <IconButton
- type="submit"
- disabled={!session.prompt.dirty() && !session.working()}
- icon={session.working() ? "stop" : "arrow-up"}
- variant="primary"
- />
+ <Tooltip
+ placement="top"
+ value={
+ <Switch>
+ <Match when={session.working()}>
+ <div class="flex items-center gap-2">
+ <span>Stop</span>
+ <span class="text-icon-base text-12-medium text-[10px]!">ESC</span>
+ </div>
+ </Match>
+ <Match when={true}>
+ <div class="flex items-center gap-2">
+ <span>Send</span>
+ <Icon name="enter" size="small" class="text-icon-base" />
+ </div>
+ </Match>
+ </Switch>
+ }
+ >
+ <IconButton
+ type="submit"
+ disabled={!session.prompt.dirty() && !session.working()}
+ icon={session.working() ? "stop" : "arrow-up"}
+ variant="primary"
+ />
+ </Tooltip>
</div>
</form>
</div>
diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx
index 617997201..2e96b9d85 100644
--- a/packages/ui/src/components/icon.tsx
+++ b/packages/ui/src/components/icon.tsx
@@ -151,6 +151,7 @@ const newIcons = {
"square-arrow-top-right": `<path d="M7.91675 2.9165H2.91675V17.0832H17.0834V12.0832M12.0834 2.9165H17.0834V7.9165M9.58342 10.4165L16.6667 3.33317" stroke="currentColor" stroke-linecap="square"/>`,
"circle-ban-sign": `<path d="M15.3675 4.63087L4.55742 15.441M17.9163 9.9987C17.9163 14.371 14.3719 17.9154 9.99967 17.9154C7.81355 17.9154 5.83438 17.0293 4.40175 15.5966C2.96911 14.164 2.08301 12.1848 2.08301 9.9987C2.08301 5.62644 5.62742 2.08203 9.99967 2.08203C12.1858 2.08203 14.165 2.96813 15.5976 4.40077C17.0302 5.8334 17.9163 7.81257 17.9163 9.9987Z" stroke="currentColor" stroke-linecap="round"/>`,
stop: `<rect x="6" y="6" width="8" height="8" fill="currentColor"/>`,
+ enter: `<path d="M5.83333 15.8334L2.5 12.5L5.83333 9.16671M3.33333 12.5H17.9167V4.58337H10" stroke="currentColor" stroke-linecap="square"/>`,
}
export interface IconProps extends ComponentProps<"svg"> {
diff --git a/packages/ui/src/components/tooltip.css b/packages/ui/src/components/tooltip.css
index 0577365d6..92825aca1 100644
--- a/packages/ui/src/components/tooltip.css
+++ b/packages/ui/src/components/tooltip.css
@@ -6,54 +6,55 @@
[data-component="tooltip"] {
z-index: 1000;
max-width: 320px;
- border-radius: 12px;
+ border-radius: 6px;
background-color: var(--surface-float-base);
- color: var(--white);
- padding: 2px 12px 2px 12px;
+ color: rgba(253, 252, 252, 0.94);
+ padding: 2px 8px;
+ border: 0.5px solid rgba(253, 252, 252, 0.2);
box-shadow: var(--shadow-md);
pointer-events: none !important;
- transition: all 150ms ease-out;
- transform: translate3d(0, 0, 0);
- transform-origin: var(--kb-tooltip-content-transform-origin);
+ /* transition: all 150ms ease-out; */
+ /* transform: translate3d(0, 0, 0); */
+ /* transform-origin: var(--kb-tooltip-content-transform-origin); */
- /* text-14-regular */
+ /* text-12-medium */
font-family: var(--font-family-sans);
- font-size: var(--font-size-base);
+ font-size: var(--font-size-small);
font-style: normal;
- font-weight: var(--font-weight-regular);
- line-height: var(--line-height-large); /* 171.429% */
+ font-weight: var(--font-weight-medium);
+ line-height: var(--line-height-large); /* 166.667% */
letter-spacing: var(--letter-spacing-normal);
&[data-expanded] {
opacity: 1;
- transform: translate3d(0, 0, 0);
+ /* transform: translate3d(0, 0, 0); */
}
&[data-closed] {
opacity: 0;
}
- &[data-placement="top"] {
- &[data-closed] {
- transform: translate3d(0, 4px, 0);
- }
- }
-
- &[data-placement="bottom"] {
- &[data-closed] {
- transform: translate3d(0, -4px, 0);
- }
- }
-
- &[data-placement="left"] {
- &[data-closed] {
- transform: translate3d(4px, 0, 0);
- }
- }
-
- &[data-placement="right"] {
- &[data-closed] {
- transform: translate3d(-4px, 0, 0);
- }
- }
+ /* &[data-placement="top"] { */
+ /* &[data-closed] { */
+ /* transform: translate3d(0, 4px, 0); */
+ /* } */
+ /* } */
+ /**/
+ /* &[data-placement="bottom"] { */
+ /* &[data-closed] { */
+ /* transform: translate3d(0, -4px, 0); */
+ /* } */
+ /* } */
+ /**/
+ /* &[data-placement="left"] { */
+ /* &[data-closed] { */
+ /* transform: translate3d(4px, 0, 0); */
+ /* } */
+ /* } */
+ /**/
+ /* &[data-placement="right"] { */
+ /* &[data-closed] { */
+ /* transform: translate3d(-4px, 0, 0); */
+ /* } */
+ /* } */
}
diff --git a/packages/ui/src/components/tooltip.tsx b/packages/ui/src/components/tooltip.tsx
index ff13c8d61..c3d1947d3 100644
--- a/packages/ui/src/components/tooltip.tsx
+++ b/packages/ui/src/components/tooltip.tsx
@@ -1,9 +1,9 @@
import { Tooltip as KobalteTooltip } from "@kobalte/core/tooltip"
-import { children, createEffect, createSignal, splitProps } from "solid-js"
+import { children, createEffect, createSignal, splitProps, type JSX } from "solid-js"
import type { ComponentProps } from "solid-js"
export interface TooltipProps extends ComponentProps<typeof KobalteTooltip> {
- value: string | (() => string)
+ value: JSX.Element
class?: string
}
@@ -29,13 +29,13 @@ export function Tooltip(props: TooltipProps) {
})
return (
- <KobalteTooltip forceMount {...others} open={open()} onOpenChange={setOpen}>
+ <KobalteTooltip forceMount {...others} open={open()} onOpenChange={setOpen} gutter={4}>
<KobalteTooltip.Trigger as={"div"} data-component="tooltip-trigger" class={local.class}>
{c()}
</KobalteTooltip.Trigger>
<KobalteTooltip.Portal>
<KobalteTooltip.Content data-component="tooltip" data-placement={props.placement}>
- {typeof others.value === "function" ? others.value() : others.value}
+ {others.value}
{/* <KobalteTooltip.Arrow data-slot="arrow" /> */}
</KobalteTooltip.Content>
</KobalteTooltip.Portal>