@akcelik/strct 0.8.0 → 0.8.1

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/README.md CHANGED
@@ -11,6 +11,7 @@ attribute swap re-skins the whole library.
11
11
  - Standalone components, signal inputs, `OnPush` everywhere
12
12
  - `ControlValueAccessor` support on every form control
13
13
  - No runtime CSS framework dependency
14
+ - WCAG-AA text contrast · OS-aware theming · `prefers-contrast` / `prefers-reduced-motion` honoured
14
15
 
15
16
  ## Install
16
17
 
@@ -44,7 +45,7 @@ external request and nothing else to load.
44
45
  Set the scheme on the document root (or let `StrctThemeService` manage it):
45
46
 
46
47
  ```html
47
- <html data-palette="arctic" data-theme="dark">
48
+ <html data-palette="arctic" data-theme="dark"></html>
48
49
  ```
49
50
 
50
51
  ```ts
@@ -52,10 +53,14 @@ import { StrctThemeService } from '@akcelik/strct';
52
53
 
53
54
  const theme = inject(StrctThemeService);
54
55
  theme.setPalette('ember'); // 'arctic' | 'ember' | 'sage'
55
- theme.setMode('light'); // 'dark' | 'light' (persisted to localStorage)
56
+ theme.setMode('light'); // 'dark' | 'light' (persisted to localStorage)
56
57
  theme.toggleMode();
57
58
  ```
58
59
 
60
+ By default `StrctThemeService` follows the operating system's light/dark
61
+ preference (`prefers-color-scheme`) — and tracks it live — until the user makes an
62
+ explicit choice, which is then persisted and wins.
63
+
59
64
  Drop the ready-made switcher anywhere:
60
65
 
61
66
  ```html
@@ -66,17 +71,17 @@ Drop the ready-made switcher anywhere:
66
71
 
67
72
  Import only what you use — every component is standalone.
68
73
 
69
- | Area | Components |
70
- |-----------|------------|
71
- | Layout | `strct-shell`, `strct-header`, `strct-footer`, `strct-vertical-nav`, `strct-nav` / `strct-nav-item`, `strct-login` |
72
- | Controls | `button[strct-button]`, `strct-badge`, `strct-tag`, `strct-avatar`, `strct-progress`, `strct-spinner`, `strct-skeleton` |
73
- | Surfaces | `strct-card` (+ header/block/footer), `strct-accordion`, `strct-tabs`, `strct-tree`, `strct-modal`, `strct-dropdown`, `strct-context-menu` (+ `strct-submenu`), `strct-wizard`, `strct-divider` |
74
- | Navigation | `strct-breadcrumb` / `strct-breadcrumb-item`, `strct-pagination` |
75
- | Forms | `strctInput`, `strct-checkbox`, `strct-toggle`, `strct-radio-group` / `strct-radio`, `strct-range`, `strct-combobox`, `strct-cascade-select`, `strct-datepicker`, `strct-password`, `strct-file`, `strct-color-picker` |
76
- | Data | `strct-table`, `strct-datagrid`, `strct-timeline` / `strct-timeline-item`, `strct-stack` / `strct-stack-item` |
77
- | Charts | `strct-sparkline`, `strct-chart` (line / area / bar), `strct-donut`, `strct-gauge` |
78
- | Feedback | `strct-alert`, `strctTooltip`, `strct-signpost`, `strct-toast-outlet` + `StrctToastService` |
79
- | Foundations | `strct-icon` (datacenter icon set + status `badge`), `strct-theme-switcher` |
74
+ | Area | Components |
75
+ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
76
+ | Layout | `strct-shell`, `strct-header`, `strct-footer`, `strct-vertical-nav`, `strct-nav` / `strct-nav-item`, `strct-rail` (collapsible icon nav), `strct-login` |
77
+ | Controls | `button[strct-button]`, `strct-button-group`, `strct-speed-dial`, `strct-badge`, `strct-tag`, `strct-avatar`, `strct-progress`, `strct-spinner`, `strct-skeleton` |
78
+ | Surfaces | `strct-card` (+ header/block/footer), `strct-accordion`, `strct-tabs`, `strct-tree`, `strct-modal`, `strct-drawer` (edge-anchored panel), `strct-dropdown`, `strct-context-menu` (+ `strct-submenu`), `strct-wizard`, `strct-divider` |
79
+ | Navigation | `strct-breadcrumb` / `strct-breadcrumb-item`, `strct-pagination` |
80
+ | Forms | `strctInput`, `strct-checkbox`, `strct-toggle`, `strct-radio-group` / `strct-radio`, `strct-range`, `strct-combobox`, `strct-cascade-select`, `strct-datepicker`, `strct-password`, `strct-file`, `strct-color-picker`, `strct-rating`, `strct-chips`, `strct-input-otp`, `strct-knob`, `strct-input-mask` |
81
+ | Data | `strct-table`, `strct-datagrid` (sort / select / expandable rows / detail pane / batch bar / per-row kebab menu / resizable / column chooser), `strct-timeline` / `strct-timeline-item`, `strct-stack` / `strct-stack-item` |
82
+ | Charts | `strct-sparkline`, `strct-chart` (line / area / bar), `strct-donut`, `strct-gauge` |
83
+ | Feedback | `strct-alert`, `strctTooltip`, `strct-signpost`, `strct-toast-outlet` + `StrctToastService` |
84
+ | Foundations | `strct-icon` (datacenter icon set + status `badge`), `strct-theme-switcher` |
80
85
 
81
86
  ### Examples
82
87
 
@@ -104,7 +109,19 @@ Components reference these CSS variables only — never hard-coded colors:
104
109
 
105
110
  `--bg-0..--bg-a` surfaces · `--hdr` header · `--b1/--b2/--b3` borders ·
106
111
  `--t1..--t4` text · `--inv` inverse · `--acc` (+ `--acc-m/-s/50/30/18`) accent ·
107
- `--ok / --wrn / --crt` semantic (+ `*-bg`) · `--sh / --shh` shadows · `--sb` scrollbar.
112
+ `--success / --warning / --critical` semantic (+ `*-bg`) · `--sh / --shh` shadows · `--sb` scrollbar.
113
+
114
+ ## Accessibility & eye comfort
115
+
116
+ Reviewed against WCAG and display-ergonomics / vision science to limit eye strain
117
+ in long, all-day console sessions:
118
+
119
+ - **WCAG AA text contrast** — `--t1/--t2/--t3` all meet AA (≥ 4.5:1) in every
120
+ palette and mode, with a preserved `t1 > t2 > t3` hierarchy.
121
+ - **OS-aware theming** — follows `prefers-color-scheme` until an explicit choice.
122
+ - **`prefers-contrast: more`** — stronger borders, text and focus ring on request.
123
+ - **`prefers-reduced-motion`** — animations collapse to instant state changes.
124
+ - **12px type-size floor**, 1.5 body line-height, softened (non-pure-white) light surfaces.
108
125
 
109
126
  ## License
110
127
 
@@ -1380,11 +1380,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
1380
1380
  /** Vertical container for `<strct-accordion-panel>` items. */
1381
1381
  class StrctAccordion {
1382
1382
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctAccordion, deps: [], target: i0.ɵɵFactoryTarget.Component });
1383
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctAccordion, isStandalone: true, selector: "strct-accordion", host: { classAttribute: "strct-accordion" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-accordion{display:flex;flex-direction:column;gap:6px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1383
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctAccordion, isStandalone: true, selector: "strct-accordion", host: { classAttribute: "strct-accordion" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-accordion{display:flex;flex-direction:column;border:1px solid var(--b2);border-radius:8px;overflow:hidden;background:var(--bg-1)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1384
1384
  }
1385
1385
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctAccordion, decorators: [{
1386
1386
  type: Component,
1387
- args: [{ selector: 'strct-accordion', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `<ng-content />`, host: { class: 'strct-accordion' }, styles: [".strct-accordion{display:flex;flex-direction:column;gap:6px}\n"] }]
1387
+ args: [{ selector: 'strct-accordion', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `<ng-content />`, host: { class: 'strct-accordion' }, styles: [".strct-accordion{display:flex;flex-direction:column;border:1px solid var(--b2);border-radius:8px;overflow:hidden;background:var(--bg-1)}\n"] }]
1388
1388
  }] });
1389
1389
  /** Collapsible panel with a header. `expanded` is two-way bindable. */
1390
1390
  class StrctAccordionPanel {
@@ -1411,7 +1411,7 @@ class StrctAccordionPanel {
1411
1411
  @if (expanded()) {
1412
1412
  <div class="strct-acc__body"><ng-content /></div>
1413
1413
  }
1414
- `, isInline: true, styles: [".strct-acc{display:block;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;overflow:hidden}.strct-acc__head{display:flex;align-items:center;gap:9px;width:100%;padding:11px 14px;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t1);text-align:left}.strct-acc__head:hover{background:var(--bg-3)}.strct-acc__chevron{display:inline-flex;color:var(--t3);transition:transform .16s ease}.strct-acc__chevron--open{transform:rotate(90deg);color:var(--acc)}.strct-acc__title{flex:1}.strct-acc__body{padding:4px 14px 14px 32px;color:var(--t2);font-size:13px;border-top:1px solid var(--b1)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1414
+ `, isInline: true, styles: [".strct-acc{display:block}.strct-acc+.strct-acc{border-top:1px solid var(--b2)}.strct-acc__head{display:flex;align-items:center;gap:9px;width:100%;padding:11px 14px;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t1);text-align:left}.strct-acc__head:hover{background:var(--bg-3)}.strct-acc__chevron{display:inline-flex;color:var(--t3);transition:transform .16s ease}.strct-acc__chevron--open{transform:rotate(90deg);color:var(--acc)}.strct-acc__title{flex:1}.strct-acc__body{padding:4px 14px 14px 32px;color:var(--t2);font-size:13px;border-top:1px solid var(--b1)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1415
1415
  }
1416
1416
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctAccordionPanel, decorators: [{
1417
1417
  type: Component,
@@ -1430,7 +1430,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
1430
1430
  @if (expanded()) {
1431
1431
  <div class="strct-acc__body"><ng-content /></div>
1432
1432
  }
1433
- `, host: { class: 'strct-acc' }, styles: [".strct-acc{display:block;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;overflow:hidden}.strct-acc__head{display:flex;align-items:center;gap:9px;width:100%;padding:11px 14px;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t1);text-align:left}.strct-acc__head:hover{background:var(--bg-3)}.strct-acc__chevron{display:inline-flex;color:var(--t3);transition:transform .16s ease}.strct-acc__chevron--open{transform:rotate(90deg);color:var(--acc)}.strct-acc__title{flex:1}.strct-acc__body{padding:4px 14px 14px 32px;color:var(--t2);font-size:13px;border-top:1px solid var(--b1)}\n"] }]
1433
+ `, host: { class: 'strct-acc' }, styles: [".strct-acc{display:block}.strct-acc+.strct-acc{border-top:1px solid var(--b2)}.strct-acc__head{display:flex;align-items:center;gap:9px;width:100%;padding:11px 14px;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t1);text-align:left}.strct-acc__head:hover{background:var(--bg-3)}.strct-acc__chevron{display:inline-flex;color:var(--t3);transition:transform .16s ease}.strct-acc__chevron--open{transform:rotate(90deg);color:var(--acc)}.strct-acc__title{flex:1}.strct-acc__body{padding:4px 14px 14px 32px;color:var(--t2);font-size:13px;border-top:1px solid var(--b1)}\n"] }]
1434
1434
  }], propDecorators: { heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: true }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }] } });
1435
1435
 
1436
1436
  /** A single tab. Place inside `<strct-tabs>`; `label` names its button. */