@lifechangers/ui
v0.9.0
Published
Design system LIFE CHANGERS : tokens clair/sombre, polices, texture « alvéoles », logos, icônes et composants du shell pour les applications du LIFE Hub.
Downloads
579
Maintainers
Readme
@lifechangers/ui — design system LIFE CHANGERS
Le socle visuel commun des applications du LIFE Hub : tokens clair et sombre, polices, texture de
marque « alvéoles iridescentes », logos et icônes (apps, domaines, sections) en composants React.
Direction « D · Épurée » validée par Redouane le 2026-09-05 sur les maquettes DonCollect
(_DOCS/DESIGN-SYSTEM/maquettes/).
Ce dépôt est l'étape 1 du chantier C3 du plan
_DOCS/DESIGN-SYSTEM/00-PLAN-HARMONISATION-DA-NAVIGATION.md.
Le suivi est dans ROADMAP-TODOLIST.md.
Ce que contient le package
| Chemin | Rôle |
|---|---|
| src/tokens/tokens.css | Toutes les variables --lc-* : couleurs (clair, sombre, accent par organisation), rayons, ombres, typographie, espacements, mouvement |
| src/tokens/tailwind-preset.cjs | Preset Tailwind 3 pour les 10 apps Lovable (React 18) |
| src/tokens/theme.tailwind4.css | Thème Tailwind 4 (@theme inline) pour les 6 apps TanStack Start (React 19) |
| src/fonts/fonts.css | Jeu libre actif (Anton, Archivo, JetBrains Mono) et emplacements du jeu officiel (Agharti, Acumin) |
| src/brand/texture.css | Surface de marque texturée, bouton principal, tuiles, médaillons, avatars (généré) |
| src/brand/logos/ | Emblème, logo application, principal, horizontal, vertical — dégradé et monochromes, SVG |
| src/tokens/shadcn-bridge.css | Le pont : donne aux variables de thème shadcn les valeurs des --lc-*. Une app l'importe et change de direction artistique sans qu'un composant soit modifié. Généré |
| src/react/ | Marque et icônes (BrandMark, AppIcon, DomainIcon, SectionIcon, HexAvatar), shell (AppShell, Sidebar, Topbar, PageHeader, DetailDrawer), primitives (Button, Pill, Card, StatCard, Segmented, FilterChip, EmptyState), données (DataTable, Honeycomb, SmoothAreaChart, DailyBars), et le style validé du 12/09 (SidebarRail, AiBar, HeroTitle, MiniTile, IconTile) |
| scripts/shadcn_bridge.py | Génère le pont, le pose dans une app (--to), dit s'il a dérivé (--check) |
| scripts/apply_to_app.py | Branche une app entière en une commande, ou vérifie qu'elle l'est (--check) |
| check/render.check.tsx | Contrôle de rendu sans framework (npm run check) |
| dist/ | JavaScript transpilé + déclarations de types, construits par npm run build (tsup). Une app ne compile jamais le TypeScript d'une dépendance |
| scripts/glyphs.py | Source de vérité des glyphes d'icônes ; scripts/build.py régénère CSS, TSX et vitrine |
| showcase/index.html | Page vitrine autonome : tout le package dans les deux thèmes |
Comment la bibliothèque arrive dans les applications (décision du 2026-09-12)
Le hub compte 14 applications, une par dépôt, réparties en deux familles, et elles ne se branchent pas pareil.
| Famille | Apps | Ce qu'elles reçoivent |
|---|---|---|
| Tailwind 3 + shadcn (Vite, déployées par Lovable) | 10 : Center, Bridge, CRM, DonCollect, Engage, People, Pilot, Projects, Studio, Tasks | shadcn-bridge.css posé par commande dans l'app |
| Tailwind 4 + TanStack Start | 4 : Drive, Finance, RGPD, Video | shadcn-bridge-tw4.css posé par la même commande, polices chargées par lien |
Pourquoi un fichier posé et non une dépendance pour la première famille, alors qu'une dépendance serait plus élégante :
- Ces apps sont construites par Lovable. Un fichier déjà présent dans le dépôt n'a rien à installer, rien à authentifier, rien à construire au moment du déploiement. Une dépendance ajoute trois points de panne dans un environnement qu'on ne contrôle pas.
- Lovable réécrit du code. Le pont agit sur les variables de thème de shadcn : tout composant que Lovable régénère hérite de la direction artistique sans rien savoir d'elle. Une bibliothèque de composants React, elle, se ferait écraser.
- Une copie posée ne dérive pas. Elle porte la version, la commande qui la régénère, et
--checkla compare à la bibliothèque. Ce n'est pas une copie recopiée, c'est une copie vérifiée.
La deuxième famille reçoit elle aussi une copie posée, par la même commande : un seul mécanisme pour
tout le hub. Ses polices sont chargées par un lien dans __root.tsx et non par un @import url() dans la
feuille, que la chaîne CSS de Tailwind 4 prend pour un fichier local.
La cible reste npm. Le jour où l'organisation @lifechangers existe sur npm, npm publish suffit :
le champ files n'embarque ni la démo ni ses chiffres réels. D'ici là le dépôt git fait le travail
pour la seconde famille, et la copie posée pour la première.
Brancher une application
Aujourd'hui — la bibliothèque n'est pas encore publiée
Le dépôt est local et n'a pas de dépôt distant. En attendant, une app reçoit une copie posée par la bibliothèque, pas une copie recopiée à la main : elle porte le numéro de version et la commande qui la régénère, et une commande dit si elle a dérivé.
cd DESIGN-SYSTEM/life-design-system
python3 scripts/apply_to_app.py ../../CENTER/life-suite-hub # brancher
python3 scripts/apply_to_app.py ../../CENTER/life-suite-hub --check # vérifierLa commande fait trois choses et ne touche aucun composant de l'app : elle pose
src/styles/lifechangers-da.css, l'importe dans src/main.tsx après ./index.css, et fait lire
var(--font-sans) / var(--font-display) à tailwind.config.ts. Elle est idempotente : la relancer
après un changement de couleur met la copie à jour.
Retour arrière dans une app : supprimer la ligne d'import dans src/main.tsx. Rien d'autre.
Deux pièges, vérifiés sur le CSS construit :
- le pont doit être importé après
index.css, depuismain.tsx. Tailwind 3 retire les at-rules@layerau build : seul l'ordre des règles dans le bundle décide. Importé depuis le haut d'index.css, il passe avant le thème d'origine et n'a aucun effet ; - si
tailwind.config.tscode les polices en dur, elles ne changent pas, quoi que disent les tokens.
Pour s'en assurer, la nouvelle valeur doit arriver en dernier :
npx vite build && grep -bo -- "--primary: [0-9][^;]*" dist/assets/*.cssAjouter une application qui n'existe pas encore
Rien de particulier : apply_to_app.py <chemin> suffit dès que l'app a un package.json, un
src/main.tsx qui importe ./index.css, et un tailwind.config.ts. C'est le cas du modèle d'app du hub.
La commande refuse et dit ce qui manque plutôt que de deviner.
Garde-fou
apply_to_app.py --check sort en erreur si le pont est absent, s'il a dérivé, s'il est importé au mauvais
endroit ou si les polices sont codées en dur. C'est la commande à mettre en intégration continue sur
chaque app du hub.
Après publication
npm install @lifechangers/ui # dans le dossier de l'APPLICATION, jamais dans celui de la bibliothèqueLancée depuis
DESIGN-SYSTEM/life-design-system, cette commande ajoute la bibliothèque comme dépendance d'elle-même. Sans gravité, mais à annuler :npm uninstall @lifechangers/ui.
/* src/index.css */
@import "@lifechangers/ui/index.css";// src/main.tsx — après "./index.css"
import "@lifechangers/ui/shadcn-bridge.css";App Lovable (React 18, Tailwind 3)
// tailwind.config.ts
import preset from "@lifechangers/ui/tailwind-preset";
export default { presets: [preset], content: ["./index.html", "./src/**/*.{ts,tsx}"] };App TanStack Start (React 19, Tailwind 4)
/* src/styles.css */
@import "tailwindcss";
@import "@lifechangers/ui/index.css";
@import "@lifechangers/ui/theme.tailwind4.css";Composants
import { AppIcon, DomainIcon, SectionIcon, BrandMark, HexAvatar } from "@lifechangers/ui";
<AppIcon app="doncollect" size={40} />
<DomainIcon domain="eau" size={32} />
<SectionIcon name="dons" />
<HexAvatar initials="RB" brand />Poser data-lc (ou la classe lc-root) sur le conteneur racine pour hériter du fond, de la couleur et
de la police. Le thème sombre suit prefers-color-scheme ; data-theme="dark" ou "light" sur <html>
force un thème.
Règles d'emploi
- Une surface texturée par écran au maximum (
.lc-surface-brand,.lc-btn-brand,AppIcon,HexAvatar brand) : bouton principal, tuile d'app, avatar d'équipe, panneau de connexion, en-tête d'email, progression. Jamais derrière un tableau, un formulaire ou un texte long. - Violet en clair, turquoise en sombre : l'accent change de couleur avec le thème pour rester lisible.
Le turquoise
#00B5BCde la charte n'est jamais utilisé en texte sur fond clair (contraste 2,2:1). - Couleur par organisation (décision D1) : une organisation cliente pose
data-org-accentet--lc-org-accentsur ses surfaces publiques (page de don, widget, email). LIFE garde le violet. - Aucune couleur en dur dans les apps : tout passe par
--lc-*ou les utilitaires Tailwindlc-*. - Polices : rôles fixes (display, corps, condensé, mono). Le jeu officiel (Agharti + Acumin) remplace le jeu libre par les tokens, sans toucher aux apps, quand les licences sont achetées.
Changer une couleur, une icône, une police
Toujours au même endroit, jamais dans une app :
| Quoi | Où | Puis |
|---|---|---|
| une couleur, un rayon, une ombre | src/tokens/tokens.css | npm run build:bridge, puis apply_to_app.py <app> sur chaque app branchée |
| une icône | scripts/glyphs.py | python3 scripts/build.py |
| la texture | scripts/texture.py | python3 scripts/build.py |
| un composant | src/react/*.tsx | npm run typecheck && npm run check && npm run build |
Les fichiers marqués « généré » en en-tête ne s'éditent pas à la main : ils seront écrasés.
Régénérer les fichiers dérivés
python3 scripts/build.pyModifie scripts/glyphs.py pour les icônes et scripts/texture.py pour la texture ; ne touche pas aux
fichiers marqués « généré ».
