summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBrett Heap <[email protected]>2025-12-29 13:21:09 -0400
committerGitHub <[email protected]>2025-12-29 11:21:09 -0600
commit82b8d8fa5dd9206607b60de6130a6115cee68830 (patch)
tree21c9a128bfc331a7ef4cab417a24e5247cae00aa
parent77c837eb1ae34332607ac17e5a1a0d403dd3e8f7 (diff)
downloadopencode-82b8d8fa5dd9206607b60de6130a6115cee68830.tar.gz
opencode-82b8d8fa5dd9206607b60de6130a6115cee68830.zip
fix(tui): make auth URLs clickable regardless of line wrapping (#6317)
Co-authored-by: brettheap <[email protected]> Co-authored-by: Claude Opus 4.5 <[email protected]> Co-authored-by: copilot-swe-agent[bot] <[email protected]>
-rw-r--r--packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx5
-rw-r--r--packages/opencode/src/cli/cmd/tui/ui/link.tsx29
2 files changed, 32 insertions, 2 deletions
diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx
index 5cc114f92..d97648531 100644
--- a/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx
+++ b/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx
@@ -5,6 +5,7 @@ import { DialogSelect } from "@tui/ui/dialog-select"
import { useDialog } from "@tui/ui/dialog"
import { useSDK } from "../context/sdk"
import { DialogPrompt } from "../ui/dialog-prompt"
+import { Link } from "../ui/link"
import { useTheme } from "../context/theme"
import { TextAttributes } from "@opentui/core"
import type { ProviderAuthAuthorization } from "@opencode-ai/sdk/v2"
@@ -128,7 +129,7 @@ function AutoMethod(props: AutoMethodProps) {
<text fg={theme.textMuted}>esc</text>
</box>
<box gap={1}>
- <text fg={theme.primary}>{props.authorization.url}</text>
+ <Link href={props.authorization.url} fg={theme.primary} />
<text fg={theme.textMuted}>{props.authorization.instructions}</text>
</box>
<text fg={theme.textMuted}>Waiting for authorization...</text>
@@ -170,7 +171,7 @@ function CodeMethod(props: CodeMethodProps) {
description={() => (
<box gap={1}>
<text fg={theme.textMuted}>{props.authorization.instructions}</text>
- <text fg={theme.primary}>{props.authorization.url}</text>
+ <Link href={props.authorization.url} fg={theme.primary} />
<Show when={error()}>
<text fg={theme.error}>Invalid code</text>
</Show>
diff --git a/packages/opencode/src/cli/cmd/tui/ui/link.tsx b/packages/opencode/src/cli/cmd/tui/ui/link.tsx
new file mode 100644
index 000000000..1f798c54c
--- /dev/null
+++ b/packages/opencode/src/cli/cmd/tui/ui/link.tsx
@@ -0,0 +1,29 @@
+import type { JSX } from "solid-js"
+import type { RGBA } from "@opentui/core"
+import open from "open"
+
+export interface LinkProps {
+ href: string
+ children?: JSX.Element | string
+ fg?: RGBA
+}
+
+/**
+ * Link component that renders clickable hyperlinks.
+ * Clicking anywhere on the link text opens the URL in the default browser.
+ */
+export function Link(props: LinkProps) {
+ const displayText = props.children ?? props.href
+
+ return (
+ <text
+ fg={props.fg}
+ underline={true}
+ onMouseUp={() => {
+ open(props.href).catch(() => {})
+ }}
+ >
+ {displayText}
+ </text>
+ )
+}