Text input component #30
57
frontend/src/components/Button/Button.tsx
Normal file
57
frontend/src/components/Button/Button.tsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import type { ButtonHTMLAttributes, ReactNode } from 'react';
|
||||||
|
|
||||||
|
export type ButtonVariant = 'primary' | 'secondary' | 'red' | 'green';
|
||||||
|
export type ButtonSize = 'sm' | 'md' | 'lg';
|
||||||
|
|
||||||
|
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
|
variant?: ButtonVariant;
|
||||||
|
size?: ButtonSize;
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const variantClasses: Record<ButtonVariant, string> = {
|
||||||
|
primary: 'bg-primary text-base-canvas border border-primary hover:bg-secondary hover:text-base-canvas hover:border-primary focus:bg-base-canvas focus:text-base-ink-strong focus:border-primary focus:outline focus:outline-sky-100',
|
||||||
|
secondary: 'bg-base-canvas text-base-ink-strong border border-base-ink-soft hover:bg-base-canvas hover:text-base-ink-strong hover:border-base-ink-medium focus:bg-base-canvas focus:text-base-ink-strong focus:border-primary focus:outline focus:outline-sky-100',
|
||||||
|
red: 'bg-other-red-100 text-su-white border border-other-red-100 focus:bg-base-canvas focus:text-base-ink-strong focus:border-primary focus:outline focus:outline-sky-100',
|
||||||
|
green: 'bg-other-green text-su-white border border-other-green focus:bg-base-canvas focus:text-base-ink-strong focus:border-primary focus:outline focus:outline-sky-100',
|
||||||
|
};
|
||||||
|
|
||||||
|
const sizeClasses: Record<ButtonSize, string> = {
|
||||||
|
sm: 'h-(--control-height-sm) min-w-(--button-min-width-sm) px-(--button-padding-x-sm) text-body-md rounded-(--border-radius-sm)',
|
||||||
|
md: 'h-(--control-height-md) min-w-(--button-min-width-md) px-(--button-padding-x-md) text-body-md rounded-(--border-radius-sm)',
|
||||||
|
lg: 'h-(--control-height-lg) min-w-(--button-min-width-lg) px-(--button-padding-x-lg) text-body-lg rounded-(--border-radius-md)',
|
||||||
|
};
|
||||||
|
|
||||||
|
const textPaddingClasses: Record<ButtonSize, string> = {
|
||||||
|
sm: 'px-(--button-text-padding-x-sm)',
|
||||||
|
md: 'px-(--button-text-padding-x-md)',
|
||||||
|
lg: 'px-(--button-text-padding-x-lg)',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Button({
|
||||||
|
variant = 'primary',
|
||||||
|
size = 'md',
|
||||||
|
className = '',
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: ButtonProps) {
|
||||||
|
const baseClasses = 'inline-flex items-center justify-center font-semibold';
|
||||||
|
|
||||||
|
const classes = [
|
||||||
|
baseClasses,
|
||||||
|
variantClasses[variant],
|
||||||
|
sizeClasses[size],
|
||||||
|
className,
|
||||||
|
]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(' ');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={classes}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<span className={textPaddingClasses[size]}>{children}</span>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user