Fixed IconButton

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
Charles de Dreuille
2025-06-18 18:18:27 +01:00
parent 6f9b502232
commit 13dbfce65e
5 changed files with 105 additions and 78 deletions
+34 -23
View File
@@ -5,13 +5,15 @@
```ts
import { Avatar as Avatar_2 } from '@base-ui-components/react/avatar';
import { Breakpoint as Breakpoint_2 } from '@backstage/canon';
import { Button as Button_2 } from 'react-aria-components';
import { ChangeEvent } from 'react';
import { Collapsible as Collapsible_2 } from '@base-ui-components/react/collapsible';
import { ComponentProps } from 'react';
import type { ComponentPropsWithRef } from 'react';
import { ComponentPropsWithoutRef } from 'react';
import { ComponentPropsWithRef } from 'react';
import { Context } from 'react';
import type { CSSProperties } from 'react';
import type { ElementType } from 'react';
import { ElementType } from 'react';
import { FC } from 'react';
import { FocusEvent as FocusEvent_2 } from 'react';
import { ForwardRefExoticComponent } from 'react';
@@ -43,8 +45,8 @@ export type ArbitraryStylingPropDef = {
};
// @public (undocumented)
export type AsProp<C extends React.ElementType> = {
as?: C;
export type As<TAs extends ElementType> = {
as?: TAs;
};
// @public (undocumented)
@@ -156,14 +158,20 @@ export type Breakpoint = 'initial' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
export const breakpoints: Breakpoint[];
// @public (undocumented)
export const Button: <C extends React.ElementType = 'button'>(
props: ButtonProps<C>,
) => JSX_2.Element;
export const Button: {
<TAs extends ElementType = typeof Button_2>(
props: ButtonProps<TAs> & {
ref?: ComponentPropsWithRef<TAs>['ref'];
},
): ReactElement;
displayName: string;
};
// @public
export type ButtonProps<C extends React.ElementType> = PolymorphicComponentProp<
C,
export type ButtonProps<TAs extends ElementType> = PolymorphicComponentProps<
TAs,
{
children?: ReactNode;
size?:
| 'small'
| 'medium'
@@ -685,14 +693,19 @@ export type HeightProps = GetPropDefTypes<typeof heightPropDefs>;
export const Icon: (props: IconProps) => JSX_2.Element | null;
// @public (undocumented)
export const IconButton: <C extends React.ElementType = 'button'>(
props: IconButtonProps<C>,
) => JSX_2.Element;
export const IconButton: {
<TAs extends ElementType = typeof Button_2>(
props: IconButtonProps<TAs> & {
ref?: ComponentPropsWithRef<TAs>['ref'];
},
): ReactElement;
displayName: string;
};
// @public
export type IconButtonProps<C extends React.ElementType> =
PolymorphicComponentProp<
C,
export type IconButtonProps<TAs extends ElementType> =
PolymorphicComponentProps<
TAs,
{
size?:
| 'small'
@@ -1002,11 +1015,12 @@ export const paddingPropDefs: (spacingValues: string[]) => {
export type PaddingProps = GetPropDefTypes<typeof paddingPropDefs>;
// @public
export type PolymorphicComponentProp<
C extends React.ElementType,
Props = {},
> = React.PropsWithChildren<Props & AsProp<C>> &
Omit<React.ComponentPropsWithoutRef<C>, PropsToOmit<C, Props>>;
export type PolymorphicComponentProps<
TAs extends ElementType,
TProps = {},
> = TProps &
As<TAs> &
Omit<ComponentPropsWithoutRef<TAs>, keyof (As<TAs> & TProps)>;
// @public (undocumented)
export const positionPropDefs: {
@@ -1024,9 +1038,6 @@ export type PositionProps = GetPropDefTypes<typeof positionPropDefs>;
// @public (undocumented)
export type PropDef<T = any> = RegularPropDef<T> | ResponsivePropDef<T>;
// @public (undocumented)
export type PropsToOmit<C extends React.ElementType, P> = keyof (AsProp<C> & P);
// @public (undocumented)
export type ReactNodePropDef = {
type: 'ReactNode';
@@ -212,7 +212,7 @@ export const Playground: Story = {
<Button
variant={variant as ButtonProps<any>['variant']}
size={size as ButtonProps<any>['size']}
disabled
isDisabled
>
Button
</Button>
@@ -220,7 +220,7 @@ export const Playground: Story = {
iconStart={<Icon name="cloud" />}
variant={variant as ButtonProps<any>['variant']}
size={size as ButtonProps<any>['size']}
disabled
isDisabled
>
Button
</Button>
@@ -228,7 +228,7 @@ export const Playground: Story = {
iconEnd={<Icon name="chevron-right" />}
variant={variant as ButtonProps<any>['variant']}
size={size as ButtonProps<any>['size']}
disabled
isDisabled
>
Button
</Button>
@@ -40,44 +40,45 @@ export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
render: args => <IconButton {...args} icon={<Icon name="cloud" />} />,
render: () => <IconButton icon={<Icon name="cloud" />} />,
};
export const Variants: Story = {
render: args => (
render: () => (
<Flex align="center" gap="2">
<IconButton {...args} icon={<Icon name="cloud" />} variant="primary" />
<IconButton {...args} icon={<Icon name="cloud" />} variant="secondary" />
<IconButton icon={<Icon name="cloud" />} variant="primary" />
<IconButton icon={<Icon name="cloud" />} variant="secondary" />
</Flex>
),
};
export const Sizes: Story = {
render: args => (
render: () => (
<Flex align="center" gap="2">
<IconButton {...args} icon={<Icon name="cloud" />} size="small" />
<IconButton {...args} icon={<Icon name="cloud" />} size="medium" />
<IconButton icon={<Icon name="cloud" />} size="small" />
<IconButton icon={<Icon name="cloud" />} size="medium" />
</Flex>
),
};
export const Disabled: Story = {
args: { disabled: true },
render: args => (
render: () => (
<Flex direction="row" gap="2">
<IconButton {...args} icon={<Icon name="cloud" />} variant="primary" />
<IconButton {...args} icon={<Icon name="cloud" />} variant="secondary" />
<IconButton isDisabled icon={<Icon name="cloud" />} variant="primary" />
<IconButton isDisabled icon={<Icon name="cloud" />} variant="secondary" />
</Flex>
),
};
export const AsLink: Story = {
args: {
as: 'a',
href: 'https://canon.backstage.io',
target: '_blank',
},
render: args => <IconButton {...args} icon={<Icon name="cloud" />} />,
render: () => (
<IconButton
as="a"
href="https://canon.backstage.io"
target="_blank"
icon={<Icon name="cloud" />}
/>
),
};
export const AsComponent: Story = {
@@ -15,42 +15,57 @@
*/
import clsx from 'clsx';
import {
ComponentPropsWithRef,
ElementType,
forwardRef,
ReactElement,
Ref,
} from 'react';
import { Button as RAButton } from 'react-aria-components';
import { useResponsiveValue } from '../../hooks/useResponsiveValue';
import type { IconButtonProps } from './types';
/** @public */
export const IconButton = <C extends React.ElementType = 'button'>(
props: IconButtonProps<C>,
) => {
const {
as,
size = 'small',
variant = 'primary',
icon,
className,
href,
style,
...rest
} = props;
export const IconButton = forwardRef(
(props: IconButtonProps<typeof RAButton>, ref: Ref<HTMLButtonElement>) => {
const {
as,
size = 'small',
variant = 'primary',
icon,
className,
style,
...rest
} = props;
const Component = as || 'button';
const responsiveSize = useResponsiveValue(size);
const responsiveVariant = useResponsiveValue(variant);
const Component = as || RAButton;
const responsiveSize = useResponsiveValue(size);
const responsiveVariant = useResponsiveValue(variant);
return (
<Component
className={clsx('canon-IconButton', className)}
data-variant={responsiveVariant}
data-size={responsiveSize}
{...rest}
>
<span
className="canon-IconButtonIcon"
aria-hidden="true"
return (
<Component
className={clsx('canon-Button', className)}
data-variant={responsiveVariant}
data-size={responsiveSize}
ref={ref}
{...rest}
>
{icon}
</span>
</Component>
);
<span
className="canon-IconButtonIcon"
aria-hidden="true"
data-size={responsiveSize}
>
{icon}
</span>
</Component>
);
},
) as {
<TAs extends ElementType = typeof RAButton>(
props: IconButtonProps<TAs> & { ref?: ComponentPropsWithRef<TAs>['ref'] },
): ReactElement;
displayName: string;
};
IconButton.displayName = 'IconButton';
@@ -15,17 +15,17 @@
*/
import { Breakpoint } from '@backstage/canon';
import { ReactElement } from 'react';
import { PolymorphicComponentProp } from '../../types';
import { ElementType, ReactElement } from 'react';
import { PolymorphicComponentProps } from '../../types';
/**
* Properties for {@link IconButton}
*
* @public
*/
export type IconButtonProps<C extends React.ElementType> =
PolymorphicComponentProp<
C,
export type IconButtonProps<TAs extends ElementType> =
PolymorphicComponentProps<
TAs,
{
size?:
| 'small'