Add Button component with variants and loading state
This commit is contained in:
parent
aab2c02c2e
commit
416b331703
2 changed files with 32 additions and 0 deletions
8
src/components/Button.module.css
Normal file
8
src/components/Button.module.css
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
.btn { padding: 8px 16px; border: none; border-radius: var(--radius-sm); cursor: pointer; font-family: var(--font-sans); }
|
||||||
|
.primary { background: var(--color-primary); color: #fff; }
|
||||||
|
.primary:hover:not(:disabled) { background: var(--color-primary-hover); }
|
||||||
|
.secondary { background: var(--color-surface); border: 1px solid var(--color-border); color: var(--color-text); }
|
||||||
|
.danger { background: var(--color-error); color: #fff; }
|
||||||
|
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||||
|
.spinner { display: inline-block; width: 12px; height: 12px; border: 2px solid currentColor; border-top-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; margin-right: 6px; }
|
||||||
|
@keyframes spin { to { transform: rotate(360deg); } }
|
||||||
24
src/components/Button.tsx
Normal file
24
src/components/Button.tsx
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import React from 'react';
|
||||||
|
import styles from './Button.module.css';
|
||||||
|
|
||||||
|
interface ButtonProps {
|
||||||
|
label: string;
|
||||||
|
onClick: () => void;
|
||||||
|
variant?: 'primary' | 'secondary' | 'danger';
|
||||||
|
disabled?: boolean;
|
||||||
|
loading?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Button: React.FC<ButtonProps> = ({
|
||||||
|
label, onClick, variant = 'primary', disabled = false, loading = false,
|
||||||
|
}) => (
|
||||||
|
<button
|
||||||
|
className={`${styles.btn} ${styles[variant]}`}
|
||||||
|
onClick={onClick}
|
||||||
|
disabled={disabled || loading}
|
||||||
|
aria-busy={loading}
|
||||||
|
>
|
||||||
|
{loading ? <span className={styles.spinner} aria-hidden /> : null}
|
||||||
|
{label}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
Loading…
Reference in a new issue