feat: button, calendar, datePicker, input, pagination, icons 추가
This commit is contained in:
147
web-app/app/shared/components/button/Button.tsx
Normal file
147
web-app/app/shared/components/button/Button.tsx
Normal file
@@ -0,0 +1,147 @@
|
||||
import type { ButtonProps as AriaButtonProps } from 'react-aria-components';
|
||||
import { Button as AriaButton, composeRenderProps } from 'react-aria-components';
|
||||
|
||||
import { tv } from 'tailwind-variants';
|
||||
import { LoadingSpinnerIcon } from '../icons/LoadingSpinner';
|
||||
|
||||
export interface ButtonProps extends AriaButtonProps {
|
||||
color?: 'primary' | 'light' | 'green' | 'lightGreen' | 'black' | 'gray' | 'orange' | 'navy' | 'lightNavy';
|
||||
size?: 'small' | 'medium' | 'large';
|
||||
stopPropagation?: boolean;
|
||||
}
|
||||
|
||||
const button = tv({
|
||||
base: 'relative inline-flex items-center justify-center gap-2 border cursor-pointer box-border data-focus-visible:ring-2 ring-offset-2',
|
||||
variants: {
|
||||
size: {
|
||||
small: 'h-6 px-3 text-xs font-medium',
|
||||
medium: 'h-9 px-3 text-xs font-medium',
|
||||
large: 'min-w-30 h-13 px-5 text-sm font-semibold',
|
||||
},
|
||||
color: {
|
||||
primary: 'text-white bg-primary border-primary disabled:bg-kc-gray-be disabled:border-kc-gray-be ring-primary',
|
||||
light:
|
||||
'text-primary border-primary bg-primary-tertiary02 disabled:text-kc-gray-99 disabled:bg-kc-gray-eb disabled:border-kc-gray-be ring-primary',
|
||||
green:
|
||||
'text-white bg-kc-green-main border-kc-green-main disabled:bg-kc-gray-be disabled:border-kc-gray-be ring-kc-green-main',
|
||||
lightGreen:
|
||||
'text-kc-green-main border-kc-green-main bg-kc-green-tertiary02 disabled:text-kc-gray-99 disabled:bg-kc-gray-eb disabled:border-kc-gray-be ring-kc-green-main',
|
||||
black:
|
||||
'text-white bg-kc-black-34 border-kc-black-34 disabled:bg-kc-gray-be disabled:border-kc-gray-be ring-kc-black-34',
|
||||
gray: 'text-kc-black-34 bg-kc-gray-eb border-kc-black-34 disabled:text-kc-gray-99 disabled:bg-kc-gray-eb disabled:border-kc-gray-be ring-kc-black-34',
|
||||
orange:
|
||||
'text-kc-orange-main bg-kc-orange-tertiary01 border-kc-orange-main disabled:text-kc-gray-99 disabled:bg-kc-gray-eb disabled:border-kc-gray-be ring-kc-orange-main',
|
||||
navy: 'text-white bg-kc-navy-main border-kc-navy-main disabled:bg-kc-gray-be disabled:border-kc-gray-be ring-kc-navy-main',
|
||||
lightNavy:
|
||||
'text-kc-navy-main border-kc-navy-main bg-kc-navy-tertiary02 disabled:text-kc-gray-99 disabled:bg-kc-gray-eb disabled:border-kc-gray-be ring-kc-navy-main',
|
||||
},
|
||||
isDisabled: {
|
||||
true: 'cursor-not-allowed',
|
||||
},
|
||||
isPending: {
|
||||
true: 'text-transparent cursor-progress',
|
||||
},
|
||||
},
|
||||
compoundVariants: [
|
||||
{
|
||||
color: 'primary',
|
||||
isDisabled: false,
|
||||
isPending: false,
|
||||
className:
|
||||
'hover:border-primary-tertiary hover:bg-primary-tertiary active:bg-primary-secondary active:border-primary-secondary',
|
||||
},
|
||||
{
|
||||
color: 'light',
|
||||
isDisabled: false,
|
||||
isPending: false,
|
||||
className:
|
||||
'hover:bg-primary-tertiary01 active:text-primary-secondary active:bg-primary-tertiary01 active:border-primary-secondary',
|
||||
},
|
||||
{
|
||||
color: 'green',
|
||||
isDisabled: false,
|
||||
isPending: false,
|
||||
className:
|
||||
'hover:bg-kc-green-tertiary hover:border-kc-green-tertiary active:bg-kc-green-secondary active:border-kc-green-secondary',
|
||||
},
|
||||
{
|
||||
color: 'lightGreen',
|
||||
isDisabled: false,
|
||||
isPending: false,
|
||||
className:
|
||||
'hover:bg-kc-green-tertiary01 active:text-kc-green-secondary active:bg-kc-green-tertiary01 active:border-kc-green-secondary',
|
||||
},
|
||||
{
|
||||
color: 'black',
|
||||
isDisabled: false,
|
||||
isPending: false,
|
||||
className: 'hover:bg-kc-black-47 hover:border-kc-black-47 active:bg-kc-black-22 active:border-kc-black-22',
|
||||
},
|
||||
{
|
||||
color: 'gray',
|
||||
isDisabled: false,
|
||||
isPending: false,
|
||||
className:
|
||||
'hover:bg-kc-gray-da hover:border-kc-black-47 active:text-kc-black-22 active:bg-kc-gray-da active:border-kc-black-22',
|
||||
},
|
||||
{
|
||||
color: 'orange',
|
||||
isDisabled: false,
|
||||
isPending: false,
|
||||
className:
|
||||
'hover:bg-kc-orange-tertiary02 active:text-kc-orange-secondary active:bg-kc-orange-tertiary02 active:border-kc-orange-secondary',
|
||||
},
|
||||
{
|
||||
color: 'navy',
|
||||
isDisabled: false,
|
||||
isPending: false,
|
||||
className:
|
||||
'hover:border-kc-navy-tertiary hover:bg-kc-navy-tertiary active:bg-kc-navy-secondary active:border-kc-navy-secondary',
|
||||
},
|
||||
{
|
||||
color: 'lightNavy',
|
||||
isDisabled: false,
|
||||
isPending: false,
|
||||
className:
|
||||
'hover:bg-kc-navy-tertiary01 active:text-kc-navy-secondary active:bg-kc-navy-tertiary01 active:border-kc-navy-secondary',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const Button = (props: ButtonProps) => {
|
||||
const {
|
||||
className,
|
||||
onClick,
|
||||
color = 'primary',
|
||||
size = 'medium',
|
||||
children,
|
||||
stopPropagation = false,
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<AriaButton
|
||||
className={composeRenderProps(className, (className, renderProps) => {
|
||||
return button({ ...renderProps, color, size, className });
|
||||
})}
|
||||
onClick={(e) => {
|
||||
if (stopPropagation) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
onClick?.(e);
|
||||
}}
|
||||
{...restProps}
|
||||
>
|
||||
{composeRenderProps(children, (children, { isPending }) => (
|
||||
<>
|
||||
{children}
|
||||
{isPending && (
|
||||
<span aria-hidden className="flex absolute inset-0 justify-center items-center">
|
||||
<LoadingSpinnerIcon className="w-4 h-4 text-white animate-spin" />
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
</AriaButton>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user