useTableFixedColumn
Ce hook détecte si le contenu d'un tableau dépasse la largeur visible (c'est-à-dire qu'il est partiellement scrollable horizontalement). Il utilise ResizeObserver et des écouteurs d'événements scroll pour déterminer en temps réel si du contenu est masqué, ce qui permet d'afficher visuellement une indication ou de gérer l'affichage de colonnes fixes.
Retour du hook
Le hook retourne :
| Type | Description |
|---|---|
boolean | true si du contenu est caché horizontalement (scroll disponible), false sinon |
Paramètres
useTableFixedColumn(ref: RefObject<HTMLTableElement | null>)
| Paramètre | Type | Description |
|---|---|---|
ref | RefObject<HTMLTableElement> | Référence React attachée à l'élément table |
Utilisation basique
import { useRef } from 'react';
import { useTableFixedColumn } from '@/hooks/use-table-fixed-column';
export function DataTable() {
const tableRef = useRef<HTMLTableElement>(null);
const isFullyScrolled = useTableFixedColumn(tableRef);
return (
<div>
{isFullyScrolled && (
<span style={{ color: 'orange', fontSize: '12px' }}>
→ Scroller pour voir plus de colonnes
</span>
)}
<table ref={tableRef}>
<thead>
<tr>
<th>ID</th>
<th>Nom</th>
<th>Email</th>
<th>Téléphone</th>
<th>Adresse</th>
<th>Ville</th>
<th>Code Postal</th>
</tr>
</thead>
<tbody>
{/* Contenu du tableau */}
</tbody>
</table>
</div>
);
}
Fonctionnement
- Détection du parent scrollable : Trouve le parent avec
data-radix-scroll-area-viewport(Radix UI) - Calcul du scroll : Compare
scrollWidthetoffsetWidthpour déterminer s'il y a du contenu caché - Écouteur d'événements : Surveillance les changements de scroll en temps réel
- Observation de redimensionnement : Utilise
ResizeObserverpour détecter les changements de taille - Débouncing : Utilise un délai de 100ms pour optimiser les performances
Architecture du DOM attendu
Le hook recherche un parent spécifique au scroll area de Radix UI :
<div data-radix-scroll-area-viewport>
<table ref={tableRef}>
<!-- Contenu -->
</table>
</div>
Cas d'usage courants
1. Afficher une indication visuelle
const tableRef = useRef<HTMLTableElement>(null);
const hasHiddenContent = useTableFixedColumn(tableRef);
return (
<div>
{hasHiddenContent && (
<div style={{ fontSize: '12px', color: '#ff9800' }}>
⚠️ Contenu caché horizontalement
</div>
)}
<table ref={tableRef}>...</table>
</div>
);
2. Appliquer un style conditionnel
const tableRef = useRef<HTMLTableElement>(null);
const isScrollable = useTableFixedColumn(tableRef);
return (
<table
ref={tableRef}
style={{
boxShadow: isScrollable ? '20px 0 10px -10px rgba(0,0,0,0.1)' : 'none',
}}
>
{/* Contenu */}
</table>
);
3. Gérer l'affichage d'une colonne fixe
const tableRef = useRef<HTMLTableElement>(null);
const hasHiddenContent = useTableFixedColumn(tableRef);
return (
<div>
<table ref={tableRef}>
<thead>
<tr>
<th style={{ position: hasHiddenContent ? 'sticky' : 'static', left: 0 }}>
ID
</th>
{/* Autres colonnes */}
</tr>
</thead>
</table>
</div>
);
4. Afficher un bouton de scroll
const tableRef = useRef<HTMLTableElement>(null);
const isScrollable = useTableFixedColumn(tableRef);
return (
<div>
{isScrollable && (
<button onClick={() => {
const scrollContainer = tableRef.current?.closest('[data-radix-scroll-area-viewport]');
if (scrollContainer) scrollContainer.scrollLeft += 200;
}}>
→ Voir plus
</button>
)}
<table ref={tableRef}>...</table>
</div>
);
Points importants
- ⚠️ Le hook recherche un parent avec
data-radix-scroll-area-viewport(spécifique à Radix UI) - ⚠️ La table doit être directement enfant du scroll area
- ℹ️ Utilise
ResizeObserverpour détecter les redimensionnements - ℹ️ Utilise
useDebouncedCallbackde TanStack React Pacer pour optimiser les performances - ✅ Détecte en temps réel les changements de scroll et de redimensionnement
- ✅ Automatiquement nettoyé lors du unmount du composant
Performance
Le hook est optimisé pour les performances :
- Débouncing : La fonction de calcul est déclenchée avec un délai de 100ms
- Event listeners : Supprimés lors du unmount
- ResizeObserver : Nettoyé automatiquement
- Minimal re-renders : Les changements d'état sont minimaux
Sources
- ResizeObserver : https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver
- TanStack React Pacer : https://tanstack.com/pacer/latest/docs/framework/react/adapter
- ScrollLeft: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft