♻️(frontend) simplify button primitive

In object-oriented terms, the previous implementation violated the Liskov
Substitution Principle. Props between these two components (Button and Link)
were not substitutable.

This led to TypeScript errors and increased overall complexity without
significant DX gains. To address this, the LinkButton has been extracted
into a dedicated component.
This commit is contained in:
lebaudantoine
2024-10-09 16:14:59 +02:00
committed by aleb_the_flash
parent 211ba332dc
commit 1875a394c6
4 changed files with 27 additions and 19 deletions

View File

@@ -1,12 +1,12 @@
import { Button } from '@/primitives'
import { css } from '@/styled-system/css'
import { RiExternalLinkLine } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import { LinkButton } from '@/primitives'
export const Feedback = () => {
const { t } = useTranslation()
return (
<Button
<LinkButton
href="https://grist.incubateur.net/o/docs/forms/1YrfNP1QSSy8p2gCxMFnSf/4"
variant="success"
target="_blank"
@@ -20,6 +20,6 @@ export const Feedback = () => {
className={css({ marginLeft: 0.5 })}
aria-hidden="true"
/>
</Button>
</LinkButton>
)
}

View File

@@ -1,8 +1,6 @@
import {
Button as RACButton,
type ButtonProps as RACButtonsProps,
Link,
LinkProps,
} from 'react-aria-components'
import { type RecipeVariantProps } from '@/styled-system/css'
import { buttonRecipe, type ButtonRecipe } from './buttonRecipe'
@@ -12,25 +10,12 @@ export type ButtonProps = RecipeVariantProps<ButtonRecipe> &
RACButtonsProps &
TooltipWrapperProps
type LinkButtonProps = RecipeVariantProps<ButtonRecipe> &
LinkProps &
TooltipWrapperProps
type ButtonOrLinkProps = ButtonProps | LinkButtonProps
export const Button = ({
tooltip,
tooltipType = 'instant',
...props
}: ButtonOrLinkProps) => {
}: ButtonProps) => {
const [variantProps, componentProps] = buttonRecipe.splitVariantProps(props)
if ((props as LinkButtonProps).href !== undefined) {
return (
<TooltipWrapper tooltip={tooltip} tooltipType={tooltipType}>
<Link className={buttonRecipe(variantProps)} {...componentProps} />
</TooltipWrapper>
)
}
return (
<TooltipWrapper tooltip={tooltip} tooltipType={tooltipType}>

View File

@@ -0,0 +1,22 @@
import { Link, LinkProps } from 'react-aria-components'
import { type RecipeVariantProps } from '@/styled-system/css'
import { buttonRecipe, type ButtonRecipe } from './buttonRecipe'
import { TooltipWrapper, type TooltipWrapperProps } from './TooltipWrapper'
type LinkButtonProps = RecipeVariantProps<ButtonRecipe> &
LinkProps &
TooltipWrapperProps
export const LinkButton = ({
tooltip,
tooltipType = 'instant',
...props
}: LinkButtonProps) => {
const [variantProps, componentProps] = buttonRecipe.splitVariantProps(props)
return (
<TooltipWrapper tooltip={tooltip} tooltipType={tooltipType}>
<Link className={buttonRecipe(variantProps)} {...componentProps} />
</TooltipWrapper>
)
}

View File

@@ -9,6 +9,7 @@ export { Badge } from './Badge'
export { Bold } from './Bold'
export { Box } from './Box'
export { Button } from './Button'
export { LinkButton } from './LinkButton'
export { useCloseDialog } from './useCloseDialog'
export { Dialog, type DialogProps } from './Dialog'
export { Div } from './Div'