Files
videoreg.ru/web-front/src/shared/ui/atoms/Button.tsx
T
2026-05-17 01:08:19 +03:00

68 lines
2.0 KiB
TypeScript

import type { AnchorHTMLAttributes, ButtonHTMLAttributes, ReactNode } from 'react';
import { cn } from '@/shared/lib/cn';
type ButtonVariant = 'primary' | 'secondary' | 'ghost';
type ButtonSize = 'sm' | 'md';
type BaseProps = {
children: ReactNode;
className?: string;
size?: ButtonSize;
variant?: ButtonVariant;
};
type LinkProps = BaseProps &
AnchorHTMLAttributes<HTMLAnchorElement> & {
href: string;
};
type NativeButtonProps = BaseProps &
ButtonHTMLAttributes<HTMLButtonElement> & {
href?: undefined;
};
type ButtonProps = LinkProps | NativeButtonProps;
const variantClasses: Record<ButtonVariant, string> = {
primary:
'border-[var(--accent)] bg-[var(--accent)] text-[var(--text-on-accent)] hover:bg-[var(--accent-strong)] hover:border-[var(--accent-strong)]',
secondary:
'border-[var(--border-strong)] bg-[var(--surface-1)] text-[var(--text-primary)] hover:bg-[var(--surface-2)]',
ghost:
'border-transparent bg-transparent text-[var(--text-muted)] hover:bg-[var(--surface-2)] hover:text-[var(--text-primary)]',
};
const sizeClasses: Record<ButtonSize, string> = {
sm: 'min-h-9 px-3 text-xs',
md: 'min-h-11 px-4 text-sm',
};
export function Button(props: ButtonProps) {
const { children, className, size = 'md', variant = 'primary' } = props;
const classes = cn(
'inline-flex items-center justify-center gap-2 rounded-[var(--radius-md)] border font-semibold transition-colors focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--focus)]',
sizeClasses[size],
variantClasses[variant],
className,
);
if (props.href) {
const { href, ...linkProps } = props;
return (
<a {...linkProps} className={classes} href={href}>
{children}
</a>
);
}
const buttonProps = props as NativeButtonProps;
const { type = 'button', ...restButtonProps } = buttonProps;
return (
<button {...restButtonProps} className={classes} type={type}>
{children}
</button>
);
}