♻️(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:
committed by
aleb_the_flash
parent
211ba332dc
commit
1875a394c6
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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}>
|
||||
|
||||
22
src/frontend/src/primitives/LinkButton.tsx
Normal file
22
src/frontend/src/primitives/LinkButton.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user