feat: unify CardHeader padding across components
- Updated `CardHeader` padding from `pb-3` to `pb-4` in `JiraLogs`, `JiraSync`, `KanbanColumn`, `ObjectivesBoard`, and `DesktopControls` for consistent spacing. - Refactored `DesktopControls` and `KanbanFilters` to utilize new `ControlPanel`, `ControlSection`, and `ControlGroup` components, enhancing layout structure and maintainability. - Replaced button elements with `ToggleButton` and `FilterChip` components in various filter sections for improved UI consistency and usability.
This commit is contained in:
78
src/components/ui/ToggleButton.tsx
Normal file
78
src/components/ui/ToggleButton.tsx
Normal file
@@ -0,0 +1,78 @@
|
||||
import { ButtonHTMLAttributes, forwardRef } from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface ToggleButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
variant?: 'primary' | 'accent' | 'secondary' | 'warning' | 'cyan';
|
||||
size?: 'sm' | 'md';
|
||||
isActive?: boolean;
|
||||
icon?: React.ReactNode;
|
||||
count?: number;
|
||||
}
|
||||
|
||||
const ToggleButton = forwardRef<HTMLButtonElement, ToggleButtonProps>(
|
||||
({ className, variant = 'primary', size = 'md', isActive = false, icon, count, children, ...props }, ref) => {
|
||||
const variants = {
|
||||
primary: isActive
|
||||
? 'bg-[var(--primary)]/20 text-[var(--primary)] border border-[var(--primary)]/30'
|
||||
: 'bg-[var(--card)] text-[var(--muted-foreground)] border border-[var(--border)] hover:border-[var(--primary)]/50',
|
||||
accent: isActive
|
||||
? 'bg-[var(--accent)]/20 text-[var(--accent)] border border-[var(--accent)]/30'
|
||||
: 'bg-[var(--card)] text-[var(--muted-foreground)] border border-[var(--border)] hover:border-[var(--accent)]/50',
|
||||
secondary: isActive
|
||||
? 'bg-[var(--secondary)]/20 text-[var(--secondary)] border border-[var(--secondary)]/30'
|
||||
: 'bg-[var(--card)] text-[var(--muted-foreground)] border border-[var(--border)] hover:border-[var(--secondary)]/50',
|
||||
warning: isActive
|
||||
? 'bg-[var(--warning)]/20 text-[var(--warning)] border border-[var(--warning)]/30'
|
||||
: 'bg-[var(--card)] text-[var(--muted-foreground)] border border-[var(--border)] hover:border-[var(--warning)]/50',
|
||||
cyan: isActive
|
||||
? 'bg-[var(--cyan)]/20 text-[var(--cyan)] border border-[var(--cyan)]/30'
|
||||
: 'bg-[var(--card)] text-[var(--muted-foreground)] border border-[var(--border)] hover:border-[var(--cyan)]/50'
|
||||
};
|
||||
|
||||
// Déterminer si c'est un bouton avec seulement des icônes
|
||||
const isIconOnly = icon && !children && count === undefined;
|
||||
|
||||
const sizes = {
|
||||
sm: isIconOnly ? 'px-2 py-1.5 text-sm' : 'px-3 py-1.5 text-sm',
|
||||
md: isIconOnly ? 'px-2 py-1.5 text-sm' : 'px-3 py-1.5 text-sm'
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex items-center gap-2 rounded-md font-mono transition-all',
|
||||
variants[variant],
|
||||
sizes[size],
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{icon && (
|
||||
<div className="flex-shrink-0">
|
||||
{icon}
|
||||
</div>
|
||||
)}
|
||||
{children && (
|
||||
<span className="flex-1 text-left">
|
||||
{children}
|
||||
{count !== undefined && count > 0 && (
|
||||
<span className="ml-1 text-xs opacity-75">
|
||||
({count})
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
{count !== undefined && count > 0 && !children && (
|
||||
<span className="text-xs opacity-75">
|
||||
({count})
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
ToggleButton.displayName = 'ToggleButton';
|
||||
|
||||
export { ToggleButton };
|
||||
Reference in New Issue
Block a user