ps-helix 6.2.3 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONFIGURATION.md +492 -0
- package/README.md +131 -125
- package/THEME.md +37 -27
- package/TOKENS.md +662 -0
- package/fesm2022/ps-helix.mjs +7777 -5714
- package/fesm2022/ps-helix.mjs.map +1 -1
- package/package.json +18 -8
- package/src/lib/styles/base/a11y.css +36 -0
- package/src/lib/styles/base/behavior.css +15 -0
- package/src/lib/styles/base/global.css +9 -26
- package/src/lib/styles/compat.css +580 -0
- package/src/lib/styles/themes/dark-auto.css +315 -0
- package/src/lib/styles/themes/dark.css +259 -157
- package/src/lib/styles/themes/light.css +236 -221
- package/src/lib/styles/tokens/animations.tokens.css +30 -21
- package/src/lib/styles/tokens/breakpoints.tokens.css +22 -6
- package/src/lib/styles/tokens/effects.tokens.css +25 -25
- package/src/lib/styles/tokens/layout.tokens.css +32 -32
- package/src/lib/styles/tokens/sizing.tokens.css +87 -75
- package/src/lib/styles/tokens/spacing.tokens.css +18 -18
- package/src/lib/styles/tokens/typography.tokens.css +34 -34
- package/src/lib/styles/utilities/animations.utils.css +18 -18
- package/src/lib/styles/utilities/colors.utils.css +196 -196
- package/src/lib/styles/utilities/focus.utils.css +13 -13
- package/src/lib/styles/utilities/layout.utils.css +9 -9
- package/src/lib/styles/utilities/responsive.utils.css +49 -49
- package/src/lib/styles/utilities/spacing.utils.css +96 -96
- package/src/lib/styles/utilities/typography.utils.css +25 -25
- package/styles-full.css +25 -0
- package/styles.css +17 -8
- package/types/ps-helix.d.ts +3251 -1724
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A comprehensive Angular component library built with Angular 22+ featuring modern design patterns, accessibility-first development, and optimal developer experience.
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/ps-helix)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
[](https://angular.dev/)
|
|
8
8
|
[](https://www.typescriptlang.org/)
|
|
@@ -14,10 +14,11 @@ A comprehensive Angular component library built with Angular 22+ featuring moder
|
|
|
14
14
|
- [Installation](#installation)
|
|
15
15
|
- [Quick Start](#quick-start)
|
|
16
16
|
- [Configuration](#configuration)
|
|
17
|
+
- [`provideHelix()`](#providehelix)
|
|
17
18
|
- [Global Styles](#global-styles)
|
|
18
19
|
- [Phosphor Icons Setup](#phosphor-icons-setup)
|
|
19
20
|
- [Theme Service](#theme-service)
|
|
20
|
-
- [
|
|
21
|
+
- [Internationalization](#internationalization)
|
|
21
22
|
- [Scroll Service](#scroll-service)
|
|
22
23
|
- [Core Concepts](#core-concepts)
|
|
23
24
|
- [Standalone Components](#standalone-components)
|
|
@@ -29,7 +30,6 @@ A comprehensive Angular component library built with Angular 22+ featuring moder
|
|
|
29
30
|
- [ThemeService](#themeservice)
|
|
30
31
|
- [ToastService](#toastservice)
|
|
31
32
|
- [ScrollService](#scrollservice)
|
|
32
|
-
- [TranslationService](#translationservice)
|
|
33
33
|
- [Exported Types](#exported-types)
|
|
34
34
|
- [Theming](#theming)
|
|
35
35
|
- [Best Practices](#best-practices)
|
|
@@ -51,7 +51,7 @@ Helix is a production-ready design system that provides:
|
|
|
51
51
|
- **Complete Type Exports** - All component types and enums exported for type-safe development
|
|
52
52
|
- **Customizable Theming** - Light/dark modes with brand color customization
|
|
53
53
|
- **Phosphor Icons** - 6000+ icons with multiple weight variants
|
|
54
|
-
- **i18n Support** -
|
|
54
|
+
- **i18n Support** - Every visible string is a configurable default, with a French preset included
|
|
55
55
|
- **Responsive Design** - Mobile-first approach with comprehensive breakpoint system
|
|
56
56
|
- **Modern Architecture** - Built with Angular 22 standalone components and signals
|
|
57
57
|
|
|
@@ -72,7 +72,6 @@ Before installing Helix, ensure your development environment meets these require
|
|
|
72
72
|
"@angular/common": "^22.0.0",
|
|
73
73
|
"@angular/core": "^22.0.0",
|
|
74
74
|
"@angular/forms": "^22.0.0",
|
|
75
|
-
"@ngx-translate/core": "^15.0.0",
|
|
76
75
|
"rxjs": "^7.8.0"
|
|
77
76
|
}
|
|
78
77
|
```
|
|
@@ -82,9 +81,12 @@ Before installing Helix, ensure your development environment meets these require
|
|
|
82
81
|
The following dependencies are bundled with ps-helix:
|
|
83
82
|
|
|
84
83
|
- **@phosphor-icons/web**: 2.0.3 - Icon library
|
|
85
|
-
- **date-fns**: ^3.3.1 - Date utility functions
|
|
86
84
|
- **tslib**: ^2.6.0 - TypeScript runtime library
|
|
87
85
|
|
|
86
|
+
The library has no i18n dependency. Every string it renders is a configurable default —
|
|
87
|
+
see [Internationalization](#internationalization) — so you translate it with whatever your
|
|
88
|
+
application already uses, or with nothing at all.
|
|
89
|
+
|
|
88
90
|
## Installation
|
|
89
91
|
|
|
90
92
|
Install the package:
|
|
@@ -96,7 +98,7 @@ npm install ps-helix
|
|
|
96
98
|
All peer dependencies should be automatically installed. If not, install them manually:
|
|
97
99
|
|
|
98
100
|
```bash
|
|
99
|
-
npm install @angular/common@^22.0.0 @angular/core@^22.0.0 @angular/forms@^22.0.0
|
|
101
|
+
npm install @angular/common@^22.0.0 @angular/core@^22.0.0 @angular/forms@^22.0.0 rxjs@^7.8.0
|
|
100
102
|
```
|
|
101
103
|
|
|
102
104
|
### Verify Installation
|
|
@@ -106,7 +108,7 @@ After installation, verify that ps-helix is in your `package.json`:
|
|
|
106
108
|
```json
|
|
107
109
|
{
|
|
108
110
|
"dependencies": {
|
|
109
|
-
"ps-helix": "^
|
|
111
|
+
"ps-helix": "^7.0.0"
|
|
110
112
|
}
|
|
111
113
|
}
|
|
112
114
|
```
|
|
@@ -121,14 +123,21 @@ In your main `styles.css` file, import the Helix stylesheet:
|
|
|
121
123
|
@import 'ps-helix/styles.css';
|
|
122
124
|
```
|
|
123
125
|
|
|
124
|
-
This
|
|
125
|
-
- CSS Reset (normalize styles across browsers)
|
|
126
|
+
This import includes:
|
|
126
127
|
- Design Tokens (spacing, typography, colors, etc.)
|
|
127
128
|
- Light and Dark theme variables
|
|
128
|
-
- Utility classes
|
|
129
|
-
-
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
- Utility classes and the responsive system
|
|
130
|
+
- Accessibility guarantees (forced-colors focus fallback, reduced-motion guard) and the
|
|
131
|
+
modal scroll lock — these always ship, whatever else you opt into
|
|
132
|
+
|
|
133
|
+
**It does not include a CSS reset or page-level styling since 7.0.0.** Importing a
|
|
134
|
+
component library used to also zero every margin and padding in your application, strip
|
|
135
|
+
your list markers and paint a gradient on your `<body>`. If you want that — typically an
|
|
136
|
+
application with no reset of its own — import the bundle instead:
|
|
137
|
+
|
|
138
|
+
```css
|
|
139
|
+
@import 'ps-helix/styles-full.css'; /* styles.css + reset.css + global.css */
|
|
140
|
+
```
|
|
132
141
|
|
|
133
142
|
### Step 2: Configure Phosphor Icons
|
|
134
143
|
|
|
@@ -167,7 +176,7 @@ import { PshButtonComponent } from 'ps-helix';
|
|
|
167
176
|
imports: [PshButtonComponent],
|
|
168
177
|
template: `
|
|
169
178
|
<psh-button
|
|
170
|
-
|
|
179
|
+
color="primary"
|
|
171
180
|
size="medium"
|
|
172
181
|
(clicked)="handleClick()">
|
|
173
182
|
Click Me
|
|
@@ -221,8 +230,8 @@ import { PshButtonComponent, PshCardComponent, PshAlertComponent } from 'ps-heli
|
|
|
221
230
|
template: `
|
|
222
231
|
<psh-card>
|
|
223
232
|
<h2>Helix Design System</h2>
|
|
224
|
-
<psh-alert
|
|
225
|
-
<psh-button
|
|
233
|
+
<psh-alert color="success" message="Installation successful!" />
|
|
234
|
+
<psh-button color="primary">Test Button</psh-button>
|
|
226
235
|
</psh-card>
|
|
227
236
|
`
|
|
228
237
|
})
|
|
@@ -231,6 +240,43 @@ export class TestComponent {}
|
|
|
231
240
|
|
|
232
241
|
## Configuration
|
|
233
242
|
|
|
243
|
+
### `provideHelix()`
|
|
244
|
+
|
|
245
|
+
One call sets the theme and every component default. Full list of the 201 settable defaults:
|
|
246
|
+
[CONFIGURATION.md](./CONFIGURATION.md).
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
import { bootstrapApplication } from '@angular/platform-browser';
|
|
250
|
+
import { provideHelix } from 'ps-helix';
|
|
251
|
+
|
|
252
|
+
bootstrapApplication(AppComponent, {
|
|
253
|
+
providers: [
|
|
254
|
+
provideHelix({
|
|
255
|
+
theme: { targetContrast: 'AAA', customerContext: BrandService },
|
|
256
|
+
components: {
|
|
257
|
+
button: { size: 'large', appearance: 'outline' },
|
|
258
|
+
modal: { dismissLabel: 'Fermer', confirmLabel: 'Valider', cancelLabel: 'Annuler' },
|
|
259
|
+
toast: { position: 'bottom-right', duration: 3000 },
|
|
260
|
+
},
|
|
261
|
+
}),
|
|
262
|
+
],
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
A partial override stays partial — `{ button: { size: 'large' } }` leaves the button's colour
|
|
267
|
+
and appearance where they were — and an attribute written on an element always wins over the
|
|
268
|
+
configuration.
|
|
269
|
+
|
|
270
|
+
`provideHelixTheme()`, `provideHelixComponentDefaults()` and `provideHelixToast()` cover one
|
|
271
|
+
part each, and every token is exported by name for a component-level override:
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
import { BUTTON_CONFIG } from 'ps-helix';
|
|
275
|
+
|
|
276
|
+
@Component({ providers: [{ provide: BUTTON_CONFIG, useValue: { size: 'small' } }] })
|
|
277
|
+
export class ToolbarComponent {}
|
|
278
|
+
```
|
|
279
|
+
|
|
234
280
|
### Global Styles
|
|
235
281
|
|
|
236
282
|
The design system provides a comprehensive set of CSS custom properties (CSS variables) that you can use in your own styles:
|
|
@@ -238,12 +284,12 @@ The design system provides a comprehensive set of CSS custom properties (CSS var
|
|
|
238
284
|
```css
|
|
239
285
|
/* Using design tokens in your custom styles */
|
|
240
286
|
.my-custom-component {
|
|
241
|
-
padding: var(--spacing-md);
|
|
242
|
-
margin-bottom: var(--spacing-lg);
|
|
243
|
-
background: var(--surface-card);
|
|
244
|
-
color: var(--text-color);
|
|
245
|
-
border-radius: var(--
|
|
246
|
-
box-shadow: var(--shadow-md);
|
|
287
|
+
padding: var(--psh-spacing-md);
|
|
288
|
+
margin-bottom: var(--psh-spacing-lg);
|
|
289
|
+
background: var(--psh-surface-card);
|
|
290
|
+
color: var(--psh-text-color);
|
|
291
|
+
border-radius: var(--psh-radius-lg);
|
|
292
|
+
box-shadow: var(--psh-shadow-md);
|
|
247
293
|
}
|
|
248
294
|
```
|
|
249
295
|
|
|
@@ -301,67 +347,64 @@ export class AppComponent {
|
|
|
301
347
|
|
|
302
348
|
For complete theming documentation including custom brand colors, see [THEME.md](./THEME.md).
|
|
303
349
|
|
|
304
|
-
###
|
|
350
|
+
### Internationalization
|
|
305
351
|
|
|
306
|
-
|
|
352
|
+
Every string the library renders — placeholders, button labels, `aria-label`s — is a
|
|
353
|
+
configurable default. There is no i18n dependency: you set them from whatever your
|
|
354
|
+
application already uses.
|
|
355
|
+
|
|
356
|
+
The defaults are English. `PSH_FRENCH_DEFAULTS` puts all 46 of them back into French:
|
|
307
357
|
|
|
308
358
|
```typescript
|
|
309
|
-
// src/main.ts
|
|
310
359
|
import { bootstrapApplication } from '@angular/platform-browser';
|
|
311
|
-
import {
|
|
312
|
-
import { TranslateModule, TranslateLoader, TranslateService } from '@ngx-translate/core';
|
|
313
|
-
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
|
314
|
-
import { HttpClient } from '@angular/common/http';
|
|
315
|
-
import { AppComponent } from './app/app.component';
|
|
316
|
-
|
|
317
|
-
export function HttpLoaderFactory(http: HttpClient) {
|
|
318
|
-
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
|
|
319
|
-
}
|
|
360
|
+
import { provideHelix, PSH_FRENCH_DEFAULTS } from 'ps-helix';
|
|
320
361
|
|
|
321
362
|
bootstrapApplication(AppComponent, {
|
|
322
|
-
providers: [
|
|
323
|
-
provideHttpClient(),
|
|
324
|
-
...TranslateModule.forRoot({
|
|
325
|
-
defaultLanguage: 'en',
|
|
326
|
-
loader: {
|
|
327
|
-
provide: TranslateLoader,
|
|
328
|
-
useFactory: HttpLoaderFactory,
|
|
329
|
-
deps: [HttpClient]
|
|
330
|
-
}
|
|
331
|
-
}).providers || []
|
|
332
|
-
]
|
|
333
|
-
}).then(ref => {
|
|
334
|
-
const translateService = ref.injector.get(TranslateService);
|
|
335
|
-
translateService.use('en');
|
|
363
|
+
providers: [provideHelix({ components: PSH_FRENCH_DEFAULTS })],
|
|
336
364
|
});
|
|
337
365
|
```
|
|
338
366
|
|
|
339
|
-
|
|
367
|
+
Merge your own on top rather than replacing it:
|
|
340
368
|
|
|
341
369
|
```typescript
|
|
342
|
-
|
|
343
|
-
|
|
370
|
+
provideHelix({
|
|
371
|
+
components: {
|
|
372
|
+
...PSH_FRENCH_DEFAULTS,
|
|
373
|
+
modal: { ...PSH_FRENCH_DEFAULTS.modal, confirmLabel: 'Envoyer' },
|
|
374
|
+
},
|
|
375
|
+
})
|
|
376
|
+
```
|
|
344
377
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
378
|
+
#### Another language, or a language that changes
|
|
379
|
+
|
|
380
|
+
Pass the strings from your own catalogue. A **function** is re-read whenever it changes, so a
|
|
381
|
+
language switcher updates the labels of components that are already on screen:
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
const t = inject(TranslateService); // ngx-translate, transloco, $localize, your own…
|
|
385
|
+
|
|
386
|
+
provideHelix({
|
|
387
|
+
components: {
|
|
388
|
+
select: { placeholder: () => t.instant('psh.select.placeholder') },
|
|
389
|
+
modal: { dismissLabel: () => t.instant('psh.modal.close') },
|
|
390
|
+
},
|
|
354
391
|
})
|
|
355
|
-
|
|
356
|
-
private translationService = inject(TranslationService);
|
|
392
|
+
```
|
|
357
393
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
394
|
+
A plain string is read once, when a component is built — right for a language fixed at
|
|
395
|
+
startup, and the common case. A function is read every time the value is needed, so anything
|
|
396
|
+
it reads that is a signal makes the label follow.
|
|
397
|
+
|
|
398
|
+
Per element, bind the input as you would any other:
|
|
399
|
+
|
|
400
|
+
```html
|
|
401
|
+
<psh-select [placeholder]="'psh.select.placeholder' | translate" />
|
|
363
402
|
```
|
|
364
403
|
|
|
404
|
+
An input always wins over the configuration.
|
|
405
|
+
|
|
406
|
+
The full list of configurable strings is in [CONFIGURATION.md](./CONFIGURATION.md).
|
|
407
|
+
|
|
365
408
|
### Scroll Service
|
|
366
409
|
|
|
367
410
|
The `ScrollService` provides utilities for scroll management:
|
|
@@ -414,7 +457,7 @@ import {
|
|
|
414
457
|
template: `
|
|
415
458
|
<psh-card>
|
|
416
459
|
<psh-input label="Email" />
|
|
417
|
-
<psh-button
|
|
460
|
+
<psh-button color="primary">Submit</psh-button>
|
|
418
461
|
</psh-card>
|
|
419
462
|
`
|
|
420
463
|
})
|
|
@@ -671,42 +714,6 @@ export class MyComponent {
|
|
|
671
714
|
}
|
|
672
715
|
```
|
|
673
716
|
|
|
674
|
-
### TranslationService
|
|
675
|
-
|
|
676
|
-
Wrapper service for ngx-translate functionality.
|
|
677
|
-
|
|
678
|
-
**Methods:**
|
|
679
|
-
- `setLanguage(lang: string)` - Change application language
|
|
680
|
-
- `getTranslation(key: string)` - Get translation for a key
|
|
681
|
-
- `instant(key: string)` - Get instant translation (synchronous)
|
|
682
|
-
|
|
683
|
-
**Example:**
|
|
684
|
-
|
|
685
|
-
```typescript
|
|
686
|
-
import { Component, inject } from '@angular/core';
|
|
687
|
-
import { TranslationService } from 'ps-helix';
|
|
688
|
-
|
|
689
|
-
@Component({
|
|
690
|
-
selector: 'app-language-selector',
|
|
691
|
-
template: `
|
|
692
|
-
<select (change)="changeLanguage($event)">
|
|
693
|
-
<option value="en">English</option>
|
|
694
|
-
<option value="fr">Français</option>
|
|
695
|
-
<option value="es">Español</option>
|
|
696
|
-
<option value="de">Deutsch</option>
|
|
697
|
-
</select>
|
|
698
|
-
`
|
|
699
|
-
})
|
|
700
|
-
export class LanguageSelectorComponent {
|
|
701
|
-
private translationService = inject(TranslationService);
|
|
702
|
-
|
|
703
|
-
changeLanguage(event: Event) {
|
|
704
|
-
const selectedLang = (event.target as HTMLSelectElement).value;
|
|
705
|
-
this.translationService.setLanguage(selectedLang);
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
```
|
|
709
|
-
|
|
710
717
|
## Exported Types
|
|
711
718
|
|
|
712
719
|
All component types and enums are exported for type-safe development:
|
|
@@ -855,33 +862,33 @@ Customize to match your brand identity using the injection token pattern. See th
|
|
|
855
862
|
Once configured, numerous CSS variables are available:
|
|
856
863
|
|
|
857
864
|
**Primary Color:**
|
|
858
|
-
- `--primary-color`
|
|
859
|
-
- `--primary-color-light`
|
|
860
|
-
- `--primary-color-lighter`
|
|
861
|
-
- `--primary-color-dark`
|
|
862
|
-
- `--primary-color-darker`
|
|
863
|
-
- `--primary-color-text`
|
|
864
|
-
- `--primary-color-rgb`
|
|
865
|
+
- `--psh-primary-color`
|
|
866
|
+
- `--psh-primary-color-light`
|
|
867
|
+
- `--psh-primary-color-lighter`
|
|
868
|
+
- `--psh-primary-color-dark`
|
|
869
|
+
- `--psh-primary-color-darker`
|
|
870
|
+
- `--psh-primary-color-text`
|
|
871
|
+
- `--psh-primary-color-rgb`
|
|
865
872
|
|
|
866
873
|
**Secondary Color:**
|
|
867
|
-
- `--secondary-color`
|
|
868
|
-
- `--secondary-color-light`
|
|
869
|
-
- `--secondary-color-lighter`
|
|
870
|
-
- `--secondary-color-dark`
|
|
871
|
-
- `--secondary-color-darker`
|
|
872
|
-
- `--secondary-color-text`
|
|
873
|
-
- `--secondary-color-rgb`
|
|
874
|
+
- `--psh-secondary-color`
|
|
875
|
+
- `--psh-secondary-color-light`
|
|
876
|
+
- `--psh-secondary-color-lighter`
|
|
877
|
+
- `--psh-secondary-color-dark`
|
|
878
|
+
- `--psh-secondary-color-darker`
|
|
879
|
+
- `--psh-secondary-color-text`
|
|
880
|
+
- `--psh-secondary-color-rgb`
|
|
874
881
|
|
|
875
882
|
### Using Custom Variables
|
|
876
883
|
|
|
877
884
|
```css
|
|
878
885
|
.my-button {
|
|
879
|
-
background: var(--primary-color);
|
|
880
|
-
color: var(--primary-color-text);
|
|
886
|
+
background: var(--psh-primary-color);
|
|
887
|
+
color: var(--psh-primary-color-text);
|
|
881
888
|
}
|
|
882
889
|
|
|
883
890
|
.my-button:hover {
|
|
884
|
-
background: var(--primary-color-light);
|
|
891
|
+
background: var(--psh-primary-color-light);
|
|
885
892
|
}
|
|
886
893
|
```
|
|
887
894
|
|
|
@@ -1119,7 +1126,7 @@ See [THEME.md](./THEME.md) for complete theming documentation.
|
|
|
1119
1126
|
1. Check browser console for specific error messages
|
|
1120
1127
|
2. Verify all required services are provided
|
|
1121
1128
|
3. Ensure ThemeService is initialized if using custom themes
|
|
1122
|
-
4. Check that
|
|
1129
|
+
4. Check that the strings you expect are set through `provideHelix` — see CONFIGURATION.md
|
|
1123
1130
|
|
|
1124
1131
|
## Browser Support
|
|
1125
1132
|
|
|
@@ -1178,11 +1185,10 @@ Copyright (c) 2025 PACK Solutions
|
|
|
1178
1185
|
- **Phosphor Icons**: [https://phosphoricons.com/](https://phosphoricons.com/)
|
|
1179
1186
|
- **Angular Documentation**: [https://angular.dev/](https://angular.dev/)
|
|
1180
1187
|
- **TypeScript Documentation**: [https://www.typescriptlang.org/](https://www.typescriptlang.org/)
|
|
1181
|
-
- **ngx-translate**: [https://github.com/ngx-translate/core](https://github.com/ngx-translate/core)
|
|
1182
1188
|
|
|
1183
1189
|
---
|
|
1184
1190
|
|
|
1185
|
-
**Version**:
|
|
1191
|
+
**Version**: 7.0.0
|
|
1186
1192
|
**Built with**: Angular 22.0.0, TypeScript 6.0.0, Phosphor Icons 2.0.3
|
|
1187
1193
|
**Author**: Fabrice PEREZ | Design Engineer at PACK Solutions
|
|
1188
1194
|
**Last Updated**: January 2026
|
package/THEME.md
CHANGED
|
@@ -194,8 +194,8 @@ When `applyCustomerTheme()` runs, each brand color is evaluated against the curr
|
|
|
194
194
|
|
|
195
195
|
- Contrast is computed using the true WCAG 2.1 relative luminance formula.
|
|
196
196
|
- If the ratio is below the target (AA by default, AAA if configured), the color is adjusted in OKLCH: the luminance is shifted (darker on light backgrounds, lighter on dark backgrounds) while hue and chroma are preserved as much as possible.
|
|
197
|
-
- The adjusted color is written into `--customer-primary-color` / `--customer-secondary-color` and consumed by every UI component.
|
|
198
|
-
- The original, unmodified brand color is written into `--customer-primary-color-source` / `--customer-secondary-color-source`, available for decorative surfaces (logos, marketing images) where the contrast rule does not apply.
|
|
197
|
+
- The adjusted color is written into `--psh-customer-primary-color` / `--psh-customer-secondary-color` and consumed by every UI component.
|
|
198
|
+
- The original, unmodified brand color is written into `--psh-customer-primary-color-source` / `--psh-customer-secondary-color-source`, available for decorative surfaces (logos, marketing images) where the contrast rule does not apply.
|
|
199
199
|
- The service never logs or warns: the adjustment is silent by design.
|
|
200
200
|
|
|
201
201
|
### Configuring the Target Ratio
|
|
@@ -230,29 +230,39 @@ Hue and chroma are preserved so the color palette stays perceptually consistent.
|
|
|
230
230
|
|
|
231
231
|
## Available CSS Variables
|
|
232
232
|
|
|
233
|
+
> **Every token is namespaced `--psh-*` since 7.0.0.** The complete, always-current list —
|
|
234
|
+
> 398 tokens with their light and dark values — lives in **[TOKENS.md](./TOKENS.md)**,
|
|
235
|
+
> generated from the stylesheets so it cannot drift. This page covers only the theming
|
|
236
|
+
> hooks; `TOKENS.md` covers the whole surface.
|
|
237
|
+
>
|
|
238
|
+
> Migrating from an earlier version? Import `ps-helix/src/lib/styles/compat.css` to keep
|
|
239
|
+
> the old unprefixed names working while you move over, then drop it. The legacy
|
|
240
|
+
> `--customer-*-color*` hooks keep working with no shim at all: both themes read the
|
|
241
|
+
> namespaced name first and fall back to the old one.
|
|
242
|
+
|
|
233
243
|
Once configured, `ThemeService` writes the following CSS variables on `:root`:
|
|
234
244
|
|
|
235
245
|
### Primary Color Variables
|
|
236
246
|
|
|
237
|
-
- `--customer-primary-color` - Accessibility-adjusted primary color (used by components)
|
|
238
|
-
- `--customer-primary-color-source` - Original brand color, unmodified (for decorative use only)
|
|
239
|
-
- `--customer-primary-color-light` - OKLCH-derived lighter variant
|
|
240
|
-
- `--customer-primary-color-lighter` - OKLCH-derived extra light variant
|
|
241
|
-
- `--customer-primary-color-dark` - OKLCH-derived darker variant
|
|
242
|
-
- `--customer-primary-color-darker` - OKLCH-derived extra dark variant
|
|
243
|
-
- `--customer-primary-color-text` - Readable text color (black or white) picked via WCAG contrast against the adjusted primary
|
|
244
|
-
- `--customer-primary-color-rgb` - `r, g, b` triplet of the adjusted primary for `rgba()` usage
|
|
247
|
+
- `--psh-customer-primary-color` - Accessibility-adjusted primary color (used by components)
|
|
248
|
+
- `--psh-customer-primary-color-source` - Original brand color, unmodified (for decorative use only)
|
|
249
|
+
- `--psh-customer-primary-color-light` - OKLCH-derived lighter variant
|
|
250
|
+
- `--psh-customer-primary-color-lighter` - OKLCH-derived extra light variant
|
|
251
|
+
- `--psh-customer-primary-color-dark` - OKLCH-derived darker variant
|
|
252
|
+
- `--psh-customer-primary-color-darker` - OKLCH-derived extra dark variant
|
|
253
|
+
- `--psh-customer-primary-color-text` - Readable text color (black or white) picked via WCAG contrast against the adjusted primary
|
|
254
|
+
- `--psh-customer-primary-color-rgb` - `r, g, b` triplet of the adjusted primary for `rgba()` usage
|
|
245
255
|
|
|
246
256
|
### Secondary Color Variables
|
|
247
257
|
|
|
248
|
-
- `--customer-secondary-color`
|
|
249
|
-
- `--customer-secondary-color-source`
|
|
250
|
-
- `--customer-secondary-color-light`
|
|
251
|
-
- `--customer-secondary-color-lighter`
|
|
252
|
-
- `--customer-secondary-color-dark`
|
|
253
|
-
- `--customer-secondary-color-darker`
|
|
254
|
-
- `--customer-secondary-color-text`
|
|
255
|
-
- `--customer-secondary-color-rgb`
|
|
258
|
+
- `--psh-customer-secondary-color`
|
|
259
|
+
- `--psh-customer-secondary-color-source`
|
|
260
|
+
- `--psh-customer-secondary-color-light`
|
|
261
|
+
- `--psh-customer-secondary-color-lighter`
|
|
262
|
+
- `--psh-customer-secondary-color-dark`
|
|
263
|
+
- `--psh-customer-secondary-color-darker`
|
|
264
|
+
- `--psh-customer-secondary-color-text`
|
|
265
|
+
- `--psh-customer-secondary-color-rgb`
|
|
256
266
|
|
|
257
267
|
### Component Usage
|
|
258
268
|
|
|
@@ -260,22 +270,22 @@ Design system components consume the stable abstract variables, which fall back
|
|
|
260
270
|
|
|
261
271
|
```css
|
|
262
272
|
/* From projects/ps-helix/src/lib/styles/themes/light.css */
|
|
263
|
-
--primary-color: var(--customer-primary-color, #0B0191);
|
|
264
|
-
--primary-color-light: var(--customer-primary-color-light, #0F02C4);
|
|
273
|
+
--psh-primary-color: var(--psh-customer-primary-color, #0B0191);
|
|
274
|
+
--psh-primary-color-light: var(--psh-customer-primary-color-light, #0F02C4);
|
|
265
275
|
```
|
|
266
276
|
|
|
267
277
|
### Using in Your Custom Styles
|
|
268
278
|
|
|
269
|
-
Use the abstract variables (`--primary-color`, `--secondary-color`, ...) in your own components so you automatically inherit the accessibility-adjusted palette:
|
|
279
|
+
Use the abstract variables (`--psh-primary-color`, `--psh-secondary-color`, ...) in your own components so you automatically inherit the accessibility-adjusted palette:
|
|
270
280
|
|
|
271
281
|
```css
|
|
272
282
|
.my-custom-button {
|
|
273
|
-
background-color: var(--primary-color);
|
|
274
|
-
color: var(--primary-color-text);
|
|
283
|
+
background-color: var(--psh-primary-color);
|
|
284
|
+
color: var(--psh-primary-color-text);
|
|
275
285
|
}
|
|
276
286
|
|
|
277
287
|
.my-custom-button:hover {
|
|
278
|
-
background-color: var(--primary-color-light);
|
|
288
|
+
background-color: var(--psh-primary-color-light);
|
|
279
289
|
}
|
|
280
290
|
```
|
|
281
291
|
|
|
@@ -283,7 +293,7 @@ For decorative brand elements that must match the literal brand color (e.g. a lo
|
|
|
283
293
|
|
|
284
294
|
```css
|
|
285
295
|
.brand-logo-surface {
|
|
286
|
-
background-color: var(--customer-primary-color-source);
|
|
296
|
+
background-color: var(--psh-customer-primary-color-source);
|
|
287
297
|
}
|
|
288
298
|
```
|
|
289
299
|
|
|
@@ -418,7 +428,7 @@ export class AppThemeContextService {
|
|
|
418
428
|
|
|
419
429
|
1. Verify that your service is provided with the `CUSTOMER_CONTEXT_SERVICE` token in your app config.
|
|
420
430
|
2. Confirm your service implements `primaryColor()` and `secondaryColor()` returning valid hex strings.
|
|
421
|
-
3. `ThemeService` is silent by design; if a brand color looks different from the one you provided, it is because the WCAG safeguard adjusted it. Read the adjusted color via `getComputedStyle(document.documentElement).getPropertyValue('--customer-primary-color')` and the original via `--customer-primary-color-source`.
|
|
431
|
+
3. `ThemeService` is silent by design; if a brand color looks different from the one you provided, it is because the WCAG safeguard adjusted it. Read the adjusted color via `getComputedStyle(document.documentElement).getPropertyValue('--psh-customer-primary-color')` and the original via `--psh-customer-primary-color-source`.
|
|
422
432
|
|
|
423
433
|
### Default colors showing instead of custom colors
|
|
424
434
|
|
|
@@ -436,7 +446,7 @@ export class AppThemeContextService {
|
|
|
436
446
|
1. Use signals in your customer context service for reactivity.
|
|
437
447
|
2. Provide valid hex colors (`#RRGGBB`).
|
|
438
448
|
3. Trust the WCAG safeguard; do not hand-tune base colors for contrast.
|
|
439
|
-
4. For decorative brand surfaces, use `--customer-*-color-source`. For every other UI use case, use the abstract variables (`--primary-color`, ...).
|
|
449
|
+
4. For decorative brand surfaces, use `--customer-*-color-source`. For every other UI use case, use the abstract variables (`--psh-primary-color`, ...).
|
|
440
450
|
5. Persist user preferences in `localStorage` when relevant.
|
|
441
451
|
6. Document brand color choices alongside your app's style guide.
|
|
442
452
|
|