diff --git a/packages/components/src/Button/Button.tsx b/packages/components/src/Button/Button.tsx
index ed64fa31be..edf95fea0d 100644
--- a/packages/components/src/Button/Button.tsx
+++ b/packages/components/src/Button/Button.tsx
@@ -1,4 +1,4 @@
-import React from "react";
+import React, { forwardRef } from "react";
import { Link } from "react-router-dom";
import classnames from "classnames";
import { type ButtonProps, type HTMLButtonType } from "./Button.types";
@@ -7,17 +7,10 @@ import { useButtonStyles } from "./useButtonStyles";
import { ButtonContent, ButtonIcon, ButtonLabel } from "./ButtonInternals";
import { ButtonProvider } from "./ButtonProvider";
-function Button(props: ButtonProps) {
- const { size } = props;
-
- return (
-
-
-
- );
-}
-
-function ButtonWrapper(props: ButtonProps) {
+const ButtonWrapper = forwardRef<
+ HTMLButtonElement | HTMLAnchorElement,
+ ButtonProps
+>((props, ref) => {
const {
ariaControls,
ariaHaspopup,
@@ -72,7 +65,7 @@ function ButtonWrapper(props: ButtonProps) {
if (to) {
return (
-
+ }>
{buttonInternals}
);
@@ -80,10 +73,65 @@ function ButtonWrapper(props: ButtonProps) {
const Tag = url ? "a" : "button";
- return {buttonInternals};
-}
+ // Use createElement for proper ref typing (similar to Chip component)
+ return React.createElement(Tag, { ...tagProps, ref }, buttonInternals);
+});
+
+ButtonWrapper.displayName = "ButtonWrapper";
+const ButtonForwarded = forwardRef<
+ HTMLButtonElement | HTMLAnchorElement,
+ ButtonProps
+>((props, ref) => {
+ const { size } = props;
+
+ return (
+
+
+
+ );
+});
+
+ButtonForwarded.displayName = "Button";
+
+// Add function overloads for type-safe refs
+export const Button = ButtonForwarded as unknown as {
+ // Overload for button (no url, no to)
+ (
+ props: ButtonProps & {
+ url?: never;
+ to?: never;
+ ref?: React.Ref;
+ },
+ ): ReturnType;
+
+ // Overload for anchor (with url, no to)
+ (
+ props: ButtonProps & {
+ url: string;
+ to?: never;
+ ref?: React.Ref;
+ },
+ ): ReturnType;
+
+ // Overload for Link (with to, no url)
+ (
+ props: ButtonProps & {
+ to: string;
+ url?: never;
+ ref?: React.Ref;
+ },
+ ): ReturnType;
+
+ // Fallback for when ref is not provided (union type)
+ (props: ButtonProps): ReturnType;
+} & {
+ Label: typeof ButtonLabel;
+ Icon: typeof ButtonIcon;
+};
+
+// Attach namespace components (preserving existing API)
Button.Label = ButtonLabel;
Button.Icon = ButtonIcon;
+
export type { ButtonProps };
-export { Button };