@scania/tegel-lite 0.0.1 → 0.0.2-rules-beta.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/README.dev.md CHANGED
@@ -11,7 +11,7 @@ Tegel Lite is a **styles-only** component library that provides the same design
11
11
  ## 📦 Installation
12
12
 
13
13
  ```bash
14
- npm install @scania/tegel-lite
14
+ npm install @scania/tegel-lite@0.0.1-beta.10
15
15
  ```
16
16
 
17
17
  ## 🚀 Quick Start
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  ## Installation
11
11
 
12
12
  ```bash
13
- npm install @scania/tegel-lite
13
+ npm install @scania/tegel-lite@0.0.1-beta.10
14
14
  ```
15
15
 
16
16
  ## Quick Start
@@ -87,6 +87,35 @@ dist/
87
87
 
88
88
  All components use the `tl-` prefix.
89
89
 
90
+ ## AI Coding Rules
91
+
92
+ This package ships with AI-aware coding rules that help AI assistants (Cursor, Claude Code, GitHub Copilot, OpenAI Codex) write correct tegel-lite markup.
93
+
94
+ After installing the package, run:
95
+
96
+ ```bash
97
+ npx tegel-lite-setup-rules
98
+ ```
99
+
100
+ An interactive CLI will let you choose which AI tools to configure:
101
+
102
+ | AI Tool | Files installed |
103
+ | --- | --- |
104
+ | **Cursor** | `.cursor/rules/tegel-lite/*.mdc` |
105
+ | **Claude Code** | `CLAUDE.md` at project root |
106
+ | **GitHub Copilot** | `.github/copilot-instructions.md` |
107
+ | **OpenAI Codex** | `AGENTS.md` at project root |
108
+
109
+ All options are selected by default. Use arrow keys to navigate, space to toggle, and enter to confirm.
110
+
111
+ To skip the interactive prompt and install all formats at once:
112
+
113
+ ```bash
114
+ npx tegel-lite-setup-rules --all
115
+ ```
116
+
117
+ Re-running the command will update existing rules in place (using section markers) without duplicating content.
118
+
90
119
  ## Documentation
91
120
 
92
121
  Full documentation: **[tegel.scania.com](https://tegel.scania.com)**
@@ -0,0 +1,347 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * setup-ai-rules.js
5
+ *
6
+ * Interactive CLI to copy @scania/tegel-lite AI coding rules into a user's project.
7
+ *
8
+ * Usage:
9
+ * npx tegel-lite-setup-rules # Interactive mode
10
+ * npx tegel-lite-setup-rules --all # Copy all rule formats (skip prompts)
11
+ *
12
+ * Plain Node.js — no external dependencies. Uses built-in readline.
13
+ */
14
+
15
+ import fs from 'fs';
16
+ import path from 'path';
17
+ import readline from 'readline';
18
+ import { fileURLToPath } from 'url';
19
+
20
+ const __filename = fileURLToPath(import.meta.url);
21
+ const __dirname = path.dirname(__filename);
22
+ const packageRoot = path.resolve(__dirname, '..');
23
+
24
+ // Where files will be copied to
25
+ const projectRoot = process.cwd();
26
+
27
+ // Markers for idempotent updates in aggregated files
28
+ const MARKER_START = '<!-- START @scania/tegel-lite rules -->';
29
+ const MARKER_END = '<!-- END @scania/tegel-lite rules -->';
30
+
31
+ // ── Tool definitions ──────────────────────────────────────────────────────────
32
+
33
+ const TOOLS = [
34
+ {
35
+ id: 'cursor',
36
+ label: 'Cursor',
37
+ description: '.cursor/rules/tegel-lite/*.mdc',
38
+ sourceDir: path.join(packageRoot, '.cursor', 'rules', 'tegel-lite'),
39
+ targetDir: path.join(projectRoot, '.cursor', 'rules', 'tegel-lite'),
40
+ mode: 'directory',
41
+ },
42
+ {
43
+ id: 'claude',
44
+ label: 'Claude Code',
45
+ description: 'CLAUDE.md at project root',
46
+ sourceFile: path.join(packageRoot, 'CLAUDE.md'),
47
+ targetFile: path.join(projectRoot, 'CLAUDE.md'),
48
+ mode: 'aggregated',
49
+ },
50
+ {
51
+ id: 'copilot',
52
+ label: 'GitHub Copilot',
53
+ description: '.github/copilot-instructions.md',
54
+ sourceFile: path.join(packageRoot, '.github', 'copilot-instructions.md'),
55
+ targetFile: path.join(projectRoot, '.github', 'copilot-instructions.md'),
56
+ mode: 'aggregated',
57
+ },
58
+ {
59
+ id: 'codex',
60
+ label: 'OpenAI Codex',
61
+ description: 'AGENTS.md at project root',
62
+ sourceFile: path.join(packageRoot, 'AGENTS.md'),
63
+ targetFile: path.join(projectRoot, 'AGENTS.md'),
64
+ mode: 'aggregated',
65
+ },
66
+ ];
67
+
68
+ // ── Helpers ───────────────────────────────────────────────────────────────────
69
+
70
+ /**
71
+ * Wrap content in section markers for idempotent updates.
72
+ */
73
+ function wrapWithMarkers(content) {
74
+ return `${MARKER_START}\n${content.trim()}\n${MARKER_END}`;
75
+ }
76
+
77
+ /**
78
+ * Replace the marked section in existing file content, or append if not found.
79
+ */
80
+ function upsertMarkedSection(existingContent, newSection) {
81
+ const pattern = `${escapeRegex(MARKER_START)}[\\s\\S]*?${escapeRegex(MARKER_END)}`;
82
+ const markerRegex = new RegExp(pattern);
83
+
84
+ if (markerRegex.test(existingContent)) {
85
+ // Replace existing section
86
+ return existingContent.replace(new RegExp(pattern), newSection);
87
+ }
88
+
89
+ // Append with spacing
90
+ const separator = existingContent.trim().length > 0 ? '\n\n' : '';
91
+ return existingContent.trimEnd() + separator + newSection + '\n';
92
+ }
93
+
94
+ function escapeRegex(str) {
95
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
96
+ }
97
+
98
+ /**
99
+ * Ask a yes/no question via readline.
100
+ */
101
+ function askYesNo(rl, question) {
102
+ return new Promise((resolve) => {
103
+ rl.question(`${question} (y/N): `, (answer) => {
104
+ resolve(answer.trim().toLowerCase() === 'y');
105
+ });
106
+ });
107
+ }
108
+
109
+ // ── Checkbox UI ───────────────────────────────────────────────────────────────
110
+
111
+ /**
112
+ * Display an interactive checkbox list in the terminal.
113
+ * Arrow keys navigate, space toggles, enter confirms.
114
+ */
115
+ function showCheckboxList(items) {
116
+ return new Promise((resolve) => {
117
+ const selected = items.map(() => true); // All selected by default
118
+ let cursor = 0;
119
+
120
+ const { stdin, stdout } = process;
121
+
122
+ // Check if we can use raw mode (not available in all environments)
123
+ if (!stdin.isTTY) {
124
+ console.log('Non-interactive terminal detected. Selecting all tools.');
125
+ resolve(items.map((_, i) => i));
126
+ return;
127
+ }
128
+
129
+ function render() {
130
+ // Move cursor up to overwrite previous render (except first time)
131
+ stdout.write('\x1B[?25l'); // Hide cursor
132
+
133
+ const lines = items.map((item, i) => {
134
+ const checkbox = selected[i] ? '\x1B[32m◉\x1B[0m' : '○';
135
+ const pointer = i === cursor ? '\x1B[36m❯\x1B[0m ' : ' ';
136
+ const desc = `\x1B[2m${item.description}\x1B[0m`;
137
+ return `${pointer}${checkbox} ${item.label} ${desc}`;
138
+ });
139
+
140
+ lines.push('');
141
+ lines.push('\x1B[2m↑↓ navigate · space toggle · enter confirm\x1B[0m');
142
+
143
+ return lines.join('\n');
144
+ }
145
+
146
+ // Initial render
147
+ const output = render();
148
+ stdout.write(output);
149
+
150
+ stdin.setRawMode(true);
151
+ stdin.resume();
152
+ stdin.setEncoding('utf-8');
153
+
154
+ function onKeypress(key) {
155
+ // Ctrl+C
156
+ if (key === '\x03') {
157
+ stdin.setRawMode(false);
158
+ stdin.removeListener('data', onKeypress);
159
+ stdout.write('\x1B[?25h\n'); // Show cursor
160
+ process.exit(0);
161
+ }
162
+
163
+ // Enter
164
+ if (key === '\r' || key === '\n') {
165
+ stdin.setRawMode(false);
166
+ stdin.removeListener('data', onKeypress);
167
+ stdout.write('\x1B[?25h\n'); // Show cursor
168
+ resolve(selected.reduce((acc, sel, i) => (sel ? [...acc, i] : acc), []));
169
+ return;
170
+ }
171
+
172
+ // Space — toggle
173
+ if (key === ' ') {
174
+ selected[cursor] = !selected[cursor];
175
+ }
176
+
177
+ // Arrow up or k
178
+ if (key === '\x1B[A' || key === 'k') {
179
+ cursor = (cursor - 1 + items.length) % items.length;
180
+ }
181
+
182
+ // Arrow down or j
183
+ if (key === '\x1B[B' || key === 'j') {
184
+ cursor = (cursor + 1) % items.length;
185
+ }
186
+
187
+ // Re-render: move up to overwrite
188
+ const lineCount = items.length + 2;
189
+ stdout.write(`\x1B[${lineCount}A\x1B[0J`);
190
+ stdout.write(render());
191
+ }
192
+
193
+ stdin.on('data', onKeypress);
194
+ });
195
+ }
196
+
197
+ // ── Copy logic ────────────────────────────────────────────────────────────────
198
+
199
+ /**
200
+ * Copy a directory of files (e.g. .cursor/rules/tegel-lite/*.mdc).
201
+ */
202
+ function copyDirectoryTool(tool, rl, skipPrompt) {
203
+ return copyDirectoryToolAsync(tool, rl, skipPrompt);
204
+ }
205
+
206
+ async function copyDirectoryToolAsync(tool, rl, skipPrompt) {
207
+ if (!fs.existsSync(tool.sourceDir)) {
208
+ console.log(` ⚠ Source not found: ${path.relative(packageRoot, tool.sourceDir)}`);
209
+ console.log(' Run "npm run generate:ai-rules" in the package first.');
210
+ return;
211
+ }
212
+
213
+ const files = fs.readdirSync(tool.sourceDir).filter((f) => f.endsWith('.mdc'));
214
+
215
+ if (files.length === 0) {
216
+ console.log(' ⚠ No .mdc files found in source directory.');
217
+ return;
218
+ }
219
+
220
+ // Check if target directory already exists
221
+ if (fs.existsSync(tool.targetDir) && !skipPrompt) {
222
+ const overwrite = await askYesNo(
223
+ rl,
224
+ ` Target exists: ${path.relative(projectRoot, tool.targetDir)}. Overwrite?`,
225
+ );
226
+ if (!overwrite) {
227
+ console.log(' Skipped.');
228
+ return;
229
+ }
230
+ }
231
+
232
+ fs.mkdirSync(tool.targetDir, { recursive: true });
233
+
234
+ for (const file of files) {
235
+ const src = path.join(tool.sourceDir, file);
236
+ const dest = path.join(tool.targetDir, file);
237
+ fs.copyFileSync(src, dest);
238
+ console.log(` Copied: ${path.relative(projectRoot, dest)}`);
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Copy an aggregated file (CLAUDE.md, AGENTS.md, copilot-instructions.md).
244
+ * Uses markers for idempotent upsert.
245
+ */
246
+ async function copyAggregatedTool(tool, rl, skipPrompt) {
247
+ if (!fs.existsSync(tool.sourceFile)) {
248
+ console.log(` ⚠ Source not found: ${path.relative(packageRoot, tool.sourceFile)}`);
249
+ console.log(' Run "npm run generate:ai-rules" in the package first.');
250
+ return;
251
+ }
252
+
253
+ const sourceContent = fs.readFileSync(tool.sourceFile, 'utf-8');
254
+ const wrappedContent = wrapWithMarkers(sourceContent);
255
+ const targetRelative = path.relative(projectRoot, tool.targetFile);
256
+
257
+ if (fs.existsSync(tool.targetFile)) {
258
+ const existingContent = fs.readFileSync(tool.targetFile, 'utf-8');
259
+
260
+ // Check if markers already exist
261
+ if (existingContent.includes(MARKER_START)) {
262
+ // Update in place
263
+ const updatedContent = upsertMarkedSection(existingContent, wrappedContent);
264
+ fs.writeFileSync(tool.targetFile, updatedContent, 'utf-8');
265
+ console.log(` Updated: ${targetRelative} (replaced existing tegel-lite section)`);
266
+ return;
267
+ }
268
+
269
+ // File exists but no markers — ask to append
270
+ if (!skipPrompt) {
271
+ const append = await askYesNo(
272
+ rl,
273
+ ` File exists: ${targetRelative}. Append tegel-lite rules?`,
274
+ );
275
+ if (!append) {
276
+ console.log(' Skipped.');
277
+ return;
278
+ }
279
+ }
280
+
281
+ const updatedContent = upsertMarkedSection(existingContent, wrappedContent);
282
+ fs.writeFileSync(tool.targetFile, updatedContent, 'utf-8');
283
+ console.log(` Updated: ${targetRelative} (appended tegel-lite section)`);
284
+ } else {
285
+ // Create new file
286
+ const dir = path.dirname(tool.targetFile);
287
+ fs.mkdirSync(dir, { recursive: true });
288
+ fs.writeFileSync(tool.targetFile, wrappedContent + '\n', 'utf-8');
289
+ console.log(` Created: ${targetRelative}`);
290
+ }
291
+ }
292
+
293
+ // ── Main ──────────────────────────────────────────────────────────────────────
294
+
295
+ async function main() {
296
+ const args = process.argv.slice(2);
297
+ const skipPrompt = args.includes('--all');
298
+
299
+ console.log('');
300
+ console.log('\x1B[1m@scania/tegel-lite — AI Coding Rules Setup\x1B[0m');
301
+ console.log('');
302
+
303
+ let selectedIndices;
304
+
305
+ if (skipPrompt) {
306
+ console.log('Installing all rule formats (--all flag).\n');
307
+ selectedIndices = TOOLS.map((_, i) => i);
308
+ } else {
309
+ console.log('Select which AI tools to configure:\n');
310
+ selectedIndices = await showCheckboxList(TOOLS);
311
+ }
312
+
313
+ if (selectedIndices.length === 0) {
314
+ console.log('No tools selected. Exiting.');
315
+ process.exit(0);
316
+ }
317
+
318
+ const selectedTools = selectedIndices.map((i) => TOOLS[i]);
319
+
320
+ console.log(`\nInstalling rules for: ${selectedTools.map((t) => t.label).join(', ')}\n`);
321
+
322
+ // Create a readline interface for yes/no prompts
323
+ const rl = readline.createInterface({
324
+ input: process.stdin,
325
+ output: process.stdout,
326
+ });
327
+
328
+ for (const tool of selectedTools) {
329
+ console.log(`\n${tool.label}:`);
330
+
331
+ if (tool.mode === 'directory') {
332
+ await copyDirectoryTool(tool, rl, skipPrompt);
333
+ } else {
334
+ await copyAggregatedTool(tool, rl, skipPrompt);
335
+ }
336
+ }
337
+
338
+ rl.close();
339
+
340
+ console.log('\n\x1B[32m✓ Done!\x1B[0m AI coding rules installed successfully.');
341
+ console.log('\nRe-run this command anytime to update rules to the latest version.\n');
342
+ }
343
+
344
+ main().catch((err) => {
345
+ console.error('Error:', err.message);
346
+ process.exit(1);
347
+ });
@@ -941,11 +941,11 @@
941
941
  }
942
942
  .traton .tl-card--primary {
943
943
  --card-box: none;
944
- --card-background: var(--card-background-secondary);
944
+ --card-background: transparent;
945
945
  }
946
946
  .traton .tl-card--secondary {
947
947
  --card-box: none;
948
- --card-background: var(--card-background-primary);
948
+ --card-background: transparent;
949
949
  }
950
950
 
951
951
  /* Dark mode */
@@ -966,7 +966,10 @@
966
966
  }
967
967
 
968
968
  .traton .tds-mode-dark .tl-card--primary {
969
- --card-background: var(--color-background-base);
969
+ --card-background: transparent;
970
+ }
971
+ .traton .tds-mode-dark .tl-card--secondary {
972
+ --card-background: transparent;
970
973
  }
971
974
 
972
975
  .tl-card {
@@ -8318,6 +8321,69 @@ body {
8318
8321
  fill: var(--folder-tabs-scroll-button-text);
8319
8322
  }
8320
8323
 
8324
+ /* tl-folder-tabs.scss (overlay buttons, no JS) */
8325
+ .tl-folder-tabs__tab {
8326
+ all: unset;
8327
+ font-family: var(--headline-07-font-family);
8328
+ font-size: var(--headline-07-font-size);
8329
+ line-height: var(--headline-07-line-height);
8330
+ font-weight: var(--headline-07-font-weight);
8331
+ letter-spacing: var(--headline-07-letter-spacing);
8332
+ text-transform: var(--headline-07-text-transform);
8333
+ box-sizing: border-box;
8334
+ position: relative;
8335
+ display: inline-flex;
8336
+ align-items: center;
8337
+ min-inline-size: 142px;
8338
+ inline-size: auto;
8339
+ flex: 0 0 auto;
8340
+ white-space: nowrap;
8341
+ padding: 16px;
8342
+ text-align: left;
8343
+ cursor: pointer;
8344
+ border-left: 1px solid transparent;
8345
+ border-top: 2px solid var(--folder-tab-surface);
8346
+ background-color: var(--folder-tab-surface);
8347
+ color: var(--folder-tab-text);
8348
+ }
8349
+ .tl-folder-tabs__tab + .tl-folder-tabs__tab {
8350
+ border-left-color: var(--folder-tab-divider);
8351
+ }
8352
+ .tl-folder-tabs__tab:focus-visible {
8353
+ outline: 2px solid currentcolor;
8354
+ outline-offset: -4px;
8355
+ box-shadow: none;
8356
+ }
8357
+ .tl-folder-tabs__tab:hover:not(.tl-folder-tabs__tab--disabled):not(.tl-folder-tabs__tab--selected) {
8358
+ background-color: var(--folder-tab-surface-hover);
8359
+ border-top-color: var(--folder-tab-surface-hover);
8360
+ color: var(--folder-tab-text);
8361
+ }
8362
+ .tl-folder-tabs__tab--selected {
8363
+ background-color: var(--folder-tab-surface-selected);
8364
+ border-top-color: var(--folder-tab-border-selected);
8365
+ color: var(--folder-tab-text);
8366
+ }
8367
+ .tl-folder-tabs__tab--selected::after {
8368
+ content: "";
8369
+ position: absolute;
8370
+ top: 0;
8371
+ right: -1px;
8372
+ bottom: 0;
8373
+ width: 1px;
8374
+ background-color: var(--folder-tab-surface-selected);
8375
+ z-index: 1;
8376
+ }
8377
+ .tl-folder-tabs__tab--disabled {
8378
+ color: var(--folder-tab-text-disabled);
8379
+ cursor: not-allowed;
8380
+ user-select: none;
8381
+ }
8382
+ .tl-folder-tabs__tab--disabled:focus-visible {
8383
+ outline: none;
8384
+ box-shadow: none;
8385
+ }
8386
+
8321
8387
  .tl-inline-tabs {
8322
8388
  /* Horizontal divider */
8323
8389
  --inline-tabs-horizontal-divider: var(--color-foreground-icon-discrete);
@@ -8411,6 +8477,86 @@ body {
8411
8477
  fill: var(--inline-tabs-scroll-button-text);
8412
8478
  }
8413
8479
 
8480
+ .tl-inline-tabs__tab {
8481
+ all: unset;
8482
+ margin-right: 32px;
8483
+ box-sizing: border-box;
8484
+ }
8485
+ .tl-inline-tabs__tab * {
8486
+ box-sizing: border-box;
8487
+ }
8488
+ .tl-inline-tabs__tab {
8489
+ font-family: var(--headline-07-font-family);
8490
+ font-size: var(--headline-07-font-size);
8491
+ line-height: var(--headline-07-line-height);
8492
+ font-weight: var(--headline-07-font-weight);
8493
+ letter-spacing: var(--headline-07-letter-spacing);
8494
+ text-transform: var(--headline-07-text-transform);
8495
+ color: var(--inline-tabs-tab);
8496
+ text-decoration: none;
8497
+ display: block;
8498
+ position: relative;
8499
+ transition: color 0.15s ease-in-out 0s;
8500
+ white-space: nowrap;
8501
+ background-color: transparent;
8502
+ border: 0;
8503
+ padding: 20px 4px;
8504
+ }
8505
+ .tl-inline-tabs__tab:focus-visible {
8506
+ outline: none;
8507
+ }
8508
+ .tl-inline-tabs__tab:focus-visible::before {
8509
+ content: "";
8510
+ position: absolute;
8511
+ inset: 18px 0;
8512
+ border-radius: 2px;
8513
+ box-shadow: 0 0 0 2px var(--inline-tabs-tab-focus) inset;
8514
+ z-index: 2;
8515
+ pointer-events: none;
8516
+ }
8517
+ .tl-inline-tabs__tab::after {
8518
+ background-color: var(--inline-tabs-tab-indicator-hover);
8519
+ content: " ";
8520
+ position: absolute;
8521
+ bottom: 0;
8522
+ right: 0;
8523
+ left: 0;
8524
+ margin-left: auto;
8525
+ width: 0%;
8526
+ margin-right: auto;
8527
+ height: 2px;
8528
+ z-index: 1;
8529
+ transition: width 0.15s ease-in-out 0s;
8530
+ }
8531
+ .tl-inline-tabs__tab:not(.tl-inline-tabs__tab--selected)::after {
8532
+ width: 0%;
8533
+ }
8534
+ .tl-inline-tabs__tab:hover {
8535
+ cursor: pointer;
8536
+ color: var(--inline-tabs-tab-hover);
8537
+ }
8538
+ .tl-inline-tabs__tab:hover::after {
8539
+ width: 100%;
8540
+ }
8541
+ .tl-inline-tabs__tab--selected {
8542
+ color: var(--inline-tabs-tab-selected);
8543
+ }
8544
+ .tl-inline-tabs__tab--selected::after {
8545
+ background-color: var(--inline-tabs-tab-indicator-active);
8546
+ width: 100%;
8547
+ }
8548
+ .tl-inline-tabs__tab--disabled {
8549
+ color: var(--inline-tabs-tab-disabled);
8550
+ pointer-events: none;
8551
+ cursor: not-allowed;
8552
+ }
8553
+ .tl-inline-tabs__tab--disabled::after {
8554
+ content: none;
8555
+ }
8556
+ .tl-inline-tabs__tab--disabled:focus-visible::before {
8557
+ box-shadow: none;
8558
+ }
8559
+
8414
8560
  .tl-navigation-tabs__tab {
8415
8561
  /* tds-navigation-tab variables */
8416
8562
  --navigation-tabs-tab: var(--color-foreground-text-soft);
@@ -8502,6 +8648,86 @@ body {
8502
8648
  fill: var(--navigation-tabs-scroll-button-color);
8503
8649
  }
8504
8650
 
8651
+ .tl-navigation-tabs__tab {
8652
+ all: unset;
8653
+ margin-right: 32px;
8654
+ box-sizing: border-box;
8655
+ }
8656
+ .tl-navigation-tabs__tab * {
8657
+ box-sizing: border-box;
8658
+ }
8659
+ .tl-navigation-tabs__tab {
8660
+ font-family: var(--headline-07-font-family);
8661
+ font-size: var(--headline-07-font-size);
8662
+ line-height: var(--headline-07-line-height);
8663
+ font-weight: var(--headline-07-font-weight);
8664
+ letter-spacing: var(--headline-07-letter-spacing);
8665
+ text-transform: var(--headline-07-text-transform);
8666
+ color: var(--navigation-tabs-tab);
8667
+ text-decoration: none;
8668
+ display: block;
8669
+ position: relative;
8670
+ transition: color 0.15s ease-in-out 0s;
8671
+ white-space: nowrap;
8672
+ background-color: transparent;
8673
+ border: 0;
8674
+ padding: 26px 4px;
8675
+ }
8676
+ .tl-navigation-tabs__tab:focus-visible {
8677
+ outline: none;
8678
+ }
8679
+ .tl-navigation-tabs__tab:focus-visible::before {
8680
+ content: "";
8681
+ position: absolute;
8682
+ inset: 18px 0;
8683
+ border-radius: 2px;
8684
+ box-shadow: 0 0 0 2px var(--navigation-tabs-tab-focus) inset;
8685
+ z-index: 2;
8686
+ pointer-events: none;
8687
+ }
8688
+ .tl-navigation-tabs__tab::after {
8689
+ background-color: var(--navigation-tabs-tab-indicator-hover);
8690
+ content: " ";
8691
+ position: absolute;
8692
+ bottom: 0;
8693
+ right: 0;
8694
+ left: 0;
8695
+ margin-left: auto;
8696
+ width: 0%;
8697
+ margin-right: auto;
8698
+ height: 2px;
8699
+ z-index: 1;
8700
+ transition: width 0.15s ease-in-out 0s;
8701
+ }
8702
+ .tl-navigation-tabs__tab:not(.tl-navigation-tabs__tab--selected)::after {
8703
+ width: 0%;
8704
+ }
8705
+ .tl-navigation-tabs__tab:hover {
8706
+ cursor: pointer;
8707
+ color: var(--navigation-tabs-tab-hover);
8708
+ }
8709
+ .tl-navigation-tabs__tab:hover::after {
8710
+ width: 100%;
8711
+ }
8712
+ .tl-navigation-tabs__tab--selected {
8713
+ color: var(--navigation-tabs-tab-selected);
8714
+ }
8715
+ .tl-navigation-tabs__tab--selected::after {
8716
+ background-color: var(--navigation-tabs-tab-indicator-active);
8717
+ width: 100%;
8718
+ }
8719
+ .tl-navigation-tabs__tab--disabled {
8720
+ color: var(--navigation-tabs-tab-disabled);
8721
+ pointer-events: none;
8722
+ cursor: not-allowed;
8723
+ }
8724
+ .tl-navigation-tabs__tab--disabled::after {
8725
+ content: none;
8726
+ }
8727
+ .tl-navigation-tabs__tab--disabled:focus-visible::before {
8728
+ box-shadow: none;
8729
+ }
8730
+
8505
8731
  .tl-textarea {
8506
8732
  --textarea-background-primary: var(--color-background-layer-01);
8507
8733
  --textarea-background-secondary: var(--color-background-layer-02);
package/dist/global.css CHANGED
@@ -4959,13 +4959,13 @@ html {
4959
4959
  .tds-mode-light .tds-mode-variant-primary {
4960
4960
  --tds-table-body-row-background: var(--tds-grey-50);
4961
4961
  --tds-table-zebra-mode-backround: var(--tds-white);
4962
- --tds-table-body-row-background-selected: var(--tds-grey-50);
4962
+ --tds-table-body-row-background-selected: var(--tds-grey-100);
4963
4963
  }
4964
4964
  :root .tds-mode-variant-secondary,
4965
4965
  .tds-mode-light .tds-mode-variant-secondary {
4966
4966
  --tds-table-body-row-background: var(--tds-white);
4967
4967
  --tds-table-zebra-mode-backround: var(--tds-grey-50);
4968
- --tds-table-body-row-background-selected: var(--tds-white);
4968
+ --tds-table-body-row-background-selected: var(--tds-grey-100);
4969
4969
  }
4970
4970
  :root,
4971
4971
  .tds-mode-light {
@@ -5017,14 +5017,18 @@ html {
5017
5017
  .tds-mode-dark .tds-mode-variant-primary {
5018
5018
  --tds-table-body-row-background: var(--tds-grey-850);
5019
5019
  --tds-table-zebra-mode-backround: var(--tds-grey-900);
5020
+ --tds-table-body-row-background-selected: var(--tds-grey-700);
5021
+ --tds-table-body-row-background-selected-hover: var(--tds-grey-800);
5020
5022
  }
5021
5023
  .tds-mode-dark .tds-mode-variant-secondary {
5022
5024
  --tds-table-body-row-background: var(--tds-grey-900);
5023
5025
  --tds-table-zebra-mode-backround: var(--tds-grey-850);
5026
+ --tds-table-body-row-background-selected: var(--tds-grey-700);
5027
+ --tds-table-body-row-background-selected-hover: var(--tds-grey-800);
5024
5028
  }
5025
5029
  .tds-mode-dark {
5026
5030
  --tds-table-body-row-background-selected: var(--tds-grey-700);
5027
- --tds-table-body-row-background-selected-hover: var(--tds-grey-700);
5031
+ --tds-table-body-row-background-selected-hover: var(--tds-grey-800);
5028
5032
  /* Table input */
5029
5033
  --tds-table-input-background-focus: var(--tds-grey-800);
5030
5034
  --tds-table-input-background-hover: var(--tds-white-50);