chore: initial DSMMG v0.2 — refonte architecturale complète
Release / Release / open changeset PR (push) Has been cancelled
CI / Build, typecheck, test, a11y (push) Has been cancelled

Mise en place du Design System ManageMate Group v0.2 — refonte du
système de tokens (préfixe --mmg-color-*), 9 presets accent
user-themable validés WCAG AA, overlays Radix UI + Floating UI,
Storybook 8 + Vitest + axe-core en CI, doc Astro Starlight,
DESIGN.md (format google-labs-code) et exports tokens DTCG/CSS/
TS/Figma/Tailwind v3 et v4.

- 4 packages monorepo pnpm : @managemate/{tokens,css,react,icons}
- 62 composants React headless-first (Sheet, HoverCard, ContextMenu,
  Slider, ToggleGroup, AvatarGroup, UserCard, ProfileHeader,
  MetricCard, PricingCard, FeatureCard, Text/Display/Eyebrow/Lead…)
- Lint contraste WCAG : 37/37 paires AA, branché CI
- Toast pile Sonner-style avec ResizeObserver
- Theming user (9 presets) sans casser sémantique fixe
- Identité Synapse (rose #D12B6A) préservée

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dinawo
2026-05-04 22:07:57 +02:00
parent 5e019857fc
commit 62317f2ad7
172 changed files with 31397 additions and 1 deletions
+191
View File
@@ -0,0 +1,191 @@
// DSMMG icon builder
// - Émet un bundle complet (icons.css) avec base + toutes les classes
// - Émet aussi des modules par icône (each/<name>.css) pour permettre le
// tree-shaking côté consommateur (import "@managemate/icons/each/check-line").
// - Émet le module base.css (la classe .mmg-icon + sizes) en stand-alone,
// utile quand on n'importe que des icônes individuelles.
import { readFile, writeFile, mkdir, rm } from "node:fs/promises";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { existsSync } from "node:fs";
const __dirname = dirname(fileURLToPath(import.meta.url));
const REMIX_DIR = join(__dirname, "node_modules", "remixicon", "icons");
const DIST_DIR = join(__dirname, "dist");
const EACH_DIR = join(DIST_DIR, "each");
if (existsSync(DIST_DIR)) await rm(DIST_DIR, { recursive: true });
await mkdir(EACH_DIR, { recursive: true });
const ICONS = [
["Arrows", "arrow-right"],
["Arrows", "arrow-left"],
["Arrows", "arrow-up"],
["Arrows", "arrow-down"],
["Arrows", "arrow-right-up"],
["Arrows", "arrow-go-back"],
["Arrows", "expand-up-down"],
["System", "external-link"],
["System", "check"],
["System", "close"],
["System", "add"],
["System", "subtract"],
["System", "search-2"],
["System", "filter-3"],
["System", "more"],
["System", "more-2"],
["System", "menu"],
["System", "settings-3"],
["System", "refresh"],
["System", "delete-bin"],
["Design", "edit"],
["System", "share"],
["System", "download"],
["System", "upload"],
["System", "information"],
["System", "alert"],
["System", "error-warning"],
["System", "checkbox-circle"],
["System", "close-circle"],
["System", "question"],
["System", "spam"],
["System", "shield-check"],
["User & Faces", "user"],
["User & Faces", "user-add"],
["User & Faces", "team"],
["User & Faces", "account-circle"],
["System", "logout-box-r"],
["System", "login-box"],
["System", "lock"],
["System", "lock-unlock"],
["System", "eye"],
["System", "eye-off"],
["Business", "mail"],
["Business", "mail-send"],
["Communication", "message-2"],
["Device", "phone"],
["Media", "notification-3"],
["Communication", "chat-3"],
["Business", "global"],
["Business", "calendar"],
["Business", "calendar-check"],
["System", "time"],
["System", "history"],
["Document", "file-text"],
["Document", "file"],
["Document", "folder"],
["Document", "folder-open"],
["Document", "file-pdf"],
["Document", "file-copy"],
["Editor", "attachment"],
["Document", "draft"],
["Business", "inbox"],
["Map", "rocket-2"],
["Buildings", "home-4"],
["Buildings", "building"],
["Buildings", "store-2"],
["Buildings", "community"],
["Map", "map-pin-2"],
["Map", "map-2"],
["Finance", "money-euro-circle"],
["Finance", "bank-card"],
["Finance", "shopping-cart-2"],
["Finance", "shopping-bag-3"],
["Finance", "price-tag-3"],
["Finance", "coins"],
["Business", "briefcase-4"],
["Business", "line-chart"],
["Business", "bar-chart"],
["Business", "pie-chart"],
["Business", "stack"],
["System", "dashboard"],
["System", "apps-2"],
["System", "function"],
["Business", "presentation"],
["Document", "newspaper"],
["Document", "article"],
["Document", "book-open"],
["Business", "bookmark-3"],
["Health & Medical", "heart-3"],
["System", "star"],
["System", "thumb-up"],
["Design", "palette"],
["Design", "magic"],
["Weather", "flashlight"],
["Weather", "sun"],
["Weather", "moon"],
];
const BASE_CSS = `/* DSMMG icons — base (auto-generated). */
.mmg-icon {
display: inline-block;
width: 1.25em;
height: 1.25em;
vertical-align: -0.225em;
background: currentColor;
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
-webkit-mask-size: contain;
flex-shrink: 0;
}
.mmg-icon--xs { width: 12px; height: 12px; }
.mmg-icon--sm { width: 14px; height: 14px; }
.mmg-icon--md { width: 18px; height: 18px; }
.mmg-icon--lg { width: 24px; height: 24px; }
.mmg-icon--xl { width: 32px; height: 32px; }
.mmg-icon--2xl { width: 48px; height: 48px; }
`;
const rules = [];
const names = [];
const missing = [];
for (const [category, base, alias] of ICONS) {
for (const variant of ["line", "fill"]) {
const file = join(REMIX_DIR, category, `${base}-${variant}.svg`);
if (!existsSync(file)) {
missing.push(`${category}/${base}-${variant}`);
continue;
}
const svg = (await readFile(file, "utf8"))
.replace(/[\r\n]+/g, "")
.replace(/"/g, "'")
.replace(/\s+/g, " ")
.trim();
const url = `data:image/svg+xml,${encodeURIComponent(svg)}`;
const className = `${alias ?? base}-${variant}`;
const rule = `.mmg-icon-${className} { mask-image: url("${url}"); -webkit-mask-image: url("${url}"); }`;
rules.push(rule);
names.push(className);
// Module subset par icône — n'inclut PAS la base, à charger séparément ou
// implicitement via @managemate/icons/base.
await writeFile(join(EACH_DIR, `${className}.css`), rule + "\n");
}
}
// Bundle complet — base + toutes les classes
await writeFile(join(DIST_DIR, "icons.css"), BASE_CSS + "\n" + rules.join("\n") + "\n");
// Base seule — utile pour ceux qui font du subset
await writeFile(join(DIST_DIR, "base.css"), BASE_CSS);
await writeFile(join(DIST_DIR, "icons.json"), JSON.stringify(names, null, 2));
await writeFile(
join(DIST_DIR, "names.js"),
`export default ${JSON.stringify(names, null, 2)};\n`,
);
await writeFile(
join(DIST_DIR, "names.d.ts"),
`declare const names: string[];\nexport default names;\n`,
);
console.log(`Built ${names.length} icon classes (${ICONS.length} icons × 2 variants)`);
console.log(` - dist/icons.css (bundle, ${BASE_CSS.length + rules.join("\n").length} bytes)`);
console.log(` - dist/base.css (base only)`);
console.log(` - dist/each/<name>.css (${names.length} per-icon modules)`);
if (missing.length) {
console.warn(`Missing ${missing.length} files:`, missing.slice(0, 5));
}
+21
View File
@@ -0,0 +1,21 @@
{
"name": "@managemate/icons",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@managemate/icons",
"version": "0.1.0",
"dependencies": {
"remixicon": "^4.9.1"
}
},
"node_modules/remixicon": {
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/remixicon/-/remixicon-4.9.1.tgz",
"integrity": "sha512-36gLSoujkabnCFZFDyP17VNh9piuBA/rsXUb4auSJWLGsHVXtmxLj/EM5FjaEAGnk8oIAj1Azob/DZ2N+90lAQ==",
"license": "Apache-2.0"
}
}
}
+35
View File
@@ -0,0 +1,35 @@
{
"name": "@managemate/icons",
"version": "0.1.0",
"description": "DSMMG icon system — CSS classes mmg-icon-* + per-icon subset modules",
"license": "UNLICENSED",
"private": true,
"sideEffects": [
"*.css"
],
"main": "./dist/icons.css",
"style": "./dist/icons.css",
"exports": {
".": {
"style": "./dist/icons.css",
"default": "./dist/icons.css"
},
"./base": "./dist/base.css",
"./each/*": "./dist/each/*.css",
"./names": {
"types": "./dist/names.d.ts",
"default": "./dist/names.js"
},
"./package.json": "./package.json"
},
"scripts": {
"build": "node build.mjs"
},
"files": [
"dist",
"build.mjs"
],
"dependencies": {
"remixicon": "^4.9.1"
}
}