Skip to content

Commit 7af1e16

Browse files
zoldyzdkcursoragent
andcommitted
fix(ui): forward button refs
Allow the shared Button component to receive forwarded refs while preserving its polymorphic as prop API. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 3a4a24b commit 7af1e16

1 file changed

Lines changed: 23 additions & 12 deletions

File tree

src/ui/Button.tsx

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type ButtonRounded = 'none' | 'md' | 'lg' | 'full'
2020

2121
type ButtonOwnProps<TElement extends React.ElementType = 'button'> = {
2222
as?: TElement
23-
children: React.ReactNode
23+
children?: React.ReactNode
2424
variant?: ButtonVariant
2525
color?: ButtonColor
2626
size?: ButtonSize
@@ -35,8 +35,11 @@ type ButtonProps<TElement extends React.ElementType = 'button'> =
3535
keyof ButtonOwnProps<TElement>
3636
>
3737

38+
type ButtonRef<TElement extends React.ElementType> =
39+
React.ComponentPropsWithRef<TElement>['ref']
40+
3841
type ButtonComponent = <TElement extends React.ElementType = 'button'>(
39-
props: ButtonProps<TElement>,
42+
props: ButtonProps<TElement> & { ref?: ButtonRef<TElement> },
4043
) => React.ReactNode
4144

4245
const primaryColorStyles: Record<ButtonColor, string> = {
@@ -102,16 +105,19 @@ function getDefaultRounded(size: ButtonSize): ButtonRounded {
102105
return 'lg'
103106
}
104107

105-
export const Button: ButtonComponent = ({
106-
as,
107-
children,
108-
variant = 'primary',
109-
color = 'blue',
110-
size,
111-
rounded,
112-
className,
113-
...props
114-
}) => {
108+
function ButtonInner<TElement extends React.ElementType = 'button'>(
109+
{
110+
as,
111+
children,
112+
variant = 'primary',
113+
color = 'blue',
114+
size,
115+
rounded,
116+
className,
117+
...props
118+
}: ButtonProps<TElement>,
119+
ref: ButtonRef<TElement>,
120+
) {
115121
const Component = as || 'button'
116122
const resolvedSize = size ?? getDefaultSize(variant)
117123
const resolvedRounded = rounded ?? getDefaultRounded(resolvedSize)
@@ -126,6 +132,7 @@ export const Button: ButtonComponent = ({
126132
return React.createElement(
127133
Component,
128134
{
135+
ref,
129136
className: twMerge(
130137
baseStyles,
131138
variantStyles[variant],
@@ -139,3 +146,7 @@ export const Button: ButtonComponent = ({
139146
children,
140147
)
141148
}
149+
150+
export const Button = React.forwardRef(
151+
ButtonInner as React.ForwardRefRenderFunction<unknown, ButtonProps>,
152+
) as unknown as ButtonComponent

0 commit comments

Comments
 (0)