diff --git a/.changeset/polite-symbols-act.md b/.changeset/polite-symbols-act.md new file mode 100644 index 0000000000..73c7950d80 --- /dev/null +++ b/.changeset/polite-symbols-act.md @@ -0,0 +1,15 @@ +--- +'@backstage/ui': minor +--- + +**BREAKING (CSS)**: Changed CSS selectors for `ButtonIcon` and `ButtonLink` components. Custom styles targeting `.bui-Button` to style these components must be updated to use `.bui-ButtonIcon` or `.bui-ButtonLink` respectively. + +```diff +-/* This no longer styles ButtonIcon or ButtonLink */ +-.bui-Button[data-variant="primary"] { ... } ++/* Use component-specific selectors */ ++.bui-ButtonIcon[data-variant="primary"] { ... } ++.bui-ButtonLink[data-variant="primary"] { ... } +``` + +Affected components: ButtonIcon, ButtonLink diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md index 6c1ea7a8a2..fdd781c80a 100644 --- a/packages/ui/report.api.md +++ b/packages/ui/report.api.md @@ -3,7 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { ButtonProps as ButtonProps_2 } from 'react-aria-components'; +import type { ButtonProps as ButtonProps_2 } from 'react-aria-components'; import { CellProps as CellProps_2 } from 'react-aria-components'; import { CheckboxProps as CheckboxProps_2 } from 'react-aria-components'; import { ColumnProps as ColumnProps_2 } from 'react-aria-components'; @@ -22,7 +22,7 @@ import { ForwardRefExoticComponent } from 'react'; import type { HeadingProps } from 'react-aria-components'; import { HTMLAttributes } from 'react'; import { JSX as JSX_2 } from 'react/jsx-runtime'; -import { LinkProps as LinkProps_2 } from 'react-aria-components'; +import type { LinkProps as LinkProps_2 } from 'react-aria-components'; import type { ListBoxItemProps } from 'react-aria-components'; import type { ListBoxProps } from 'react-aria-components'; import type { MenuItemProps as MenuItemProps_2 } from 'react-aria-components'; @@ -33,7 +33,7 @@ import type { ModalOverlayProps } from 'react-aria-components'; import { PopoverProps as PopoverProps_2 } from 'react-aria-components'; import type { RadioGroupProps as RadioGroupProps_2 } from 'react-aria-components'; import type { RadioProps as RadioProps_2 } from 'react-aria-components'; -import { ReactElement } from 'react'; +import type { ReactElement } from 'react'; import { ReactNode } from 'react'; import { RefAttributes } from 'react'; import { RowProps } from 'react-aria-components'; @@ -290,28 +290,48 @@ export const ButtonIcon: ForwardRefExoticComponent< // @public export const ButtonIconDefinition: { + readonly styles: { + readonly [key: string]: string; + }; readonly classNames: { readonly root: 'bui-ButtonIcon'; readonly content: 'bui-ButtonIconContent'; readonly spinner: 'bui-ButtonIconSpinner'; }; + readonly surface: 'leaf'; + readonly propDefs: { + readonly size: { + readonly dataAttribute: true; + readonly default: 'small'; + }; + readonly variant: { + readonly dataAttribute: true; + readonly default: 'primary'; + }; + readonly loading: { + readonly dataAttribute: true; + }; + readonly icon: {}; + readonly onSurface: {}; + readonly className: {}; + readonly style: {}; + }; +}; + +// @public (undocumented) +export type ButtonIconOwnProps = LeafSurfaceProps & { + size?: Responsive<'small' | 'medium'>; + variant?: Responsive<'primary' | 'secondary' | 'tertiary'>; + icon?: ReactElement; + loading?: boolean; + className?: string; + style?: CSSProperties; }; // @public -export interface ButtonIconProps extends ButtonProps_2 { - // (undocumented) - icon?: ReactElement; - // (undocumented) - loading?: boolean; - // (undocumented) - size?: 'small' | 'medium' | Partial>; - // (undocumented) - variant?: - | 'primary' - | 'secondary' - | 'tertiary' - | Partial>; -} +export interface ButtonIconProps + extends Omit, + ButtonIconOwnProps {} // @public (undocumented) export const ButtonLink: ForwardRefExoticComponent< @@ -320,37 +340,55 @@ export const ButtonLink: ForwardRefExoticComponent< // @public export const ButtonLinkDefinition: { + readonly styles: { + readonly [key: string]: string; + }; readonly classNames: { readonly root: 'bui-ButtonLink'; + readonly content: 'bui-ButtonLinkContent'; + }; + readonly surface: 'leaf'; + readonly propDefs: { + readonly size: { + readonly dataAttribute: true; + readonly default: 'small'; + }; + readonly variant: { + readonly dataAttribute: true; + readonly default: 'primary'; + }; + readonly iconStart: {}; + readonly iconEnd: {}; + readonly onSurface: {}; + readonly children: {}; + readonly className: {}; + readonly style: {}; }; }; -// @public -export interface ButtonLinkProps extends LinkProps_2 { - // (undocumented) - children?: ReactNode; - // (undocumented) - iconEnd?: ReactElement; - // (undocumented) +// @public (undocumented) +export type ButtonLinkOwnProps = LeafSurfaceProps & { + size?: Responsive<'small' | 'medium'>; + variant?: Responsive<'primary' | 'secondary' | 'tertiary'>; iconStart?: ReactElement; - // (undocumented) - size?: 'small' | 'medium' | Partial>; - // (undocumented) - variant?: - | 'primary' - | 'secondary' - | 'tertiary' - | Partial>; -} + iconEnd?: ReactElement; + children?: ReactNode; + className?: string; + style?: CSSProperties; +}; // @public -export type ButtonOwnProps = { +export interface ButtonLinkProps + extends Omit, + ButtonLinkOwnProps {} + +// @public (undocumented) +export type ButtonOwnProps = LeafSurfaceProps & { size?: Responsive<'small' | 'medium' | 'large'>; variant?: Responsive<'primary' | 'secondary' | 'tertiary'>; iconStart?: ReactElement; iconEnd?: ReactElement; loading?: boolean; - onSurface?: Responsive; children?: ReactNode; className?: string; style?: CSSProperties; @@ -583,6 +621,12 @@ export interface ContainerProps { style?: React.CSSProperties; } +// @public (undocumented) +export interface ContainerSurfaceProps { + // (undocumented) + surface?: Responsive; +} + // @public (undocumented) export interface CursorParams { // (undocumented) @@ -981,6 +1025,12 @@ export type JustifyContent = | 'around' | 'between'; +// @public (undocumented) +export interface LeafSurfaceProps { + // (undocumented) + onSurface?: Responsive; +} + // @public (undocumented) export const Link: ForwardRefExoticComponent< LinkProps & RefAttributes diff --git a/packages/ui/src/components/ButtonIcon/ButtonIcon.module.css b/packages/ui/src/components/ButtonIcon/ButtonIcon.module.css index d26df27ec7..da1b053701 100644 --- a/packages/ui/src/components/ButtonIcon/ButtonIcon.module.css +++ b/packages/ui/src/components/ButtonIcon/ButtonIcon.module.css @@ -18,17 +18,205 @@ @layer components { .bui-ButtonIcon { + --loading-duration: 200ms; + --bg: transparent; + --bg-hover: transparent; + --bg-active: transparent; + --fg: inherit; + + position: relative; + display: inline-flex; align-items: center; justify-content: center; + border: none; + user-select: none; + padding: 0; + cursor: pointer; + border-radius: var(--bui-radius-2); + flex-shrink: 0; + transition: background-color var(--loading-duration) ease-out, + box-shadow var(--loading-duration) ease-out; + + /* Apply variables */ + color: var(--fg); + background-color: var(--bg); + + &:hover { + background-color: var(--bg-hover); + transition: background-color 150ms ease; + } + + &:active { + background-color: var(--bg-active); + } + + &[data-disabled='true'] { + cursor: not-allowed; + } + + &[data-loading='true'] { + cursor: wait; + } + } + + .bui-ButtonIcon[data-variant='primary'] { + --bg: var(--bui-bg-solid); + --bg-hover: var(--bui-bg-solid-hover); + --bg-active: var(--bui-bg-solid-pressed); + --fg: var(--bui-fg-solid); + + &[data-disabled='true'], + &[data-loading='true'] { + --bg: var(--bui-bg-solid-disabled); + --bg-hover: var(--bui-bg-solid-disabled); + --bg-active: var(--bui-bg-solid-disabled); + --fg: var(--bui-fg-solid-disabled); + } + + &:focus-visible { + outline: 2px solid var(--bui-ring); + outline-offset: 2px; + } + } + + .bui-ButtonIcon[data-variant='secondary'] { + --bg: var(--bui-bg-neutral-on-surface-0); + --bg-hover: var(--bui-bg-neutral-on-surface-0-hover); + --bg-active: var(--bui-bg-neutral-on-surface-0-pressed); + --fg: var(--bui-fg-primary); + + &[data-on-surface='1'] { + --bg: var(--bui-bg-neutral-on-surface-1); + --bg-hover: var(--bui-bg-neutral-on-surface-1-hover); + --bg-active: var(--bui-bg-neutral-on-surface-1-pressed); + } + + &[data-on-surface='2'] { + --bg: var(--bui-bg-neutral-on-surface-2); + --bg-hover: var(--bui-bg-neutral-on-surface-2-hover); + --bg-active: var(--bui-bg-neutral-on-surface-2-pressed); + } + + &[data-on-surface='3'] { + --bg: var(--bui-bg-neutral-on-surface-3); + --bg-hover: var(--bui-bg-neutral-on-surface-3-hover); + --bg-active: var(--bui-bg-neutral-on-surface-3-pressed); + } + + &[data-disabled='true'], + &[data-loading='true'] { + --bg-hover: var(--bg); + --bg-active: var(--bg); + --fg: var(--bui-fg-disabled); + } + + &:focus-visible { + outline: none; + transition: none; + box-shadow: inset 0 0 0 2px var(--bui-ring); + } + } + + .bui-ButtonIcon[data-variant='tertiary'] { + --bg-hover: var(--bui-bg-neutral-on-surface-0-hover); + --bg-active: var(--bui-bg-neutral-on-surface-0-pressed); + --fg: var(--bui-fg-primary); + + &[data-on-surface='1'] { + --bg-hover: var(--bui-bg-neutral-on-surface-1-hover); + --bg-active: var(--bui-bg-neutral-on-surface-1-pressed); + } + + &[data-on-surface='2'] { + --bg-hover: var(--bui-bg-neutral-on-surface-2-hover); + --bg-active: var(--bui-bg-neutral-on-surface-2-pressed); + } + + &[data-on-surface='3'] { + --bg-hover: var(--bui-bg-neutral-on-surface-3-hover); + --bg-active: var(--bui-bg-neutral-on-surface-3-pressed); + } + + &[data-disabled='true'], + &[data-loading='true'] { + --bg-hover: var(--bg); + --bg-active: var(--bg); + --fg: var(--bui-fg-disabled); + } + + &:focus-visible { + outline: none; + transition: none; + box-shadow: inset 0 0 0 2px var(--bui-ring); + } } .bui-ButtonIcon[data-size='small'] { - padding: 0; width: 2rem; + height: 2rem; + + svg { + width: 1rem; + height: 1rem; + } } .bui-ButtonIcon[data-size='medium'] { - padding: 0; width: 2.5rem; + height: 2.5rem; + + svg { + width: 1.25rem; + height: 1.25rem; + } + } + + .bui-ButtonIconContent { + display: inline-flex; + align-items: center; + justify-content: center; + height: 100%; + width: 100%; + transition: opacity var(--loading-duration) ease-out; + + .bui-ButtonIcon[data-loading='true'] & { + opacity: 0; + } + } + + .bui-ButtonIconSpinner { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + display: flex; + opacity: 0; + transition: opacity var(--loading-duration) ease-in; + + .bui-ButtonIcon[data-loading='true'] & { + opacity: 1; + } + + & svg { + animation: bui-spin 1s linear infinite; + } + } + + @media (prefers-reduced-motion: reduce) { + .bui-ButtonIcon { + transition-duration: 50ms; + } + + .bui-ButtonIconContent { + transition-duration: 50ms; + } + + .bui-ButtonIconSpinner { + transition-duration: 50ms; + } + + .bui-ButtonIconSpinner svg { + animation: none; + } } } diff --git a/packages/ui/src/components/ButtonIcon/ButtonIcon.tsx b/packages/ui/src/components/ButtonIcon/ButtonIcon.tsx index 9bbeca9d5b..3e9953fafa 100644 --- a/packages/ui/src/components/ButtonIcon/ButtonIcon.tsx +++ b/packages/ui/src/components/ButtonIcon/ButtonIcon.tsx @@ -14,71 +14,39 @@ * limitations under the License. */ -import clsx from 'clsx'; import { forwardRef, Ref } from 'react'; import { Button as RAButton, ProgressBar } from 'react-aria-components'; import { RiLoader4Line } from '@remixicon/react'; import type { ButtonIconProps } from './types'; -import { useStyles } from '../../hooks/useStyles'; -import { ButtonDefinition } from '../Button/definition'; +import { useDefinition } from '../../hooks/useDefinition'; import { ButtonIconDefinition } from './definition'; -import stylesButtonIcon from './ButtonIcon.module.css'; -import stylesButton from '../Button/Button.module.css'; /** @public */ export const ButtonIcon = forwardRef( (props: ButtonIconProps, ref: Ref) => { - const { classNames, dataAttributes, cleanedProps } = useStyles( - ButtonDefinition, - { - size: 'small', - variant: 'primary', - ...props, - }, + const { ownProps, restProps, dataAttributes } = useDefinition( + ButtonIconDefinition, + props, ); - - const { classNames: classNamesButtonIcon } = - useStyles(ButtonIconDefinition); - - const { className, icon, loading, ...rest } = cleanedProps; + const { classes, icon, loading } = ownProps; return ( {({ isPending }) => ( <> - - {icon} - + {icon} {isPending && ( diff --git a/packages/ui/src/components/ButtonIcon/definition.ts b/packages/ui/src/components/ButtonIcon/definition.ts index 48d0a558ab..3befeef7c1 100644 --- a/packages/ui/src/components/ButtonIcon/definition.ts +++ b/packages/ui/src/components/ButtonIcon/definition.ts @@ -14,16 +14,29 @@ * limitations under the License. */ -import type { ComponentDefinition } from '../../types'; +import { defineComponent } from '../../hooks/useDefinition'; +import type { ButtonIconOwnProps } from './types'; +import styles from './ButtonIcon.module.css'; /** * Component definition for ButtonIcon * @public */ -export const ButtonIconDefinition = { +export const ButtonIconDefinition = defineComponent()({ + styles, classNames: { root: 'bui-ButtonIcon', content: 'bui-ButtonIconContent', spinner: 'bui-ButtonIconSpinner', }, -} as const satisfies ComponentDefinition; + surface: 'leaf', + propDefs: { + size: { dataAttribute: true, default: 'small' }, + variant: { dataAttribute: true, default: 'primary' }, + loading: { dataAttribute: true }, + icon: {}, + onSurface: {}, + className: {}, + style: {}, + }, +}); diff --git a/packages/ui/src/components/ButtonIcon/types.ts b/packages/ui/src/components/ButtonIcon/types.ts index 6af3d12361..750e0db5e9 100644 --- a/packages/ui/src/components/ButtonIcon/types.ts +++ b/packages/ui/src/components/ButtonIcon/types.ts @@ -14,22 +14,25 @@ * limitations under the License. */ -import { Breakpoint } from '../..'; -import { ReactElement } from 'react'; -import { ButtonProps as RAButtonProps } from 'react-aria-components'; +import type { ReactElement, CSSProperties } from 'react'; +import type { ButtonProps as RAButtonProps } from 'react-aria-components'; +import type { LeafSurfaceProps, Responsive } from '../../types'; + +/** @public */ +export type ButtonIconOwnProps = LeafSurfaceProps & { + size?: Responsive<'small' | 'medium'>; + variant?: Responsive<'primary' | 'secondary' | 'tertiary'>; + icon?: ReactElement; + loading?: boolean; + className?: string; + style?: CSSProperties; +}; /** * Properties for {@link ButtonIcon} * * @public */ -export interface ButtonIconProps extends RAButtonProps { - size?: 'small' | 'medium' | Partial>; - variant?: - | 'primary' - | 'secondary' - | 'tertiary' - | Partial>; - icon?: ReactElement; - loading?: boolean; -} +export interface ButtonIconProps + extends Omit, + ButtonIconOwnProps {} diff --git a/packages/ui/src/components/ButtonLink/ButtonLink.module.css b/packages/ui/src/components/ButtonLink/ButtonLink.module.css new file mode 100644 index 0000000000..be539123a0 --- /dev/null +++ b/packages/ui/src/components/ButtonLink/ButtonLink.module.css @@ -0,0 +1,182 @@ +/* + * Copyright 2026 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. + */ + +@layer tokens, base, components, utilities; + +@layer components { + .bui-ButtonLink { + --bg: transparent; + --bg-hover: transparent; + --bg-active: transparent; + --fg: inherit; + + position: relative; + display: inline-flex; + border: none; + user-select: none; + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-bold); + padding: 0; + cursor: pointer; + border-radius: var(--bui-radius-2); + flex-shrink: 0; + text-decoration: none; + transition: background-color 200ms ease-out, box-shadow 200ms ease-out; + + /* Apply variables */ + color: var(--fg); + background-color: var(--bg); + + &:hover { + background-color: var(--bg-hover); + transition: background-color 150ms ease; + } + + &:active { + background-color: var(--bg-active); + } + + &[data-disabled='true'] { + cursor: not-allowed; + } + } + + .bui-ButtonLink[data-variant='primary'] { + --bg: var(--bui-bg-solid); + --bg-hover: var(--bui-bg-solid-hover); + --bg-active: var(--bui-bg-solid-pressed); + --fg: var(--bui-fg-solid); + + &[data-disabled='true'] { + --bg: var(--bui-bg-solid-disabled); + --bg-hover: var(--bui-bg-solid-disabled); + --bg-active: var(--bui-bg-solid-disabled); + --fg: var(--bui-fg-solid-disabled); + } + + &:focus-visible { + outline: 2px solid var(--bui-ring); + outline-offset: 2px; + } + } + + .bui-ButtonLink[data-variant='secondary'] { + --bg: var(--bui-bg-neutral-on-surface-0); + --bg-hover: var(--bui-bg-neutral-on-surface-0-hover); + --bg-active: var(--bui-bg-neutral-on-surface-0-pressed); + --fg: var(--bui-fg-primary); + + &[data-on-surface='1'] { + --bg: var(--bui-bg-neutral-on-surface-1); + --bg-hover: var(--bui-bg-neutral-on-surface-1-hover); + --bg-active: var(--bui-bg-neutral-on-surface-1-pressed); + } + + &[data-on-surface='2'] { + --bg: var(--bui-bg-neutral-on-surface-2); + --bg-hover: var(--bui-bg-neutral-on-surface-2-hover); + --bg-active: var(--bui-bg-neutral-on-surface-2-pressed); + } + + &[data-on-surface='3'] { + --bg: var(--bui-bg-neutral-on-surface-3); + --bg-hover: var(--bui-bg-neutral-on-surface-3-hover); + --bg-active: var(--bui-bg-neutral-on-surface-3-pressed); + } + + &[data-disabled='true'] { + --bg-hover: var(--bg); + --bg-active: var(--bg); + --fg: var(--bui-fg-disabled); + } + + &:focus-visible { + outline: none; + transition: none; + box-shadow: inset 0 0 0 2px var(--bui-ring); + } + } + + .bui-ButtonLink[data-variant='tertiary'] { + --bg-hover: var(--bui-bg-neutral-on-surface-0-hover); + --bg-active: var(--bui-bg-neutral-on-surface-0-pressed); + --fg: var(--bui-fg-primary); + + &[data-on-surface='1'] { + --bg-hover: var(--bui-bg-neutral-on-surface-1-hover); + --bg-active: var(--bui-bg-neutral-on-surface-1-pressed); + } + + &[data-on-surface='2'] { + --bg-hover: var(--bui-bg-neutral-on-surface-2-hover); + --bg-active: var(--bui-bg-neutral-on-surface-2-pressed); + } + + &[data-on-surface='3'] { + --bg-hover: var(--bui-bg-neutral-on-surface-3-hover); + --bg-active: var(--bui-bg-neutral-on-surface-3-pressed); + } + + &[data-disabled='true'] { + --bg-hover: var(--bg); + --bg-active: var(--bg); + --fg: var(--bui-fg-disabled); + } + + &:focus-visible { + outline: none; + transition: none; + box-shadow: inset 0 0 0 2px var(--bui-ring); + } + } + + .bui-ButtonLink[data-size='small'] { + font-size: var(--bui-font-size-3); + padding: 0 var(--bui-space-2); + height: 2rem; + + svg { + width: 1rem; + height: 1rem; + } + } + + .bui-ButtonLink[data-size='medium'] { + font-size: var(--bui-font-size-4); + padding: 0 var(--bui-space-3); + height: 2.5rem; + + svg { + width: 1.25rem; + height: 1.25rem; + } + } + + .bui-ButtonLinkContent { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--bui-space-1_5); + height: 100%; + width: 100%; + } + + @media (prefers-reduced-motion: reduce) { + .bui-ButtonLink { + transition-duration: 50ms; + } + } +} diff --git a/packages/ui/src/components/ButtonLink/ButtonLink.tsx b/packages/ui/src/components/ButtonLink/ButtonLink.tsx index db3c95ee54..1f6e375062 100644 --- a/packages/ui/src/components/ButtonLink/ButtonLink.tsx +++ b/packages/ui/src/components/ButtonLink/ButtonLink.tsx @@ -14,55 +14,35 @@ * limitations under the License. */ -import clsx from 'clsx'; import { forwardRef, Ref } from 'react'; import { Link as RALink, RouterProvider } from 'react-aria-components'; import { useNavigate, useHref } from 'react-router-dom'; import type { ButtonLinkProps } from './types'; -import { useStyles } from '../../hooks/useStyles'; -import { ButtonDefinition } from '../Button/definition'; +import { useDefinition } from '../../hooks/useDefinition'; import { ButtonLinkDefinition } from './definition'; import { isExternalLink } from '../../utils/isExternalLink'; -import stylesButton from '../Button/Button.module.css'; /** @public */ export const ButtonLink = forwardRef( (props: ButtonLinkProps, ref: Ref) => { const navigate = useNavigate(); - const { classNames, dataAttributes, cleanedProps } = useStyles( - ButtonDefinition, - { - size: 'small', - variant: 'primary', - ...props, - }, + const { ownProps, restProps, dataAttributes } = useDefinition( + ButtonLinkDefinition, + props, ); + const { classes, iconStart, iconEnd, children } = ownProps; - const { classNames: classNamesButtonLink } = - useStyles(ButtonLinkDefinition); - - const { children, className, iconStart, iconEnd, href, ...rest } = - cleanedProps; - - const isExternal = isExternalLink(href); + const isExternal = isExternalLink(restProps.href); const linkButton = ( - + {iconStart} {children} {iconEnd} diff --git a/packages/ui/src/components/ButtonLink/definition.ts b/packages/ui/src/components/ButtonLink/definition.ts index daf3fae1ea..e6a80e09b3 100644 --- a/packages/ui/src/components/ButtonLink/definition.ts +++ b/packages/ui/src/components/ButtonLink/definition.ts @@ -14,14 +14,29 @@ * limitations under the License. */ -import type { ComponentDefinition } from '../../types'; +import { defineComponent } from '../../hooks/useDefinition'; +import type { ButtonLinkOwnProps } from './types'; +import styles from './ButtonLink.module.css'; /** * Component definition for ButtonLink * @public */ -export const ButtonLinkDefinition = { +export const ButtonLinkDefinition = defineComponent()({ + styles, classNames: { root: 'bui-ButtonLink', + content: 'bui-ButtonLinkContent', }, -} as const satisfies ComponentDefinition; + surface: 'leaf', + propDefs: { + size: { dataAttribute: true, default: 'small' }, + variant: { dataAttribute: true, default: 'primary' }, + iconStart: {}, + iconEnd: {}, + onSurface: {}, + children: {}, + className: {}, + style: {}, + }, +}); diff --git a/packages/ui/src/components/ButtonLink/types.ts b/packages/ui/src/components/ButtonLink/types.ts index e6b0556349..0379d72adb 100644 --- a/packages/ui/src/components/ButtonLink/types.ts +++ b/packages/ui/src/components/ButtonLink/types.ts @@ -14,23 +14,26 @@ * limitations under the License. */ -import { Breakpoint } from '../..'; -import { ReactElement, ReactNode } from 'react'; -import { LinkProps as RALinkProps } from 'react-aria-components'; +import type { ReactElement, ReactNode, CSSProperties } from 'react'; +import type { LinkProps as RALinkProps } from 'react-aria-components'; +import type { LeafSurfaceProps, Responsive } from '../../types'; + +/** @public */ +export type ButtonLinkOwnProps = LeafSurfaceProps & { + size?: Responsive<'small' | 'medium'>; + variant?: Responsive<'primary' | 'secondary' | 'tertiary'>; + iconStart?: ReactElement; + iconEnd?: ReactElement; + children?: ReactNode; + className?: string; + style?: CSSProperties; +}; /** * Properties for {@link ButtonLink} * * @public */ -export interface ButtonLinkProps extends RALinkProps { - size?: 'small' | 'medium' | Partial>; - variant?: - | 'primary' - | 'secondary' - | 'tertiary' - | Partial>; - iconStart?: ReactElement; - iconEnd?: ReactElement; - children?: ReactNode; -} +export interface ButtonLinkProps + extends Omit, + ButtonLinkOwnProps {}