Skip to main content

react-dsfr

Créer des interfaces React conformes au Design System de l'État français (DSFR) avec @codegouvfr/react-dsfr. Utiliser cette skill quand l'utilisateur demande de créer des pages, composants ou interfaces en React utilisant le DSFR, quand il mentionne react-dsfr, le design system de l'État, ou quand le projet utilise @codegouvfr/react-dsfr. Couvre les composants natifs react-dsfr (pas MUI), le routing, les icônes, les couleurs et les patterns de mise en page.

소스 정보

저장소
etalab-ia/skills
최근 소스 활동
2026년 9월 3일 14:49
감지된 SKILL.md 언어
프랑스어
스타
23
포크
0

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
4 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
react-dsfr
description
Créer des interfaces React conformes au Design System de l'État français (DSFR) avec @codegouvfr/react-dsfr. Utiliser cette skill quand l'utilisateur demande de créer des pages, composants ou interfaces en React utilisant le DSFR, quand il mentionne react-dsfr, le design system de l'État, ou quand le projet utilise @codegouvfr/react-dsfr. Couvre les composants natifs react-dsfr (pas MUI), le routing, les icônes, les couleurs et les patterns de mise en page.
# react-dsfr Bibliothèque React pour le Design System de l'État français. Package : `@codegouvfr/react-dsfr`. ## Import pattern Chaque composant a son propre chemin d'import : ```tsx import { Button } from "@codegouvfr/react-dsfr/Button"; import { Alert } from "@codegouvfr/react-dsfr/Alert"; import { Card } from "@codegouvfr/react-dsfr/Card"; // etc. ``` ## Setup Next.js App Router > ⚠️ **Pattern obligatoire** : sans `getScriptToRunAsap()` dans `<head>`, le mode sombre cause un **flash blanc visible au chargement** (régression la plus courante). Le code ci-dessous est le minimum incompressible — ne pas écrire un `layout.tsx` plus simple. Pattern minimal en 3 fichiers (Next.js 14+ App Router, react-dsfr v1.30+), aligné sur le starter officiel react-dsfr (`dsfr-bootstrap`) : **1. `src/dsfr-bootstrap/defaultColorScheme.ts`** — constante partagée par le layout (serveur) et le provider (client) : ```tsx export const defaultColorScheme = "system" as const; ``` **2. `src/dsfr-bootstrap/index.tsx`** — wrapper `"use client"` qui importe `Link` : ```tsx "use client"; import { DsfrProviderBase, StartDsfrOnHydration, type DsfrProviderProps } from "@codegouvfr/react-dsfr/next-app-router"; import { defaultColorScheme } from "./defaultColorScheme"; import Link from "next/link"; declare module "@codegouvfr/react-dsfr/next-app-router" { interface RegisterLink { Link: typeof Link; } } export function DsfrProvider(props: DsfrProviderProps) { return ( <DsfrProviderBase defaultColorScheme={defaultColorScheme} Link={Link} {...props} /> ); } export { StartDsfrOnHydration }; ``` **3. `src/app/layout.tsx`** — composant serveur, ne passe au provider que des props sérialisables : ```tsx import { createGetHtmlAttributes } from "@codegouvfr/react-dsfr/next-app-router/getHtmlAttributes"; import { getScriptToRunAsap } from "@codegouvfr/react-dsfr/useIsDark/scriptToRunAsap"; import "@codegouvfr/react-dsfr/dsfr/dsfr.min.css"; import "@codegouvfr/react-dsfr/dsfr/utility/icons/icons.main.min.css"; import { DsfrProvider, StartDsfrOnHydration } from "../dsfr-bootstrap"; import { defaultColorScheme } from "../dsfr-bootstrap/defaultColorScheme"; const { getHtmlAttributes } = createGetHtmlAttributes({ defaultColorScheme }); export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html {...getHtmlAttributes({ lang: "fr" })}> <head> <script dangerouslySetInnerHTML={{ __html: getScriptToRunAsap({ defaultColorScheme, nonce: undefined, trustedTypesPolicyName: "react-dsfr", }), }} /> </head> <body> <DsfrProvider lang="fr"> {children} <StartDsfrOnHydration /> </DsfrProvider> </body> </html> ); } ``` **Pourquoi le wrapper `"use client"` ?** `layout.tsx` est un composant serveur ; `DsfrProviderBase` est un composant client (module `"use client"` dans le package). Le pattern officiel react-dsfr garde l'import de `Link` et la déclaration `RegisterLink` dans un module client dédié, le layout serveur ne passant que des props sérialisables (`lang`, `children`). `defaultColorScheme` vit dans son propre module (hors `"use client"`) car il est lu des deux côtés de la frontière serveur/client. **Trois éléments critiques** (ne pas omettre) : 1. **`createGetHtmlAttributes()`** : pose `data-fr-scheme` / `data-fr-theme` / `suppressHydrationWarning` sur `<html>` côté SSR 2. **`getScriptToRunAsap()` dans `<head>`** : script inline qui détecte le thème (localStorage ou `prefers-color-scheme`) **avant le premier paint CSS** — c'est lui qui élimine le flash. `nonce: undefined` ne vaut qu'en dev ; **sous CSP**, passer un `nonce` par requête (cf. [references/setup.md](references/setup.md#pattern-1--recommandé--sans-transpilepackages-imports-directs)) 3. **`StartDsfrOnHydration`** : re-scan du DOM après hydratation React pour bind les `Display`, modales, accordéons (sans ça, les boutons `aria-controls` sont muets au clic) **Noms react-dsfr v1.30+** : `DsfrProviderBase`, `StartDsfrOnHydration`, `createGetHtmlAttributes`, `DsfrHeadBase`. Les anciens noms (`DsfrProvider`, `StartDsfr`, `getHtmlAttributes`, `DsfrHead`) **n'existent plus dans le package** — ne pas les écrire. (Le wrapper local `DsfrProvider` créé ci-dessus est le nôtre, calqué sur le starter officiel — ce n'est pas un export du package.) Cette approche n'a **pas besoin de `transpilePackages`** dans `next.config.mjs` (les imports directs depuis `.../getHtmlAttributes` et `.../scriptToRunAsap` évitent le tree-shake de `DsfrHead.js` qui tire les `.woff2`). Pour les variantes (avec `DsfrHeadBase` + `transpilePackages`, icônes dynamiques via `iconId`, re-init manuelle DSFR), voir [references/setup.md](references/setup.md#nextjs-app-router). ## Routing et liens Enregistrer le composant `Link` du framework une seule fois au démarrage. Tous les composants react-dsfr utilisant `linkProps` s'en serviront automatiquement. - Liens internes : utilisent le routeur (client-side navigation) - URLs externes (`https://...`) : rendus comme `<a>` classiques - `href="#"` + `onClick` : convertis automatiquement en `<button>` accessible Voir [references/setup.md](references/setup.md) pour le setup par framework (Next.js, Vite, CRA). ## Utilitaire CSS : `fr.cx()` ```tsx import { fr } from "@codegouvfr/react-dsfr"; // Appliquer des classes utilitaires DSFR <div className={fr.cx("fr-grid-row", "fr-grid-row--gutters")}> <div className={fr.cx("fr-col-12", "fr-col-md-6")}>...</div> </div> // Spacing <div className={fr.cx("fr-mt-4w", "fr-mb-2w", "fr-p-3w")}>...</div> ``` ## Grille Le DSFR utilise une grille 12 colonnes : ```tsx <div className={fr.cx("fr-grid-row", "fr-grid-row--gutters")}> <div className={fr.cx("fr-col-12", "fr-col-md-6", "fr-col-lg-4")}>Col 1</div> <div className={fr.cx("fr-col-12", "fr-col-md-6", "fr-col-lg-4")}>Col 2</div> <div className={fr.cx("fr-col-12", "fr-col-lg-4")}>Col 3</div> </div> ``` Breakpoints : `sm` (576px), `md` (768px), `lg` (992px), `xl` (1248px). ## Icônes Deux familles d'icônes disponibles : - **DSFR** : `fr-icon-*` (ex: `"fr-icon-add-line"`, `"fr-icon-delete-fill"`, `"fr-icon-arrow-right-line"`) - **Remix Icon** : `ri-*` (ex: `"ri-account-box-line"`, `"ri-information-line"`) Les icônes sont typées : TypeScript offre l'autocomplétion. ## Couleurs et thème ```tsx import { useColors } from "@codegouvfr/react-dsfr/useColors"; function MyComponent() { const theme = useColors(); // theme.decisions.background.default.grey.default // theme.decisions.text.title.grey.default // theme.decisions.border.default.grey.default } ``` Le thème respecte automatiquement le mode clair/sombre, à condition que le setup du layout soit complet (cf. section "Setup Next.js App Router" plus haut). Le mode sombre est résolu côté SSR + script anti-flash dans `<head>` ; le `useColors()` lit ensuite la palette résolue. ## Pattern : page complète ```tsx import { Header } from "@codegouvfr/react-dsfr/Header"; import { Footer } from "@codegouvfr/react-dsfr/Footer"; import { Breadcrumb } from "@codegouvfr/react-dsfr/Breadcrumb"; import { fr } from "@codegouvfr/react-dsfr"; export function Page() { return ( <> <Header brandTop={<>RÉPUBLIQUE<br />FRANÇAISE</>} homeLinkProps={{ href: "/", title: "Accueil" }} serviceTitle="Mon service" /> <div className={fr.cx("fr-container", "fr-my-4w")}> <Breadcrumb homeLinkProps={{ href: "/" }} segments={[{ label: "Section", linkProps: { href: "/section" } }]} currentPageLabel="Page courante" /> <h1>Titre de la page</h1> {/* Contenu */} </div> <Footer accessibility="partially compliant" brandTop={<>RÉPUBLIQUE<br />FRANÇAISE</>} homeLinkProps={{ href: "/", title: "Accueil" }} /> </> ); } ``` ## Pattern : page avec menu latéral ```tsx <div className={fr.cx("fr-container", "fr-my-4w")}> <div className={fr.cx("fr-grid-row", "fr-grid-row--gutters")}> <div className={fr.cx("fr-col-12", "fr-col-md-4")}> <SideMenu title="Rubrique" burgerMenuButtonText="Menu" items={[ { text: "Page 1", linkProps: { href: "/p1" }, isActive: true }, { text: "Page 2", linkProps: { href: "/p2" } }, ]} /> </div> <div className={fr.cx("fr-col-12", "fr-col-md-8")}> {/* Contenu principal */} </div> </div> </div> ``` ## Pattern : formulaire ```tsx import { Input } from "@codegouvfr/react-dsfr/Input"; import { Select } from "@codegouvfr/react-dsfr/Select"; import { Checkbox } from "@codegouvfr/react-dsfr/Checkbox"; import { ButtonsGroup } from "@codegouvfr/react-dsfr/ButtonsGroup"; import { Alert } from "@codegouvfr/react-dsfr/Alert"; export function MyForm() { return ( <form> <Input label="Nom" nativeInputProps={{ required: true }} /> <Input label="Email" nativeInputProps={{ type: "email" }} /> <Select label="Département" nativeSelectProps={{ name: "dept" }}> <option value="" disabled hidden>Sélectionnez</option> <option value="75">Paris</option> </Select> <Checkbox legend="Préférences" options={[{ label: "Newsletter", nativeInputProps: { name: "newsletter" } }]} /> <ButtonsGroup inlineLayoutWhen="always" buttons={[ { children: "Envoyer", type: "submit" }, { children: "Annuler", priority: "secondary", type: "reset" }, ]} /> </form> ); } ``` ## Pattern : liste de cartes ```tsx <div className={fr.cx("fr-grid-row", "fr-grid-row--gutters")}> {items.map(item => ( <div key={item.id} className={fr.cx("fr-col-12", "fr-col-md-6", "fr-col-lg-4")}> <Card enlargeLink title={item.title} desc={item.description} linkProps={{ href: `/items/${item.id}` }} imageUrl={item.imageUrl} imageAlt={item.imageAlt} badge={<Badge severity="info">{item.category}</Badge>} /> </div> ))} </div> ``` ## Référence des composants Consulter [references/components.md](references/components.md) pour l'API complète de chaque composant : - **Layout** : Header, Footer, SideMenu, Breadcrumb, Pagination, Stepper
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기