diff --git a/.changeset/kind-houses-feel.md b/.changeset/kind-houses-feel.md
new file mode 100644
index 0000000000..a4b3ac0d14
--- /dev/null
+++ b/.changeset/kind-houses-feel.md
@@ -0,0 +1,5 @@
+---
+'@backstage/canon': patch
+---
+
+Added a render prop to the Button component in Canon to use it as a link.
diff --git a/canon-docs/src/app/(docs)/components/button/page.mdx b/canon-docs/src/app/(docs)/components/button/page.mdx
index e1ecee8920..3554ee39f9 100644
--- a/canon-docs/src/app/(docs)/components/button/page.mdx
+++ b/canon-docs/src/app/(docs)/components/button/page.mdx
@@ -125,6 +125,20 @@ Here's a view when buttons are disabled.
code={``}
/>
+### As Link
+
+Here's a view when buttons are rendered as a link.
+
+}
+ code={`}>
+ I am a link
+ `}
+/>
+
### Responsive
Here's a view when buttons are responsive.
diff --git a/canon-docs/src/app/(docs)/components/button/props.ts b/canon-docs/src/app/(docs)/components/button/props.ts
index 813dcaa6f0..36b0f73066 100644
--- a/canon-docs/src/app/(docs)/components/button/props.ts
+++ b/canon-docs/src/app/(docs)/components/button/props.ts
@@ -14,6 +14,12 @@ export const buttonPropDefs: Record = {
default: 'medium',
responsive: true,
},
+ render: {
+ type: 'enum',
+ values: ['ReactNode'],
+ responsive: false,
+ default: '',
+ },
...classNamePropDefs,
...stylePropDefs,
};
diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md
index bc0ad71e90..b6ce130ecc 100644
--- a/packages/canon/report.api.md
+++ b/packages/canon/report.api.md
@@ -149,7 +149,7 @@ export const breakpoints: Breakpoint[];
// @public (undocumented)
export const Button: ForwardRefExoticComponent<
- ButtonProps & RefAttributes
+ Omit & RefAttributes
>;
// @public (undocumented)
@@ -174,9 +174,7 @@ export const buttonPropDefs: {
};
// @public
-export interface ButtonProps
- extends Omit, 'children'> {
- children: React.ReactNode;
+export interface ButtonProps extends useRender.ComponentProps<'button'> {
iconEnd?: ReactElement;
iconStart?: ReactElement;
size?: ButtonOwnProps['size'];
diff --git a/packages/canon/src/components/Button/Button.stories.tsx b/packages/canon/src/components/Button/Button.stories.tsx
index c0519cb279..2d79da7e29 100644
--- a/packages/canon/src/components/Button/Button.stories.tsx
+++ b/packages/canon/src/components/Button/Button.stories.tsx
@@ -131,6 +131,18 @@ export const Disabled: Story = {
),
};
+export const AsLink: Story = {
+ args: {
+ children: 'I am a link',
+ },
+ render: args => (
+ }
+ />
+ ),
+};
+
export const Responsive: Story = {
args: {
children: 'Button',
diff --git a/packages/canon/src/components/Button/Button.tsx b/packages/canon/src/components/Button/Button.tsx
index e9774ad083..9775f3f629 100644
--- a/packages/canon/src/components/Button/Button.tsx
+++ b/packages/canon/src/components/Button/Button.tsx
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-import { forwardRef } from 'react';
+import { forwardRef, useRef } from 'react';
import clsx from 'clsx';
import { useResponsiveValue } from '../../hooks/useResponsiveValue';
+import { useRender } from '@base-ui-components/react/use-render';
import type { ButtonProps } from './types';
@@ -26,10 +27,10 @@ export const Button = forwardRef(
const {
size = 'small',
variant = 'primary',
- disabled,
iconStart,
iconEnd,
children,
+ render = ,
className,
style,
...rest
@@ -38,38 +39,43 @@ export const Button = forwardRef(
// Get the responsive value for the variant
const responsiveSize = useResponsiveValue(size);
const responsiveVariant = useResponsiveValue(variant);
+ const internalRef = useRef(null);
- return (
-
- );
+ const { renderElement } = useRender({
+ render,
+ props: {
+ className: clsx('canon-Button', className),
+ ['data-variant']: responsiveVariant,
+ ['data-size']: responsiveSize,
+ ...rest,
+ children: (
+ <>
+ {iconStart && (
+
+ {iconStart}
+
+ )}
+ {children}
+ {iconEnd && (
+
+ {iconEnd}
+
+ )}
+ >
+ ),
+ },
+ refs: [ref, internalRef],
+ });
+
+ return renderElement();
},
);
diff --git a/packages/canon/src/components/Button/types.ts b/packages/canon/src/components/Button/types.ts
index 4ab62d5683..e91538299e 100644
--- a/packages/canon/src/components/Button/types.ts
+++ b/packages/canon/src/components/Button/types.ts
@@ -16,14 +16,14 @@
import type { ButtonOwnProps } from './Button.props';
import { ReactElement } from 'react';
+import type { useRender } from '@base-ui-components/react/use-render';
/**
* Properties for {@link Button}
*
* @public
*/
-export interface ButtonProps
- extends Omit, 'children'> {
+export interface ButtonProps extends useRender.ComponentProps<'button'> {
/**
* The size of the button
* @defaultValue 'medium'
@@ -36,11 +36,6 @@ export interface ButtonProps
*/
variant?: ButtonOwnProps['variant'];
- /**
- * The content of the button
- */
- children: React.ReactNode;
-
/**
* Optional icon to display at the start of the button
*/