fix(desktop): align web search results presentation with figma (#44039)
This commit is contained in:
@@ -116,7 +116,7 @@
|
||||
letter-spacing: var(--letter-spacing-normal);
|
||||
color: var(--v2-text-text-muted);
|
||||
|
||||
&.clickable {
|
||||
&.clickable:not(.webfetch-link) {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
transition: color 0.15s ease;
|
||||
@@ -145,62 +145,6 @@
|
||||
color: var(--text-interactive-base);
|
||||
}
|
||||
}
|
||||
|
||||
&.webfetch-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: var(--v2-text-text-accent);
|
||||
text-decoration: none;
|
||||
|
||||
&:visited,
|
||||
&:active {
|
||||
color: var(--v2-text-text-accent);
|
||||
}
|
||||
|
||||
[data-slot="webfetch-link-text"] {
|
||||
text-decoration: none;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.webfetch-link-icon {
|
||||
display: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
color: var(--v2-icon-icon-accent, var(--v2-text-text-accent));
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--v2-text-text-accent);
|
||||
text-decoration: none;
|
||||
|
||||
[data-slot="webfetch-link-text"] {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
.webfetch-link-icon {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 1px solid var(--v2-text-text-accent);
|
||||
outline-offset: 2px;
|
||||
|
||||
[data-slot="webfetch-link-text"] {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
.webfetch-link-icon {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="basic-tool-tool-arg"] {
|
||||
@@ -381,3 +325,72 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.webfetch-link,
|
||||
[data-slot="basic-tool-tool-subtitle"].webfetch-link,
|
||||
[data-slot="exa-tool-link"].webfetch-link,
|
||||
[data-component="tool-trigger"] [data-slot="basic-tool-tool-subtitle"].webfetch-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: var(--v2-text-text-accent);
|
||||
text-decoration: none;
|
||||
overflow: visible;
|
||||
max-width: 100%;
|
||||
font-family: var(--font-family-sans);
|
||||
font-variant-numeric: tabular-nums;
|
||||
font-size: inherit;
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-regular, 440);
|
||||
line-height: inherit;
|
||||
letter-spacing: var(--letter-spacing-normal);
|
||||
|
||||
&:visited,
|
||||
&:active {
|
||||
color: var(--v2-text-text-accent);
|
||||
}
|
||||
|
||||
[data-slot="webfetch-link-text"] {
|
||||
text-decoration: none;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.webfetch-link-icon {
|
||||
display: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
color: var(--v2-icon-icon-accent, var(--v2-text-text-accent));
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--v2-text-text-accent);
|
||||
text-decoration: none;
|
||||
|
||||
[data-slot="webfetch-link-text"] {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
.webfetch-link-icon {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 1px solid var(--v2-text-text-accent);
|
||||
outline-offset: 2px;
|
||||
|
||||
[data-slot="webfetch-link-text"] {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
.webfetch-link-icon {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { createSignal, For, Show } from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { Button } from "@opencode-ai/ui/button"
|
||||
import { Icon } from "@opencode-ai/ui/icon"
|
||||
import { BasicTool } from "./basic-tool"
|
||||
|
||||
export default {
|
||||
@@ -73,3 +75,108 @@ export const Controlled = {
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
export const WebFetch = {
|
||||
render: () => (
|
||||
<BasicTool
|
||||
icon="window-cursor"
|
||||
hideDetails
|
||||
trigger={
|
||||
<div data-slot="basic-tool-tool-info-structured">
|
||||
<div data-slot="basic-tool-tool-info-main">
|
||||
<span data-slot="basic-tool-tool-title">Webfetch</span>
|
||||
<a
|
||||
data-slot="basic-tool-tool-subtitle"
|
||||
class="webfetch-link"
|
||||
href="https://www.figma.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<span data-slot="webfetch-link-text">https://www.figma.com</span>
|
||||
<Icon name="outline-square-arrow" class="webfetch-link-icon" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
),
|
||||
}
|
||||
|
||||
const mockSearchUrls = [
|
||||
"https://www.figma.com/community/file/1606560040358762787/figma-mcp-console-setup-guide",
|
||||
"https://designagentlab.com",
|
||||
"https://www.figma.com/community/whiteboarding?resource_type=widgets",
|
||||
"https://figma-console-mcp.southleft.com/mcp",
|
||||
"https://designagentlab.com/figma-console-mcp",
|
||||
"https://designagentlab.com/figma-tutorials",
|
||||
"https://github.com/southleft/figma-console-mcp/issues",
|
||||
"https://designagentlab.com/ui-kits",
|
||||
"https://designagentlab.com/prototyping-tools",
|
||||
"https://www.inthepocket.design/guidelines/figma-mcp/setup-figma-mcp",
|
||||
"https://www.figma.com/community/plugins",
|
||||
"https://figma-console-mcp.southleft.com/docs",
|
||||
"https://designagentlab.com/resources",
|
||||
"https://github.com/southleft/figma-console-mcp/releases",
|
||||
"https://www.inthepocket.design/blog/figma-mcp",
|
||||
"https://designagentlab.com/community",
|
||||
]
|
||||
|
||||
export const WebSearch = {
|
||||
render: () => {
|
||||
const [showAll, setShowAll] = createSignal(false)
|
||||
let firstRevealedRef: HTMLAnchorElement | undefined
|
||||
const visibleLinks = () => (showAll() ? mockSearchUrls : mockSearchUrls.slice(0, 10))
|
||||
const remaining = () => Math.max(0, mockSearchUrls.length - 10)
|
||||
|
||||
const expand = (event: MouseEvent) => {
|
||||
event.stopPropagation()
|
||||
setShowAll(true)
|
||||
requestAnimationFrame(() => {
|
||||
firstRevealedRef?.focus()
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<BasicTool
|
||||
icon="window-cursor"
|
||||
defaultOpen
|
||||
trigger={{
|
||||
title: "Firecrawl Web Search",
|
||||
subtitle: "figma mcp setup",
|
||||
subtitleClass: "exa-tool-query",
|
||||
}}
|
||||
>
|
||||
<div data-component="exa-tool-output">
|
||||
<div data-slot="exa-tool-rail">
|
||||
<div data-slot="exa-tool-rail-line" />
|
||||
</div>
|
||||
<div data-slot="exa-tool-links">
|
||||
<For each={visibleLinks()}>
|
||||
{(url, index) => (
|
||||
<a
|
||||
ref={(el) => {
|
||||
if (index() === 10) firstRevealedRef = el
|
||||
}}
|
||||
data-slot="exa-tool-link"
|
||||
class="webfetch-link"
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
>
|
||||
<span data-slot="webfetch-link-text">{url}</span>
|
||||
<Icon name="outline-square-arrow" class="webfetch-link-icon" />
|
||||
</a>
|
||||
)}
|
||||
</For>
|
||||
<Show when={!showAll() && remaining() > 0}>
|
||||
<button type="button" data-slot="exa-tool-more" onClick={expand}>
|
||||
+{remaining()} more
|
||||
</button>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</BasicTool>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -569,15 +569,31 @@
|
||||
}
|
||||
|
||||
[data-component="exa-tool-output"] {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
min-width: 0;
|
||||
font-family: var(--font-family-sans);
|
||||
font-size: var(--font-size-base);
|
||||
line-height: var(--line-height-large);
|
||||
font-size: 13px;
|
||||
line-height: 16px;
|
||||
color: var(--v2-text-text-muted);
|
||||
}
|
||||
|
||||
[data-slot="exa-tool-rail"] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
flex-shrink: 0;
|
||||
padding-bottom: 12px;
|
||||
padding-inline-start: 12px;
|
||||
padding-inline-end: 16px;
|
||||
}
|
||||
|
||||
[data-slot="exa-tool-rail-line"] {
|
||||
width: 0.5px;
|
||||
height: 100%;
|
||||
background-color: var(--v2-border-border-muted, rgba(0, 0, 0, 0.08));
|
||||
}
|
||||
|
||||
[data-slot="basic-tool-tool-subtitle"].exa-tool-query {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
@@ -589,27 +605,39 @@
|
||||
[data-slot="exa-tool-links"] {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
flex: 1 0 0;
|
||||
}
|
||||
|
||||
[data-slot="exa-tool-link"] {
|
||||
display: block;
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
font: inherit;
|
||||
line-height: inherit;
|
||||
color: var(--v2-text-text-accent);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
[data-slot="exa-tool-more"] {
|
||||
all: unset;
|
||||
cursor: pointer;
|
||||
width: fit-content;
|
||||
font-family: var(--font-family-sans);
|
||||
font-size: 13px;
|
||||
font-weight: var(--font-weight-regular, 440);
|
||||
line-height: 16px;
|
||||
letter-spacing: -0.04px;
|
||||
color: var(--v2-text-text-faint, #808080);
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
color: var(--v2-text-text-accent);
|
||||
color: var(--v2-text-text-muted);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
&:visited {
|
||||
color: var(--v2-text-text-accent);
|
||||
&:focus-visible {
|
||||
outline: 1px solid var(--v2-text-text-accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -702,15 +702,32 @@ export const webResearchDocument = document([
|
||||
id: "tool_web_search",
|
||||
name: "websearch",
|
||||
offset: 73_100,
|
||||
args: { query: "WAI ARIA live region status message guidance" },
|
||||
output: "WAI-ARIA Authoring Practices and MDN live region guidance",
|
||||
metadata: { provider: "exa" },
|
||||
args: { query: "figma mcp setup" },
|
||||
output: [
|
||||
"https://www.figma.com/community/file/1606560040358762787/figma-mcp-console-setup-guide",
|
||||
"https://designagentlab.com",
|
||||
"https://www.figma.com/community/whiteboarding?resource_type=widgets",
|
||||
"https://figma-console-mcp.southleft.com/mcp",
|
||||
"https://designagentlab.com/figma-console-mcp",
|
||||
"https://designagentlab.com/figma-tutorials",
|
||||
"https://github.com/southleft/figma-console-mcp/issues",
|
||||
"https://designagentlab.com/ui-kits",
|
||||
"https://designagentlab.com/prototyping-tools",
|
||||
"https://www.inthepocket.design/guidelines/figma-mcp/setup-figma-mcp",
|
||||
"https://www.figma.com/community/plugins",
|
||||
"https://figma-console-mcp.southleft.com/docs",
|
||||
"https://designagentlab.com/resources",
|
||||
"https://github.com/southleft/figma-console-mcp/releases",
|
||||
"https://www.inthepocket.design/blog/figma-mcp",
|
||||
"https://designagentlab.com/community",
|
||||
].join("\n"),
|
||||
metadata: { provider: "firecrawl" },
|
||||
}),
|
||||
completedTool({
|
||||
id: "tool_web_fetch",
|
||||
name: "webfetch",
|
||||
offset: 74_000,
|
||||
args: { url: "https://www.w3.org/WAI/WCAG22/Understanding/status-messages.html" },
|
||||
args: { url: "https://www.figma.com" },
|
||||
output: "Status messages should be programmatically determinable without receiving focus.",
|
||||
}),
|
||||
],
|
||||
|
||||
@@ -412,25 +412,55 @@ function taskSession(
|
||||
}
|
||||
|
||||
function ExaOutput(props: { output?: string }) {
|
||||
const i18n = useI18n()
|
||||
const [showAll, setShowAll] = createSignal(false)
|
||||
let firstRevealedRef: HTMLAnchorElement | undefined
|
||||
const links = createMemo(() => urls(props.output))
|
||||
const visibleLinks = createMemo(() => {
|
||||
const all = links()
|
||||
if (showAll() || all.length <= 10) return all
|
||||
return all.slice(0, 10)
|
||||
})
|
||||
const remaining = createMemo(() => Math.max(0, links().length - 10))
|
||||
|
||||
const expand = (event: MouseEvent) => {
|
||||
event.stopPropagation()
|
||||
setShowAll(true)
|
||||
requestAnimationFrame(() => {
|
||||
firstRevealedRef?.focus()
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Show when={links().length > 0}>
|
||||
<div data-component="exa-tool-output">
|
||||
<div data-slot="exa-tool-rail">
|
||||
<div data-slot="exa-tool-rail-line" />
|
||||
</div>
|
||||
<div data-slot="exa-tool-links">
|
||||
<For each={links()}>
|
||||
{(url) => (
|
||||
<For each={visibleLinks()}>
|
||||
{(url, index) => (
|
||||
<a
|
||||
ref={(el) => {
|
||||
if (index() === 10) firstRevealedRef = el
|
||||
}}
|
||||
data-slot="exa-tool-link"
|
||||
class="webfetch-link"
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
>
|
||||
{url}
|
||||
<span data-slot="webfetch-link-text">{url}</span>
|
||||
<Icon name="outline-square-arrow" class="webfetch-link-icon" />
|
||||
</a>
|
||||
)}
|
||||
</For>
|
||||
<Show when={!showAll() && remaining() > 0}>
|
||||
<button type="button" data-slot="exa-tool-more" onClick={expand}>
|
||||
{i18n.plural("ui.common.moreCount", remaining())}
|
||||
</button>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
@@ -898,7 +928,7 @@ ToolRegistry.register({
|
||||
<Show when={!pending() && url()}>
|
||||
<a
|
||||
data-slot="basic-tool-tool-subtitle"
|
||||
class="clickable webfetch-link"
|
||||
class="webfetch-link"
|
||||
href={url()}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
|
||||
@@ -35,7 +35,7 @@ function CollapsibleArrow(props?: ComponentProps<"div">) {
|
||||
return (
|
||||
<div data-slot="collapsible-arrow" {...(props || {})}>
|
||||
<span data-slot="collapsible-arrow-icon">
|
||||
<Icon name="chevron-down" size="small" />
|
||||
<Icon name="fill-triangle-down" size="small" />
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -188,6 +188,8 @@ const source = {
|
||||
"ui.common.next": "Next",
|
||||
"ui.common.submit": "Submit",
|
||||
"ui.common.showMore": "Show more",
|
||||
"ui.common.moreCount.one": "+{{count}} more",
|
||||
"ui.common.moreCount.other": "+{{count}} more",
|
||||
|
||||
"ui.permission.deny": "Deny",
|
||||
"ui.permission.allowAlways": "Allow always",
|
||||
|
||||
@@ -160,6 +160,10 @@ const icons = {
|
||||
viewBox: "0 0 20 20",
|
||||
body: `<path d="M5.83333 4.16406L2.5 7.4974L5.83333 10.8307M3.33333 7.4974H17.9167V15.4141H10" stroke="currentColor" stroke-linecap="square"/>`,
|
||||
},
|
||||
"fill-triangle-down": {
|
||||
viewBox: "0 0 16 16",
|
||||
body: `<path d="M5.37624 6.75194C5.1818 6.41861 5.42223 6 5.80813 6H10.1921C10.578 6 10.8184 6.41861 10.624 6.75194L8.43199 10.5096C8.23905 10.8404 7.76115 10.8404 7.56821 10.5096L5.37624 6.75194Z" fill="currentColor"/>`,
|
||||
},
|
||||
archive: {
|
||||
viewBox: "0 0 16 16",
|
||||
body: `<path d="M13.1112 13.5555V14.0555H13.6112V13.5555H13.1112ZM2.889 13.5555H2.389L2.389 14.0555H2.889V13.5555ZM3.38901 5.55546L3.38901 5.05546L2.38901 5.05546L2.38901 5.55546L2.88901 5.55546L3.38901 5.55546ZM14.4446 2.44434H14.9446V1.94434L14.4446 1.94434L14.4446 2.44434ZM14.4446 5.55545L14.4446 6.05545L14.9446 6.05545V5.55545H14.4446ZM1.55566 5.55546L1.05566 5.55545L1.05566 6.05546L1.55566 6.05546L1.55566 5.55546ZM1.5557 2.44436L1.5557 1.94436L1.05571 1.94436L1.0557 2.44435L1.5557 2.44436ZM13.1112 5.55546H12.6112V13.5555H13.1112H13.6112V5.55546H13.1112ZM2.889 13.5555H3.389L3.38901 5.55546L2.88901 5.55546L2.38901 5.55546L2.389 13.5555H2.889ZM14.4446 2.44434H13.9446V5.55545H14.4446H14.9446V2.44434H14.4446ZM1.55566 5.55546L2.05566 5.55547L2.0557 2.44436L1.5557 2.44436L1.0557 2.44435L1.05566 5.55545L1.55566 5.55546ZM6.22234 8.22213V8.72213H9.7779V8.22213V7.72213H6.22234V8.22213ZM13.1112 13.5555V13.0555H2.889V13.5555V14.0555H13.1112V13.5555ZM1.5557 2.44436L1.5557 2.94436L14.4446 2.94434L14.4446 2.44434L14.4446 1.94434L1.5557 1.94436L1.5557 2.44436ZM14.4446 5.55545L14.4446 5.05545L1.55566 5.05546L1.55566 5.55546L1.55566 6.05546L14.4446 6.05545L14.4446 5.55545Z" fill="currentColor"/>`,
|
||||
|
||||
Reference in New Issue
Block a user