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:
Julien Froidefond
2025-09-28 21:53:22 +02:00
parent bdf8ab9fb4
commit 0fcd4d68c1
20 changed files with 1011 additions and 451 deletions

View File

@@ -8,7 +8,7 @@ import { Alert, AlertTitle, AlertDescription } from '@/components/ui/Alert';
import { Input } from '@/components/ui/Input';
import { StyledCard } from '@/components/ui/StyledCard';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card';
import { StatCard, ProgressBar, ActionCard, TaskCard, MetricCard } from '@/components/ui';
import { StatCard, ProgressBar, ActionCard, TaskCard, MetricCard, ToggleButton, SearchInput, ControlPanel, ControlSection, ControlGroup, FilterSummary, FilterChip } from '@/components/ui';
import { ThemeSelector } from '@/components/ThemeSelector';
export function UIShowcaseClient() {
@@ -562,6 +562,243 @@ export function UIShowcaseClient() {
</div>
</section>
{/* Kanban Components Section */}
<section className="space-y-8">
<h2 className="text-2xl font-mono font-semibold text-[var(--foreground)] border-b border-[var(--border)] pb-3">
Kanban Components
</h2>
{/* Toggle Buttons */}
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">Toggle Buttons</h3>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
variant="primary" isActive={true}
</div>
<ToggleButton
variant="primary"
isActive={true}
count={3}
icon={
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4" />
</svg>
}
>
Filtres
</ToggleButton>
</div>
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
variant="primary" isActive={true} - Icône seule (padding réduit)
</div>
<ToggleButton
variant="primary"
isActive={true}
icon={
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4" />
</svg>
}
/>
</div>
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
variant="accent" isActive={false}
</div>
<ToggleButton
variant="accent"
isActive={false}
icon={
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z" />
</svg>
}
>
Objectifs
</ToggleButton>
</div>
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
variant="warning" isActive={true}
</div>
<ToggleButton
variant="warning"
isActive={true}
icon={
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z" />
</svg>
}
>
Swimlanes
</ToggleButton>
</div>
</div>
</div>
{/* Search Input */}
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">Search Input</h3>
<div className="space-y-4 max-w-md">
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
placeholder="Rechercher des tâches..."
</div>
<SearchInput
placeholder="Rechercher des tâches..."
onChange={(value) => console.log('Search:', value)}
/>
</div>
</div>
</div>
{/* Control Panel */}
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">Control Panel</h3>
<div className="space-y-4">
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
ControlPanel + ControlSection + ControlGroup
</div>
<ControlPanel>
<ControlSection>
<SearchInput
placeholder="Rechercher..."
onChange={(value) => console.log('Search:', value)}
/>
<ControlGroup>
<ToggleButton
variant="primary"
isActive={true}
count={2}
icon={
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4" />
</svg>
}
>
Filtres
</ToggleButton>
<ToggleButton
variant="accent"
isActive={false}
icon={
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z" />
</svg>
}
>
Objectifs
</ToggleButton>
</ControlGroup>
</ControlSection>
</ControlPanel>
</div>
</div>
</div>
{/* Filter Summary */}
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">Filter Summary</h3>
<div className="space-y-4 max-w-2xl">
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
Exemple avec filtres actifs
</div>
<FilterSummary
filters={{
search: "refactorisation",
priorities: ["Haute", "Moyenne"],
tags: ["Frontend", "UI"],
showWithDueDate: true,
showJiraOnly: true,
jiraProjects: ["PROJ-1", "PROJ-2"],
jiraTypes: ["Bug", "Story"]
}}
activeFiltersCount={7}
onClearFilters={() => console.log('Clear filters')}
/>
</div>
</div>
</div>
{/* Filter Chips */}
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">Filter Chips</h3>
<div className="space-y-4">
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
variant="default"
</div>
<div className="flex flex-wrap gap-2">
<FilterChip variant="default" onClick={() => console.log('Default chip')}>
Filtre par défaut
</FilterChip>
<FilterChip variant="default" count={5} onClick={() => console.log('With count')}>
Avec compteur
</FilterChip>
<FilterChip variant="default" icon="🏷️" onClick={() => console.log('With icon')}>
Avec icône
</FilterChip>
</div>
</div>
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
variant="selected"
</div>
<div className="flex flex-wrap gap-2">
<FilterChip variant="selected" onClick={() => console.log('Selected chip')}>
Filtre sélectionné
</FilterChip>
<FilterChip variant="selected" count={3} color="#8b5cf6" onClick={() => console.log('Selected with color')}>
Avec couleur
</FilterChip>
</div>
</div>
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
variant="hidden"
</div>
<div className="flex flex-wrap gap-2">
<FilterChip variant="hidden" icon="👁️‍🗨️" onClick={() => console.log('Hidden chip')}>
Colonne masquée
</FilterChip>
<FilterChip variant="hidden" count={0} icon="👁️‍🗨️" onClick={() => console.log('Hidden empty')}>
Colonne vide
</FilterChip>
</div>
</div>
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
Exemples avec icônes (Jira/TFS)
</div>
<div className="flex flex-wrap gap-2">
<FilterChip variant="selected" icon="📋" count={5} onClick={() => console.log('Jira project')}>
PROJ-123
</FilterChip>
<FilterChip variant="selected" icon="🐛" count={2} onClick={() => console.log('Bug type')}>
Bug
</FilterChip>
<FilterChip variant="default" icon="📦" count={3} onClick={() => console.log('TFS project')}>
TFS-Projet
</FilterChip>
<FilterChip variant="selected" icon="✨" count={1} onClick={() => console.log('Feature type')}>
Feature
</FilterChip>
</div>
</div>
</div>
</div>
</section>
{/* Footer */}
<div className="text-center pt-8 border-t border-[var(--border)]">
<p className="text-[var(--muted-foreground)]">