forked from CodebuffAI/codebuff
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbutton.tsx
More file actions
66 lines (57 loc) · 1.93 KB
/
Copy pathbutton.tsx
File metadata and controls
66 lines (57 loc) · 1.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { memo, useRef } from 'react'
import { makeTextUnselectable } from './clickable'
import type { ReactNode } from 'react'
interface ButtonProps {
onClick?: (e?: unknown) => void | Promise<unknown>
onMouseOver?: () => void
onMouseOut?: () => void
style?: Record<string, unknown>
children?: ReactNode
// pass-through for box host props
[key: string]: unknown
}
/**
* A button component with proper click detection and non-selectable text.
*
* Key behavior:
* - All nested `<text>`/`<span>` children are made `selectable={false}` via `makeTextUnselectable`
* - Uses mouseDown/mouseUp tracking so hover or stray mouse events don't trigger clicks
*
* When to use:
* - Use `Button` for standard button-like interactions (primary choice for clickable controls)
* - Use {@link Clickable} when you need direct control over mouse events but still want
* non-selectable text for an interactive region.
*/
export const Button = memo(function Button({ onClick, onMouseOver, onMouseOut, style, children, ...rest }: ButtonProps) {
const processedChildren = makeTextUnselectable(children)
// Track whether mouse down occurred on this element to implement proper click detection
// This prevents hover from triggering clicks in some terminals
const mouseDownRef = useRef(false)
const handleMouseDown = () => {
mouseDownRef.current = true
}
const handleMouseUp = (e?: unknown) => {
// Only trigger click if mouse down happened on this element
if (mouseDownRef.current && onClick) {
onClick(e)
}
mouseDownRef.current = false
}
const handleMouseOut = () => {
// Reset mouse down state when leaving the element
mouseDownRef.current = false
onMouseOut?.()
}
return (
<box
{...rest}
style={style}
onMouseDown={handleMouseDown}
onMouseUp={handleMouseUp}
onMouseOver={onMouseOver}
onMouseOut={handleMouseOut}
>
{processedChildren}
</box>
)
})