Scaffolding UI Intelligent
Génère des composants complexes (Radix UI / Tailwind) à partir de spécifications fonctionnelles, de la description à l'implémentation en 30 secondes.
3.1Le gabarit de forge
Dans un jeu de fabrication, tu ne forgilles pas une épée en improvisant. Tu suis un plan : matériaux → dimensions → enchantements → finitions. Chaque étape est définie à l'avance.
Générer un composant UI avec l'IA fonctionne pareil. Plus ton spec est précis, plus le composant généré sera directement utilisable sans retouche.
3.2Le template de prompt "scaffold composant"
Tu es un dev React/TypeScript senior spécialisé Next.js + Tailwind + Radix UI.
## Composant à créer
Nom : ArticleCard
## Spécification fonctionnelle
Affiche un aperçu d'article de blog.
- Image à la une (avec fallback si absente)
- Catégorie colorée (badge en haut à droite)
- Titre cliquable (lien vers /[slug])
- Extrait tronqué à 2 lignes
- Auteur + date de publication
- Bouton "Lire la suite" avec arrow icon
## Props (TypeScript strict)
interface ArticleCardProps {
post: WpPost // le type défini dans lib/types
variant?: 'default' | 'featured' | 'compact'
className?: string
}
## Stack
- Tailwind CSS (pas de style inline)
- Radix UI si interaction nécessaire
- Next.js Image pour l'image optimisée
- next/link pour les liens
## Contraintes
- Server Component (pas de 'use client')
- Accessible : rôles ARIA, alt text significatif
- Responsive mobile-first
- Animation hover subtile (scale + shadow)Résultat typique généré par l'IA :
import Image from 'next/image';
import Link from 'next/link';
import { cn } from '@/lib/utils';
import type { WpPost } from '@/lib/types';
interface ArticleCardProps {
post: WpPost;
variant?: 'default' | 'featured' | 'compact';
className?: string;
}
const CATEGORY_COLORS: Record<number, string> = {
1: 'bg-blue-100 text-blue-800',
2: 'bg-green-100 text-green-800',
};
export function ArticleCard({ post, variant = 'default', className }: ArticleCardProps) {
const featuredImage = post._embedded?.['wp:featuredmedia']?.[0]?.source_url;
const author = post._embedded?.author?.[0];
const categoryId = post.categories[0];
return (
<article
className={cn(
'group rounded-2xl overflow-hidden bg-white border border-slate-200',
'shadow-sm hover:shadow-md transition-all duration-300 hover:-translate-y-0.5',
variant === 'featured' && 'md:col-span-2',
className
)}
>
{/* Image */}
{featuredImage && (
<div className="relative overflow-hidden aspect-video">
<Image
src={featuredImage}
alt={post.title.rendered}
fill
className="object-cover group-hover:scale-105 transition-transform duration-500"
sizes="(max-width: 768px) 100vw, 50vw"
/>
{categoryId && (
<span className={cn(
'absolute top-3 right-3 text-xs font-medium px-2 py-1 rounded-full',
CATEGORY_COLORS[categoryId] ?? 'bg-slate-100 text-slate-700'
)}>
Catégorie
</span>
)}
</div>
)}
{/* Contenu */}
<div className="p-5">
<h2 className="font-bold text-lg text-slate-900 mb-2 line-clamp-2">
<Link href={`/${post.slug}`} className="hover:text-blue-600 transition-colors">
{post.title.rendered}
</Link>
</h2>
<p
className="text-slate-500 text-sm mb-4 line-clamp-2"
dangerouslySetInnerHTML={{ __html: post.excerpt.rendered }}
/>
{/* Meta */}
<div className="flex items-center justify-between">
<div className="flex items-center gap-2 text-xs text-slate-400">
<span>{author?.name}</span>
<span>·</span>
<time dateTime={post.date}>
{new Date(post.date).toLocaleDateString('fr-FR', { day: 'numeric', month: 'short', year: 'numeric' })}
</time>
</div>
<Link
href={`/${post.slug}`}
className="text-xs font-medium text-blue-600 hover:text-blue-800 flex items-center gap-1"
aria-label={`Lire ${post.title.rendered}`}
>
Lire <i className="fa-solid fa-arrow-right text-xs" />
</Link>
</div>
</div>
</article>
);
}3.3La variante "composant Radix UI"
Pour les composants interactifs (dialog, dropdown, tooltip…), précise l'utilisation de Radix dans ton prompt :
Crée un composant React "DeleteConfirmDialog" avec Radix UI Dialog.
Comportement :
- Bouton déclencheur rouge "Supprimer"
- Dialog de confirmation avec titre et description
- Bouton "Annuler" (secondary) et "Confirmer" (destructive, rouge)
- Fermeture avec Escape et clic overlay
Props :
- itemName: string - le nom de l'élément à supprimer
- onConfirm: () => Promise<void> - action asynchrone
- isLoading?: boolean - état de chargement
Stack : Radix UI Dialog + Tailwind CSS + TypeScript strict
Accessibilité : focus trap, aria-describedby, loading state désactive les boutonsLe ratio qualité/temps
Sans scaffold IA
45 min - 1h par composant complexe
Avec scaffold IA
5-10 min avec un prompt précis