diff --git a/AGENTS.md b/AGENTS.md index ba40321..2a299ea 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -352,6 +352,13 @@ $focus-ring-width: utils.$form-focus-ring-width; // ← replace the value here t 3. Create the story + the `.mdx` **co-located** in `projects/ui-kit//ui-/` (outside `src/`; global doc only → `storybook/docs/`) — pick `` from `storybook/docs/Overview.mdx`'s sections, or ask if the component doesn't fit an existing one 4. Check off the component in `components-index.md` +> File **placement** does not drive the Storybook sidebar tree — the `title` does +> (``, or the story's `title:`). Placement only decides what ships: a +> co-located `.stories.ts`/`.mdx` sits outside the entry point's `src/`, which is where +> `ng-packagr` starts from, so it never reaches `@4sh/ui-kit`. It does travel in +> `@4sh/ui-kit-schematics` (FSHSP-125), which copies it next to the component so a +> starter project documents its own copies. + ### Create a business component (domain) Like a `ui-*`, but: project prefix, `domain/` folder, and **composition of `ui-*` instances** (never style copying). diff --git a/CHANGELOG.md b/CHANGELOG.md index 54ee0db..8c1c771 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Le format suit [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/) et le pr Les imports suivent les copies, comme pour les sources — mais les extraits de code des pages ne sont pas réécrits : ce sont des exemples destinés au lecteur, pas des imports à résoudre. Les liens `parameters.design` vers notre fichier Figma sont retirés à la copie : le consommateur n'y a pas accès. Les pages transverses embarquées se limitent à *Foundations*, *Spécifications* et *Configuration* ; `Introduction`, `NpmPackage` et `Overview` parlent du kit lui-même et restent ici. Désactivé par défaut : sans Storybook, story et MDX sont deux fichiers qui importent des packages absents. Le choix est retenu dans `ui-kit.json` et `update` s'y tient. +- **Les README du kit (EN + FR) présentent les deux modes de consommation** (FSHSP-116) : section « Deux modes de consommation » avant l'installation — tableau comparatif *dépendance* / *starter* (ce qui arrive dans le dépôt, imports, styles, documentation, personnalisation, mise à jour), qui renvoie au package compagnon pour la voie starter. FSHSP-109 avait livré le mode starter sans qu'il apparaisse nulle part sur la page npm, où le README est la seule documentation. - **`@4sh/ui-kit-schematics` embarque son `LICENSE` et ses README** (EN + FR). Le package déclarait `Apache-2.0` sans en fournir le texte, alors que la licence (§4a) demande qu'une redistribution en joigne une copie — d'autant plus ici que ce package existe pour que son contenu soit recopié ailleurs. Sa page npmjs, jusque-là vide, redirige maintenant vers `@4sh/ui-kit` : le compagnon ne s'installe jamais directement. ### Fixed diff --git a/README.md b/README.md index b176d09..1c91f76 100644 --- a/README.md +++ b/README.md @@ -10,20 +10,20 @@ This is the **Starter Angular** side of the *Dual-Engine* strategy: - The layer shared across stacks = the **design tokens** (CSS variables). - The **component styling is co-located** (Angular scoped `.scss`) and consumes these tokens. -The `ui-*` kit is published as the **[`@4sh/ui-kit`](https://www.npmjs.com/package/@4sh/ui-kit)** -npm package (one secondary entry point per component) — see -[`projects/ui-kit/README.md`](projects/ui-kit/README.md). This repo holds both the -package and the demo application that consumes it. +This repo holds the **[`@4sh/ui-kit`](https://www.npmjs.com/package/@4sh/ui-kit)** package +(53 secondary entry points / 54 `ui-*` components) and the demo application that consumes it. -Both are published to GitHub Pages on every push to `main` -([`deploy-pages.yml`](.github/workflows/deploy-pages.yml)): +| | | +|---|---| +| **Storybook** — component catalogue and foundations | | +| **Demo application** — the kit in a real app | | +| **Package** | [npmjs.com/package/@4sh/ui-kit](https://www.npmjs.com/package/@4sh/ui-kit) | -- **Storybook** (published catalogue): - -- **Demo application** (the kit in a real app): - +Both sites are redeployed on every push to `main` +([`deploy-pages.yml`](.github/workflows/deploy-pages.yml)). --- + ## Stack | Layer | Tech | @@ -31,176 +31,68 @@ Both are published to GitHub Pages on every push to `main` | Framework | Angular 22 standalone, signals, zoneless | | Behavior | Components + `@angular/cdk` | | Style | Co-located per component (scoped `.scss`) + CSS custom properties | -| Tokens | JSON (Token Flow Manager) → `scripts/tokens.build.mjs` → SCSS (`projects/ui-kit/styles/generated/`) | +| Tokens | JSON (Token Flow Manager) → `scripts/tokens.build.mjs` → SCSS | | Storybook | 10.x + addon-designs (Figma) | | Grid | Gridaflex | | Icons | FontAwesome Free | - ---- - -## Getting started - -```bash -npm install # install + postinstall: tokens:build, ui-kit:build, docs:config -npm start # Storybook → http://localhost:6006 -npm run serve # demo application → http://localhost:4200 -npm run tokens:build # regenerate the token CSS variables -npm run ui-kit:build # build the @4sh/ui-kit package into dist/ui-kit -npm run docs:config # regenerate the Theming tables of the Storybook docs -npm run build && npm run build-storybook -npm run lint -``` - -> `npm start`, `npm run serve` and the two builds all run `ui-kit:build` first: the -> demo app consumes the kit through its **built** output (`dist/ui-kit`, mapped by the -> `@4sh/ui-kit/*` `paths` of `tsconfig.json`), exactly like an external consumer would. - -### Themes & modes (runtime, via attributes on ``) - -| Dimension | Attribute | Service | -|---|---|---| -| Brand | `[data-brand='brand2'\|'brand3']` (brand1 = default) | `BrandService` (maps the subdomain) | -| Light/Dark | `[data-theme='dark']` (light = default) | `ThemeService` | - -The semantics reference the primitives (`var(--primitives-*)`): switching brand or mode -recomposes everything without duplication. - --- -## Structure - -``` -projects/ui-kit/ ← the @4sh/ui-kit PACKAGE (published) -├── ui-button/ … ui-tooltip/ ← 53 entry points / 54 ui-* components -│ ├── src/lib/ui-x.{ts,html,scss} ← the component, co-located -│ └── ui-x.{stories.ts,mdx} ← its doc, outside src/ (not packaged) -├── forms/ ← BaseControlValueAccessor, BaseFieldControl, BaseFormField… -├── theming/ ← ThemeService ([data-theme]), BrandService ([data-brand]) -├── motion/ overlay/ types/ ← UiMotion · closeOnNavigation · UiLevel, UiSize… -└── styles/ ← SCSS foundation shipped with the package - ├── generated/ ← GENERATED CSS variables — do not edit - ├── base/ settings/ utils/ ← base layer, settings, utils API (no CSS emitted) - └── index.scss ← compiled to dist/ui-kit/styles.css - -src/ ← DEMO application only -├── app/shared/components/domain/ ← business components (project prefix), compose ui-* -├── design-tokens/ ← token SOURCE (JSON, Token Flow Manager export) -└── styles/ ← app-side global styles (Gridaflex, layout, vendors) - -scripts/tokens.build.mjs ← token resolver (DTCG → SCSS vars) -scripts/docs.config.mjs ← SCSS roles → storybook/generated/ui-config.json -storybook/ ← config + global documentation -docs/ ← VERSIONING.md · PUBLISHING.md · Figma runbooks -``` - -> `projects/ui-kit/styles/generated/` is **generated** (gitignored), rebuilt by -> `npm run tokens:build`. Same for `storybook/generated/` (`npm run docs:config`). +## Using the kit in an application -### CSS variable naming +**You do not need this repo.** The kit is published on the public npm registry and +consumed in one of two modes: -`--primitives-*` · `--metrics-*` · semantics without prefix (`--actions-high-surface-default`, -`--global-*`) · `--fontfamily-*` / `--weight-*` · `--transition-*`. - ---- - -## CSS class conventions (no BEM) - -| Element | Convention | SCSS | -|---|---|---| -| Root | `ui-{name}` | `.ui-{name}` | -| Sub-element | `ui-{name}-{part}` | `&-{part}` | -| Modifier | `_{modifier}` | `&._{modifier}` | - -```scss -.ui-button { - &-icon { … } // .ui-button-icon - &._small { … } // modifier - &._high { … } // level modifier - &:hover { … } // states = pseudo-classes (never a modifier class) -} +```bash +npm install @4sh/ui-kit # dependency — compiled components, updated by version bump +ng add @4sh/ui-kit-schematics # starter — component sources copied into your project, yours to edit ``` ---- +Starter mode goes through the companion package, and deliberately leaves +`@4sh/ui-kit` out of `node_modules`: the one command lays the foundation and +copies the components you pick, `--with-storybook` brings their documentation +along, and `ng generate @4sh/ui-kit-schematics:update` replays their diff after a +kit release. -## Adding a new component (recipe) +Everything a consumer needs — choosing between the two modes, the list of entry +points, the stylesheet to load, the providers expected by `ui-image` and +`BrandService`, building your own field on `@4sh/ui-kit/forms` — is documented +**once**, in the README shipped with the package (which is also what the npmjs +page displays): -Replicate the `actions/ui-button` (+ `base/ui-icon`) reference pattern. One folder -per component under `projects/ui-kit//` (grouped by category — see -`storybook/docs/Overview.mdx` for the mapping), which **is** the secondary entry -point — example for `@4sh/ui-kit/forms/ui-input`: +**[`projects/ui-kit/README.md`](projects/ui-kit/README.md)** · +[Français](projects/ui-kit/README.fr.md) -``` -projects/ui-kit/forms/ui-input/ -├── ng-package.json ← declares the entry point (entryFile + styleIncludePaths) -├── src/ -│ ├── public-api.ts ← what the entry point exports -│ └── lib/ui-input.{ts,html,scss} -├── ui-input.stories.ts ← OUTSIDE src/: Storybook only, never packaged -└── ui-input.mdx -``` - -1. **Component** — in `src/lib/`: - - `ui-input.ts`: `input()` signals + `computed()` that assembles the class list. - - `ui-input.html`: headless native HTML (+ CDK if overlay/a11y), accessible. - - `ui-input.scss`: **co-located style**, classes `.ui-input` / `&-…` / `&._…`, - values only via `var(--…)`. Document the public roles with `///` comments — - they feed the `## Theming` section of the MDX (see below). -2. **Entry point** — copy the `ng-package.json` of a neighbouring component and export - the class from `src/public-api.ts`. -3. **Story & doc** — `ui-input.stories.ts` + `ui-input.mdx` at the folder root. - -⚠️ Importing from **another entry point** must use the real package name -(`@4sh/ui-kit/base/ui-icon`), never a relative path: `ng-packagr` only records the -dependency in that form — otherwise the build order is undefined and fails -intermittently. - -Golden rules: **no** hardcoded values (everything via tokens) · **accessibility** (native element, -`aria-label`, `:focus-visible`, `disabled`). +The API of each component, the tokens, the themes and the responsive rules are in +the [Storybook](https://4sh.github.io/starter-angular/?path=/docs/introduction--docs). --- -## Storybook — file organization - -Three locations, one simple rule: +## Working in this repo -- **Component → co-location.** Each component carries its `*.stories.ts` and `*.mdx` - files **in its own folder**, at the entry point root (outside `src/`, so they never - ship in the package): `projects/ui-kit//ui-x/ui-x.stories.ts` + `ui-x.mdx`. -- **Global documentation** (foundations, guidelines, design system, overview) → **`storybook/docs/`** - (subfolders `foundations/`, `specifications/`). Never put component-specific doc there. +Only needed to build the design system itself: add or modify a `ui-*` component, +edit the tokens, cut a release. -The `storybook/main.js` config targets all three sources: - -```js -stories: [ - './docs/**/*.mdx', // global doc - '../projects/ui-kit/**/*.mdx', // co-located kit doc - '../projects/ui-kit/**/*.stories.@(js|jsx|mjs|ts|tsx)', - '../src/app/shared/components/**/*.mdx', // app-side domain/ components - '../src/app/shared/components/**/*.stories.@(js|jsx|mjs|ts|tsx)', -] +```bash +npm install # install + postinstall: tokens:build, ui-kit:build, docs:config +npm start # Storybook → http://localhost:6006 +npm run serve # demo application → http://localhost:4200 +npm run tokens:build # regenerate the token CSS variables +npm run ui-kit:build # build the package into dist/ui-kit +npm run lint # ESLint --fix ``` -> File **placement** does not affect the sidebar tree: it is driven by the -> `title` (`` or the story's `title:`). Co-located `.stories.ts` files -> never reach the published package: they sit outside the entry point's `src/`, which -> is where `ng-packagr` starts from. - -### The `## Theming` section is generated, never written by hand - -`npm run docs:config` (`scripts/docs.config.mjs`) reads the `///` comments of each -component `.scss` and produces `storybook/generated/ui-config.json`, rendered by -``. So a role is documented **where it is declared**: - -```scss -$card-padding: var(--units-lg); /// Inset du corps. -$card-radius: var(--radius-md); /// Rayon des coins. -``` +> `npm start`, `npm run serve` and the builds all run `ui-kit:build` first: the demo app +> consumes the kit through its **built** output (`dist/ui-kit`, mapped by the +> `@4sh/ui-kit/*` `paths` of `tsconfig.json`), exactly like an external consumer would. +> +> `projects/ui-kit/styles/generated/` and `storybook/generated/` are **generated** +> (gitignored), rebuilt by `tokens:build` and `docs:config`. -Never write a resolved value (`(12px)`) in a role: the doc measures it at runtime, in -the active theme, brand and viewport. `npm run docs:config:check` fails if the manifest -is stale — it runs on `postinstall` and before `storybook` / `build-storybook`. +Conventions to follow before writing code — repo layout, naming, CSS/SCSS rules +(no BEM), component creation recipe, Storybook file organization, token workflow — +are all in **[`AGENTS.md`](AGENTS.md)**. It is the single source of truth for +them, for humans as much as for AI agents. --- @@ -209,7 +101,9 @@ is stale — it runs on `postinstall` and before `storybook` / `build-storybook` | Topic | Where | |---|---| | Consuming the package | [`projects/ui-kit/README.md`](projects/ui-kit/README.md) ([FR](projects/ui-kit/README.fr.md)) | +| Coding conventions in this repo | [`AGENTS.md`](AGENTS.md) · [`CLAUDE.md`](CLAUDE.md) | | Versioning & releases | [`docs/VERSIONING.md`](docs/VERSIONING.md) · [`CHANGELOG.md`](CHANGELOG.md) | | Publishing to npm | [`docs/PUBLISHING.md`](docs/PUBLISHING.md) | -| Conventions for AI agents | [`AGENTS.md`](AGENTS.md) · [`CLAUDE.md`](CLAUDE.md) | +| Schematics companion package | [`projects/ui-kit-schematics/README.md`](projects/ui-kit-schematics/README.md) | | Figma ↔ code workflow | [`CLAUDE.md`](CLAUDE.md) · [`docs/figma-migration-global.md`](docs/figma-migration-global.md) | +| Security policy | [`SECURITY.md`](SECURITY.md) | diff --git a/projects/ui-kit/README.fr.md b/projects/ui-kit/README.fr.md index 6f4dd75..8100cc7 100644 --- a/projects/ui-kit/README.fr.md +++ b/projects/ui-kit/README.fr.md @@ -10,6 +10,32 @@ natif (signals + Angular CDK), style piloté par les design tokens. --- +## Deux modes de consommation + +À choisir **avant** d'installer : la décision conditionne toute la suite. + +| | **dépendance** | **starter** | +|---|---|---| +| Installation | `npm install @4sh/ui-kit` | `ng add @4sh/ui-kit-schematics` | +| Ce qui arrive dans votre dépôt | rien — les composants compilés restent dans `node_modules` | les *sources* des composants, dans `src/app/shared/` | +| Imports | `@4sh/ui-kit/actions/ui-button` | votre propre chemin (`./shared/components/ui/actions/ui-button`) | +| Styles | `node_modules/@4sh/ui-kit/styles.css`, chargée globalement | copiés dans `src/styles/`, avec la chaîne de génération des tokens (`npm run tokens:build`) | +| Documentation | le Storybook lié ci-dessus | la vôtre, sur vos copies (`--with-storybook`) | +| Personnalisation | inputs + variables CSS | modifier le code lui-même | +| Mise à jour | bump de version | `ng generate @4sh/ui-kit-schematics:update` — diff par composant, appliquer ou ignorer | + +**dépendance** est le mode par défaut : rien à maintenir, une seule version à +suivre, et la garantie que tous les projets affichent le même kit. **starter** — +l'approche de shadcn/ui ou spartan-ng — échange cette garantie contre la +possession du code : à choisir quand le projet doit s'écarter du Design System, +en assumant que les mises à jour deviennent semi-manuelles. + +Les deux modes décrivent les mêmes composants. **La suite de cette page décrit le +mode `dépendance`** ; la voie starter a son propre package et son propre README +(voir [plus bas](#ou-copier-les-sources-à-la-place)). + +--- + ## Installation ```bash diff --git a/projects/ui-kit/README.md b/projects/ui-kit/README.md index a2a5416..c7a21e2 100644 --- a/projects/ui-kit/README.md +++ b/projects/ui-kit/README.md @@ -10,6 +10,32 @@ built in natively (signals + Angular CDK), styling driven by design tokens. --- +## Two ways to consume the kit + +Choose **before** installing: the decision shapes everything that follows. + +| | **dependency** | **starter** | +|---|---|---| +| Install | `npm install @4sh/ui-kit` | `ng add @4sh/ui-kit-schematics` | +| What lands in your repo | nothing — compiled components stay in `node_modules` | the component *sources*, in `src/app/shared/` | +| Imports | `@4sh/ui-kit/actions/ui-button` | your own path (`./shared/components/ui/actions/ui-button`) | +| Styles | `node_modules/@4sh/ui-kit/styles.css`, loaded globally | copied into `src/styles/`, with the token generation chain (`npm run tokens:build`) | +| Documentation | the Storybook linked above | yours, on your own copies (`--with-storybook`) | +| Customization | inputs + CSS variables | edit the code itself | +| Updating | bump the version | `ng generate @4sh/ui-kit-schematics:update` — per-component diff, accept or skip | + +**dependency** is the default: nothing to maintain, one version to follow, and a +guarantee that every project renders the same kit. **starter** — the shadcn/ui or +spartan-ng approach — trades that guarantee for ownership of the code: pick it +when the project needs to diverge from the Design System, and accept that +updates are then semi-manual. + +Both modes describe the same components. **The rest of this page describes the +`dependency` mode**; the starter path has its own package and its own README (see +[below](#or-copy-the-sources-instead)). + +--- + ## Installation ```bash diff --git a/storybook/docs/NpmPackage.mdx b/storybook/docs/NpmPackage.mdx index 71c5147..137abb1 100644 --- a/storybook/docs/NpmPackage.mdx +++ b/storybook/docs/NpmPackage.mdx @@ -38,6 +38,28 @@ composant, dans la barre latérale, donne l'import exact à recopier. --- +## Ou : posséder les sources (mode *starter*) + +`npm install` livre les composants **compilés**. Le second mode de consommation +les installe en **sources**, dans votre dépôt, libres d'être modifiées : + +```bash +ng add @4sh/ui-kit-schematics # fondation + composants, en une commande +ng add @4sh/ui-kit-schematics --with-storybook # avec la doc des composants copiés +ng generate @4sh/ui-kit-schematics:update # diff par composant après une release du kit +``` + +Le parcours passe par le package compagnon, et `@4sh/ui-kit` n'entre jamais dans +`node_modules` : absent, rien ne peut importer son code compilé à la place de vos +copies. + +Le choix entre les deux — ce qui arrive dans le dépôt, les imports, les styles, la +personnalisation, les mises à jour — est comparé dans le README du package, +ci-dessous. La documentation des composants, elle, est la même dans les deux cas : +c'est ce Storybook. + +--- + ## Le mode d'emploi complet vit dans le README du package Installation, liste des entry points, feuille de styles à charger, providers