🎨 style: update button and button icon only theme

This commit is contained in:
Wahyu Kurniawan 2024-02-19 21:15:29 +07:00
parent 6a3af491ca
commit 862862a9c5
No known key found for this signature in database
GPG Key ID: 040A1549143A8E33
2 changed files with 98 additions and 55 deletions

View File

@ -7,20 +7,20 @@ import type { VariantProps } from 'tailwind-variants';
export const buttonTheme = tv( export const buttonTheme = tv(
{ {
base: [ base: [
'h-fit',
'inline-flex', 'inline-flex',
'items-center', 'items-center',
'justify-center', 'justify-center',
'font-medium',
'whitespace-nowrap', 'whitespace-nowrap',
'focus-ring', 'focus-ring',
'disabled:cursor-not-allowed', 'disabled:cursor-not-allowed',
], ],
variants: { variants: {
size: { size: {
lg: ['gap-3', 'py-4', 'px-6', 'rounded-lg', 'text-lg'], lg: ['gap-2', 'py-3.5', 'px-5', 'text-base', 'tracking-[-0.011em]'],
md: ['gap-2', 'py-3', 'px-4', 'rounded-lg', 'text-base'], md: ['gap-2', 'py-3.25', 'px-5', 'text-sm', 'tracking-[-0.006em]'],
sm: ['gap-1', 'py-2', 'px-2', 'rounded-md', 'text-xs'], sm: ['gap-1', 'py-2', 'px-3', 'text-xs'],
xs: ['gap-1', 'py-1', 'px-2', 'rounded-md', 'text-xs'], xs: ['gap-1', 'py-1', 'px-2', 'text-xs'],
}, },
fullWidth: { fullWidth: {
true: 'w-full', true: 'w-full',
@ -29,11 +29,14 @@ export const buttonTheme = tv(
default: '', default: '',
rounded: 'rounded-full', rounded: 'rounded-full',
}, },
iconOnly: {
true: '',
},
variant: { variant: {
primary: [ primary: [
'text-elements-on-primary', 'text-elements-on-primary',
'border', 'border',
'border-primary-700', 'border-transparent',
'bg-controls-primary', 'bg-controls-primary',
'shadow-button', 'shadow-button',
'hover:bg-controls-primary-hovered', 'hover:bg-controls-primary-hovered',
@ -44,86 +47,108 @@ export const buttonTheme = tv(
'disabled:shadow-none', 'disabled:shadow-none',
], ],
secondary: [ secondary: [
'text-components-buttons-secondary-foreground', 'text-elements-on-secondary',
'border', 'border',
'border-primary-500', 'border-transparent',
'bg-components-buttons-secondary-background', 'bg-controls-secondary',
'hover:text-components-buttons-secondary-foreground-hover', 'hover:bg-controls-secondary-hovered',
'hover:bg-components-buttons-secondary-background-hover', 'focus-visible:bg-controls-secondary-hovered',
'focus-visible:text-components-buttons-secondary-foreground-focus', 'disabled:text-elements-on-disabled',
'focus-visible:bg-components-buttons-secondary-background-focus', 'disabled:bg-controls-disabled',
'disabled:text-components-buttons-secondary-foreground-disabled',
'disabled:bg-components-buttons-secondary-background-disabled ',
'disabled:border-transparent', 'disabled:border-transparent',
'disabled:shadow-none',
], ],
tertiary: [ tertiary: [
'text-components-buttons-tertiary-background', 'text-elements-on-tertiary',
'border', 'border',
'border-components-buttons-tertiary-background', 'border-border-interactive/10',
'bg-transparent', 'bg-transparent',
'hover:text-components-buttons-tertiary-hover', 'hover:bg-controls-tertiary-hovered',
'hover:border-components-buttons-tertiary-hover', 'hover:border-border-interactive-hovered',
'focus-visible:text-components-buttons-tertiary-focus', 'hover:border-border-interactive-hovered/[0.14]',
'focus-visible:border-components-buttons-tertiary-focus', 'focus-visible:bg-controls-tertiary-hovered',
'disabled:text-components-buttons-tertiary-disabled', 'focus-visible:border-border-interactive-hovered',
'disabled:border-components-buttons-tertiary-disabled', 'focus-visible:border-border-interactive-hovered/[0.14]',
'disabled:text-elements-on-disabled',
'disabled:bg-controls-disabled',
'disabled:border-transparent',
'disabled:shadow-none',
], ],
'text-only': [ ghost: [
'text-components-buttons-text-only-background', 'text-elements-on-tertiary',
'border', 'border',
'border-transparent', 'border-transparent',
'bg-transparent', 'bg-transparent',
'hover:text-components-buttons-text-only-foreground-hover', 'hover:bg-controls-tertiary-hovered',
'hover:bg-components-buttons-text-only-background-hover', 'hover:border-border-interactive-hovered',
'focus-visible:text-components-buttons-text-only-foreground-focus', 'hover:border-border-interactive-hovered/[0.14]',
'focus-visible:bg-components-buttons-text-only-background-focus', 'focus-visible:bg-controls-tertiary-hovered',
'disabled:text-components-buttons-tertiary-disabled', 'focus-visible:border-border-interactive-hovered',
'disabled:bg-transparent', 'focus-visible:border-border-interactive-hovered/[0.14]',
'disabled:text-elements-on-disabled',
'disabled:bg-controls-disabled',
'disabled:border-transparent',
'disabled:shadow-none',
], ],
danger: [ danger: [
'text-components-button-icon-alert-foreground', 'text-elements-on-danger',
'border', 'border',
'border-transparent', 'border-transparent',
'bg-components-buttons-alert-background', 'bg-border-danger',
'hover:text-components-buttons-alert-foreground-hover', 'hover:bg-controls-danger-hovered',
'hover:bg-components-buttons-alert-background-hover', 'focus-visible:bg-controls-danger-hovered',
'focus-visible:text-components-buttons-alert-foreground-focus', 'disabled:text-elements-on-disabled',
'focus-visible:bg-components-buttons-alert-background-focus', 'disabled:bg-controls-disabled',
'disabled:text-components-button-icon-alert-foreground-disabled', 'disabled:border-transparent',
'disabled:bg-components-button-icon-alert-background-disabled', 'disabled:shadow-none',
], ],
'icon-only': [ 'danger-ghost': [
'p-0 flex items-center justify-center', 'text-elements-danger',
'text-components-button-icon-text-only-foreground',
'border', 'border',
'border-transparent', 'border-transparent',
'bg-transparent', 'bg-transparent',
'hover:text-components-button-icon-text-only-foreground-hover', 'hover:bg-controls-tertiary-hovered',
'hover:bg-components-button-icon-text-only-background-hover', 'hover:border-border-interactive-hovered',
'focus-visible:text-components-button-icon-low-emphasis-foreground-focus', 'hover:border-border-interactive-hovered/[0.14]',
'focus-visible:bg-components-button-icon-low-emphasis-background-focus', 'focus-visible:bg-controls-tertiary-hovered',
'disabled:text-components-button-icon-low-emphasis-outlined-foreground-disabled', 'focus-visible:border-border-interactive-hovered',
'disabled:bg-transparent', 'focus-visible:border-border-interactive-hovered/[0.14]',
'disabled:text-elements-on-disabled',
'disabled:bg-controls-disabled',
'disabled:border-transparent',
'disabled:shadow-none',
], ],
unstyled: [], unstyled: [],
}, },
}, },
compoundVariants: [ compoundVariants: [
{
size: 'lg',
iconOnly: true,
class: ['py-3.5', 'px-3.5'],
},
{ {
size: 'md', size: 'md',
variant: 'icon-only', iconOnly: true,
class: ['h-11', 'w-11', 'rounded-lg'], class: ['py-3.25', 'px-3.25'],
}, },
{ {
size: 'sm', size: 'sm',
variant: 'icon-only', iconOnly: true,
class: ['h-8', 'w-8', 'rounded-md'], class: ['py-2', 'px-2'],
},
{
size: 'xs',
iconOnly: true,
class: ['py-1', 'px-1'],
}, },
], ],
defaultVariants: { defaultVariants: {
size: 'md', size: 'md',
variant: 'primary', variant: 'primary',
fullWidth: false, fullWidth: false,
iconOnly: false,
shape: 'rounded',
}, },
}, },
{ {

View File

@ -4,6 +4,7 @@ import type { ComponentPropsWithoutRef, ReactNode } from 'react';
import { buttonTheme } from './Button.theme'; import { buttonTheme } from './Button.theme';
import type { ButtonTheme } from './Button.theme'; import type { ButtonTheme } from './Button.theme';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { cloneIcon } from 'utils/cloneIcon';
/** /**
* Represents the properties of a base button component. * Represents the properties of a base button component.
@ -69,6 +70,7 @@ const Button = ({
leftIcon, leftIcon,
rightIcon, rightIcon,
fullWidth, fullWidth,
iconOnly,
shape, shape,
variant, variant,
...props ...props
@ -114,15 +116,17 @@ const Button = ({
variant = 'primary', variant = 'primary',
size = 'md', size = 'md',
fullWidth = false, fullWidth = false,
iconOnly = false,
shape = 'rounded', shape = 'rounded',
as, as,
}) => ({ }) => ({
variant, variant,
size, size,
fullWidth, fullWidth,
iconOnly,
shape, shape,
as, as,
}))({ ...props, fullWidth, shape, variant }); }))({ ...props, fullWidth, iconOnly, shape, variant });
/** /**
* Validates that a button component has either children or an aria-label prop. * Validates that a button component has either children or an aria-label prop.
@ -133,14 +137,28 @@ const Button = ({
); );
} }
const iconSize = useCallback(() => {
switch (styleProps.size) {
case 'lg':
return { width: 20, height: 20 };
case 'sm':
case 'xs':
return { width: 16, height: 16 };
case 'md':
default: {
return { width: 18, height: 18 };
}
}
}, [styleProps.size])();
return ( return (
<Component <Component
{...props} {...props}
className={buttonTheme({ ...styleProps, class: className })} className={buttonTheme({ ...styleProps, class: className })}
> >
{leftIcon} {cloneIcon(leftIcon, { ...iconSize })}
{children} {children}
{rightIcon} {cloneIcon(rightIcon, { ...iconSize })}
</Component> </Component>
); );
}; };