@rt-tools/ui-kit 0.0.19 → 0.0.20

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.
Files changed (69) hide show
  1. package/fesm2022/rt-tools-ui-kit.mjs +205 -80
  2. package/fesm2022/rt-tools-ui-kit.mjs.map +1 -1
  3. package/package.json +1 -1
  4. package/rt-tools-ui-kit-0.0.20.tgz +0 -0
  5. package/src/lib/ui-kit/action-bar/components/bar/rtui-action-bar.component.scss +18 -18
  6. package/src/lib/ui-kit/action-bar/components/container/rtui-action-bar-container.component.scss +5 -7
  7. package/src/lib/ui-kit/aside/components/container/aside-container.component.scss +1 -0
  8. package/src/lib/ui-kit/aside/components/error-notification/aside-error-box.component.scss +6 -6
  9. package/src/lib/ui-kit/aside/components/panel/aside-panel.component.scss +25 -32
  10. package/src/lib/ui-kit/aside/stories/aside-component/test-aside.component.scss +1 -1
  11. package/src/lib/ui-kit/buttons/icon-round/rtui-round-icon-button.component.scss +4 -4
  12. package/src/lib/ui-kit/buttons/multi-button/rtui-multi-button.component.scss +7 -7
  13. package/src/lib/ui-kit/checkbox/rtui-checkbox.component.scss +10 -10
  14. package/src/lib/ui-kit/checkbox/stories/component/test-checkbox.component.scss +2 -2
  15. package/src/lib/ui-kit/dynamic-selectors/components/actions/rtui-dynamic-selector-list-actions.component.scss +2 -2
  16. package/src/lib/ui-kit/dynamic-selectors/components/dynamic-selector/rtui-dynamic-selector.component.scss +3 -3
  17. package/src/lib/ui-kit/dynamic-selectors/components/multi-selector-popup/rtui-multi-selector-popup.component.scss +17 -17
  18. package/src/lib/ui-kit/dynamic-selectors/components/placeholder/rtui-dynamic-selector-placeholder.component.scss +3 -4
  19. package/src/lib/ui-kit/dynamic-selectors/components/selected-list/rtui-dynamic-selector-selected-list.component.scss +2 -2
  20. package/src/lib/ui-kit/dynamic-selectors/strories/component/input/test-dynamic-input.component.scss +2 -3
  21. package/src/lib/ui-kit/dynamic-selectors/strories/component/selector/test-selector.component.scss +4 -5
  22. package/src/lib/ui-kit/file-uploader/rtui-file-upload.component.scss +5 -5
  23. package/src/lib/ui-kit/file-uploader/stories/component/test-file-upload.component.scss +1 -1
  24. package/src/lib/ui-kit/header/header.component.scss +1 -0
  25. package/src/lib/ui-kit/header/stories/component/test-header.component.scss +3 -3
  26. package/src/lib/ui-kit/image-uploader/image-uploader/rtui-image-upload.component.scss +5 -5
  27. package/src/lib/ui-kit/image-uploader/stories/component/test-image-upload.component.scss +2 -2
  28. package/src/lib/ui-kit/info-badge/info-badge.component.scss +20 -19
  29. package/src/lib/ui-kit/info-badge/stories/component/test-info-badge/test-info-badge.component.scss +1 -1
  30. package/src/lib/ui-kit/modal/modal.component.scss +5 -5
  31. package/src/lib/ui-kit/popover/rtui-popover-container.component.scss +2 -3
  32. package/src/lib/ui-kit/scrollable/scrollable-container.component.scss +3 -5
  33. package/src/lib/ui-kit/side-menu/menu/rtui-side-menu.component.scss +25 -25
  34. package/src/lib/ui-kit/side-menu/menu-sub-item/rtui-side-menu-sub-item.component.scss +14 -14
  35. package/src/lib/ui-kit/side-menu/stories/component/test-side-menu-wrapper.component.scss +10 -10
  36. package/src/lib/ui-kit/snack-bar/snack-bar.component.scss +9 -9
  37. package/src/lib/ui-kit/snack-bar/stories/component/test-snack-bar.component.scss +3 -3
  38. package/src/lib/ui-kit/spinner/spinner.component.scss +10 -13
  39. package/src/lib/ui-kit/table/components/clear-search-button/rtui-clear-button.component.scss +5 -5
  40. package/src/lib/ui-kit/table/components/pagination-view/rtui-pagination.component.scss +14 -22
  41. package/src/lib/ui-kit/table/components/table-base-cell/table-base-cell.component.scss +8 -9
  42. package/src/lib/ui-kit/table/components/table-config-aside/rt-table-config-aside.component.scss +1 -1
  43. package/src/lib/ui-kit/table/components/table-container/table-container.component.scss +16 -14
  44. package/src/lib/ui-kit/table/components/table-header-cell/table-header-cell.component.scss +6 -7
  45. package/src/lib/ui-kit/table/components/table-header-filter-cell/table-header-filter-cell.component.scss +3 -3
  46. package/src/lib/ui-kit/table/dynamic-list.component.scss +2 -2
  47. package/src/lib/ui-kit/table/stories/dynamic-list/test-dynamic-list.component.scss +1 -1
  48. package/src/lib/ui-kit/table/stories/pagination/test-pagination-component.scss +4 -4
  49. package/src/lib/ui-kit/table/stories/table/test-table-component.scss +1 -1
  50. package/src/lib/ui-kit/toggle/rtui-toggle.component.scss +15 -21
  51. package/src/lib/ui-kit/toggle/stories/component/test-toggle.component.scss +2 -2
  52. package/src/lib/ui-kit/toolbar/toolbar.component.scss +5 -10
  53. package/src/styles/TOKENS.md +95 -2
  54. package/src/styles/base/_base.scss +4 -5
  55. package/src/styles/base/_color-scheme.scss +86 -0
  56. package/src/styles/base/_mixin.scss +12 -15
  57. package/src/styles/base/_tokens.scss +139 -99
  58. package/src/styles/base/_variables.scss +5 -11
  59. package/src/styles/color-scheme.spec.ts +236 -0
  60. package/src/styles/components/_button.scss +32 -24
  61. package/src/styles/components/_dynamic-selectors.scss +9 -10
  62. package/src/styles/components/_form.scss +8 -13
  63. package/src/styles/components/_material-bridge.scss +30 -0
  64. package/src/styles/components/_rtui_button.scss +5 -5
  65. package/src/styles/components/_table.scss +23 -39
  66. package/src/styles/main.scss +4 -0
  67. package/styles/tokens.css +79 -101
  68. package/types/rt-tools-ui-kit.d.ts +55 -7
  69. package/rt-tools-ui-kit-0.0.19.tgz +0 -0
@@ -1,11 +1,8 @@
1
1
  /* Material Theme */
2
2
  $main-theme: light;
3
-
4
- $styles-clr-prefix: 'clr';
5
3
  $styles-prefix: 'rt';
6
4
 
7
5
  /* Base */
8
- $avalon-color: var(--clr-avalon);
9
6
  $base-accent: var(--rt-text-accent-brand);
10
7
 
11
8
  /* Device Definitions */
@@ -21,14 +18,11 @@ $base-font-weight: 400;
21
18
  $base-font-size: 1rem;
22
19
  $base-text-color: var(--rt-text-base-primary);
23
20
 
24
- /* Colors */
25
- $clr-red-100: #eb5055;
26
- $clr-red-10: #fdedee;
27
-
28
- $clr-green-80: #00b894;
29
- $clr-green-10: #e5f8f4;
21
+ /* Button palette seeds (static — fed to sass color.scale() for hover/active states) */
22
+ $btn-danger: #eb5055;
23
+ $btn-danger-soft: #fdedee;
24
+ $btn-success: #00b894; // outlier: not on the --rt-color-green scale
25
+ $btn-success-soft: #e5f8f4;
30
26
 
31
27
  /* Components */
32
- $side-panel-dynamic-clr: var(--rt-text-accent-brand);
33
- $pagination-dynamic-clr: var(--rt-text-accent-brand);
34
28
  $text-highlight-color: #0077bf;
@@ -0,0 +1,236 @@
1
+ import * as path from 'path';
2
+ import * as sass from 'sass';
3
+
4
+ /**
5
+ * Build-time guarantees for the custom color-scheme mechanism:
6
+ * 1. Δ0 — moving the accent tier onto the `--rt-color-{role}-{N}` indirection
7
+ * keeps every accent semantic token byte-for-byte identical (own palette).
8
+ * 2. The `rt.color-scheme` Sass mixin emits a scoped `[data-rt-scheme]` block.
9
+ * 3. Input validation rejects unknown roles / out-of-range tones.
10
+ * 4. The teal case: a custom teal ramp drives `--rt-bg-accent-primary-solid` to teal.
11
+ */
12
+
13
+ const STYLES_DIR: string = __dirname;
14
+
15
+ /** Frozen resolved (own-palette) values of every accent token BEFORE the indirection refactor. */
16
+ const BASELINE: Record<string, string> = {
17
+ '--rt-bg-accent-primary-subtle': 'light-dark(#eaedfc, color-mix(in srgb, #4284d7 18%, #1c1b1e))',
18
+ '--rt-bg-accent-primary-solid': '#4284d7',
19
+ '--rt-bg-accent-primary-hover': 'light-dark(color-mix(in srgb, #4284d7 90%, #000), color-mix(in srgb, #4284d7 90%, #fff))',
20
+ '--rt-bg-accent-primary-disabled': 'color-mix(in srgb, #4284d7 38%, transparent)',
21
+ '--rt-bg-accent-success-subtle': 'light-dark(#e5f8f4, color-mix(in srgb, #01af8d 18%, #1c1b1e))',
22
+ '--rt-bg-accent-success-solid': '#21b18e',
23
+ '--rt-bg-accent-success-hover': 'light-dark(color-mix(in srgb, #21b18e 90%, #000), color-mix(in srgb, #21b18e 90%, #fff))',
24
+ '--rt-bg-accent-success-disabled': 'color-mix(in srgb, #21b18e 38%, transparent)',
25
+ '--rt-bg-accent-warning-subtle': 'light-dark(#e8cbbf, color-mix(in srgb, #ef7128 18%, #1c1b1e))',
26
+ '--rt-bg-accent-warning-solid': '#ee7a34',
27
+ '--rt-bg-accent-warning-hover': 'light-dark(color-mix(in srgb, #ee7a34 90%, #000), color-mix(in srgb, #ee7a34 90%, #fff))',
28
+ '--rt-bg-accent-warning-disabled': 'color-mix(in srgb, #ee7a34 38%, transparent)',
29
+ '--rt-bg-accent-danger-subtle': 'light-dark(#fdedee, color-mix(in srgb, #eb5055 18%, #1c1b1e))',
30
+ '--rt-bg-accent-danger-solid': '#eb5055',
31
+ '--rt-bg-accent-danger-hover': 'light-dark(color-mix(in srgb, #eb5055 90%, #000), color-mix(in srgb, #eb5055 90%, #fff))',
32
+ '--rt-bg-accent-danger-disabled': 'color-mix(in srgb, #eb5055 38%, transparent)',
33
+ '--rt-bg-accent-info-subtle': 'light-dark(#eaedfc, color-mix(in srgb, #4284d7 18%, #1c1b1e))',
34
+ '--rt-bg-accent-info-solid': '#4284d7',
35
+ '--rt-bg-accent-info-hover': 'light-dark(color-mix(in srgb, #4284d7 90%, #000), color-mix(in srgb, #4284d7 90%, #fff))',
36
+ '--rt-bg-accent-info-disabled': 'color-mix(in srgb, #4284d7 38%, transparent)',
37
+ '--rt-text-accent-brand': 'light-dark(#0d1c2b, #e8e8e8)',
38
+ '--rt-text-accent-primary': 'light-dark(#4284d7, #6d96e8)',
39
+ '--rt-text-accent-success': '#01af8d',
40
+ '--rt-text-accent-success-soft': '#21b18e',
41
+ '--rt-text-accent-warning': '#ef7128',
42
+ '--rt-text-accent-warning-soft': '#ee7a34',
43
+ '--rt-text-accent-danger': '#eb5055',
44
+ '--rt-text-accent-danger-soft': '#e88487',
45
+ '--rt-text-accent-info': '#4284d7',
46
+ '--rt-text-accent-info-soft': '#4285f4',
47
+ '--rt-icon-accent-brand': 'light-dark(#0d1c2b, #e8e8e8)',
48
+ '--rt-icon-accent-primary': 'light-dark(#4284d7, #6d96e8)',
49
+ '--rt-icon-accent-success': '#01af8d',
50
+ '--rt-icon-accent-warning': '#ef7128',
51
+ '--rt-icon-accent-danger': '#eb5055',
52
+ '--rt-icon-accent-info': '#4284d7',
53
+ '--rt-border-accent-primary': 'light-dark(#4284d7, #6d96e8)',
54
+ '--rt-border-accent-success': '#01af8d',
55
+ '--rt-border-accent-warning': '#ef7128',
56
+ '--rt-border-accent-danger': '#eb5055',
57
+ '--rt-border-accent-danger-soft': '#e88487',
58
+ '--rt-border-accent-info': '#4284d7',
59
+ '--rt-border-focus': 'light-dark(#b3ceef, #6d96e8)',
60
+ };
61
+
62
+ /** Resolve `var(--mat-sys-X, FALLBACK)` to its fallback (own-palette, no Material configured). */
63
+ function stripMat(input: string): string {
64
+ let value: string = input;
65
+ let index: number = value.indexOf('var(--mat-sys-');
66
+
67
+ while (index >= 0) {
68
+ let depth: number = 0;
69
+ let j: number = index + 4;
70
+
71
+ for (; j < value.length; j++) {
72
+ if (value[j] === '(') {
73
+ depth++;
74
+ } else if (value[j] === ')') {
75
+ if (depth === 0) {
76
+ break;
77
+ }
78
+ depth--;
79
+ }
80
+ }
81
+
82
+ const inner: string = value.slice(index + 4, j);
83
+ const comma: number = inner.indexOf(',');
84
+ value = value.slice(0, index) + inner.slice(comma + 1).trim() + value.slice(j + 1);
85
+ index = value.indexOf('var(--mat-sys-');
86
+ }
87
+
88
+ return value;
89
+ }
90
+
91
+ /** Collapse `light-dark(X, X)` to `X` (identical branches render the same in both modes). */
92
+ function normalize(input: string): string {
93
+ let value: string = input.replace(/\s+/g, ' ').trim();
94
+ let prev: string = '';
95
+
96
+ while (value !== prev) {
97
+ prev = value;
98
+ value = value.replace(/light-dark\(\s*([^,()]+?)\s*,\s*\1\s*\)/g, '$1');
99
+ }
100
+
101
+ return value.replace(/\s+/g, ' ').trim();
102
+ }
103
+
104
+ /** Extract `--name: value;` declarations matching a name pattern from compiled CSS. */
105
+ function extractDeclarations(css: string, namePattern: string): Record<string, string> {
106
+ const out: Record<string, string> = {};
107
+ const re: RegExp = new RegExp(`(${namePattern}):\\s*([^;]+);`, 'g');
108
+ let match: RegExpExecArray | null = re.exec(css);
109
+
110
+ while (match !== null) {
111
+ out[match[1]] = match[2].trim();
112
+ match = re.exec(css);
113
+ }
114
+
115
+ return out;
116
+ }
117
+
118
+ function compileTokens(): string {
119
+ return sass.compile(path.join(STYLES_DIR, 'tokens.scss')).css;
120
+ }
121
+
122
+ function compileWithMixin(body: string): sass.CompileResult {
123
+ return sass.compileString(`@use 'main' as rt;\n${body}`, { loadPaths: [STYLES_DIR] });
124
+ }
125
+
126
+ describe('rt-tools color schemes', () => {
127
+ describe('Δ0 regression — accent indirection keeps the own palette byte-for-byte', () => {
128
+ it('every accent semantic token resolves to its pre-refactor value', () => {
129
+ const css: string = compileTokens();
130
+ const ramp: Record<string, string> = extractDeclarations(css, '--rt-color-(?:primary|info|success|warning|danger|brand)-\\d+');
131
+ const semantic: Record<string, string> = extractDeclarations(
132
+ css,
133
+ '--rt-(?:bg|text|icon|border)-accent[\\w-]*|--rt-border-focus'
134
+ );
135
+
136
+ const resolveRamp: (value: string) => string = (value: string): string => {
137
+ let resolved: string = value;
138
+ let prev: string = '';
139
+
140
+ while (resolved !== prev) {
141
+ prev = resolved;
142
+ for (const key of Object.keys(ramp)) {
143
+ resolved = resolved.split(`var(${key})`).join(stripMat(ramp[key]));
144
+ }
145
+ }
146
+
147
+ return normalize(stripMat(resolved));
148
+ };
149
+
150
+ for (const token of Object.keys(BASELINE)) {
151
+ expect(semantic[token]).toBeDefined();
152
+ expect(resolveRamp(semantic[token])).toBe(BASELINE[token]);
153
+ }
154
+ });
155
+ });
156
+
157
+ describe('Material hybrid — default honors --mat-sys-*, a scheme overrides it', () => {
158
+ it('default ramp tones carry the --mat-sys-* fallback where the original token did', () => {
159
+ const ramp: Record<string, string> = extractDeclarations(
160
+ compileTokens(),
161
+ '--rt-color-(?:primary|info|success|warning|danger|brand)-\\d+'
162
+ );
163
+
164
+ // tones that mapped to a Material system color carry the fallback (default honors Material)
165
+ expect(ramp['--rt-color-primary-100']).toBe('var(--mat-sys-primary, #4284d7)');
166
+ expect(ramp['--rt-color-primary-20']).toBe('var(--mat-sys-primary-container, #eaedfc)');
167
+ expect(ramp['--rt-color-danger-100']).toBe('var(--mat-sys-error, #eb5055)');
168
+ expect(ramp['--rt-color-brand-100']).toBe('var(--mat-sys-primary, #0d1c2b)');
169
+
170
+ // roles with no Material mapping stay raw — and a scheme overriding ANY tone with a raw
171
+ // value drops the fallback entirely, so the scheme wins over an active Material theme.
172
+ expect(ramp['--rt-color-info-100']).toBe('#4284d7');
173
+ expect(ramp['--rt-color-success-100']).toBe('#01af8d');
174
+ expect(ramp['--rt-color-warning-100']).toBe('#ef7128');
175
+ });
176
+ });
177
+
178
+ describe('dark mode — a scheme drives both modes via distinct ramp tones', () => {
179
+ it('accent tokens pick tone-100 in light and tone-60 in dark (scheme controls each)', () => {
180
+ const semantic: Record<string, string> = extractDeclarations(
181
+ compileTokens(),
182
+ '--rt-text-accent-primary|--rt-border-accent-primary|--rt-icon-accent-primary'
183
+ );
184
+
185
+ // light-dark(primary-100, primary-60): the kit fixes WHICH tone per mode; the scheme
186
+ // supplies the VALUE of each tone → a scheme can set a different dark tone (tone-60) than light.
187
+ for (const token of Object.keys(semantic)) {
188
+ expect(semantic[token]).toContain('var(--rt-color-primary-100)');
189
+ expect(semantic[token]).toContain('var(--rt-color-primary-60)');
190
+ expect(semantic[token].indexOf('primary-100')).toBeLessThan(semantic[token].indexOf('primary-60'));
191
+ }
192
+ });
193
+ });
194
+
195
+ describe('rt.color-scheme mixin', () => {
196
+ it('emits a scoped [data-rt-scheme] block with only raw role rows', () => {
197
+ const css: string = compileWithMixin(
198
+ '@include rt.color-scheme(\'teal\', (primary: (20: #b3e3e1, 100: #008582), brand: (100: #008582)));'
199
+ ).css;
200
+
201
+ const block: string = css.slice(css.indexOf('[data-rt-scheme=teal]'));
202
+
203
+ expect(block).toContain('[data-rt-scheme=teal]');
204
+ expect(block).toContain('--rt-color-primary-100: #008582');
205
+ expect(block).toContain('--rt-color-primary-20: #b3e3e1');
206
+ expect(block).toContain('--rt-color-brand-100: #008582');
207
+ // schemes never duplicate the semantic derivation layer
208
+ expect(block).not.toContain('--rt-bg-accent-primary-solid:');
209
+ });
210
+
211
+ it('rejects an unknown role', () => {
212
+ expect(() => compileWithMixin('@include rt.color-scheme(\'x\', (foo: (100: #000000)));')).toThrow(/unknown role/i);
213
+ });
214
+
215
+ it('rejects an out-of-range tone', () => {
216
+ expect(() => compileWithMixin('@include rt.color-scheme(\'x\', (primary: (150: #000000)));')).toThrow(/integer 0–100/i);
217
+ });
218
+
219
+ it('rejects an empty role map', () => {
220
+ expect(() => compileWithMixin('@include rt.color-scheme(\'x\', ());')).toThrow(/non-empty map/i);
221
+ });
222
+ });
223
+
224
+ describe('teal reference case', () => {
225
+ it('a teal primary ramp recolors --rt-bg-accent-primary-solid to teal', () => {
226
+ const css: string = compileWithMixin(
227
+ '@include rt.color-scheme(\'teal\', (primary: (20: #b3e3e1, 40: #5cb8b5, 60: #1a9d99, 100: #008582)));'
228
+ ).css;
229
+
230
+ const scheme: Record<string, string> = extractDeclarations(css, '--rt-color-primary-\\d+');
231
+ // bg-accent-primary-solid === var(--rt-color-primary-100); under the teal scheme that is #008582
232
+ expect(scheme['--rt-color-primary-100']).toBe('#008582');
233
+ expect(normalize(stripMat(css.match(/--rt-bg-accent-primary-solid:\s*([^;]+);/)![1]))).toBe('var(--rt-color-primary-100)');
234
+ });
235
+ });
236
+ });
@@ -1,3 +1,10 @@
1
+ /// @deprecated — legacy `.c-button` system. New code uses `.rtui-btn` (_rtui_button.scss);
2
+ /// ~60% of this module duplicates it. Kept because consumers still apply `.c-button`
3
+ /// classes AND override `--rt-button-*` vars directly (incl. dark mode) — rerouting these rules
4
+ /// onto `--rt-rtui-btn-*` would silently kill those overrides. Removal plan (next major):
5
+ /// map classes `--fill-green→success`, `--fill-red→error`, `--fill-blue→accent-light`,
6
+ /// `--outline-*→*-outline`; `--txt-*`/`--fab` first need a text/icon appearance in .rtui-btn.
7
+ /// See TOKENS.md "Buttons: legacy vs rtui".
1
8
  @use '../base/mixin' as mixins;
2
9
  @use '../base/variables' as vars;
3
10
  @use 'sass:color' as color;
@@ -20,7 +27,8 @@ $button: (
20
27
  background: var(--rt-color-neutral-25),
21
28
  ),
22
29
  text-active: (
23
- background: var(--clr-black-30),
30
+ background: #b2cbca,
31
+ // palette outlier, no neutral-scale equivalent
24
32
  ),
25
33
  text-base: (
26
34
  color: var(--rt-color-neutral-60),
@@ -57,36 +65,36 @@ $button: (
57
65
  color: var(--rt-color-neutral-0),
58
66
  ),
59
67
  fill-green: (
60
- border: 1px solid color.scale(vars.$clr-green-80, $lightness: -10%),
68
+ border: 1px solid color.scale(vars.$btn-success, $lightness: -10%),
61
69
  color: var(--rt-color-neutral-0),
62
70
  background-color: var(--rt-color-green-80),
63
71
  ),
64
72
  fill-green-hover: (
65
- background-color: color.scale(vars.$clr-green-80, $lightness: -10%),
73
+ background-color: color.scale(vars.$btn-success, $lightness: -10%),
66
74
  ),
67
75
  fill-green-light: (
68
- border-color: color.scale(vars.$clr-green-10, $lightness: -10%),
76
+ border-color: color.scale(vars.$btn-success-soft, $lightness: -10%),
69
77
  color: var(--rt-color-green-100),
70
78
  background-color: var(--rt-color-green-10),
71
79
  ),
72
80
  fill-green-light-hover: (
73
- background-color: color.scale(vars.$clr-green-10, $lightness: -10%),
81
+ background-color: color.scale(vars.$btn-success-soft, $lightness: -10%),
74
82
  ),
75
83
  fill-red: (
76
- border: 1px solid color.scale(vars.$clr-red-100, $lightness: -10%),
84
+ border: 1px solid color.scale(vars.$btn-danger, $lightness: -10%),
77
85
  color: var(--rt-color-neutral-0),
78
- background-color: vars.$clr-red-100,
86
+ background-color: vars.$btn-danger,
79
87
  ),
80
88
  fill-red-hover: (
81
- background-color: color.scale(vars.$clr-red-100, $lightness: -10%),
89
+ background-color: color.scale(vars.$btn-danger, $lightness: -10%),
82
90
  ),
83
91
  fill-red-light: (
84
- border-color: color.scale(vars.$clr-red-10, $lightness: -10%),
92
+ border-color: color.scale(vars.$btn-danger-soft, $lightness: -10%),
85
93
  color: var(--rt-color-red-100),
86
94
  background-color: var(--rt-color-red-10),
87
95
  ),
88
96
  fill-red-light-hover: (
89
- background-color: color.scale(vars.$clr-red-10, $lightness: -10%),
97
+ background-color: color.scale(vars.$btn-danger-soft, $lightness: -10%),
90
98
  ),
91
99
  outline: (
92
100
  border: 1px solid var(--rt-color-blue-40),
@@ -112,22 +120,22 @@ $button: (
112
120
  }
113
121
 
114
122
  button {
115
- line-height: 1;
116
123
  cursor: pointer;
124
+ line-height: 1;
117
125
  }
118
126
 
119
127
  .c-button {
128
+ position: relative;
120
129
  display: inline-flex;
121
130
  align-items: center;
122
- font-family: var(--rt-button-base-font-family);
123
- line-height: 1;
124
- position: relative;
125
131
  justify-content: center;
126
- font-size: 1rem;
127
132
  color: var(--rt-button-base-color);
133
+ font-family: var(--rt-button-base-font-family);
134
+ font-size: 1rem;
135
+ line-height: 1;
128
136
  transition: all 0.15s linear;
129
137
 
130
- //FAB
138
+ // FAB
131
139
  &[class*='--fab'] {
132
140
  border: 0;
133
141
  background-color: transparent;
@@ -149,8 +157,8 @@ button {
149
157
  // TEXT
150
158
  &[class*='--txt-'] {
151
159
  border: 0;
152
- background-color: transparent;
153
160
  border-radius: 5px;
161
+ background-color: transparent;
154
162
 
155
163
  &:hover {
156
164
  background: var(--rt-button-text-hover-background);
@@ -239,9 +247,9 @@ button {
239
247
  &[class*='green'] {
240
248
  border: var(--rt-button-fill-green-border);
241
249
  border-radius: 2px;
242
- color: var(--rt-button-fill-green-color);
243
- box-shadow: 0 2px 4px rgba(24, 24, 24, 0.1);
244
250
  background-color: var(--rt-button-fill-green-background-color);
251
+ box-shadow: 0 2px 4px rgb(24 24 24 / 10%);
252
+ color: var(--rt-button-fill-green-color);
245
253
 
246
254
  &:hover {
247
255
  background-color: var(--rt-button-fill-green-hover-background-color);
@@ -249,8 +257,8 @@ button {
249
257
 
250
258
  &[class*='-light'] {
251
259
  border-color: var(--rt-button-fill-green-light-border-color);
252
- color: var(--rt-button-fill-green-light-color);
253
260
  background-color: var(--rt-button-fill-green-light-background-color);
261
+ color: var(--rt-button-fill-green-light-color);
254
262
 
255
263
  &:hover {
256
264
  background-color: var(--rt-button-fill-green-light-hover-background-color);
@@ -261,9 +269,9 @@ button {
261
269
  &[class*='red'] {
262
270
  border: var(--rt-button-fill-red-border);
263
271
  border-radius: 2px;
264
- color: var(--rt-button-fill-red-color);
265
- box-shadow: 0 2px 4px rgba(24, 24, 24, 0.1);
266
272
  background-color: var(--rt-button-fill-red-background-color);
273
+ box-shadow: 0 2px 4px rgb(24 24 24 / 10%);
274
+ color: var(--rt-button-fill-red-color);
267
275
 
268
276
  &:hover {
269
277
  background-color: var(--rt-button-fill-red-hover-background-color);
@@ -271,8 +279,8 @@ button {
271
279
 
272
280
  &[class*='-light'] {
273
281
  border-color: var(--rt-button-fill-red-light-border-color);
274
- color: var(--rt-button-fill-red-light-color);
275
282
  background-color: var(--rt-button-fill-red-light-background-color);
283
+ color: var(--rt-button-fill-red-light-color);
276
284
 
277
285
  &:hover {
278
286
  background-color: var(--rt-button-fill-red-light-hover-background-color);
@@ -348,7 +356,7 @@ button {
348
356
 
349
357
  // SHADOW
350
358
  &[class*='--shadow'] {
351
- box-shadow: 0 2px 4px rgba(24, 24, 24, 0.1);
359
+ box-shadow: 0 2px 4px rgb(24 24 24 / 10%);
352
360
  }
353
361
 
354
362
  // --shadow
@@ -46,15 +46,14 @@ $dynamic-selector: (
46
46
 
47
47
  .rtui-dynamic-selector {
48
48
  &__item {
49
- height: var(--rt-dynamic-selector-item-height);
50
49
  display: flex;
51
- justify-content: flex-start;
50
+ height: var(--rt-dynamic-selector-item-height);
52
51
  align-items: center;
53
-
54
- background-color: var(--rt-dynamic-selector-item-background-color);
52
+ justify-content: flex-start;
53
+ padding: var(--rt-dynamic-selector-item-padding);
55
54
  border-radius: var(--rt-dynamic-selector-item-border-radius);
56
55
  margin-bottom: var(--rt-dynamic-selector-item-margin-bottom);
57
- padding: var(--rt-dynamic-selector-item-padding);
56
+ background-color: var(--rt-dynamic-selector-item-background-color);
58
57
 
59
58
  &::-webkit-scrollbar {
60
59
  display: none;
@@ -66,17 +65,17 @@ $dynamic-selector: (
66
65
 
67
66
  &-mover {
68
67
  display: flex;
69
- justify-content: center;
70
68
  align-items: center;
69
+ justify-content: center;
71
70
  padding: var(--rt-dynamic-selector-item-mover-padding);
72
71
  border-right: var(--rt-dynamic-selector-item-mover-border-right);
73
72
  margin-right: var(--rt-dynamic-selector-item-mover-margin-right);
74
73
  }
75
74
 
76
75
  &-title {
77
- white-space: nowrap;
78
76
  overflow: hidden;
79
77
  text-overflow: ellipsis;
78
+ white-space: nowrap;
80
79
  }
81
80
 
82
81
  &-input {
@@ -92,11 +91,11 @@ $dynamic-selector: (
92
91
 
93
92
  &-control {
94
93
  display: flex;
95
- justify-content: center;
96
94
  align-items: center;
97
- gap: var(--rt-dynamic-selector-item-control-gap);
95
+ justify-content: center;
98
96
  padding: var(--rt-dynamic-selector-item-control-padding);
99
97
  border-right: var(--rt-dynamic-selector-item-control-border-right);
98
+ gap: var(--rt-dynamic-selector-item-control-gap);
100
99
 
101
100
  &:last-child {
102
101
  padding: var(--rt-dynamic-selector-item-control-last-child-padding);
@@ -105,8 +104,8 @@ $dynamic-selector: (
105
104
 
106
105
  &-button {
107
106
  display: flex;
108
- justify-content: center;
109
107
  align-items: center;
108
+ justify-content: center;
110
109
 
111
110
  .mat-icon {
112
111
  width: var(--rt-dynamic-selector-item-control-icon-size);
@@ -3,30 +3,28 @@
3
3
 
4
4
  // FORM
5
5
  .c-form {
6
- width: 100%;
7
-
8
6
  display: flex;
7
+ width: 100%;
8
+ flex: 1 1 100%;
9
9
  flex-direction: column;
10
- justify-content: flex-start;
11
10
  align-items: flex-start;
12
- flex: 1 1 100%;
11
+ justify-content: flex-start;
13
12
 
14
13
  &__title {
15
14
  font-size: 1.5rem;
16
- line-height: 1.1;
17
15
  font-weight: 600;
16
+ line-height: 1.1;
18
17
  }
19
18
 
20
19
  &__title-descr {
21
20
  margin-top: 0.75rem;
22
- font-size: 1rem;
23
21
  color: var(--rt-text-base-secondary);
22
+ font-size: 1rem;
24
23
  }
25
24
 
26
25
  &__item {
27
- width: 100%;
28
-
29
26
  display: flex;
27
+ width: 100%;
30
28
  flex-direction: column;
31
29
  align-items: center;
32
30
  justify-content: flex-start;
@@ -38,18 +36,15 @@
38
36
 
39
37
  &__controls {
40
38
  position: relative;
41
- width: 100%;
42
-
43
39
  display: flex;
40
+ width: 100%;
44
41
  flex-direction: column;
45
-
46
42
  margin-top: 2rem;
47
43
  }
48
44
 
49
45
  &__control-item {
50
- width: 100%;
51
-
52
46
  display: flex;
47
+ width: 100%;
53
48
  align-items: center;
54
49
  justify-content: flex-start;
55
50
 
@@ -0,0 +1,30 @@
1
+ /// Material bridge — the single global touch-point between rt-tools and Angular Material.
2
+ ///
3
+ /// Rule: every GLOBAL override of Material internals (--mat-* / --mdc-* vars, .mat-* / .cdk-* selectors
4
+ /// that is not scoped to a component's own DOM) lives here, so a Material upgrade is reviewed in one file.
5
+ ///
6
+ /// Scoped piercings stay next to their component (they target Material nodes inside the component's
7
+ /// own template) — current inventory, revisit on every Angular Material major:
8
+ /// - snack-bar: styles/components/_snackbar.scss (panelClass .snack-bar-*: --mat-snack-bar-*, --mdc-snackbar-*)
9
+ /// - table: styles/components/_table.scss (consumes --mat-form-field-filled-container-color)
10
+ /// - checkbox: styles/components/_checkbox.scss (consumes --mat-button-text-label-text-color)
11
+ /// - dynamic-selectors: styles/components/_dynamic-selectors.scss (+ ::ng-deep .mat-mdc-form-field-* in
12
+ /// multi-selector-popup / selected-list component scss)
13
+ /// - side-menu: menu-sub-item component scss (::ng-deep .mat-expansion-*)
14
+ /// - modal: modal.component.scss (::ng-deep .mat-icon)
15
+ /// - spinner: spinner.component.scss (::ng-deep circle of mat-spinner SVG)
16
+ /// - aside: aside-panel.component.scss (.mat-mdc-tab-header, .mat-badge-content — encapsulation: None)
17
+ /// - toolbar: toolbar.component.scss (--mat-tab-*, --mdc-secondary-navigation-tab-*)
18
+
19
+ /* Keep CDK overlays (aside drawer, selector popups, modals) above app chrome.
20
+ Moved from aside-panel.component.scss — applies app-wide by design. */
21
+ .cdk-overlay-container,
22
+ .cdk-overlay-pane {
23
+ z-index: 9999;
24
+ }
25
+
26
+ /* Mat tab groups stretch to their container (aside tabs rely on it).
27
+ Moved from aside-panel.component.scss. */
28
+ .mat-mdc-tab-group {
29
+ width: 100%;
30
+ }
@@ -171,27 +171,27 @@ $rtui-button: (
171
171
  --shadow: var(--rt-rtui-btn-base-shadow);
172
172
  --shadow-blur: var(--rt-rtui-btn-base-shadow-blur);
173
173
 
174
+ display: var(--display);
174
175
  width: var(--width);
175
176
  align-items: center;
176
- background-color: var(--bg);
177
+ justify-content: center;
178
+ padding: var(--padding);
177
179
  border: var(--border);
178
180
  border-radius: 6px;
181
+ background-color: var(--bg);
179
182
  box-shadow: var(--shadow);
180
183
  color: var(--color);
181
184
  cursor: pointer;
182
- display: var(--display);
183
185
  font-size: var(--font-size);
184
186
  font-weight: 600;
185
187
  gap: var(--gap);
186
- justify-content: center;
187
188
  line-height: 1;
188
- padding: var(--padding);
189
+ text-decoration: none;
189
190
  transition:
190
191
  background-color 0.15s linear,
191
192
  color 0.15s linear,
192
193
  box-shadow 0.15s linear,
193
194
  border-color 0.15s linear;
194
- text-decoration: none;
195
195
 
196
196
  &:focus {
197
197
  outline: none;