Skip to content

Commit a196d6b

Browse files
committed
Improve terminal button ui style
1 parent 6906a50 commit a196d6b

1 file changed

Lines changed: 30 additions & 39 deletions

File tree

cli/src/components/tools/render-ui.tsx

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import { TextAttributes } from '@opentui/core'
2-
import { useCallback, useState } from 'react'
2+
import { useCallback, useEffect, useRef, useState } from 'react'
33

44
import { defineToolComponent } from './types'
55
import { useTheme } from '../../hooks/use-theme'
66
import { safeOpen } from '../../utils/open-url'
77
import { Button } from '../button'
88

9-
import type { ChatTheme } from '../../types/theme-system'
109
import type { ToolRenderConfig } from './types'
1110
import type { RenderUIButtonWidget } from '@codebuff/common/tools/params/tool/render-ui'
1211

@@ -33,25 +32,10 @@ const isRenderUIButtonWidget = (
3332
}
3433

3534
const getButtonColors = (
36-
theme: ChatTheme,
35+
theme: ReturnType<typeof useTheme>,
3736
variant: RenderUIButtonVariant,
3837
isHovered: boolean,
39-
status: 'idle' | 'opened' | 'failed',
4038
) => {
41-
if (status === 'failed') {
42-
return {
43-
backgroundColor: theme.surface,
44-
foregroundColor: theme.error,
45-
}
46-
}
47-
48-
if (status === 'opened') {
49-
return {
50-
backgroundColor: theme.surface,
51-
foregroundColor: theme.success,
52-
}
53-
}
54-
5539
if (variant === 'secondary') {
5640
return {
5741
backgroundColor: isHovered ? theme.surfaceHover : theme.surface,
@@ -65,36 +49,51 @@ const getButtonColors = (
6549
}
6650
}
6751

52+
const CLICK_FLASH_DURATION_MS = 150
53+
6854
const RenderUIButton = ({ widget }: { widget: RenderUIButtonWidget }) => {
6955
const theme = useTheme()
7056
const [isHovered, setIsHovered] = useState(false)
71-
const [status, setStatus] = useState<'idle' | 'opened' | 'failed'>('idle')
57+
const [isClicked, setIsClicked] = useState(false)
58+
const clickTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
7259
const variant = widget.variant ?? 'primary'
7360
const { backgroundColor, foregroundColor } = getButtonColors(
7461
theme,
7562
variant,
7663
isHovered,
77-
status,
7864
)
7965

80-
const handleClick = useCallback(async () => {
81-
const opened = await safeOpen(widget.link)
82-
setStatus(opened ? 'opened' : 'failed')
66+
useEffect(() => {
67+
return () => {
68+
if (clickTimeoutRef.current) {
69+
clearTimeout(clickTimeoutRef.current)
70+
}
71+
}
72+
}, [])
73+
74+
const handleClick = useCallback(() => {
75+
if (clickTimeoutRef.current) {
76+
clearTimeout(clickTimeoutRef.current)
77+
}
78+
setIsClicked(true)
79+
safeOpen(widget.link)
80+
clickTimeoutRef.current = setTimeout(
81+
() => setIsClicked(false),
82+
CLICK_FLASH_DURATION_MS,
83+
)
8384
}, [widget.link])
8485

85-
const statusText =
86-
status === 'opened'
87-
? 'Opened'
88-
: status === 'failed'
89-
? `Could not open: ${widget.link}`
90-
: ''
86+
const textAttributes = isClicked
87+
? TextAttributes.DIM
88+
: isHovered
89+
? TextAttributes.BOLD
90+
: undefined
9191

9292
return (
9393
<box
9494
style={{
9595
flexDirection: 'row',
9696
alignItems: 'center',
97-
gap: statusText ? 1 : 0,
9897
}}
9998
>
10099
<Button
@@ -108,19 +107,11 @@ const RenderUIButton = ({ widget }: { widget: RenderUIButtonWidget }) => {
108107
}}
109108
>
110109
<text>
111-
<span
112-
fg={foregroundColor}
113-
attributes={isHovered ? TextAttributes.BOLD : undefined}
114-
>
110+
<span fg={foregroundColor} attributes={textAttributes}>
115111
{widget.text}
116112
</span>
117113
</text>
118114
</Button>
119-
<text style={{ wrapMode: 'word' }}>
120-
<span fg={status === 'failed' ? theme.error : theme.muted}>
121-
{statusText}
122-
</span>
123-
</text>
124115
</box>
125116
)
126117
}

0 commit comments

Comments
 (0)