Add render prop to Button
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/canon': patch
|
||||
---
|
||||
|
||||
Added a render prop to the Button component in Canon to use it as a link.
|
||||
@@ -149,7 +149,7 @@ export const breakpoints: Breakpoint[];
|
||||
|
||||
// @public (undocumented)
|
||||
export const Button: ForwardRefExoticComponent<
|
||||
ButtonProps & RefAttributes<HTMLButtonElement>
|
||||
Omit<ButtonProps, 'ref'> & RefAttributes<HTMLButtonElement>
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
@@ -174,9 +174,7 @@ export const buttonPropDefs: {
|
||||
};
|
||||
|
||||
// @public
|
||||
export interface ButtonProps
|
||||
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
|
||||
children: React.ReactNode;
|
||||
export interface ButtonProps extends useRender.ComponentProps<'button'> {
|
||||
iconEnd?: ReactElement;
|
||||
iconStart?: ReactElement;
|
||||
size?: ButtonOwnProps['size'];
|
||||
|
||||
@@ -131,6 +131,18 @@ export const Disabled: Story = {
|
||||
),
|
||||
};
|
||||
|
||||
export const AsLink: Story = {
|
||||
args: {
|
||||
children: 'Button',
|
||||
},
|
||||
render: args => (
|
||||
<Button
|
||||
{...args}
|
||||
render={<a href="https://canon.backstage.io">Button</a>}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
export const Responsive: Story = {
|
||||
args: {
|
||||
children: 'Button',
|
||||
|
||||
@@ -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<HTMLButtonElement, ButtonProps>(
|
||||
const {
|
||||
size = 'small',
|
||||
variant = 'primary',
|
||||
disabled,
|
||||
iconStart,
|
||||
iconEnd,
|
||||
children,
|
||||
render = <button />,
|
||||
className,
|
||||
style,
|
||||
...rest
|
||||
@@ -38,38 +39,43 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
// Get the responsive value for the variant
|
||||
const responsiveSize = useResponsiveValue(size);
|
||||
const responsiveVariant = useResponsiveValue(variant);
|
||||
const internalRef = useRef<HTMLElement | null>(null);
|
||||
|
||||
return (
|
||||
<button
|
||||
ref={ref}
|
||||
disabled={disabled}
|
||||
className={clsx('canon-Button', className)}
|
||||
data-size={responsiveSize}
|
||||
data-variant={responsiveVariant}
|
||||
style={style}
|
||||
{...rest}
|
||||
>
|
||||
{iconStart && (
|
||||
<span
|
||||
className="canon-ButtonIcon"
|
||||
aria-hidden="true"
|
||||
data-size={responsiveSize}
|
||||
>
|
||||
{iconStart}
|
||||
</span>
|
||||
)}
|
||||
{children}
|
||||
{iconEnd && (
|
||||
<span
|
||||
className="canon-ButtonIcon"
|
||||
aria-hidden="true"
|
||||
data-size={responsiveSize}
|
||||
>
|
||||
{iconEnd}
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
const { renderElement } = useRender({
|
||||
render,
|
||||
props: {
|
||||
className: clsx('canon-Button', className),
|
||||
['data-variant']: responsiveVariant,
|
||||
['data-size']: responsiveSize,
|
||||
...rest,
|
||||
children: (
|
||||
<>
|
||||
{iconStart && (
|
||||
<span
|
||||
className="canon-ButtonIcon"
|
||||
aria-hidden="true"
|
||||
data-size={responsiveSize}
|
||||
>
|
||||
{iconStart}
|
||||
</span>
|
||||
)}
|
||||
{children}
|
||||
{iconEnd && (
|
||||
<span
|
||||
className="canon-ButtonIcon"
|
||||
aria-hidden="true"
|
||||
data-size={responsiveSize}
|
||||
>
|
||||
{iconEnd}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
},
|
||||
refs: [ref, internalRef],
|
||||
});
|
||||
|
||||
return renderElement();
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -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<React.ButtonHTMLAttributes<HTMLButtonElement>, '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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user