refactor(libs): graduate Icon / LayoutStateService / brand tokens to libs/shared/*
Per ADR-0020 §"Shared-libs graduation": the three primitives that
both `portal-shell` (today) and `portal-admin` (next) will share
move out of `apps/portal-shell/src/` and into the workspace libs.
Mechanical move — no behaviour change.
Graduated:
- `Icon` component → `libs/shared/ui/src/lib/icon/`. Selector
renamed `app-icon` → `lib-icon` (consumed via `<lib-icon>`),
`IconName` re-exported from `shared-ui`.
- `LayoutStateService` (+ `ThemeMode` type) →
`libs/shared/state/src/lib/`. New library generated via
`nx g @nx/angular:library` to match the existing
`feature-auth` / `shared-ui` shape.
- Brand-palette `@theme` block →
`libs/shared/tokens/src/brand-tokens.css`. `portal-shell`'s
`styles.css` imports it by relative path.
Lib tags updated so the module-boundary lint rule lets both apps
consume them:
- `shared-state`: new lib → `scope:shared, type:shared`.
- `shared-ui`: was `scope:portal-shell` (stopgap from the initial
scaffold) → `scope:shared, type:shared`.
Side-edits:
- `tsconfig.base.json` gains the `shared-state` path alias
(generator-applied).
- `shared-tokens` is now CSS-only — its placeholder TS function is
removed and its vitest config flips `passWithNoTests: true` since
there is nothing to test there yet.
- Placeholder `shared-ui/shared-ui.{ts,html,css,spec.ts}` files
removed.
Verification:
- Lint / test / build run-many across the four projects — green.
- portal-shell: 28 tests, shared-state: 9, shared-ui: 3 (= the same
40 specs as before, redistributed across the new libs).
- Production build: 128.7 KB gzip initial per locale (was 128.5 KB
on main — noise-level delta).
- Brand tokens still inlined in the produced `styles-*.css`.
- Both `dist/.../browser/{en,fr}/` emitted as expected.
No public-API breakage. The migration to `portal-admin` is now a
clean `import { Icon } from 'shared-ui'` + `LayoutStateService`
inject + `@import` of `brand-tokens.css` on admin's `styles.css` —
no duplication.
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Brand palette — APF charte graphique.
|
||||
*
|
||||
* primary: #12546c (dark teal) — header bar, sidebar active items,
|
||||
* primary buttons, headings on light bg
|
||||
* accent: #f7a919 (warm orange) — CTAs, highlights, focus rings on
|
||||
* branded surfaces
|
||||
*
|
||||
* The two scales below are hand-tuned (each step roughly halves the
|
||||
* delta from the previous toward white / black). Tailwind v4 surfaces
|
||||
* them automatically as utility classes — `bg-brand-primary-700`,
|
||||
* `text-brand-accent-500`, `ring-brand-primary-500`, etc.
|
||||
*
|
||||
* Use the `500` step as the canonical brand value; the lighter / darker
|
||||
* steps are for hover / focus / muted text without dropping out of the
|
||||
* brand family.
|
||||
*
|
||||
* Owned by `libs/shared/tokens` so every app in the workspace
|
||||
* (`portal-shell`, `portal-admin`) reads from the same source. To
|
||||
* consume, `@import` this file from the app's entry stylesheet.
|
||||
*/
|
||||
@theme {
|
||||
--color-brand-primary-50: #eaf3f7;
|
||||
--color-brand-primary-100: #cae0e8;
|
||||
--color-brand-primary-200: #9ac4d2;
|
||||
--color-brand-primary-300: #5fa2b6;
|
||||
--color-brand-primary-400: #2f7f96;
|
||||
--color-brand-primary-500: #12546c;
|
||||
--color-brand-primary-600: #0f475c;
|
||||
--color-brand-primary-700: #0c394a;
|
||||
--color-brand-primary-800: #082a36;
|
||||
--color-brand-primary-900: #051c24;
|
||||
--color-brand-primary-950: #020e12;
|
||||
|
||||
--color-brand-accent-50: #fef5e0;
|
||||
--color-brand-accent-100: #fce6b3;
|
||||
--color-brand-accent-200: #fad17a;
|
||||
--color-brand-accent-300: #f8bb47;
|
||||
--color-brand-accent-400: #f7a919;
|
||||
--color-brand-accent-500: #de9415;
|
||||
--color-brand-accent-600: #b97a11;
|
||||
--color-brand-accent-700: #93600d;
|
||||
--color-brand-accent-800: #6e4709;
|
||||
--color-brand-accent-900: #4a3006;
|
||||
--color-brand-accent-950: #271903;
|
||||
}
|
||||
@@ -1 +1,7 @@
|
||||
export * from './lib/shared-tokens';
|
||||
// `shared-tokens` is currently CSS-only — see `./brand-tokens.css`,
|
||||
// which apps import from their entry stylesheet (e.g.
|
||||
// `apps/portal-shell/src/styles.css`). The TS module exists so the
|
||||
// Nx lib boilerplate / package layout stays uniform with the other
|
||||
// shared libs; expand when a typed token API (e.g. CSS-variable
|
||||
// name constants for runtime lookups) is genuinely needed.
|
||||
export {};
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import { sharedTokens } from './shared-tokens';
|
||||
|
||||
describe('sharedTokens', () => {
|
||||
it('should work', () => {
|
||||
expect(sharedTokens()).toEqual('shared-tokens');
|
||||
});
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
export function sharedTokens(): string {
|
||||
return 'shared-tokens';
|
||||
}
|
||||
@@ -12,6 +12,9 @@ export default defineConfig(() => ({
|
||||
globals: true,
|
||||
environment: 'node',
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
// CSS-only library — no TS to test yet. Pass instead of failing
|
||||
// the gate; revisit when a typed token API lands.
|
||||
passWithNoTests: true,
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../../../coverage/libs/shared/tokens',
|
||||
|
||||
Reference in New Issue
Block a user