@tx-angular-design-system/ui-kit 0.1.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.
@@ -0,0 +1,330 @@
1
+ /* =============================================================================
2
+ * @tx-angular-design-system/ui-kit — global base layer
3
+ *
4
+ * Everything here reads from the token layer in theme.css. There are no
5
+ * literal colours, sizes or font names: re-theming by overriding the tokens
6
+ * re-skins this file too.
7
+ *
8
+ * Lives in @layer base so any consumer rule (layered or not) outranks it.
9
+ * ========================================================================== */
10
+
11
+ @layer base {
12
+ *,
13
+ ::before,
14
+ ::after {
15
+ box-sizing: border-box;
16
+ }
17
+
18
+ html,
19
+ body {
20
+ margin: 0;
21
+ padding: 0;
22
+ }
23
+
24
+ body {
25
+ background-color: var(--color-tx-canvas);
26
+ color: var(--color-tx-text-primary);
27
+ font-family: var(--font-tx-sans);
28
+ font-size: var(--text-tx-lg);
29
+ line-height: var(--leading-tx-normal);
30
+ -webkit-font-smoothing: antialiased;
31
+ -moz-osx-font-smoothing: grayscale;
32
+ }
33
+
34
+ h1,
35
+ h2,
36
+ h3,
37
+ h4,
38
+ h5,
39
+ h6 {
40
+ margin: 0;
41
+ font-family: var(--font-tx-display);
42
+ font-weight: 700;
43
+ letter-spacing: var(--tracking-tx-tight);
44
+ color: var(--color-tx-text-heading);
45
+ }
46
+
47
+ button {
48
+ font: inherit;
49
+ color: inherit;
50
+ cursor: pointer;
51
+ }
52
+
53
+ input,
54
+ select,
55
+ textarea {
56
+ font: inherit;
57
+ color: var(--color-tx-text-primary);
58
+ }
59
+
60
+ /* One focus treatment for the whole kit. Modern engines draw `outline`
61
+ following the element's own border-radius, so this needs no radius of its
62
+ own — which is what kept the POC from having to re-round focused rows. */
63
+ :focus-visible {
64
+ outline: var(--width-tx-focus-ring) solid var(--color-tx-focus-ring);
65
+ outline-offset: var(--width-tx-focus-offset);
66
+ }
67
+
68
+ input[type='checkbox'],
69
+ input[type='radio'] {
70
+ accent-color: var(--color-tx-primary-hover);
71
+ }
72
+
73
+ ::selection {
74
+ background-color: var(--color-tx-primary-subtle);
75
+ color: var(--color-tx-text-primary);
76
+ }
77
+
78
+ /* Scrollbars — a bare thumb, no track furniture, on every scroll container:
79
+ * the page, dropdown and tree popups, the dialog body, the sidebar, the
80
+ * table's horizontal scroller.
81
+ *
82
+ * Two engines, two mechanisms, and the order matters:
83
+ *
84
+ * `scrollbar-width`/`scrollbar-color` are the standard properties, but they
85
+ * only recolour the platform scrollbar — they cannot remove Chromium's
86
+ * stepper arrows on Windows, so on their own the result still reads as the
87
+ * native scrollbar with a tint. Worse, Chromium ignores every
88
+ * `::-webkit-scrollbar` rule for any element those properties apply to, and
89
+ * they are inherited, so one declaration on :root switches the whole
90
+ * document back to the platform scrollbar.
91
+ *
92
+ * The pseudo-elements can draw the scrollbar outright, arrows included. So
93
+ * the standard properties are confined to engines that have no
94
+ * pseudo-elements to offer — Firefox, which draws no arrows anyway — and
95
+ * everything else takes the pseudo-element path.
96
+ *
97
+ * Being in @layer base, any rule a consumer writes outranks this; an app
98
+ * that wants the platform scrollbar back sets `scrollbar-width: auto` on
99
+ * :root, which also hands Chromium's own scrollbar back by the rule above. */
100
+ @supports not selector(::-webkit-scrollbar) {
101
+ :root {
102
+ scrollbar-width: thin;
103
+ scrollbar-color: var(--color-tx-scrollbar-thumb) var(--color-tx-scrollbar-track);
104
+ }
105
+ }
106
+
107
+ ::-webkit-scrollbar {
108
+ width: var(--spacing-tx-scrollbar);
109
+ height: var(--spacing-tx-scrollbar);
110
+ }
111
+
112
+ /* The stepper arrows, and the corner where two scrollbars meet. Removing
113
+ them is the whole reason this path exists. */
114
+ ::-webkit-scrollbar-button {
115
+ display: none;
116
+ width: 0;
117
+ height: 0;
118
+ }
119
+
120
+ ::-webkit-scrollbar-track,
121
+ ::-webkit-scrollbar-track-piece,
122
+ ::-webkit-scrollbar-corner {
123
+ background-color: var(--color-tx-scrollbar-track);
124
+ }
125
+
126
+ ::-webkit-scrollbar-thumb {
127
+ border-radius: var(--radius-tx-full);
128
+ background-color: var(--color-tx-scrollbar-thumb);
129
+ /* A transparent border plus padding-box clipping is what insets the thumb
130
+ within the track. Padding would not do it: the pseudo-element's box is
131
+ the thumb itself. */
132
+ border: var(--spacing-tx-scrollbar-inset) solid transparent;
133
+ background-clip: padding-box;
134
+ }
135
+
136
+ ::-webkit-scrollbar-thumb:hover {
137
+ background-color: var(--color-tx-scrollbar-thumb-hover);
138
+ }
139
+
140
+ @media (prefers-reduced-motion: reduce) {
141
+ *,
142
+ ::before,
143
+ ::after {
144
+ transition-duration: 0.01ms !important;
145
+ animation-duration: 0.01ms !important;
146
+ animation-iteration-count: 1 !important;
147
+ scroll-behavior: auto !important;
148
+ }
149
+ }
150
+ }
151
+
152
+ /* -----------------------------------------------------------------------------
153
+ * CDK overlay integration.
154
+ *
155
+ * Deliberately unlayered so it outranks @angular/cdk/overlay-prebuilt.css
156
+ * regardless of which order the two are imported in.
157
+ * -------------------------------------------------------------------------- */
158
+
159
+ .cdk-overlay-dark-backdrop {
160
+ background-color: var(--color-tx-scrim);
161
+ }
162
+
163
+ /* The overlay container sits above app chrome but below nothing else we ship;
164
+ CDK's own z-index (1000) is respected — this only re-points the colour and
165
+ makes panes inherit the kit's font so popup text matches its trigger. */
166
+ .cdk-overlay-container,
167
+ .cdk-global-overlay-wrapper {
168
+ font-family: var(--font-tx-sans);
169
+ font-size: var(--text-tx-base);
170
+ line-height: var(--leading-tx-normal);
171
+ color: var(--color-tx-text-primary);
172
+ }
173
+
174
+ /* Popups must never exceed the viewport on a small screen. CDK's flexible
175
+ position strategy sets max-height/max-width on the pane; this guarantees the
176
+ pane's own content scrolls rather than the page. */
177
+ .tx-overlay-pane {
178
+ display: flex;
179
+ min-width: 0;
180
+ max-width: calc(100vw - (2 * var(--spacing-tx-3)));
181
+ flex-direction: column;
182
+ }
183
+
184
+ /* The trigger-to-popup gap. Applied to the pane as padding on whichever edge
185
+ * faces the trigger, chosen per position by TxConnectedOverlayDirective. Doing
186
+ * it here rather than as a numeric CDK offset keeps the gap a spacing token —
187
+ * re-spacing the kit in theme.css moves it, and no pixel value is compiled
188
+ * into TypeScript. */
189
+ .tx-overlay-gap-top-sm {
190
+ padding-top: var(--spacing-tx-1);
191
+ }
192
+ .tx-overlay-gap-top-md {
193
+ padding-top: var(--spacing-tx-2);
194
+ }
195
+ .tx-overlay-gap-bottom-sm {
196
+ padding-bottom: var(--spacing-tx-1);
197
+ }
198
+ .tx-overlay-gap-bottom-md {
199
+ padding-bottom: var(--spacing-tx-2);
200
+ }
201
+ .tx-overlay-gap-left-sm {
202
+ padding-left: var(--spacing-tx-1);
203
+ }
204
+ .tx-overlay-gap-left-md {
205
+ padding-left: var(--spacing-tx-2);
206
+ }
207
+ .tx-overlay-gap-right-sm {
208
+ padding-right: var(--spacing-tx-1);
209
+ }
210
+ .tx-overlay-gap-right-md {
211
+ padding-right: var(--spacing-tx-2);
212
+ }
213
+
214
+ /* -----------------------------------------------------------------------------
215
+ * Tree connector guides.
216
+ *
217
+ * Pseudo-elements, so they cannot be expressed as utility classes — but every
218
+ * value is still a token, and the whole ornament is opt-in through the tree's
219
+ * `guides` config. The indent narrows on small screens so a deep tree stays
220
+ * readable at 360px instead of scrolling sideways.
221
+ * -------------------------------------------------------------------------- */
222
+
223
+ .tx-tree-guides ul {
224
+ margin: 0;
225
+ list-style: none;
226
+ border-left: var(--width-tx-border) solid var(--color-tx-border);
227
+ padding-left: var(--spacing-tx-5);
228
+ }
229
+
230
+ .tx-tree-guides > ul {
231
+ border-left: none;
232
+ padding-left: 0;
233
+ }
234
+
235
+ .tx-tree-guides li {
236
+ position: relative;
237
+ }
238
+
239
+ .tx-tree-guides ul > li::before {
240
+ position: absolute;
241
+ top: var(--spacing-tx-3-5);
242
+ left: calc(-1 * var(--spacing-tx-5));
243
+ width: var(--spacing-tx-3-5);
244
+ height: var(--width-tx-border);
245
+ background-color: var(--color-tx-border);
246
+ content: '';
247
+ }
248
+
249
+ /* Roots have no parent to connect to. */
250
+ .tx-tree-guides > ul > li::before {
251
+ display: none;
252
+ }
253
+
254
+ @media (width < 40rem) {
255
+ .tx-tree-guides ul {
256
+ padding-left: var(--spacing-tx-3-5);
257
+ }
258
+
259
+ .tx-tree-guides ul > li::before {
260
+ left: calc(-1 * var(--spacing-tx-3-5));
261
+ width: var(--spacing-tx-2-5);
262
+ }
263
+ }
264
+
265
+ /* Without guides the list is still a plain, un-bulleted, indented list. */
266
+ .tx-tree-plain ul {
267
+ margin: 0;
268
+ list-style: none;
269
+ padding-left: var(--spacing-tx-5);
270
+ }
271
+
272
+ .tx-tree-plain > ul {
273
+ padding-left: 0;
274
+ }
275
+
276
+ @media (width < 40rem) {
277
+ .tx-tree-plain ul {
278
+ padding-left: var(--spacing-tx-3-5);
279
+ }
280
+ }
281
+
282
+ /* Dialog panes get viewport padding so a dialog never touches the screen edge
283
+ * on a small device, and the toast pane must not swallow clicks over the page
284
+ * behind it — each toast re-enables pointer events for itself. */
285
+ .tx-dialog-pane {
286
+ width: 100%;
287
+ max-width: calc(100vw - (2 * var(--spacing-tx-4)));
288
+ margin: var(--spacing-tx-4);
289
+ }
290
+
291
+ .tx-toast-pane {
292
+ pointer-events: none;
293
+ max-width: 100vw;
294
+ }
295
+
296
+ /* -----------------------------------------------------------------------------
297
+ * The tread groove — the brand's one ornament, used by tx-divider's `groove`
298
+ * variant and tx-header's `groove` option.
299
+ *
300
+ * Defined once here rather than as a gradient literal in each component: the
301
+ * stripe geometry is the ornament's identity, not a design value a consumer
302
+ * re-themes, and duplicating it in TypeScript is how the two would drift apart.
303
+ * The colours are still tokens, so it re-themes with everything else.
304
+ * -------------------------------------------------------------------------- */
305
+
306
+ .tx-groove {
307
+ display: block;
308
+ width: 100%;
309
+ height: var(--spacing-tx-1-5);
310
+ background-color: var(--color-tx-primary-subtle);
311
+ background-image:
312
+ repeating-linear-gradient(105deg, var(--color-tx-primary) 0 3px, transparent 3px 9px),
313
+ linear-gradient(var(--color-tx-primary-border), var(--color-tx-primary-border));
314
+ }
315
+
316
+ /* CDK drag-and-drop, used by the reorder list. */
317
+ .cdk-drag-preview {
318
+ border-radius: var(--radius-tx-sm);
319
+ box-shadow: var(--shadow-tx-lg);
320
+ opacity: 0.95;
321
+ }
322
+
323
+ .cdk-drag-placeholder {
324
+ opacity: 0.35;
325
+ }
326
+
327
+ .cdk-drag-animating,
328
+ .cdk-drop-list-dragging .cdk-drag:not(.cdk-drag-placeholder) {
329
+ transition: transform var(--duration-tx-slow) var(--ease-tx-standard);
330
+ }
@@ -0,0 +1,320 @@
1
+ /* =============================================================================
2
+ * @tx-angular-design-system/ui-kit — token layer
3
+ *
4
+ * Two layers, both re-themeable:
5
+ * 1. Numbered palette --color-tx-FAMILY-50..950
6
+ * 2. Semantic roles --color-tx-ROLE, declared as var() references into
7
+ * layer 1 so overriding a palette value cascades to every role.
8
+ *
9
+ * To re-theme: redeclare any of these names at a narrower scope (e.g. :root in
10
+ * the consumer's global stylesheet, AFTER importing this file). Keep the names
11
+ * and the shape identical; change only the values. No component code changes.
12
+ *
13
+ * `static` is deliberate: every token is emitted whether or not a utility used
14
+ * it in this build, so a consumer override always has something to override.
15
+ * ========================================================================== */
16
+
17
+ @theme static {
18
+ /* ---------------------------------------------------------------------- *
19
+ * LAYER 1 — numbered palette
20
+ * ---------------------------------------------------------------------- */
21
+
22
+ /* brand — signal green. Anchors 50/200/500/700/950 are exact POC values. */
23
+ --color-tx-brand-50: #eef7e2;
24
+ --color-tx-brand-100: #e0f0cc;
25
+ --color-tx-brand-200: #cfe6b4;
26
+ --color-tx-brand-300: #b3d888;
27
+ --color-tx-brand-400: #90c95a;
28
+ --color-tx-brand-500: #6fb92c;
29
+ --color-tx-brand-600: #5da324;
30
+ --color-tx-brand-700: #4d8a1b;
31
+ --color-tx-brand-800: #3d6d16;
32
+ --color-tx-brand-900: #2f5411;
33
+ --color-tx-brand-950: #12300a;
34
+
35
+ /* ink — deep navy. Secondary brand family: headings, solid buttons, header
36
+ bar, scrims. Anchors 700/900 are exact POC values. */
37
+ --color-tx-ink-50: #e7edf2;
38
+ --color-tx-ink-100: #c9d6e0;
39
+ --color-tx-ink-200: #9db1c4;
40
+ --color-tx-ink-300: #6f8ba5;
41
+ --color-tx-ink-400: #4a6987;
42
+ --color-tx-ink-500: #33556f;
43
+ --color-tx-ink-600: #2a4a63;
44
+ --color-tx-ink-700: #22405a;
45
+ --color-tx-ink-800: #1a344a;
46
+ --color-tx-ink-900: #14293a;
47
+ --color-tx-ink-950: #0c1a26;
48
+
49
+ /* neutral — cool instrument-panel greys. Surfaces, borders, body text.
50
+ Anchors 50/100/200/300/500/600/700/900 are exact POC values. */
51
+ --color-tx-neutral-0: #ffffff;
52
+ --color-tx-neutral-50: #f8fafb;
53
+ --color-tx-neutral-100: #f4f7f9;
54
+ --color-tx-neutral-200: #eef2f5;
55
+ --color-tx-neutral-300: #e2e8ed;
56
+ --color-tx-neutral-400: #c3d0da;
57
+ --color-tx-neutral-500: #96a4b0;
58
+ --color-tx-neutral-600: #8494a3;
59
+ --color-tx-neutral-700: #64798c;
60
+ --color-tx-neutral-800: #46596b;
61
+ --color-tx-neutral-900: #1b2b38;
62
+ --color-tx-neutral-950: #0f1a23;
63
+
64
+ /* danger — anchors 50/200/500 are exact POC values. */
65
+ --color-tx-danger-50: #fbecea;
66
+ --color-tx-danger-100: #f7dbd8;
67
+ --color-tx-danger-200: #eccbc7;
68
+ --color-tx-danger-300: #e0a9a3;
69
+ --color-tx-danger-400: #d17a72;
70
+ --color-tx-danger-500: #c2453b;
71
+ --color-tx-danger-600: #a93a31;
72
+ --color-tx-danger-700: #8c2f27;
73
+ --color-tx-danger-800: #70251f;
74
+ --color-tx-danger-900: #571c17;
75
+ --color-tx-danger-950: #2e0e0b;
76
+
77
+ /* warning — anchors 50/200/500/700 are exact POC values. */
78
+ --color-tx-warning-50: #fdf4e3;
79
+ --color-tx-warning-100: #fbe9c6;
80
+ --color-tx-warning-200: #efd9ad;
81
+ --color-tx-warning-300: #e9c377;
82
+ --color-tx-warning-400: #e2ab48;
83
+ --color-tx-warning-500: #d99420;
84
+ --color-tx-warning-600: #bd7d19;
85
+ --color-tx-warning-700: #8c6212;
86
+ --color-tx-warning-800: #6f4d0e;
87
+ --color-tx-warning-900: #573c0b;
88
+ --color-tx-warning-950: #2e1f06;
89
+
90
+ /* info — anchors 50/200/500/700 are exact POC values. */
91
+ --color-tx-info-50: #eaf2f8;
92
+ --color-tx-info-100: #d8e7f1;
93
+ --color-tx-info-200: #bcd0e0;
94
+ --color-tx-info-300: #94b5cf;
95
+ --color-tx-info-400: #5c92b6;
96
+ --color-tx-info-500: #2c6f9b;
97
+ --color-tx-info-600: #275f85;
98
+ --color-tx-info-700: #255578;
99
+ --color-tx-info-800: #1e4460;
100
+ --color-tx-info-900: #18364c;
101
+ --color-tx-info-950: #0d1d29;
102
+
103
+ /* success — seeded from the same green the POC uses for `.ok`, but kept an
104
+ independent family so re-theming `brand` to a non-green hue does not turn
105
+ success states that hue too. */
106
+ --color-tx-success-50: #eef7e2;
107
+ --color-tx-success-100: #e0f0cc;
108
+ --color-tx-success-200: #cfe6b4;
109
+ --color-tx-success-300: #b3d888;
110
+ --color-tx-success-400: #90c95a;
111
+ --color-tx-success-500: #6fb92c;
112
+ --color-tx-success-600: #5da324;
113
+ --color-tx-success-700: #4d8a1b;
114
+ --color-tx-success-800: #3d6d16;
115
+ --color-tx-success-900: #2f5411;
116
+ --color-tx-success-950: #12300a;
117
+
118
+ /* ---------------------------------------------------------------------- *
119
+ * LAYER 2 — semantic roles
120
+ * Every one is a var() reference into layer 1. Override either layer.
121
+ * ---------------------------------------------------------------------- */
122
+
123
+ /* surfaces */
124
+ --color-tx-canvas: var(--color-tx-neutral-100);
125
+ --color-tx-surface: var(--color-tx-neutral-0);
126
+ --color-tx-surface-raised: var(--color-tx-neutral-0);
127
+ --color-tx-surface-sunken: var(--color-tx-neutral-50);
128
+ --color-tx-surface-inverse: var(--color-tx-ink-900);
129
+
130
+ /* borders */
131
+ --color-tx-border: var(--color-tx-neutral-300);
132
+ --color-tx-border-subtle: var(--color-tx-neutral-200);
133
+ --color-tx-border-strong: var(--color-tx-neutral-700);
134
+ --color-tx-border-inverse: color-mix(in srgb, var(--color-tx-neutral-0) 12%, transparent);
135
+
136
+ /* text */
137
+ --color-tx-text-primary: var(--color-tx-neutral-900);
138
+ --color-tx-text-heading: var(--color-tx-ink-900);
139
+ --color-tx-text-muted: var(--color-tx-neutral-700);
140
+ --color-tx-text-subtle: var(--color-tx-neutral-600);
141
+ --color-tx-text-disabled: var(--color-tx-neutral-500);
142
+ --color-tx-text-inverse: var(--color-tx-neutral-0);
143
+ --color-tx-text-on-primary: var(--color-tx-brand-950);
144
+ --color-tx-text-on-accent: var(--color-tx-neutral-0);
145
+ --color-tx-text-on-danger: var(--color-tx-neutral-0);
146
+
147
+ /* primary (brand) role */
148
+ --color-tx-primary: var(--color-tx-brand-500);
149
+ --color-tx-primary-hover: var(--color-tx-brand-700);
150
+ --color-tx-primary-active: var(--color-tx-brand-800);
151
+ --color-tx-primary-subtle: var(--color-tx-brand-50);
152
+ --color-tx-primary-border: var(--color-tx-brand-200);
153
+ --color-tx-primary-text: var(--color-tx-brand-700);
154
+
155
+ /* accent (navy) role — solid default buttons, header, toast */
156
+ --color-tx-accent: var(--color-tx-ink-900);
157
+ --color-tx-accent-hover: var(--color-tx-ink-700);
158
+ --color-tx-accent-active: var(--color-tx-ink-950);
159
+ --color-tx-accent-subtle: var(--color-tx-ink-50);
160
+ --color-tx-accent-border: var(--color-tx-ink-200);
161
+ --color-tx-accent-text: var(--color-tx-ink-900);
162
+
163
+ /* status roles */
164
+ --color-tx-danger: var(--color-tx-danger-500);
165
+ --color-tx-danger-hover: var(--color-tx-danger-600);
166
+ --color-tx-danger-subtle: var(--color-tx-danger-50);
167
+ --color-tx-danger-border: var(--color-tx-danger-200);
168
+ --color-tx-danger-text: var(--color-tx-danger-500);
169
+
170
+ --color-tx-warning: var(--color-tx-warning-500);
171
+ --color-tx-warning-hover: var(--color-tx-warning-600);
172
+ --color-tx-warning-subtle: var(--color-tx-warning-50);
173
+ --color-tx-warning-border: var(--color-tx-warning-200);
174
+ --color-tx-warning-text: var(--color-tx-warning-700);
175
+
176
+ --color-tx-success: var(--color-tx-success-500);
177
+ --color-tx-success-hover: var(--color-tx-success-600);
178
+ --color-tx-success-subtle: var(--color-tx-success-50);
179
+ --color-tx-success-border: var(--color-tx-success-200);
180
+ --color-tx-success-text: var(--color-tx-success-700);
181
+
182
+ --color-tx-info: var(--color-tx-info-500);
183
+ --color-tx-info-hover: var(--color-tx-info-600);
184
+ --color-tx-info-subtle: var(--color-tx-info-50);
185
+ --color-tx-info-border: var(--color-tx-info-200);
186
+ --color-tx-info-text: var(--color-tx-info-700);
187
+
188
+ /* interaction */
189
+ --color-tx-focus-ring: var(--color-tx-brand-700);
190
+ --color-tx-focus-glow: color-mix(in srgb, var(--color-tx-brand-500) 16%, transparent);
191
+ --color-tx-scrim: color-mix(in srgb, var(--color-tx-ink-900) 50%, transparent);
192
+ --color-tx-hover-fill: var(--color-tx-neutral-200);
193
+ --color-tx-control-off: var(--color-tx-neutral-300);
194
+ --color-tx-selected-fill: var(--color-tx-brand-50);
195
+ --color-tx-skeleton: var(--color-tx-neutral-200);
196
+ --color-tx-skeleton-sheen: var(--color-tx-neutral-100);
197
+
198
+ /* scrollbars — applied in base.css. The thumb is a mid neutral rather than
199
+ the border colour: at this width a border-weight grey is all but invisible,
200
+ and the scrollbar is an affordance, not a divider. The track is transparent
201
+ so a scroll area keeps whatever surface it sits on. */
202
+ --color-tx-scrollbar-thumb: var(--color-tx-neutral-400);
203
+ --color-tx-scrollbar-thumb-hover: var(--color-tx-neutral-600);
204
+ --color-tx-scrollbar-track: transparent;
205
+
206
+ /* ---------------------------------------------------------------------- *
207
+ * Typography
208
+ * ---------------------------------------------------------------------- */
209
+ --font-tx-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
210
+ --font-tx-display: "Archivo", "IBM Plex Sans", system-ui, sans-serif;
211
+ --font-tx-mono: "IBM Plex Mono", ui-monospace, Menlo, Consolas, monospace;
212
+
213
+ /* 10-step ladder. `base` (14px) is the workhorse control/table size;
214
+ `lg` (15px) is body copy. Monotonic, so the names never mislead. */
215
+ --text-tx-2xs: 0.656rem; /* 10.5px — uppercase mono labels, th, badges */
216
+ --text-tx-xs: 0.719rem; /* 11.5px — chip text, secondary sub-lines */
217
+ --text-tx-sm: 0.781rem; /* 12.5px — small buttons, dense meta */
218
+ --text-tx-md: 0.844rem; /* 13.5px — buttons, checklists */
219
+ --text-tx-base: 0.875rem; /* 14px — inputs, table cells */
220
+ --text-tx-lg: 0.938rem; /* 15px — body copy */
221
+ --text-tx-xl: 1.063rem; /* 17px — section heading, wordmark */
222
+ --text-tx-2xl: 1.313rem; /* 21px — page title (mobile) */
223
+ --text-tx-3xl: 1.563rem; /* 25px — page title */
224
+ --text-tx-4xl: 2rem; /* 32px — stat value */
225
+
226
+ --leading-tx-tight: 1.25;
227
+ --leading-tx-snug: 1.35;
228
+ --leading-tx-normal: 1.55;
229
+ --leading-tx-relaxed: 1.65;
230
+
231
+ --tracking-tx-tight: -0.01em;
232
+ --tracking-tx-normal: 0em;
233
+ --tracking-tx-wide: 0.05em;
234
+ --tracking-tx-wider: 0.07em;
235
+ --tracking-tx-widest: 0.09em;
236
+ --tracking-tx-caps: 0.22em; /* login mark / wordmark lockup */
237
+
238
+ /* ---------------------------------------------------------------------- *
239
+ * Spacing — a 2px-based grid. Component padding rounds to this grid rather
240
+ * than reproducing the POC's odd 9/11/13px values, so a designer can
241
+ * re-space the whole kit from here.
242
+ * ---------------------------------------------------------------------- */
243
+ --spacing-tx-0: 0px;
244
+ --spacing-tx-px: 1px;
245
+ --spacing-tx-0-5: 0.125rem; /* 2px */
246
+ --spacing-tx-1: 0.25rem; /* 4px */
247
+ --spacing-tx-1-5: 0.375rem; /* 6px */
248
+ --spacing-tx-2: 0.5rem; /* 8px */
249
+ --spacing-tx-2-5: 0.625rem; /* 10px */
250
+ --spacing-tx-3: 0.75rem; /* 12px */
251
+ --spacing-tx-3-5: 0.875rem; /* 14px */
252
+ --spacing-tx-4: 1rem; /* 16px */
253
+ --spacing-tx-5: 1.25rem; /* 20px */
254
+ --spacing-tx-6: 1.5rem; /* 24px */
255
+ --spacing-tx-7: 1.75rem; /* 28px */
256
+ --spacing-tx-8: 2rem; /* 32px */
257
+ --spacing-tx-10: 2.5rem; /* 40px */
258
+ --spacing-tx-12: 3rem; /* 48px */
259
+ --spacing-tx-14: 3.5rem; /* 56px */
260
+ --spacing-tx-16: 4rem; /* 64px */
261
+ --spacing-tx-20: 5rem; /* 80px */
262
+
263
+ /* Named sizes live in the spacing namespace on purpose: Tailwind v4 draws
264
+ w-* / h-* / min-w-* / size-* from --spacing-*, so `h-tx-control-md` and
265
+ `w-tx-sidebar` only exist as utilities if they are declared here. */
266
+ --spacing-tx-control-sm: 1.75rem; /* 28px */
267
+ --spacing-tx-control-md: 2.25rem; /* 36px */
268
+ --spacing-tx-control-lg: 2.75rem; /* 44px — also the mobile touch target */
269
+ --spacing-tx-icon-sm: 0.9375rem; /* 15px */
270
+ --spacing-tx-icon-md: 1.125rem; /* 18px */
271
+ --spacing-tx-icon-lg: 1.5rem; /* 24px */
272
+ --spacing-tx-sidebar: 14.75rem; /* 236px */
273
+ --spacing-tx-scrollbar: 0.625rem; /* 10px — WebKit track; see base.css */
274
+ --spacing-tx-scrollbar-inset: 0.125rem; /* 2px of track either side of the thumb */
275
+ --spacing-tx-popup-sm: 12rem; /* 192px — dropdown list max height */
276
+ --spacing-tx-popup-md: 18rem; /* 288px */
277
+ --spacing-tx-popup-lg: 24rem; /* 384px */
278
+
279
+ /* ---------------------------------------------------------------------- *
280
+ * Radius / shadow / motion / sizing
281
+ * ---------------------------------------------------------------------- */
282
+ --radius-tx-none: 0px;
283
+ --radius-tx-xs: 0.1875rem; /* 3px — focus ring rounding */
284
+ --radius-tx-sm: 0.375rem; /* 6px — buttons, inputs, chips */
285
+ --radius-tx-md: 0.5rem; /* 8px — panels, cards, tiles */
286
+ --radius-tx-lg: 0.75rem; /* 12px — dialogs */
287
+ --radius-tx-xl: 0.875rem; /* 14px — hero/login card */
288
+ --radius-tx-full: 9999px; /* pills, badges, avatars */
289
+
290
+ --shadow-tx-none: none;
291
+ --shadow-tx-sm: 0 1px 2px color-mix(in srgb, var(--color-tx-ink-900) 6%, transparent);
292
+ --shadow-tx-md:
293
+ 0 1px 2px color-mix(in srgb, var(--color-tx-ink-900) 6%, transparent),
294
+ 0 6px 18px color-mix(in srgb, var(--color-tx-ink-900) 5%, transparent);
295
+ --shadow-tx-popup:
296
+ 0 2px 6px color-mix(in srgb, var(--color-tx-ink-900) 8%, transparent),
297
+ 0 10px 30px color-mix(in srgb, var(--color-tx-ink-900) 14%, transparent);
298
+ --shadow-tx-lg: 0 24px 60px color-mix(in srgb, var(--color-tx-ink-900) 28%, transparent);
299
+ --shadow-tx-focus: 0 0 0 3px var(--color-tx-focus-glow);
300
+ /* The same ring in the error colour, so an invalid control's focus state
301
+ is a token rather than a hand-written shadow inside a component. */
302
+ --shadow-tx-focus-danger: 0 0 0 3px var(--color-tx-danger-subtle);
303
+
304
+ --inset-shadow-tx-selected: inset 3px 0 0 var(--color-tx-primary);
305
+
306
+ --ease-tx-standard: cubic-bezier(0.2, 0, 0.2, 1);
307
+ --ease-tx-emphasis: cubic-bezier(0.2, 0, 0, 1);
308
+
309
+ --duration-tx-fast: 120ms;
310
+ --duration-tx-base: 150ms;
311
+ --duration-tx-slow: 250ms;
312
+
313
+ /* Focus ring geometry. Not a Tailwind utility namespace — these exist so the
314
+ base layer's :focus-visible rule stays literal-free and re-tunable. */
315
+ --width-tx-focus-ring: 2px;
316
+ --width-tx-focus-offset: 2px;
317
+ --width-tx-border: 1px;
318
+ --width-tx-border-strong: 2px;
319
+ --width-tx-accent-bar: 4px; /* toast / part-card leading edge */
320
+ }
@@ -0,0 +1,18 @@
1
+ /* =============================================================================
2
+ * @tx-angular-design-system/ui-kit — single stylesheet entry point.
3
+ *
4
+ * In a consumer app, `ng add @tx-angular-design-system/ui-kit` writes:
5
+ *
6
+ * @import 'tailwindcss';
7
+ * @import '@angular/cdk/overlay-prebuilt.css';
8
+ * @import '@tx-angular-design-system/ui-kit/styles/ui-kit.css';
9
+ * @source '../../node_modules/@tx-angular-design-system/ui-kit';
10
+ *
11
+ * The @source line is what makes the kit's utility classes exist at all:
12
+ * Tailwind skips node_modules during automatic content detection, so without
13
+ * it every class in the library's compiled .mjs templates is scanned out and
14
+ * the components render unstyled.
15
+ * ========================================================================== */
16
+
17
+ @import './theme.css';
18
+ @import './base.css';