Improve types for both Button and IconButton
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
@@ -106,7 +106,7 @@ Here's a view when buttons are responsive.
|
||||
|
||||
### As Link
|
||||
|
||||
Use the `href` prop to make a button act as a link.
|
||||
You can use the `as` prop to make a button act as a link.
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
|
||||
@@ -62,6 +62,12 @@ export const buttonResponsiveSnippet = `<Button variant={{ initial: 'primary', l
|
||||
Responsive Button
|
||||
</Button>`;
|
||||
|
||||
export const buttonAsLinkSnippet = `<Button href="https://canon.backstage.io" target="_blank">
|
||||
export const buttonAsLinkSnippet = `// Using the \`as\` prop
|
||||
<Button as="a" href="https://canon.backstage.io" target="_blank">
|
||||
I am a link
|
||||
</Button>
|
||||
|
||||
// Using a custom component
|
||||
<Button as={Link} to="/">
|
||||
I am a using a custom component
|
||||
</Button>`;
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { AnchorHTMLAttributes } from 'react';
|
||||
import { Avatar as Avatar_2 } from '@base-ui-components/react/avatar';
|
||||
import { Breakpoint as Breakpoint_2 } from '@backstage/canon';
|
||||
import { ButtonHTMLAttributes } from 'react';
|
||||
import { ChangeEvent } from 'react';
|
||||
import { Collapsible as Collapsible_2 } from '@base-ui-components/react/collapsible';
|
||||
import { ComponentProps } from 'react';
|
||||
@@ -44,6 +42,11 @@ export type ArbitraryStylingPropDef = {
|
||||
parseValue?: (value: string) => string | undefined;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type AsProp<C extends React.ElementType> = {
|
||||
as?: C;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type AsProps =
|
||||
| 'div'
|
||||
@@ -153,40 +156,26 @@ export type Breakpoint = 'initial' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
||||
export const breakpoints: Breakpoint[];
|
||||
|
||||
// @public (undocumented)
|
||||
export const Button: ForwardRefExoticComponent<
|
||||
ButtonProps & RefAttributes<HTMLElement>
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type ButtonAnchorProps = ButtonCommonProps &
|
||||
Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'type' | 'onClick'> & {
|
||||
href: string;
|
||||
onClick?: React.MouseEventHandler<HTMLAnchorElement>;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type ButtonCommonProps = {
|
||||
size?: 'small' | 'medium' | Partial<Record<Breakpoint_2, 'small' | 'medium'>>;
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint_2, 'primary' | 'secondary'>>;
|
||||
iconStart?: ReactElement;
|
||||
iconEnd?: ReactElement;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type ButtonNativeProps = ButtonCommonProps &
|
||||
Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'href'> & {
|
||||
href?: undefined;
|
||||
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||
};
|
||||
export const Button: <C extends React.ElementType = 'button'>(
|
||||
props: ButtonProps<C>,
|
||||
) => JSX_2.Element;
|
||||
|
||||
// @public
|
||||
export type ButtonProps = ButtonAnchorProps | ButtonNativeProps;
|
||||
export type ButtonProps<C extends React.ElementType> = PolymorphicComponentProp<
|
||||
C,
|
||||
{
|
||||
size?:
|
||||
| 'small'
|
||||
| 'medium'
|
||||
| Partial<Record<Breakpoint_2, 'small' | 'medium'>>;
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint_2, 'primary' | 'secondary'>>;
|
||||
iconStart?: ReactElement;
|
||||
iconEnd?: ReactElement;
|
||||
}
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const Checkbox: ForwardRefExoticComponent<
|
||||
@@ -696,39 +685,26 @@ export type HeightProps = GetPropDefTypes<typeof heightPropDefs>;
|
||||
export const Icon: (props: IconProps) => JSX_2.Element | null;
|
||||
|
||||
// @public (undocumented)
|
||||
export const IconButton: ForwardRefExoticComponent<
|
||||
IconButtonProps & RefAttributes<HTMLElement>
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type IconButtonAnchorProps = IconButtonCommonProps &
|
||||
Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'type' | 'onClick'> & {
|
||||
href: string;
|
||||
onClick?: React.MouseEventHandler<HTMLAnchorElement>;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type IconButtonCommonProps = {
|
||||
size?: 'small' | 'medium' | Partial<Record<Breakpoint_2, 'small' | 'medium'>>;
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint_2, 'primary' | 'secondary'>>;
|
||||
icon?: ReactElement;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type IconButtonNativeProps = IconButtonCommonProps &
|
||||
Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'href'> & {
|
||||
href?: undefined;
|
||||
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||
};
|
||||
export const IconButton: <C extends React.ElementType = 'button'>(
|
||||
props: IconButtonProps<C>,
|
||||
) => JSX_2.Element;
|
||||
|
||||
// @public
|
||||
export type IconButtonProps = IconButtonAnchorProps | IconButtonNativeProps;
|
||||
export type IconButtonProps<C extends React.ElementType> =
|
||||
PolymorphicComponentProp<
|
||||
C,
|
||||
{
|
||||
size?:
|
||||
| 'small'
|
||||
| 'medium'
|
||||
| Partial<Record<Breakpoint_2, 'small' | 'medium'>>;
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint_2, 'primary' | 'secondary'>>;
|
||||
icon?: ReactElement;
|
||||
}
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const IconContext: Context<IconContextProps>;
|
||||
@@ -1025,6 +1001,13 @@ export const paddingPropDefs: (spacingValues: string[]) => {
|
||||
// @public (undocumented)
|
||||
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>>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const positionPropDefs: {
|
||||
position: {
|
||||
@@ -1041,6 +1024,9 @@ 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';
|
||||
|
||||
@@ -133,12 +133,26 @@ export const Disabled: Story = {
|
||||
|
||||
export const AsLink: Story = {
|
||||
args: {
|
||||
children: 'I am a link',
|
||||
children: 'Button',
|
||||
href: 'https://canon.backstage.io',
|
||||
target: '_blank',
|
||||
},
|
||||
};
|
||||
|
||||
export const AsComponent: Story = {
|
||||
render: () => {
|
||||
const Link = (props: { children: React.ReactNode; to: string }) => (
|
||||
<a {...props} />
|
||||
);
|
||||
|
||||
return (
|
||||
<Button as={Link} to="/">
|
||||
I am a using a custom component
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const Responsive: Story = {
|
||||
args: {
|
||||
children: 'Button',
|
||||
@@ -167,22 +181,22 @@ export const Playground: Story = {
|
||||
{['small', 'medium'].map(size => (
|
||||
<Flex align="center" key={size}>
|
||||
<Button
|
||||
variant={variant as ButtonProps['variant']}
|
||||
size={size as ButtonProps['size']}
|
||||
variant={variant as ButtonProps<any>['variant']}
|
||||
size={size as ButtonProps<any>['size']}
|
||||
>
|
||||
Button
|
||||
</Button>
|
||||
<Button
|
||||
iconStart={<Icon name="cloud" />}
|
||||
variant={variant as ButtonProps['variant']}
|
||||
size={size as ButtonProps['size']}
|
||||
variant={variant as ButtonProps<any>['variant']}
|
||||
size={size as ButtonProps<any>['size']}
|
||||
>
|
||||
Button
|
||||
</Button>
|
||||
<Button
|
||||
iconEnd={<Icon name="chevron-right" />}
|
||||
variant={variant as ButtonProps['variant']}
|
||||
size={size as ButtonProps['size']}
|
||||
variant={variant as ButtonProps<any>['variant']}
|
||||
size={size as ButtonProps<any>['size']}
|
||||
>
|
||||
Button
|
||||
</Button>
|
||||
@@ -190,30 +204,30 @@ export const Playground: Story = {
|
||||
iconStart={<Icon name="cloud" />}
|
||||
iconEnd={<Icon name="chevron-right" />}
|
||||
style={{ width: '200px' }}
|
||||
variant={variant as ButtonProps['variant']}
|
||||
size={size as ButtonProps['size']}
|
||||
variant={variant as ButtonProps<any>['variant']}
|
||||
size={size as ButtonProps<any>['size']}
|
||||
>
|
||||
Button
|
||||
</Button>
|
||||
<Button
|
||||
variant={variant as ButtonProps['variant']}
|
||||
size={size as ButtonProps['size']}
|
||||
variant={variant as ButtonProps<any>['variant']}
|
||||
size={size as ButtonProps<any>['size']}
|
||||
disabled
|
||||
>
|
||||
Button
|
||||
</Button>
|
||||
<Button
|
||||
iconStart={<Icon name="cloud" />}
|
||||
variant={variant as ButtonProps['variant']}
|
||||
size={size as ButtonProps['size']}
|
||||
variant={variant as ButtonProps<any>['variant']}
|
||||
size={size as ButtonProps<any>['size']}
|
||||
disabled
|
||||
>
|
||||
Button
|
||||
</Button>
|
||||
<Button
|
||||
iconEnd={<Icon name="chevron-right" />}
|
||||
variant={variant as ButtonProps['variant']}
|
||||
size={size as ButtonProps['size']}
|
||||
variant={variant as ButtonProps<any>['variant']}
|
||||
size={size as ButtonProps<any>['size']}
|
||||
disabled
|
||||
>
|
||||
Button
|
||||
|
||||
@@ -14,32 +14,36 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { AnchorHTMLAttributes, ButtonHTMLAttributes, forwardRef } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { useResponsiveValue } from '../../hooks/useResponsiveValue';
|
||||
import type { ButtonProps } from './types';
|
||||
|
||||
/** @public */
|
||||
export const Button = forwardRef<HTMLElement, ButtonProps>((props, ref) => {
|
||||
export const Button = <C extends React.ElementType = 'button'>(
|
||||
props: ButtonProps<C>,
|
||||
) => {
|
||||
const {
|
||||
as,
|
||||
size = 'small',
|
||||
variant = 'primary',
|
||||
iconStart,
|
||||
iconEnd,
|
||||
children,
|
||||
href,
|
||||
className,
|
||||
style,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const isAnchor = typeof props.href === 'string';
|
||||
|
||||
const Component = as || 'button';
|
||||
const responsiveSize = useResponsiveValue(size);
|
||||
const responsiveVariant = useResponsiveValue(variant);
|
||||
|
||||
const content = (
|
||||
<>
|
||||
return (
|
||||
<Component
|
||||
className={clsx('canon-Button', className)}
|
||||
data-variant={responsiveVariant}
|
||||
data-size={responsiveSize}
|
||||
{...rest}
|
||||
>
|
||||
{iconStart && (
|
||||
<span
|
||||
className="canon-ButtonIcon"
|
||||
@@ -59,44 +63,6 @@ export const Button = forwardRef<HTMLElement, ButtonProps>((props, ref) => {
|
||||
{iconEnd}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
</Component>
|
||||
);
|
||||
|
||||
if (isAnchor) {
|
||||
const { onClick, ...anchorRest } =
|
||||
rest as AnchorHTMLAttributes<HTMLAnchorElement>;
|
||||
return (
|
||||
<a
|
||||
href={href}
|
||||
className={clsx('canon-Button', className)}
|
||||
data-variant={responsiveVariant}
|
||||
data-size={responsiveSize}
|
||||
style={style}
|
||||
ref={ref as React.Ref<HTMLAnchorElement>}
|
||||
onClick={onClick}
|
||||
{...anchorRest}
|
||||
>
|
||||
{content}
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
const { onClick, ...buttonRest } =
|
||||
rest as ButtonHTMLAttributes<HTMLButtonElement>;
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={clsx('canon-Button', className)}
|
||||
data-variant={responsiveVariant}
|
||||
data-size={responsiveSize}
|
||||
style={style}
|
||||
ref={ref as React.Ref<HTMLButtonElement>}
|
||||
onClick={onClick}
|
||||
{...buttonRest}
|
||||
>
|
||||
{content}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Button.displayName = 'Button';
|
||||
};
|
||||
|
||||
@@ -15,43 +15,23 @@
|
||||
*/
|
||||
|
||||
import { Breakpoint } from '@backstage/canon';
|
||||
import {
|
||||
ReactElement,
|
||||
AnchorHTMLAttributes,
|
||||
ButtonHTMLAttributes,
|
||||
} from 'react';
|
||||
|
||||
/** @public */
|
||||
export type ButtonCommonProps = {
|
||||
size?: 'small' | 'medium' | Partial<Record<Breakpoint, 'small' | 'medium'>>;
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
iconStart?: ReactElement;
|
||||
iconEnd?: ReactElement;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type ButtonAnchorProps = ButtonCommonProps &
|
||||
Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'type' | 'onClick'> & {
|
||||
href: string;
|
||||
onClick?: React.MouseEventHandler<HTMLAnchorElement>;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type ButtonNativeProps = ButtonCommonProps &
|
||||
Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'href'> & {
|
||||
href?: undefined;
|
||||
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||
};
|
||||
import { ReactElement } from 'react';
|
||||
import { PolymorphicComponentProp } from '../../types';
|
||||
|
||||
/**
|
||||
* Properties for {@link Button}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type ButtonProps = ButtonAnchorProps | ButtonNativeProps;
|
||||
export type ButtonProps<C extends React.ElementType> = PolymorphicComponentProp<
|
||||
C,
|
||||
{
|
||||
size?: 'small' | 'medium' | Partial<Record<Breakpoint, 'small' | 'medium'>>;
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
iconStart?: ReactElement;
|
||||
iconEnd?: ReactElement;
|
||||
}
|
||||
>;
|
||||
|
||||
@@ -84,11 +84,23 @@ export const Disabled: Story = {
|
||||
};
|
||||
|
||||
export const AsLink: Story = {
|
||||
args: {
|
||||
icon: <Icon name="cloud" />,
|
||||
href: 'https://canon.backstage.io',
|
||||
target: '_blank',
|
||||
'aria-label': 'Cloud icon button',
|
||||
render: () => (
|
||||
<IconButton
|
||||
as="a"
|
||||
href="https://canon.backstage.io"
|
||||
target="_blank"
|
||||
icon={<Icon name="cloud" />}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
export const AsComponent: Story = {
|
||||
render: () => {
|
||||
const Link = (props: { children?: React.ReactNode; to: string }) => (
|
||||
<a {...props} />
|
||||
);
|
||||
|
||||
return <IconButton as={Link} to="/" icon={<Icon name="cloud" />} />;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -123,22 +135,22 @@ export const Playground: Story = {
|
||||
<Flex align="center" key={size}>
|
||||
<IconButton
|
||||
{...args}
|
||||
variant={variant as IconButtonProps['variant']}
|
||||
size={size as IconButtonProps['size']}
|
||||
variant={variant as IconButtonProps<any>['variant']}
|
||||
size={size as IconButtonProps<any>['size']}
|
||||
/>
|
||||
<IconButton
|
||||
{...args}
|
||||
icon={<Icon name="chevron-right" />}
|
||||
aria-label="Chevron right icon button"
|
||||
variant={variant as IconButtonProps['variant']}
|
||||
size={size as IconButtonProps['size']}
|
||||
variant={variant as IconButtonProps<any>['variant']}
|
||||
size={size as IconButtonProps<any>['size']}
|
||||
/>
|
||||
<IconButton
|
||||
{...args}
|
||||
icon={<Icon name="chevron-right" />}
|
||||
aria-label="Chevron right icon button"
|
||||
variant={variant as IconButtonProps['variant']}
|
||||
size={size as IconButtonProps['size']}
|
||||
variant={variant as IconButtonProps<any>['variant']}
|
||||
size={size as IconButtonProps<any>['size']}
|
||||
/>
|
||||
</Flex>
|
||||
))}
|
||||
|
||||
@@ -14,29 +14,36 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { AnchorHTMLAttributes, ButtonHTMLAttributes, forwardRef } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { useResponsiveValue } from '../../hooks/useResponsiveValue';
|
||||
import type { IconButtonProps } from './types';
|
||||
|
||||
/** @public */
|
||||
export const IconButton = forwardRef<HTMLElement, IconButtonProps>(
|
||||
(props, ref) => {
|
||||
const {
|
||||
size = 'small',
|
||||
variant = 'primary',
|
||||
icon,
|
||||
className,
|
||||
href,
|
||||
style,
|
||||
...rest
|
||||
} = props;
|
||||
export const IconButton = <C extends React.ElementType = 'button'>(
|
||||
props: IconButtonProps<C>,
|
||||
) => {
|
||||
const {
|
||||
as,
|
||||
size = 'small',
|
||||
variant = 'primary',
|
||||
icon,
|
||||
className,
|
||||
href,
|
||||
style,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const isAnchor = typeof props.href === 'string';
|
||||
const responsiveSize = useResponsiveValue(size);
|
||||
const responsiveVariant = useResponsiveValue(variant);
|
||||
const Component = as || 'button';
|
||||
const responsiveSize = useResponsiveValue(size);
|
||||
const responsiveVariant = useResponsiveValue(variant);
|
||||
|
||||
const content = (
|
||||
return (
|
||||
<Component
|
||||
className={clsx('canon-IconButton', className)}
|
||||
data-variant={responsiveVariant}
|
||||
data-size={responsiveSize}
|
||||
{...rest}
|
||||
>
|
||||
<span
|
||||
className="canon-IconButtonIcon"
|
||||
aria-hidden="true"
|
||||
@@ -44,44 +51,6 @@ export const IconButton = forwardRef<HTMLElement, IconButtonProps>(
|
||||
>
|
||||
{icon}
|
||||
</span>
|
||||
);
|
||||
|
||||
if (isAnchor) {
|
||||
const { onClick, ...anchorRest } =
|
||||
rest as AnchorHTMLAttributes<HTMLAnchorElement>;
|
||||
return (
|
||||
<a
|
||||
href={href}
|
||||
className={clsx('canon-IconButton', className)}
|
||||
data-variant={responsiveVariant}
|
||||
data-size={responsiveSize}
|
||||
style={style}
|
||||
ref={ref as React.Ref<HTMLAnchorElement>}
|
||||
onClick={onClick}
|
||||
{...anchorRest}
|
||||
>
|
||||
{content}
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
const { onClick, ...buttonRest } =
|
||||
rest as ButtonHTMLAttributes<HTMLButtonElement>;
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={clsx('canon-Button', className)}
|
||||
data-variant={responsiveVariant}
|
||||
data-size={responsiveSize}
|
||||
style={style}
|
||||
ref={ref as React.Ref<HTMLButtonElement>}
|
||||
onClick={onClick}
|
||||
{...buttonRest}
|
||||
>
|
||||
{content}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
IconButton.displayName = 'IconButton';
|
||||
</Component>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -14,43 +14,27 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
AnchorHTMLAttributes,
|
||||
ButtonHTMLAttributes,
|
||||
ReactElement,
|
||||
} from 'react';
|
||||
import { Breakpoint } from '@backstage/canon';
|
||||
|
||||
/** @public */
|
||||
export type IconButtonCommonProps = {
|
||||
size?: 'small' | 'medium' | Partial<Record<Breakpoint, 'small' | 'medium'>>;
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
icon?: ReactElement;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type IconButtonAnchorProps = IconButtonCommonProps &
|
||||
Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'type' | 'onClick'> & {
|
||||
href: string;
|
||||
onClick?: React.MouseEventHandler<HTMLAnchorElement>;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type IconButtonNativeProps = IconButtonCommonProps &
|
||||
Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'href'> & {
|
||||
href?: undefined;
|
||||
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||
};
|
||||
import { ReactElement } from 'react';
|
||||
import { PolymorphicComponentProp } from '../../types';
|
||||
|
||||
/**
|
||||
* Properties for {@link IconButton}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type IconButtonProps = IconButtonAnchorProps | IconButtonNativeProps;
|
||||
export type IconButtonProps<C extends React.ElementType> =
|
||||
PolymorphicComponentProp<
|
||||
C,
|
||||
{
|
||||
size?:
|
||||
| 'small'
|
||||
| 'medium'
|
||||
| Partial<Record<Breakpoint, 'small' | 'medium'>>;
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
icon?: ReactElement;
|
||||
}
|
||||
>;
|
||||
|
||||
@@ -131,3 +131,21 @@ export interface UtilityProps extends SpaceProps {
|
||||
justifyContent?: Responsive<JustifyContent>;
|
||||
rowSpan?: Responsive<Columns | 'full'>;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export type AsProp<C extends React.ElementType> = {
|
||||
as?: C;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type PropsToOmit<C extends React.ElementType, P> = keyof (AsProp<C> & P);
|
||||
|
||||
/**
|
||||
* This is the first reusable type utility we built
|
||||
* @public
|
||||
*/
|
||||
export type PolymorphicComponentProp<
|
||||
C extends React.ElementType,
|
||||
Props = {},
|
||||
> = React.PropsWithChildren<Props & AsProp<C>> &
|
||||
Omit<React.ComponentPropsWithoutRef<C>, PropsToOmit<C, Props>>;
|
||||
|
||||
Reference in New Issue
Block a user