Checkpoint: Remplacement des min-w Tailwind par des width/minWidth/maxWidth explicites en style inline (Code=110px, Établissement=220px, left=110px) pour garantir la cohérence entre la largeur réelle et la position left des colonnes sticky. Ajout d'un title sur la cellule Établissement pour voir le nom complet en cas de troncature.

This commit is contained in:
Manus
2026-06-10 09:08:19 +00:00
parent 8de20ba62e
commit 9e8830e929

View File

@@ -1252,8 +1252,8 @@ export default function DsiOpex() {
<table className="text-xs border-separate border-spacing-0" style={{ minWidth: 'max-content', width: '100%' }}>
<thead>
<tr className="border-b border-border bg-muted/40">
<th className="text-left px-3 py-3 font-medium text-muted-foreground sticky left-0 z-20 min-w-[80px]" style={{ background: 'hsl(var(--muted) / 0.4)', boxShadow: '2px 0 0 0 hsl(var(--border))' }}>Code</th>
<th className="text-left px-3 py-3 font-medium text-muted-foreground sticky left-[80px] z-20 min-w-[200px]" style={{ background: 'hsl(var(--muted) / 0.4)', boxShadow: '2px 0 4px -2px rgba(0,0,0,0.15)' }}>
<th className="text-left px-3 py-3 font-medium text-muted-foreground sticky left-0 z-20" style={{ background: 'hsl(var(--muted) / 0.4)', boxShadow: '2px 0 0 0 hsl(var(--border))', width: '110px', minWidth: '110px', maxWidth: '110px' }}>Code</th>
<th className="text-left px-3 py-3 font-medium text-muted-foreground sticky z-20" style={{ left: '110px', background: 'hsl(var(--muted) / 0.4)', boxShadow: '2px 0 6px -2px rgba(0,0,0,0.2)', width: '220px', minWidth: '220px', maxWidth: '220px' }}>
<SortBtn col="nom" label="Établissement" />
</th>
{/* Colonnes postes — vert = prorata auto, bleu = manuel */}
@@ -1285,10 +1285,10 @@ export default function DsiOpex() {
<tbody>
{sortedEtabs.map((etab, idx) => (
<tr key={etab.code} className={`border-b border-border/50 hover:bg-muted/20 transition-colors ${idx % 2 === 0 ? '' : 'bg-muted/5'}`}>
<td className="px-3 py-2 sticky left-0 z-10 whitespace-nowrap" style={{ background: idx % 2 === 0 ? 'hsl(var(--card))' : 'hsl(var(--muted) / 0.05)', boxShadow: '2px 0 0 0 hsl(var(--border))' }}>
<td className="px-3 py-2 sticky left-0 z-10 whitespace-nowrap" style={{ background: idx % 2 === 0 ? 'hsl(var(--card))' : 'hsl(var(--muted) / 0.05)', boxShadow: '2px 0 0 0 hsl(var(--border))', width: '110px', minWidth: '110px', maxWidth: '110px' }}>
<span className="font-mono bg-muted px-1.5 py-0.5 rounded text-muted-foreground">{etab.code}</span>
</td>
<td className="px-3 py-2 font-medium text-foreground sticky left-[80px] z-10 whitespace-nowrap" style={{ background: idx % 2 === 0 ? 'hsl(var(--card))' : 'hsl(var(--muted) / 0.05)', boxShadow: '2px 0 4px -2px rgba(0,0,0,0.15)' }}>{etab.nom}</td>
<td className="px-3 py-2 font-medium text-foreground sticky z-10 whitespace-nowrap overflow-hidden text-ellipsis" style={{ left: '110px', background: idx % 2 === 0 ? 'hsl(var(--card))' : 'hsl(var(--muted) / 0.05)', boxShadow: '2px 0 6px -2px rgba(0,0,0,0.2)', width: '220px', minWidth: '220px', maxWidth: '220px' }} title={etab.nom}>{etab.nom}</td>
{opexState.lignes.map(ligne => {
const srcPoste = getOpexDataForAnnee(annee).postes.find(p => p.libelle === ligne.libelle);
const isManuel = srcPoste?.mode_ventilation === 'Manuel' || ligne.isCustom;
@@ -1351,7 +1351,7 @@ export default function DsiOpex() {
</tbody>
<tfoot>
<tr className="bg-muted/40 border-t-2 border-border">
<td colSpan={2} className="px-3 py-3 font-bold text-foreground sticky left-0 z-10" style={{ background: 'hsl(var(--muted) / 0.4)', boxShadow: '2px 0 4px -2px rgba(0,0,0,0.15)' }}>
<td colSpan={2} className="px-3 py-3 font-bold text-foreground sticky left-0 z-10" style={{ background: 'hsl(var(--muted) / 0.4)', boxShadow: '2px 0 6px -2px rgba(0,0,0,0.2)', width: '330px', minWidth: '330px' }}>
TOTAL — {sortedEtabs.length} établissements
</td>
{opexState.lignes.map(ligne => {