Dans le paysage frontend moderne, les systèmes de design comblent souvent le fossé entre le design et le développement. Cependant, en créer un à partir de zéro peut être intimidant. Découvrez la puissante combinaison de Tailwind CSS et Headless UI. Cette association permet aux développeurs de créer des composants accessibles, réutilisables et cohérents sans être contraints par un style imposé. Cet article explore comment architecturer un système de design robuste qui accélère votre flux de travail de prototypage tout en maintenant une haute qualité de code.
Pourquoi combiner Tailwind et Headless UI ?
Tailwind CSS excelle dans le style utilitaire, vous offrant un contrôle granulaire sur chaque aspect de votre interface. Cependant, il ne gère pas la gestion d'état complexe ou l'accessibilité (a11y) par défaut pour des widgets complexes comme les listes déroulantes, les modales ou les onglets. Les composants Headless UI, tels que ceux fournis par la bibliothèque React Headless, résolvent ce problème. Ils fournissent la logique JavaScript, la navigation au clavier et les attributs ARIA, tout en laissant le style visuel entièrement à votre discrétion via les classes Tailwind.
Cette séparation des responsabilités signifie que votre bibliothèque de composants reste légère, accessible et entièrement personnalisable, ce qui est le Graal d'un système de design évolutif.
Étape 1 : Configuration du projet
Avant d'écrire du code, assurez-vous que votre environnement est correctement configuré. Installez les dépendances nécessaires. Pour cet exemple, nous supposons un environnement React utilisant Tailwind CSS.
npm install @headlessui/react @headlessui/vue
# Ou si vous utilisez npm/yarn/pnpm selon votre configuration
Ensuite, configurez votre fichier tailwind.config.js pour étendre votre thème. Un bon système de design commence par une palette de couleurs cohérente et une échelle d'espacement.
// tailwind.config.js
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
500: '#3b82f6',
700: '#1d4ed8',
},
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
},
},
},
plugins: [],
}
Étape 2 : Création de primitives réutilisables
Pour véritablement construire un système de design, vous ne devez pas utiliser les composants Headless UI directement dans vos fichiers de vue de manière répétée. Au lieu de cela, enveloppez-les dans vos propres composants primitifs. Cela garantit que chaque bouton, champ de saisie ou modale de votre application respecte les directives de votre marque.
Par exemple, créons un CustomButton réutilisable qui enveloppe les styles standard de bouton de Tailwind. Bien que Headless UI se concentre sur les interactions complexes, les éléments simples bénéficient d'une gestion centralisée des styles.
// components/CustomButton.jsx
import React from 'react';
const CustomButton = ({ children, variant = 'primary', className, ...props }) => {
const baseStyles = "px-4 py-2 rounded-md font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2";
const variants = {
primary: "bg-primary-500 text-white hover:bg-primary-700 focus:ring-primary-500",
secondary: "bg-gray-200 text-gray-800 hover:bg-gray-300 focus:ring-gray-500",
};
return (
);
};
export default CustomButton;
Étape 3 : Intégration de composants Headless complexes
Regardons maintenant un composant plus complexe : un Combobox. Headless UI rend cela incroyablement facile en gérant la logique de la liste déroulante, tandis que nous appliquons nos classes Tailwind.
import { Combobox } from '@headlessui/react';
import { CheckIcon, ChevronUpDownIcon } from '@heroicons/react/20/solid';
const people = [
{ id: 1, name: 'Wade Cooper' },
{ id: 2, name: 'Arlene Mccoy' },
];
export default function UserCombobox() {
const [selected, setSelected] = React.useState(people[0]);
const [query, setQuery] = React.useState('');
const filteredPeople = query === ''
? people
: people.filter((person) =>
person.name.toLowerCase().replace(/\s+,/, '').includes(query.toLowerCase())
);
return (
setQuery(event.target.value)}
/>
{filteredPeople.length === 0 && query !== '' ? (
Aucun résultat trouvé.
) : (
filteredPeople.map((person) => (
`relative cursor-default select-none py-2 pl-10 pr-4 ${active ? 'bg-blue-600 text-white' : 'text-gray-900'}`
}
value={person}
>
{({ selected, active }) => (
<>
{person.name}
{selected ? (
) : null}
>
)}
))
)}
);
}
Meilleures pratiques pour la maintenance
- Conservez les composants purs : Laissez Headless UI gérer l'état et utilisez Tailwind pour la présentation. Évitez de mélanger la logique d'état dans les classes de style.
- Documentez les variantes : Créez un site de documentation comme Storybook pour vos primitives afin de montrer toutes les variantes disponibles.
- Imposez l'accessibilité : Puisque Headless UI gère les attributs ARIA, assurez-vous de ne jamais les supprimer. Testez vos composants régulièrement avec des lecteurs d'écran.
Conclusion
Construire un système de design avec Tailwind CSS et Headless UI est l'un des moyens les plus efficaces d'équilibrer vitesse et qualité. En découplant la logique du style, vous créez une base flexible qui permet à vos designers et développeurs d'avancer main dans la main. À mesure que votre projet évolue, cette approche empêche l'inflation du style et garantit que votre interface reste accessible et cohérente. Commencez petit, construisez vos primitives, et voyez votre vélocité de prototypage s'envoler.