Removed support for the as prop
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
@@ -69,21 +69,21 @@
|
||||
.canon-Button[data-size="medium"] {
|
||||
font-size: var(--canon-font-size-4);
|
||||
padding: 0 var(--canon-space-3);
|
||||
height: 40px;
|
||||
height: 2.5rem;
|
||||
}
|
||||
|
||||
.canon-Button[data-size="small"] {
|
||||
font-size: var(--canon-font-size-3);
|
||||
padding: 0 var(--canon-space-2);
|
||||
height: 32px;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size="small"], .canon-ButtonIcon[data-size="small"] svg {
|
||||
.canon-Button[data-size="small"] svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size="medium"], .canon-ButtonIcon[data-size="medium"] svg {
|
||||
.canon-Button[data-size="medium"] svg {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
.canon-ButtonIcon {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size="small"] {
|
||||
width: 2rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size="medium"] {
|
||||
width: 2.5rem;
|
||||
padding: 0;
|
||||
}
|
||||
@@ -125,25 +125,40 @@
|
||||
.canon-Button[data-size="medium"] {
|
||||
font-size: var(--canon-font-size-4);
|
||||
padding: 0 var(--canon-space-3);
|
||||
height: 40px;
|
||||
height: 2.5rem;
|
||||
}
|
||||
|
||||
.canon-Button[data-size="small"] {
|
||||
font-size: var(--canon-font-size-3);
|
||||
padding: 0 var(--canon-space-2);
|
||||
height: 32px;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size="small"], .canon-ButtonIcon[data-size="small"] svg {
|
||||
.canon-Button[data-size="small"] svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size="medium"], .canon-ButtonIcon[data-size="medium"] svg {
|
||||
.canon-Button[data-size="medium"] svg {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size="small"] {
|
||||
width: 2rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size="medium"] {
|
||||
width: 2.5rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.canon-CheckboxRoot {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
@@ -351,96 +366,6 @@
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.canon-IconButton {
|
||||
user-select: none;
|
||||
font-family: var(--canon-font-regular);
|
||||
font-weight: var(--canon-font-weight-bold);
|
||||
cursor: pointer;
|
||||
border-radius: var(--canon-radius-2);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: var(--canon-space-1_5);
|
||||
border: none;
|
||||
padding: 0;
|
||||
display: inline-flex;
|
||||
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
.canon-IconButton[data-variant="primary"] {
|
||||
background-color: var(--canon-bg-solid);
|
||||
color: var(--canon-fg-solid);
|
||||
transition: background-color .15s, box-shadow .15s;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--canon-bg-solid-hover);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--canon-bg-solid-pressed);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid var(--canon-ring);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: var(--canon-bg-solid-disabled);
|
||||
color: var(--canon-fg-solid-disabled);
|
||||
}
|
||||
}
|
||||
|
||||
.canon-IconButton[data-variant="secondary"] {
|
||||
background-color: var(--canon-bg-surface-1);
|
||||
box-shadow: inset 0 0 0 1px var(--canon-border);
|
||||
color: var(--canon-fg-primary);
|
||||
transition: box-shadow .15s;
|
||||
|
||||
&:hover {
|
||||
box-shadow: inset 0 0 0 1px var(--canon-border-hover);
|
||||
}
|
||||
|
||||
&:active {
|
||||
box-shadow: inset 0 0 0 1px var(--canon-border-pressed);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
box-shadow: inset 0 0 0 2px var(--canon-ring);
|
||||
outline: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
box-shadow: inset 0 0 0 1px var(--canon-border-disabled);
|
||||
color: var(--canon-fg-disabled);
|
||||
}
|
||||
}
|
||||
|
||||
.canon-IconButton[data-size="medium"] {
|
||||
font-size: var(--canon-font-size-4);
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.canon-IconButton[data-size="small"] {
|
||||
font-size: var(--canon-font-size-3);
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.canon-IconButtonIcon[data-size="small"], .canon-IconButtonIcon[data-size="small"] svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.canon-IconButtonIcon[data-size="medium"], .canon-IconButtonIcon[data-size="medium"] svg {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.canon-Link {
|
||||
font-family: var(--canon-font-regular);
|
||||
color: var(--canon-fg-link);
|
||||
|
||||
@@ -9349,25 +9349,40 @@
|
||||
.canon-Button[data-size="medium"] {
|
||||
font-size: var(--canon-font-size-4);
|
||||
padding: 0 var(--canon-space-3);
|
||||
height: 40px;
|
||||
height: 2.5rem;
|
||||
}
|
||||
|
||||
.canon-Button[data-size="small"] {
|
||||
font-size: var(--canon-font-size-3);
|
||||
padding: 0 var(--canon-space-2);
|
||||
height: 32px;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size="small"], .canon-ButtonIcon[data-size="small"] svg {
|
||||
.canon-Button[data-size="small"] svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size="medium"], .canon-ButtonIcon[data-size="medium"] svg {
|
||||
.canon-Button[data-size="medium"] svg {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size="small"] {
|
||||
width: 2rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size="medium"] {
|
||||
width: 2.5rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.canon-CheckboxRoot {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
@@ -9575,96 +9590,6 @@
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.canon-IconButton {
|
||||
user-select: none;
|
||||
font-family: var(--canon-font-regular);
|
||||
font-weight: var(--canon-font-weight-bold);
|
||||
cursor: pointer;
|
||||
border-radius: var(--canon-radius-2);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: var(--canon-space-1_5);
|
||||
border: none;
|
||||
padding: 0;
|
||||
display: inline-flex;
|
||||
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
.canon-IconButton[data-variant="primary"] {
|
||||
background-color: var(--canon-bg-solid);
|
||||
color: var(--canon-fg-solid);
|
||||
transition: background-color .15s, box-shadow .15s;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--canon-bg-solid-hover);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--canon-bg-solid-pressed);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid var(--canon-ring);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: var(--canon-bg-solid-disabled);
|
||||
color: var(--canon-fg-solid-disabled);
|
||||
}
|
||||
}
|
||||
|
||||
.canon-IconButton[data-variant="secondary"] {
|
||||
background-color: var(--canon-bg-surface-1);
|
||||
box-shadow: inset 0 0 0 1px var(--canon-border);
|
||||
color: var(--canon-fg-primary);
|
||||
transition: box-shadow .15s;
|
||||
|
||||
&:hover {
|
||||
box-shadow: inset 0 0 0 1px var(--canon-border-hover);
|
||||
}
|
||||
|
||||
&:active {
|
||||
box-shadow: inset 0 0 0 1px var(--canon-border-pressed);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
box-shadow: inset 0 0 0 2px var(--canon-ring);
|
||||
outline: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
box-shadow: inset 0 0 0 1px var(--canon-border-disabled);
|
||||
color: var(--canon-fg-disabled);
|
||||
}
|
||||
}
|
||||
|
||||
.canon-IconButton[data-size="medium"] {
|
||||
font-size: var(--canon-font-size-4);
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.canon-IconButton[data-size="small"] {
|
||||
font-size: var(--canon-font-size-3);
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.canon-IconButtonIcon[data-size="small"], .canon-IconButtonIcon[data-size="small"] svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.canon-IconButtonIcon[data-size="medium"], .canon-IconButtonIcon[data-size="medium"] svg {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.canon-Link {
|
||||
font-family: var(--canon-font-regular);
|
||||
color: var(--canon-fg-link);
|
||||
|
||||
@@ -5,15 +5,14 @@
|
||||
```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 { ButtonProps as ButtonProps_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 { ComponentPropsWithoutRef } from 'react';
|
||||
import { ComponentPropsWithRef } from 'react';
|
||||
import type { ComponentPropsWithRef } from 'react';
|
||||
import { Context } from 'react';
|
||||
import type { CSSProperties } from 'react';
|
||||
import { ElementType } from 'react';
|
||||
import type { ElementType } from 'react';
|
||||
import { FC } from 'react';
|
||||
import { FocusEvent as FocusEvent_2 } from 'react';
|
||||
import { ForwardRefExoticComponent } from 'react';
|
||||
@@ -44,11 +43,6 @@ export type ArbitraryStylingPropDef = {
|
||||
parseValue?: (value: string) => string | undefined;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type As<TAs extends ElementType> = {
|
||||
as?: TAs;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type AsProps =
|
||||
| 'div'
|
||||
@@ -158,32 +152,44 @@ export type Breakpoint = 'initial' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
||||
export const breakpoints: Breakpoint[];
|
||||
|
||||
// @public (undocumented)
|
||||
export const Button: {
|
||||
<TAs extends ElementType = typeof Button_2>(
|
||||
props: ButtonProps<TAs> & {
|
||||
ref?: ComponentPropsWithRef<TAs>['ref'];
|
||||
},
|
||||
): ReactElement;
|
||||
displayName: string;
|
||||
};
|
||||
export const Button: ForwardRefExoticComponent<
|
||||
ButtonProps & RefAttributes<HTMLButtonElement>
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const ButtonIcon: ForwardRefExoticComponent<
|
||||
ButtonIconProps & RefAttributes<HTMLButtonElement>
|
||||
>;
|
||||
|
||||
// @public
|
||||
export type ButtonProps<TAs extends ElementType> = PolymorphicComponentProps<
|
||||
TAs,
|
||||
{
|
||||
children?: ReactNode;
|
||||
size?:
|
||||
| 'small'
|
||||
| 'medium'
|
||||
| Partial<Record<Breakpoint_2, 'small' | 'medium'>>;
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint_2, 'primary' | 'secondary'>>;
|
||||
iconStart?: ReactElement;
|
||||
iconEnd?: ReactElement;
|
||||
}
|
||||
>;
|
||||
export interface ButtonIconProps extends ButtonProps_2 {
|
||||
// (undocumented)
|
||||
icon?: ReactElement;
|
||||
// (undocumented)
|
||||
size?: 'small' | 'medium' | Partial<Record<Breakpoint_2, 'small' | 'medium'>>;
|
||||
// (undocumented)
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint_2, 'primary' | 'secondary'>>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface ButtonProps extends ButtonProps_2 {
|
||||
// (undocumented)
|
||||
children?: ReactNode;
|
||||
// (undocumented)
|
||||
iconEnd?: ReactElement;
|
||||
// (undocumented)
|
||||
iconStart?: ReactElement;
|
||||
// (undocumented)
|
||||
size?: 'small' | 'medium' | Partial<Record<Breakpoint_2, 'small' | 'medium'>>;
|
||||
// (undocumented)
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint_2, 'primary' | 'secondary'>>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export const Checkbox: ForwardRefExoticComponent<
|
||||
@@ -692,33 +698,6 @@ export type HeightProps = GetPropDefTypes<typeof heightPropDefs>;
|
||||
// @public (undocumented)
|
||||
export const Icon: (props: IconProps) => JSX_2.Element | null;
|
||||
|
||||
// @public (undocumented)
|
||||
export const IconButton: {
|
||||
<TAs extends ElementType = typeof Button_2>(
|
||||
props: IconButtonProps<TAs> & {
|
||||
ref?: ComponentPropsWithRef<TAs>['ref'];
|
||||
},
|
||||
): ReactElement;
|
||||
displayName: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
export type IconButtonProps<TAs extends ElementType> =
|
||||
PolymorphicComponentProps<
|
||||
TAs,
|
||||
{
|
||||
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>;
|
||||
|
||||
@@ -1014,14 +993,6 @@ export const paddingPropDefs: (spacingValues: string[]) => {
|
||||
// @public (undocumented)
|
||||
export type PaddingProps = GetPropDefTypes<typeof paddingPropDefs>;
|
||||
|
||||
// @public
|
||||
export type PolymorphicComponentProps<
|
||||
TAs extends ElementType,
|
||||
TProps = {},
|
||||
> = TProps &
|
||||
As<TAs> &
|
||||
Omit<ComponentPropsWithoutRef<TAs>, keyof (As<TAs> & TProps)>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const positionPropDefs: {
|
||||
position: {
|
||||
|
||||
@@ -130,29 +130,6 @@ export const Disabled: Story = {
|
||||
),
|
||||
};
|
||||
|
||||
export const AsLink: Story = {
|
||||
args: {
|
||||
as: 'a',
|
||||
children: 'I am a link',
|
||||
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',
|
||||
|
||||
@@ -15,22 +15,15 @@
|
||||
*/
|
||||
|
||||
import clsx from 'clsx';
|
||||
import {
|
||||
ComponentPropsWithRef,
|
||||
ElementType,
|
||||
forwardRef,
|
||||
ReactElement,
|
||||
Ref,
|
||||
} from 'react';
|
||||
import { forwardRef, Ref } from 'react';
|
||||
import { Button as RAButton } from 'react-aria-components';
|
||||
import { useResponsiveValue } from '../../hooks/useResponsiveValue';
|
||||
import type { ButtonProps } from './types';
|
||||
|
||||
/** @public */
|
||||
export const Button = forwardRef(
|
||||
(props: ButtonProps<typeof RAButton>, ref: Ref<HTMLButtonElement>) => {
|
||||
(props: ButtonProps, ref: Ref<HTMLButtonElement>) => {
|
||||
const {
|
||||
as,
|
||||
size = 'small',
|
||||
variant = 'primary',
|
||||
iconStart,
|
||||
@@ -40,45 +33,23 @@ export const Button = forwardRef(
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const Component = as || RAButton;
|
||||
const responsiveSize = useResponsiveValue(size);
|
||||
const responsiveVariant = useResponsiveValue(variant);
|
||||
|
||||
return (
|
||||
<Component
|
||||
<RAButton
|
||||
className={clsx('canon-Button', className)}
|
||||
data-variant={responsiveVariant}
|
||||
data-size={responsiveSize}
|
||||
ref={ref}
|
||||
{...rest}
|
||||
>
|
||||
{iconStart && (
|
||||
<span
|
||||
className="canon-ButtonIcon"
|
||||
aria-hidden="true"
|
||||
data-size={responsiveSize}
|
||||
>
|
||||
{iconStart}
|
||||
</span>
|
||||
)}
|
||||
{iconStart}
|
||||
{children}
|
||||
{iconEnd && (
|
||||
<span
|
||||
className="canon-ButtonIcon"
|
||||
aria-hidden="true"
|
||||
data-size={responsiveSize}
|
||||
>
|
||||
{iconEnd}
|
||||
</span>
|
||||
)}
|
||||
</Component>
|
||||
{iconEnd}
|
||||
</RAButton>
|
||||
);
|
||||
},
|
||||
) as {
|
||||
<TAs extends ElementType = typeof RAButton>(
|
||||
props: ButtonProps<TAs> & { ref?: ComponentPropsWithRef<TAs>['ref'] },
|
||||
): ReactElement;
|
||||
displayName: string;
|
||||
};
|
||||
);
|
||||
|
||||
Button.displayName = 'Button';
|
||||
|
||||
@@ -85,23 +85,21 @@
|
||||
.canon-Button[data-size='medium'] {
|
||||
font-size: var(--canon-font-size-4);
|
||||
padding: 0 var(--canon-space-3);
|
||||
height: 40px;
|
||||
height: 2.5rem;
|
||||
}
|
||||
|
||||
.canon-Button[data-size='small'] {
|
||||
font-size: var(--canon-font-size-3);
|
||||
padding: 0 var(--canon-space-2);
|
||||
height: 32px;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size='small'],
|
||||
.canon-ButtonIcon[data-size='small'] svg {
|
||||
.canon-Button[data-size='small'] svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size='medium'],
|
||||
.canon-ButtonIcon[data-size='medium'] svg {
|
||||
.canon-Button[data-size='medium'] svg {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
@@ -15,24 +15,21 @@
|
||||
*/
|
||||
|
||||
import { Breakpoint } from '@backstage/canon';
|
||||
import { ElementType, ReactElement, ReactNode } from 'react';
|
||||
import { PolymorphicComponentProps } from '../../types';
|
||||
import { ReactElement, ReactNode } from 'react';
|
||||
import { ButtonProps as RAButtonProps } from 'react-aria-components';
|
||||
|
||||
/**
|
||||
* Properties for {@link Button}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type ButtonProps<TAs extends ElementType> = PolymorphicComponentProps<
|
||||
TAs,
|
||||
{
|
||||
children?: ReactNode;
|
||||
size?: 'small' | 'medium' | Partial<Record<Breakpoint, 'small' | 'medium'>>;
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
iconStart?: ReactElement;
|
||||
iconEnd?: ReactElement;
|
||||
}
|
||||
>;
|
||||
export interface ButtonProps extends RAButtonProps {
|
||||
size?: 'small' | 'medium' | Partial<Record<Breakpoint, 'small' | 'medium'>>;
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
iconStart?: ReactElement;
|
||||
iconEnd?: ReactElement;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
+15
-36
@@ -15,14 +15,14 @@
|
||||
*/
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { IconButton } from './IconButton';
|
||||
import { ButtonIcon } from './ButtonIcon';
|
||||
import { Flex } from '../Flex';
|
||||
import { Text } from '../Text';
|
||||
import { Icon } from '../Icon';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/IconButton',
|
||||
component: IconButton,
|
||||
title: 'Components/ButtonIcon',
|
||||
component: ButtonIcon,
|
||||
argTypes: {
|
||||
size: {
|
||||
control: 'select',
|
||||
@@ -33,20 +33,20 @@ const meta = {
|
||||
options: ['primary', 'secondary'],
|
||||
},
|
||||
},
|
||||
} satisfies Meta<typeof IconButton>;
|
||||
} satisfies Meta<typeof ButtonIcon>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {
|
||||
render: () => <IconButton icon={<Icon name="cloud" />} />,
|
||||
render: () => <ButtonIcon icon={<Icon name="cloud" />} />,
|
||||
};
|
||||
|
||||
export const Variants: Story = {
|
||||
render: () => (
|
||||
<Flex align="center" gap="2">
|
||||
<IconButton icon={<Icon name="cloud" />} variant="primary" />
|
||||
<IconButton icon={<Icon name="cloud" />} variant="secondary" />
|
||||
<ButtonIcon icon={<Icon name="cloud" />} variant="primary" />
|
||||
<ButtonIcon icon={<Icon name="cloud" />} variant="secondary" />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
@@ -54,8 +54,8 @@ export const Variants: Story = {
|
||||
export const Sizes: Story = {
|
||||
render: () => (
|
||||
<Flex align="center" gap="2">
|
||||
<IconButton icon={<Icon name="cloud" />} size="small" />
|
||||
<IconButton icon={<Icon name="cloud" />} size="medium" />
|
||||
<ButtonIcon icon={<Icon name="cloud" />} size="small" />
|
||||
<ButtonIcon icon={<Icon name="cloud" />} size="medium" />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
@@ -63,33 +63,12 @@ export const Sizes: Story = {
|
||||
export const Disabled: Story = {
|
||||
render: () => (
|
||||
<Flex direction="row" gap="2">
|
||||
<IconButton isDisabled icon={<Icon name="cloud" />} variant="primary" />
|
||||
<IconButton isDisabled icon={<Icon name="cloud" />} variant="secondary" />
|
||||
<ButtonIcon isDisabled icon={<Icon name="cloud" />} variant="primary" />
|
||||
<ButtonIcon isDisabled icon={<Icon name="cloud" />} variant="secondary" />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const AsLink: Story = {
|
||||
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" />} />;
|
||||
},
|
||||
};
|
||||
|
||||
export const Responsive: Story = {
|
||||
args: {
|
||||
variant: {
|
||||
@@ -101,7 +80,7 @@ export const Responsive: Story = {
|
||||
sm: 'medium',
|
||||
},
|
||||
},
|
||||
render: args => <IconButton {...args} icon={<Icon name="cloud" />} />,
|
||||
render: args => <ButtonIcon {...args} icon={<Icon name="cloud" />} />,
|
||||
};
|
||||
|
||||
const variants = ['primary', 'secondary'] as const;
|
||||
@@ -115,20 +94,20 @@ export const Playground: Story = {
|
||||
<Text>{variant}</Text>
|
||||
{sizes.map(size => (
|
||||
<Flex align="center" key={size}>
|
||||
<IconButton
|
||||
<ButtonIcon
|
||||
{...args}
|
||||
variant={variant}
|
||||
size={size}
|
||||
icon={<Icon name="cloud" />}
|
||||
/>
|
||||
<IconButton
|
||||
<ButtonIcon
|
||||
{...args}
|
||||
icon={<Icon name="chevron-right" />}
|
||||
aria-label="Chevron right icon button"
|
||||
variant={variant}
|
||||
size={size}
|
||||
/>
|
||||
<IconButton
|
||||
<ButtonIcon
|
||||
{...args}
|
||||
icon={<Icon name="chevron-right" />}
|
||||
aria-label="Chevron right icon button"
|
||||
+12
-29
@@ -15,22 +15,15 @@
|
||||
*/
|
||||
|
||||
import clsx from 'clsx';
|
||||
import {
|
||||
ComponentPropsWithRef,
|
||||
ElementType,
|
||||
forwardRef,
|
||||
ReactElement,
|
||||
Ref,
|
||||
} from 'react';
|
||||
import { forwardRef, Ref } from 'react';
|
||||
import { Button as RAButton } from 'react-aria-components';
|
||||
import { useResponsiveValue } from '../../hooks/useResponsiveValue';
|
||||
import type { IconButtonProps } from './types';
|
||||
import type { ButtonIconProps } from './types';
|
||||
|
||||
/** @public */
|
||||
export const IconButton = forwardRef(
|
||||
(props: IconButtonProps<typeof RAButton>, ref: Ref<HTMLButtonElement>) => {
|
||||
export const ButtonIcon = forwardRef(
|
||||
(props: ButtonIconProps, ref: Ref<HTMLButtonElement>) => {
|
||||
const {
|
||||
as,
|
||||
size = 'small',
|
||||
variant = 'primary',
|
||||
icon,
|
||||
@@ -39,33 +32,23 @@ export const IconButton = forwardRef(
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const Component = as || RAButton;
|
||||
const responsiveSize = useResponsiveValue(size);
|
||||
const responsiveVariant = useResponsiveValue(variant);
|
||||
|
||||
console.log(clsx('canon-Button', 'canon-ButtonIcon', className));
|
||||
|
||||
return (
|
||||
<Component
|
||||
className={clsx('canon-IconButton', className)}
|
||||
<RAButton
|
||||
className={clsx('canon-Button', 'canon-ButtonIcon', className)}
|
||||
data-variant={responsiveVariant}
|
||||
data-size={responsiveSize}
|
||||
ref={ref}
|
||||
{...rest}
|
||||
>
|
||||
<span
|
||||
className="canon-IconButtonIcon"
|
||||
aria-hidden="true"
|
||||
data-size={responsiveSize}
|
||||
>
|
||||
{icon}
|
||||
</span>
|
||||
</Component>
|
||||
{icon}
|
||||
</RAButton>
|
||||
);
|
||||
},
|
||||
) as {
|
||||
<TAs extends ElementType = typeof RAButton>(
|
||||
props: IconButtonProps<TAs> & { ref?: ComponentPropsWithRef<TAs>['ref'] },
|
||||
): ReactElement;
|
||||
displayName: string;
|
||||
};
|
||||
);
|
||||
|
||||
IconButton.displayName = 'IconButton';
|
||||
ButtonIcon.displayName = 'ButtonIcon';
|
||||
+1
-1
@@ -14,5 +14,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './IconButton';
|
||||
export * from './ButtonIcon';
|
||||
export * from './types';
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
.canon-ButtonIcon {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size='small'] {
|
||||
padding: 0;
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.canon-ButtonIcon[data-size='medium'] {
|
||||
padding: 0;
|
||||
width: 2.5rem;
|
||||
}
|
||||
+11
-18
@@ -15,26 +15,19 @@
|
||||
*/
|
||||
|
||||
import { Breakpoint } from '@backstage/canon';
|
||||
import { ElementType, ReactElement } from 'react';
|
||||
import { PolymorphicComponentProps } from '../../types';
|
||||
import { ReactElement } from 'react';
|
||||
import { ButtonProps as RAButtonProps } from 'react-aria-components';
|
||||
|
||||
/**
|
||||
* Properties for {@link IconButton}
|
||||
* Properties for {@link ButtonIcon}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type IconButtonProps<TAs extends ElementType> =
|
||||
PolymorphicComponentProps<
|
||||
TAs,
|
||||
{
|
||||
size?:
|
||||
| 'small'
|
||||
| 'medium'
|
||||
| Partial<Record<Breakpoint, 'small' | 'medium'>>;
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
icon?: ReactElement;
|
||||
}
|
||||
>;
|
||||
export interface ButtonIconProps extends RAButtonProps {
|
||||
size?: 'small' | 'medium' | Partial<Record<Breakpoint, 'small' | 'medium'>>;
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
icon?: ReactElement;
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { ButtonLink } from './ButtonLink';
|
||||
import { Flex } from '../Flex';
|
||||
import { Text } from '../Text';
|
||||
import { Icon } from '../Icon';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/ButtonLink',
|
||||
component: ButtonLink,
|
||||
argTypes: {
|
||||
size: {
|
||||
control: 'select',
|
||||
options: ['small', 'medium'],
|
||||
},
|
||||
variant: {
|
||||
control: 'select',
|
||||
options: ['primary', 'secondary'],
|
||||
},
|
||||
},
|
||||
} satisfies Meta<typeof ButtonLink>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
children: 'Button',
|
||||
},
|
||||
};
|
||||
|
||||
export const Variants: Story = {
|
||||
args: {
|
||||
children: 'Button',
|
||||
},
|
||||
parameters: {
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
render: () => (
|
||||
<Flex align="center">
|
||||
<ButtonLink iconStart={<Icon name="cloud" />} variant="primary">
|
||||
Button
|
||||
</ButtonLink>
|
||||
<ButtonLink iconStart={<Icon name="cloud" />} variant="secondary">
|
||||
Button
|
||||
</ButtonLink>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const Sizes: Story = {
|
||||
args: {
|
||||
children: 'Button',
|
||||
},
|
||||
render: () => (
|
||||
<Flex align="center">
|
||||
<ButtonLink size="small" iconStart={<Icon name="cloud" />}>
|
||||
Small
|
||||
</ButtonLink>
|
||||
<ButtonLink size="medium" iconStart={<Icon name="cloud" />}>
|
||||
Medium
|
||||
</ButtonLink>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const WithIcons: Story = {
|
||||
args: {
|
||||
children: 'Button',
|
||||
},
|
||||
render: args => (
|
||||
<Flex align="center">
|
||||
<ButtonLink {...args} iconStart={<Icon name="cloud" />} />
|
||||
<ButtonLink {...args} iconEnd={<Icon name="chevron-right" />} />
|
||||
<ButtonLink
|
||||
{...args}
|
||||
iconStart={<Icon name="cloud" />}
|
||||
iconEnd={<Icon name="chevron-right" />}
|
||||
/>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const FullWidth: Story = {
|
||||
args: {
|
||||
children: 'Button',
|
||||
},
|
||||
render: args => (
|
||||
<Flex direction="column" gap="4" style={{ width: '300px' }}>
|
||||
<ButtonLink {...args} iconStart={<Icon name="cloud" />} />
|
||||
<ButtonLink {...args} iconEnd={<Icon name="chevron-right" />} />
|
||||
<ButtonLink
|
||||
{...args}
|
||||
iconStart={<Icon name="cloud" />}
|
||||
iconEnd={<Icon name="chevron-right" />}
|
||||
/>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const Disabled: Story = {
|
||||
render: () => (
|
||||
<Flex direction="row" gap="4">
|
||||
<ButtonLink variant="primary" isDisabled>
|
||||
Primary
|
||||
</ButtonLink>
|
||||
<ButtonLink variant="secondary" isDisabled>
|
||||
Secondary
|
||||
</ButtonLink>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const Responsive: Story = {
|
||||
args: {
|
||||
children: 'Button',
|
||||
variant: {
|
||||
initial: 'primary',
|
||||
sm: 'secondary',
|
||||
},
|
||||
size: {
|
||||
xs: 'small',
|
||||
sm: 'medium',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const variants = ['primary', 'secondary'] as const;
|
||||
const sizes = ['small', 'medium'] as const;
|
||||
|
||||
export const Playground: Story = {
|
||||
args: {
|
||||
children: 'Button',
|
||||
},
|
||||
render: () => (
|
||||
<Flex direction="column">
|
||||
{variants.map(variant => (
|
||||
<Flex direction="column" key={variant}>
|
||||
<Text>{variant}</Text>
|
||||
{sizes.map(size => (
|
||||
<Flex align="center" key={size}>
|
||||
<ButtonLink variant={variant} size={size}>
|
||||
Button
|
||||
</ButtonLink>
|
||||
<ButtonLink
|
||||
iconStart={<Icon name="cloud" />}
|
||||
variant={variant}
|
||||
size={size}
|
||||
>
|
||||
Button
|
||||
</ButtonLink>
|
||||
<ButtonLink
|
||||
iconEnd={<Icon name="chevron-right" />}
|
||||
variant={variant}
|
||||
size={size}
|
||||
>
|
||||
Button
|
||||
</ButtonLink>
|
||||
<ButtonLink
|
||||
iconStart={<Icon name="cloud" />}
|
||||
iconEnd={<Icon name="chevron-right" />}
|
||||
style={{ width: '200px' }}
|
||||
variant={variant}
|
||||
size={size}
|
||||
>
|
||||
Button
|
||||
</ButtonLink>
|
||||
<ButtonLink variant={variant} size={size} isDisabled>
|
||||
Button
|
||||
</ButtonLink>
|
||||
<ButtonLink
|
||||
iconStart={<Icon name="cloud" />}
|
||||
variant={variant}
|
||||
size={size}
|
||||
isDisabled
|
||||
>
|
||||
Button
|
||||
</ButtonLink>
|
||||
<ButtonLink
|
||||
iconEnd={<Icon name="chevron-right" />}
|
||||
variant={variant}
|
||||
size={size}
|
||||
isDisabled
|
||||
>
|
||||
Button
|
||||
</ButtonLink>
|
||||
</Flex>
|
||||
))}
|
||||
</Flex>
|
||||
))}
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import clsx from 'clsx';
|
||||
import { forwardRef, Ref } from 'react';
|
||||
import { Link as RALink } from 'react-aria-components';
|
||||
import { useResponsiveValue } from '../../hooks/useResponsiveValue';
|
||||
import type { ButtonLinkProps } from './types';
|
||||
|
||||
/** @public */
|
||||
export const ButtonLink = forwardRef(
|
||||
(props: ButtonLinkProps, ref: Ref<HTMLAnchorElement>) => {
|
||||
const {
|
||||
size = 'small',
|
||||
variant = 'primary',
|
||||
iconStart,
|
||||
iconEnd,
|
||||
children,
|
||||
className,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const responsiveSize = useResponsiveValue(size);
|
||||
const responsiveVariant = useResponsiveValue(variant);
|
||||
|
||||
return (
|
||||
<RALink
|
||||
className={clsx('canon-Button', 'canon-ButtonLink', className)}
|
||||
data-variant={responsiveVariant}
|
||||
data-size={responsiveSize}
|
||||
ref={ref}
|
||||
{...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>
|
||||
)}
|
||||
</RALink>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
ButtonLink.displayName = 'ButtonLink';
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './ButtonLink';
|
||||
export * from './types';
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Breakpoint } from '@backstage/canon';
|
||||
import { ReactElement, ReactNode } from 'react';
|
||||
import { LinkProps as RALinkProps } from 'react-aria-components';
|
||||
|
||||
/**
|
||||
* Properties for {@link ButtonLink}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface ButtonLinkProps extends RALinkProps {
|
||||
size?: 'small' | 'medium' | Partial<Record<Breakpoint, 'small' | 'medium'>>;
|
||||
variant?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
iconStart?: ReactElement;
|
||||
iconEnd?: ReactElement;
|
||||
children?: ReactNode;
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
import { forwardRef } from 'react';
|
||||
import { Text } from '../../Text';
|
||||
import { DataTablePaginationProps } from './types';
|
||||
import { IconButton } from '../../IconButton';
|
||||
import { ButtonIcon } from '../../ButtonIcon';
|
||||
import clsx from 'clsx';
|
||||
import { Select } from '../../Select';
|
||||
import { useDataTable } from '../Root/DataTableRoot';
|
||||
@@ -71,14 +71,14 @@ const DataTablePagination = forwardRef(
|
||||
</div>
|
||||
<div className="canon-DataTablePagination--right">
|
||||
<Text variant="body">{`${fromCount} - ${toCount} of ${rowCount}`}</Text>
|
||||
<IconButton
|
||||
<ButtonIcon
|
||||
variant="secondary"
|
||||
size="small"
|
||||
onClick={() => table?.previousPage()}
|
||||
isDisabled={!table?.getCanPreviousPage()}
|
||||
icon={<Icon name="chevron-left" />}
|
||||
/>
|
||||
<IconButton
|
||||
<ButtonIcon
|
||||
variant="secondary"
|
||||
size="small"
|
||||
onClick={() => table?.nextPage()}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
.canon-IconButton {
|
||||
border: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
user-select: none;
|
||||
font-family: var(--canon-font-regular);
|
||||
font-weight: var(--canon-font-weight-bold);
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
border-radius: var(--canon-radius-2);
|
||||
gap: var(--canon-space-1_5);
|
||||
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
.canon-IconButton[data-variant='primary'] {
|
||||
background-color: var(--canon-bg-solid);
|
||||
color: var(--canon-fg-solid);
|
||||
transition: background-color 150ms ease, box-shadow 150ms ease;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--canon-bg-solid-hover);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--canon-bg-solid-pressed);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid var(--canon-ring);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: var(--canon-bg-solid-disabled);
|
||||
color: var(--canon-fg-solid-disabled);
|
||||
}
|
||||
}
|
||||
|
||||
.canon-IconButton[data-variant='secondary'] {
|
||||
background-color: var(--canon-bg-surface-1);
|
||||
box-shadow: inset 0 0 0 1px var(--canon-border);
|
||||
color: var(--canon-fg-primary);
|
||||
transition: box-shadow 150ms ease;
|
||||
|
||||
&:hover {
|
||||
box-shadow: inset 0 0 0 1px var(--canon-border-hover);
|
||||
}
|
||||
|
||||
&:active {
|
||||
box-shadow: inset 0 0 0 1px var(--canon-border-pressed);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
transition: none;
|
||||
box-shadow: inset 0 0 0 2px var(--canon-ring);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
box-shadow: inset 0 0 0 1px var(--canon-border-disabled);
|
||||
color: var(--canon-fg-disabled);
|
||||
}
|
||||
}
|
||||
|
||||
.canon-IconButton[data-size='medium'] {
|
||||
font-size: var(--canon-font-size-4);
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.canon-IconButton[data-size='small'] {
|
||||
font-size: var(--canon-font-size-3);
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
.canon-IconButtonIcon[data-size='small'],
|
||||
.canon-IconButtonIcon[data-size='small'] svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.canon-IconButtonIcon[data-size='medium'],
|
||||
.canon-IconButtonIcon[data-size='medium'] svg {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
@import '../components/Avatar/Avatar.styles.css';
|
||||
@import '../components/Box/styles.css';
|
||||
@import '../components/Button/styles.css';
|
||||
@import '../components/ButtonIcon/styles.css';
|
||||
@import '../components/Checkbox/styles.css';
|
||||
@import '../components/Collapsible/Collapsible.styles.css';
|
||||
@import '../components/Container/styles.css';
|
||||
@@ -27,7 +28,6 @@
|
||||
@import '../components/Grid/styles.css';
|
||||
@import '../components/Heading/styles.css';
|
||||
@import '../components/Icon/styles.css';
|
||||
@import '../components/IconButton/styles.css';
|
||||
@import '../components/Link/styles.css';
|
||||
@import '../components/Menu/Menu.styles.css';
|
||||
@import '../components/Table/styles.css';
|
||||
|
||||
@@ -38,7 +38,7 @@ export * from './components/Collapsible';
|
||||
export * from './components/DataTable';
|
||||
export * from './components/FieldLabel';
|
||||
export * from './components/Icon';
|
||||
export * from './components/IconButton';
|
||||
export * from './components/ButtonIcon';
|
||||
export * from './components/Checkbox';
|
||||
export * from './components/Table';
|
||||
export * from './components/Tabs';
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ComponentPropsWithoutRef, ElementType } from 'react';
|
||||
|
||||
/** @public */
|
||||
export type AsProps =
|
||||
| 'div'
|
||||
@@ -133,19 +131,3 @@ export interface UtilityProps extends SpaceProps {
|
||||
justifyContent?: Responsive<JustifyContent>;
|
||||
rowSpan?: Responsive<Columns | 'full'>;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export type As<TAs extends ElementType> = {
|
||||
as?: TAs;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is the first reusable type utility we built
|
||||
* @public
|
||||
*/
|
||||
export type PolymorphicComponentProps<
|
||||
TAs extends ElementType,
|
||||
TProps = {},
|
||||
> = TProps &
|
||||
As<TAs> &
|
||||
Omit<ComponentPropsWithoutRef<TAs>, keyof (As<TAs> & TProps)>;
|
||||
|
||||
Reference in New Issue
Block a user