@dialpad/dialtone-css 8.80.0-next.6 → 8.80.0-next.7

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 (134) hide show
  1. package/lib/build/js/dialtone_migrate_border_radius/index.mjs +273 -0
  2. package/lib/build/js/dialtone_migrate_border_radius/test.mjs +422 -0
  3. package/lib/build/js/dialtone_migrate_typography/index.mjs +1628 -0
  4. package/lib/build/js/dialtone_migrate_typography/test.mjs +1020 -0
  5. package/lib/build/js/dialtone_migration_helper/configs/theme-to-mode.mjs +108 -0
  6. package/lib/build/js/dialtone_migration_helper/tests/theme-to-mode-test-examples.vue +24 -0
  7. package/lib/build/js/dialtone_migration_helper/tests/theme-to-mode.test.mjs +177 -0
  8. package/lib/build/less/components/button.less +2 -0
  9. package/lib/build/less/components/emoji-picker.less +10 -11
  10. package/lib/build/less/components/forms.less +22 -16
  11. package/lib/build/less/components/modal.less +8 -2
  12. package/lib/build/less/components/notice.less +4 -0
  13. package/lib/build/less/components/popover.less +1 -1
  14. package/lib/build/less/components/presence.less +23 -3
  15. package/lib/build/less/recipes/leftbar_row.less +1 -0
  16. package/lib/dist/dialtone-default-theme.css +67 -34
  17. package/lib/dist/dialtone-default-theme.min.css +1 -1
  18. package/lib/dist/dialtone-docs.json +1 -1
  19. package/lib/dist/dialtone.css +66 -34
  20. package/lib/dist/dialtone.min.css +1 -1
  21. package/lib/dist/js/dialtone_migrate_border_radius/index.mjs +273 -0
  22. package/lib/dist/js/dialtone_migrate_border_radius/test.mjs +422 -0
  23. package/lib/dist/js/dialtone_migrate_typography/index.mjs +1628 -0
  24. package/lib/dist/js/dialtone_migrate_typography/test.mjs +1020 -0
  25. package/lib/dist/js/dialtone_migration_helper/configs/theme-to-mode.mjs +108 -0
  26. package/lib/dist/js/dialtone_migration_helper/tests/theme-to-mode-test-examples.vue +24 -0
  27. package/lib/dist/js/dialtone_migration_helper/tests/theme-to-mode.test.mjs +177 -0
  28. package/lib/dist/tokens/tokens-101-dark.css +1 -0
  29. package/lib/dist/tokens/tokens-101-light.css +1 -0
  30. package/lib/dist/tokens/tokens-102-dark.css +1 -0
  31. package/lib/dist/tokens/tokens-102-light.css +1 -0
  32. package/lib/dist/tokens/tokens-103-dark.css +1 -0
  33. package/lib/dist/tokens/tokens-103-light.css +1 -0
  34. package/lib/dist/tokens/tokens-104-dark.css +1 -0
  35. package/lib/dist/tokens/tokens-104-light.css +1 -0
  36. package/lib/dist/tokens/tokens-105-dark.css +1 -0
  37. package/lib/dist/tokens/tokens-105-light.css +1 -0
  38. package/lib/dist/tokens/tokens-106-dark.css +1 -0
  39. package/lib/dist/tokens/tokens-106-light.css +1 -0
  40. package/lib/dist/tokens/tokens-107-dark.css +1 -0
  41. package/lib/dist/tokens/tokens-107-light.css +1 -0
  42. package/lib/dist/tokens/tokens-108-dark.css +1 -0
  43. package/lib/dist/tokens/tokens-108-light.css +1 -0
  44. package/lib/dist/tokens/tokens-109-dark.css +1 -0
  45. package/lib/dist/tokens/tokens-109-light.css +1 -0
  46. package/lib/dist/tokens/tokens-110-dark.css +1 -0
  47. package/lib/dist/tokens/tokens-110-light.css +1 -0
  48. package/lib/dist/tokens/tokens-111-dark.css +1 -0
  49. package/lib/dist/tokens/tokens-111-light.css +1 -0
  50. package/lib/dist/tokens/tokens-112-dark.css +1 -0
  51. package/lib/dist/tokens/tokens-112-light.css +1 -0
  52. package/lib/dist/tokens/tokens-113-dark.css +1 -0
  53. package/lib/dist/tokens/tokens-113-light.css +1 -0
  54. package/lib/dist/tokens/tokens-114-dark.css +1 -0
  55. package/lib/dist/tokens/tokens-114-light.css +1 -0
  56. package/lib/dist/tokens/tokens-115-dark.css +1 -0
  57. package/lib/dist/tokens/tokens-115-light.css +1 -0
  58. package/lib/dist/tokens/tokens-116-dark.css +1 -0
  59. package/lib/dist/tokens/tokens-116-light.css +1 -0
  60. package/lib/dist/tokens/tokens-117-dark.css +1 -0
  61. package/lib/dist/tokens/tokens-117-light.css +1 -0
  62. package/lib/dist/tokens/tokens-118-dark.css +1 -0
  63. package/lib/dist/tokens/tokens-118-light.css +1 -0
  64. package/lib/dist/tokens/tokens-119-dark.css +1 -0
  65. package/lib/dist/tokens/tokens-119-light.css +1 -0
  66. package/lib/dist/tokens/tokens-120-dark.css +1 -0
  67. package/lib/dist/tokens/tokens-120-light.css +1 -0
  68. package/lib/dist/tokens/tokens-121-dark.css +1 -0
  69. package/lib/dist/tokens/tokens-121-light.css +1 -0
  70. package/lib/dist/tokens/tokens-122-dark.css +1 -0
  71. package/lib/dist/tokens/tokens-122-light.css +1 -0
  72. package/lib/dist/tokens/tokens-123-dark.css +1 -0
  73. package/lib/dist/tokens/tokens-123-light.css +1 -0
  74. package/lib/dist/tokens/tokens-124-dark.css +1 -0
  75. package/lib/dist/tokens/tokens-124-light.css +1 -0
  76. package/lib/dist/tokens/tokens-125-dark.css +1 -0
  77. package/lib/dist/tokens/tokens-125-light.css +1 -0
  78. package/lib/dist/tokens/tokens-126-dark.css +1 -0
  79. package/lib/dist/tokens/tokens-126-light.css +1 -0
  80. package/lib/dist/tokens/tokens-127-dark.css +1 -0
  81. package/lib/dist/tokens/tokens-127-light.css +1 -0
  82. package/lib/dist/tokens/tokens-128-dark.css +1 -0
  83. package/lib/dist/tokens/tokens-128-light.css +1 -0
  84. package/lib/dist/tokens/tokens-129-dark.css +1 -0
  85. package/lib/dist/tokens/tokens-129-light.css +1 -0
  86. package/lib/dist/tokens/tokens-130-dark.css +1 -0
  87. package/lib/dist/tokens/tokens-130-light.css +1 -0
  88. package/lib/dist/tokens/tokens-131-dark.css +1 -0
  89. package/lib/dist/tokens/tokens-131-light.css +1 -0
  90. package/lib/dist/tokens/tokens-132-dark.css +1 -0
  91. package/lib/dist/tokens/tokens-132-light.css +1 -0
  92. package/lib/dist/tokens/tokens-133-dark.css +1 -0
  93. package/lib/dist/tokens/tokens-133-light.css +1 -0
  94. package/lib/dist/tokens/tokens-134-dark.css +1 -0
  95. package/lib/dist/tokens/tokens-134-light.css +1 -0
  96. package/lib/dist/tokens/tokens-135-dark.css +1 -0
  97. package/lib/dist/tokens/tokens-135-light.css +1 -0
  98. package/lib/dist/tokens/tokens-136-dark.css +1 -0
  99. package/lib/dist/tokens/tokens-136-light.css +1 -0
  100. package/lib/dist/tokens/tokens-137-dark.css +1 -0
  101. package/lib/dist/tokens/tokens-137-light.css +1 -0
  102. package/lib/dist/tokens/tokens-aegean-dark.css +1 -0
  103. package/lib/dist/tokens/tokens-aegean-light.css +1 -0
  104. package/lib/dist/tokens/tokens-botany-dark.css +1 -0
  105. package/lib/dist/tokens/tokens-botany-light.css +1 -0
  106. package/lib/dist/tokens/tokens-buttercream-dark.css +1 -0
  107. package/lib/dist/tokens/tokens-buttercream-light.css +1 -0
  108. package/lib/dist/tokens/tokens-ceruleo-dark.css +1 -0
  109. package/lib/dist/tokens/tokens-ceruleo-light.css +1 -0
  110. package/lib/dist/tokens/tokens-debug-dp.css +1 -0
  111. package/lib/dist/tokens/tokens-dp-dark.css +1 -0
  112. package/lib/dist/tokens/tokens-dp-light.css +1 -0
  113. package/lib/dist/tokens/tokens-expressive-dark.css +1 -0
  114. package/lib/dist/tokens/tokens-expressive-light.css +1 -0
  115. package/lib/dist/tokens/tokens-expressive-sm-dark.css +1 -0
  116. package/lib/dist/tokens/tokens-expressive-sm-light.css +1 -0
  117. package/lib/dist/tokens/tokens-high-desert-dark.css +1 -0
  118. package/lib/dist/tokens/tokens-high-desert-light.css +1 -0
  119. package/lib/dist/tokens/tokens-melon-dark.css +1 -0
  120. package/lib/dist/tokens/tokens-melon-light.css +1 -0
  121. package/lib/dist/tokens/tokens-plum-dark.css +1 -0
  122. package/lib/dist/tokens/tokens-plum-light.css +1 -0
  123. package/lib/dist/tokens/tokens-prota-deuter-dark.css +1 -0
  124. package/lib/dist/tokens/tokens-prota-deuter-light.css +1 -0
  125. package/lib/dist/tokens/tokens-sunflower-dark.css +1 -0
  126. package/lib/dist/tokens/tokens-sunflower-light.css +1 -0
  127. package/lib/dist/tokens/tokens-tmo-dark.css +1 -0
  128. package/lib/dist/tokens/tokens-tmo-light.css +1 -0
  129. package/lib/dist/tokens/tokens-trita-dark.css +1 -0
  130. package/lib/dist/tokens/tokens-trita-light.css +1 -0
  131. package/lib/dist/tokens/tokens-verdant-haze-dark.css +1 -0
  132. package/lib/dist/tokens/tokens-verdant-haze-light.css +1 -0
  133. package/lib/dist/tokens-docs.json +1 -1
  134. package/package.json +5 -3
@@ -0,0 +1,108 @@
1
+ // Migration: deprecated `setTheme()` and `data-dt-theme` attribute → layered API.
2
+ //
3
+ // - Startup call: setTheme(KnownTheme) → initDialtoneTheme(KnownTheme, 'mode')
4
+ // - Dynamic calls: setTheme(expr) → flagged with TODO comment
5
+ // - HTML attributes: data-dt-theme= → data-dt-mode=
6
+ // - JS attribute methods: setAttribute/getAttribute('data-dt-theme') → 'data-dt-mode'
7
+ // - CSS selectors: [data-dt-theme...] → [data-dt-mode...]
8
+ // - Invert regions (data-dt-theme="invert") are flagged with a TODO comment
9
+ // rather than auto-rewritten — the v-dt-mode directive uses a live
10
+ // MutationObserver that cannot be replicated with a static replacement.
11
+
12
+ // Identifiers and their mode extracted from the known legacy theme names.
13
+ const KNOWN_LIGHT = ['DpLight', 'TmoLight', 'ExpressiveLight', 'ExpressiveSmLight'];
14
+ const KNOWN_DARK = ['DpDark', 'TmoDark', 'ExpressiveDark', 'ExpressiveSmDark'];
15
+ const ALL_KNOWN = [...KNOWN_LIGHT, ...KNOWN_DARK];
16
+ const KNOWN_PATTERN = ALL_KNOWN.join('|');
17
+
18
+ export default {
19
+ description:
20
+ 'Migrates from the deprecated setTheme() / data-dt-theme API to the layered theming API.\n' +
21
+ '- setTheme(DpLight) → initDialtoneTheme(DpLight, \'light\')\n' +
22
+ '- setTheme(DpDark) → initDialtoneTheme(DpDark, \'dark\')\n' +
23
+ '- Same for TmoLight, TmoDark, ExpressiveLight, ExpressiveDark, ExpressiveSmLight, ExpressiveSmDark\n' +
24
+ '- setTheme(dynamicExpr) → preserved + TODO comment\n' +
25
+ '- data-dt-theme= → data-dt-mode= (HTML attributes, JS attr methods, CSS selectors)\n' +
26
+ '- data-dt-theme="invert" → preserved + TODO comment (review for v-dt-mode directive)\n',
27
+
28
+ patterns: ['**/*.{vue,html,js,ts,jsx,tsx,css,less,scss,mjs}'],
29
+
30
+ globbyConfig: {
31
+ ignore: [
32
+ '**/dialtone_migration_helper/tests/**',
33
+ '**/guides/migration/theme-to-mode/**',
34
+ '**/guides/theme-and-mode/index.md',
35
+ '**/whats-new/posts/2024-8-1.md',
36
+ ],
37
+ },
38
+
39
+ expressions: [
40
+ // 1. setTheme() call rewrites for known light identifiers.
41
+ // Must run BEFORE the unknown-call flag expression (3) so these are
42
+ // fully consumed before the fallthrough regex fires.
43
+ {
44
+ from: new RegExp(
45
+ `(?<!\\.)setTheme\\(\\s*(${KNOWN_LIGHT.join('|')})\\s*\\)`,
46
+ 'g',
47
+ ),
48
+ to: (_match, identifier) => `initDialtoneTheme(${identifier}, 'light')`,
49
+ },
50
+
51
+ // 2. setTheme() call rewrites for known dark identifiers.
52
+ {
53
+ from: new RegExp(
54
+ `(?<!\\.)setTheme\\(\\s*(${KNOWN_DARK.join('|')})\\s*\\)`,
55
+ 'g',
56
+ ),
57
+ to: (_match, identifier) => `initDialtoneTheme(${identifier}, 'dark')`,
58
+ },
59
+
60
+ // 3. setTheme() calls with unknown / dynamic arguments → TODO comment.
61
+ // Negative-lookahead skips the eight known identifiers already rewritten above.
62
+ // Negative-lookbehind on '.' prevents matching unrelated .setTheme() methods.
63
+ {
64
+ from: new RegExp(
65
+ `(?<!\\.)setTheme\\(\\s*(?!(${KNOWN_PATTERN})\\s*\\))([^)]*)\\)`,
66
+ 'g',
67
+ ),
68
+ to: (match) =>
69
+ `// TODO: review for layered API migration — see /guides/migration/theme-to-mode/\n${match}`,
70
+ },
71
+
72
+ // 4. Attribute rename: data-dt-theme → data-dt-mode
73
+ // Covers HTML/Vue/JSX attributes, JS string literals, and CSS selectors.
74
+ // Negative lookahead (?!-) prevents matching data-dt-theme-x (longer names).
75
+ // Works correctly with applyConfig's inner match.replace() since the inner
76
+ // call operates on just the matched text "data-dt-theme" where (?!-) passes
77
+ // at end-of-string (no "-" follows).
78
+ {
79
+ from: /\bdata-dt-theme(?!-)/g,
80
+ to: () => 'data-dt-mode',
81
+ },
82
+
83
+ // 5. CSS selector invert — add TODO comment before the renamed selector.
84
+ // Expression 5 already renamed [data-dt-theme=...] → [data-dt-mode=...],
85
+ // so we match on the result. HTML attribute invert is handled by
86
+ // expression 5 (just renamed, no comment — inserting HTML comments inside
87
+ // tags produces invalid markup; consumers grep for data-dt-mode="invert"
88
+ // to find regions needing v-dt-mode review).
89
+ {
90
+ from: /\[data-dt-mode="invert"\]|\[data-dt-mode=invert\]/g,
91
+ to: (match) =>
92
+ `/* TODO: review for v-dt-mode adoption — see /guides/migration/theme-to-mode/ */\n${match}`,
93
+ },
94
+
95
+ // 6. JS attribute methods: setAttribute/getAttribute/etc. on 'data-dt-theme'
96
+ {
97
+ from: /(\.(?:set|get|toggle|remove|has)Attribute\(\s*['"])data-dt-theme(['"])/g,
98
+ to: (_match, prefix, suffix) => `${prefix}data-dt-mode${suffix}`,
99
+ },
100
+
101
+ // 7. CSS attribute selectors: [data-dt-theme...] → [data-dt-mode...]
102
+ // Runs after the invert-flagging expressions to avoid double-processing.
103
+ {
104
+ from: /\[data-dt-theme(\]|=[^\]]*\])/g,
105
+ to: (_match, rest) => `[data-dt-mode${rest}`,
106
+ },
107
+ ],
108
+ };
@@ -0,0 +1,24 @@
1
+ <template>
2
+ <!-- Module path example (should be rewritten by codemod) -->
3
+ <section data-dt-theme="light">
4
+ Light mode section
5
+ </section>
6
+
7
+ <!-- CSS selector example (for stylesheet tests) -->
8
+ <div class="themed-container">
9
+ Theme-aware container
10
+ </div>
11
+ </template>
12
+
13
+ <script>
14
+ // Legacy imports — these paths and calls are transformed by the codemod
15
+ import DpLight from '@dialpad/dialtone/themes/dp-light';
16
+ import DpDark from '@dialpad/dialtone/themes/dp-dark';
17
+ import { setTheme } from '@dialpad/dialtone/themes/config';
18
+
19
+ // Startup initialization
20
+ setTheme(DpLight);
21
+
22
+ // Mode switching (runtime)
23
+ setTheme(DpDark);
24
+ </script>
@@ -0,0 +1,177 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import config from '../configs/theme-to-mode.mjs';
4
+ import { applyConfig } from './helpers.mjs';
5
+
6
+ const apply = (input) => applyConfig(config, input);
7
+
8
+ describe('theme-to-mode config', () => {
9
+ // ─── setTheme call rewrites ───────────────────────────────────────────────
10
+
11
+ describe('setTheme() → initDialtoneTheme() for known identifiers', () => {
12
+ it('rewrites setTheme(DpLight) → initDialtoneTheme(DpLight, \'light\')', () => {
13
+ const input = `setTheme(DpLight);`;
14
+ const expected = `initDialtoneTheme(DpLight, 'light');`;
15
+ assert.equal(apply(input), expected);
16
+ });
17
+
18
+ it('rewrites setTheme(DpDark) → initDialtoneTheme(DpDark, \'dark\')', () => {
19
+ const input = `setTheme(DpDark);`;
20
+ const expected = `initDialtoneTheme(DpDark, 'dark');`;
21
+ assert.equal(apply(input), expected);
22
+ });
23
+
24
+ it('rewrites setTheme(TmoLight) → initDialtoneTheme(TmoLight, \'light\')', () => {
25
+ const input = `setTheme(TmoLight);`;
26
+ const expected = `initDialtoneTheme(TmoLight, 'light');`;
27
+ assert.equal(apply(input), expected);
28
+ });
29
+
30
+ it('rewrites setTheme(TmoDark) → initDialtoneTheme(TmoDark, \'dark\')', () => {
31
+ const input = `setTheme(TmoDark);`;
32
+ const expected = `initDialtoneTheme(TmoDark, 'dark');`;
33
+ assert.equal(apply(input), expected);
34
+ });
35
+
36
+ it('rewrites setTheme(ExpressiveLight) → initDialtoneTheme(ExpressiveLight, \'light\')', () => {
37
+ const input = `setTheme(ExpressiveLight);`;
38
+ const expected = `initDialtoneTheme(ExpressiveLight, 'light');`;
39
+ assert.equal(apply(input), expected);
40
+ });
41
+
42
+ it('rewrites setTheme(ExpressiveDark) → initDialtoneTheme(ExpressiveDark, \'dark\')', () => {
43
+ const input = `setTheme(ExpressiveDark);`;
44
+ const expected = `initDialtoneTheme(ExpressiveDark, 'dark');`;
45
+ assert.equal(apply(input), expected);
46
+ });
47
+
48
+ it('handles whitespace inside setTheme call', () => {
49
+ const input = `setTheme( DpLight );`;
50
+ const expected = `initDialtoneTheme(DpLight, 'light');`;
51
+ assert.equal(apply(input), expected);
52
+ });
53
+
54
+ it('rewrites setTheme(DpLight) as part of onMounted setup', () => {
55
+ const input = `onMounted(() => { setTheme(DpLight); });`;
56
+ const expected = `onMounted(() => { initDialtoneTheme(DpLight, 'light'); });`;
57
+ assert.equal(apply(input), expected);
58
+ });
59
+
60
+ it('does NOT rewrite setTheme() with a dynamic variable — emits TODO comment', () => {
61
+ const input = `setTheme(myDynamicTheme);`;
62
+ const result = apply(input);
63
+ assert.ok(result.includes('setTheme(myDynamicTheme)'), 'original call preserved');
64
+ assert.ok(result.includes('TODO: review for layered API migration'), 'TODO comment inserted');
65
+ });
66
+
67
+ it('does NOT rewrite setTheme() with an expression — emits TODO comment', () => {
68
+ const input = `setTheme(isDark ? DpDark : DpLight);`;
69
+ const result = apply(input);
70
+ assert.ok(result.includes('setTheme(isDark ? DpDark : DpLight)'), 'original call preserved');
71
+ assert.ok(result.includes('TODO: review for layered API migration'), 'TODO comment inserted');
72
+ });
73
+
74
+ it('does NOT rewrite myObj.setTheme() — unrelated method', () => {
75
+ const input = `myThemeManager.setTheme(DpLight);`;
76
+ assert.equal(apply(input), input);
77
+ });
78
+ });
79
+
80
+ // ─── Attribute renames ────────────────────────────────────────────────────
81
+
82
+ describe('data-dt-theme → data-dt-mode in HTML attributes', () => {
83
+ it('rewrites data-dt-theme= in HTML attribute', () => {
84
+ const input = `<html data-dt-theme="dp-light">`;
85
+ const expected = `<html data-dt-mode="dp-light">`;
86
+ assert.equal(apply(input), expected);
87
+ });
88
+
89
+ it('rewrites data-dt-theme= with single quotes', () => {
90
+ const input = `<section data-dt-theme='dark'>content</section>`;
91
+ const expected = `<section data-dt-mode='dark'>content</section>`;
92
+ assert.equal(apply(input), expected);
93
+ });
94
+
95
+ it('does NOT rewrite data-dt-theme-x (longer attribute with same prefix)', () => {
96
+ const input = `<div data-dt-theme-custom="foo">`;
97
+ assert.equal(apply(input), input);
98
+ });
99
+
100
+ it('rewrites data-dt-theme= in Vue template binding (static)', () => {
101
+ const input = `<div data-dt-theme="light">`;
102
+ const expected = `<div data-dt-mode="light">`;
103
+ assert.equal(apply(input), expected);
104
+ });
105
+ });
106
+
107
+ describe('data-dt-theme in JS setAttribute/getAttribute', () => {
108
+ it('rewrites setAttribute first argument', () => {
109
+ const input = `el.setAttribute('data-dt-theme', 'dark');`;
110
+ const expected = `el.setAttribute('data-dt-mode', 'dark');`;
111
+ assert.equal(apply(input), expected);
112
+ });
113
+
114
+ it('rewrites getAttribute first argument', () => {
115
+ const input = `const mode = el.getAttribute('data-dt-theme');`;
116
+ const expected = `const mode = el.getAttribute('data-dt-mode');`;
117
+ assert.equal(apply(input), expected);
118
+ });
119
+
120
+ it('rewrites removeAttribute first argument', () => {
121
+ const input = `el.removeAttribute('data-dt-theme');`;
122
+ const expected = `el.removeAttribute('data-dt-mode');`;
123
+ assert.equal(apply(input), expected);
124
+ });
125
+
126
+ it('rewrites hasAttribute first argument', () => {
127
+ const input = `if (el.hasAttribute('data-dt-theme')) {`;
128
+ const expected = `if (el.hasAttribute('data-dt-mode')) {`;
129
+ assert.equal(apply(input), expected);
130
+ });
131
+ });
132
+
133
+ describe('data-dt-theme in CSS attribute selectors', () => {
134
+ it('rewrites [data-dt-theme] bare selector', () => {
135
+ const input = `[data-dt-theme] { color: red; }`;
136
+ const expected = `[data-dt-mode] { color: red; }`;
137
+ assert.equal(apply(input), expected);
138
+ });
139
+
140
+ it('rewrites [data-dt-theme="value"] selector', () => {
141
+ const input = `[data-dt-theme="dp-light"] { background: white; }`;
142
+ const expected = `[data-dt-mode="dp-light"] { background: white; }`;
143
+ assert.equal(apply(input), expected);
144
+ });
145
+
146
+ it('rewrites [data-dt-theme=value] selector (unquoted)', () => {
147
+ const input = `[data-dt-theme=light] .d-banner { border: 1px; }`;
148
+ const expected = `[data-dt-mode=light] .d-banner { border: 1px; }`;
149
+ assert.equal(apply(input), expected);
150
+ });
151
+ });
152
+
153
+ // ─── Invert handling ──────────────────────────────────────────────────────
154
+
155
+ describe('data-dt-theme="invert" handling', () => {
156
+ it('renames data-dt-theme="invert" to data-dt-mode="invert" (grep to find for v-dt-mode review)', () => {
157
+ const input = `<section data-dt-theme="invert">content</section>`;
158
+ const result = apply(input);
159
+ assert.ok(result.includes('data-dt-mode="invert"'), 'attribute renamed');
160
+ assert.ok(!result.includes('data-dt-theme="invert"'), 'old attribute removed');
161
+ });
162
+
163
+ it('adds TODO comment before [data-dt-theme="invert"] CSS selector', () => {
164
+ const input = `[data-dt-theme="invert"] .d-card { box-shadow: none; }`;
165
+ const result = apply(input);
166
+ assert.ok(result.includes('[data-dt-mode="invert"]'), 'selector renamed');
167
+ assert.ok(result.includes('TODO: review for v-dt-mode adoption'), 'TODO inserted');
168
+ });
169
+
170
+ it('adds TODO comment before [data-dt-theme=invert] unquoted CSS selector', () => {
171
+ const input = `[data-dt-theme=invert] { background: red; }`;
172
+ const result = apply(input);
173
+ assert.ok(result.includes('[data-dt-mode=invert]'), 'selector renamed');
174
+ assert.ok(result.includes('TODO: review for v-dt-mode adoption'), 'TODO inserted');
175
+ });
176
+ });
177
+ });
@@ -274,6 +274,7 @@
274
274
  // ----------------------------------------------------------------------------
275
275
  .d-btn__leading,
276
276
  .d-btn__trailing {
277
+ z-index: var(--zi-base1);
277
278
  display: inline-flex;
278
279
  align-items: center;
279
280
  align-self: stretch;
@@ -318,6 +319,7 @@
318
319
  }
319
320
 
320
321
  .d-btn__icon {
322
+ z-index: var(--zi-base1);
321
323
  display: flex;
322
324
 
323
325
  :where(.d-btn--disabled) & ,
@@ -17,7 +17,7 @@
17
17
  // with this width we have 9 emoji per row
18
18
  inline-size: var(--dt-layout-550);
19
19
  block-size: 100%;
20
- background-color: var(--dt-color-surface-primary);
20
+ background-color: var(--dt-color-surface-overlay);
21
21
  border-radius: var(--dt-size-radius-300);
22
22
 
23
23
  &--header {
@@ -28,8 +28,8 @@
28
28
  position: absolute;
29
29
  inset-inline: 0;
30
30
  inset-block-end: 0;
31
- block-size: var(--dt-size-border-200);
32
- background-color: var(--dt-color-surface-moderate) !important;
31
+ block-size: var(--dt-size-border-100);
32
+ background-color: var(--dt-color-border-subtle) !important;
33
33
  content: '';
34
34
  }
35
35
  }
@@ -49,7 +49,6 @@
49
49
  justify-content: space-between;
50
50
  block-size: calc(var(--dt-layout-100) - var(--dt-spacing-75));
51
51
  padding: 0 var(--dt-spacing-200);
52
- background: var(--dt-color-surface-secondary);
53
52
  border-block-start: var(--dt-size-border-100) solid var(--dt-color-border-subtle);
54
53
  }
55
54
 
@@ -62,7 +61,7 @@
62
61
  gap: var(--dt-spacing-0);
63
62
 
64
63
  &::after {
65
- background-color: var(--dt-color-surface-moderate) !important;
64
+ background-color: var(--dt-color-neutral-transparent) !important;
66
65
  }
67
66
 
68
67
  .d-tablist__item {
@@ -92,8 +91,8 @@
92
91
  margin: 0;
93
92
  padding: 0;
94
93
  background: none;
95
- border: var(--dt-size-border-100) solid transparent;
96
- border-radius: var(--dt-size-radius-350);
94
+ border: var(--dt-size-border-100) solid var(--dt-color-neutral-transparent);
95
+ border-radius: var(--dt-size-radius-circle);
97
96
  outline: none;
98
97
  cursor: pointer;
99
98
 
@@ -103,7 +102,7 @@
103
102
 
104
103
  &:active,
105
104
  &.selected {
106
- border-color: var(--dt-color-border-bold);
105
+ border-color: var(--dt-color-border-moderate);
107
106
  }
108
107
  }
109
108
  }
@@ -116,13 +115,13 @@
116
115
  margin: 0;
117
116
  padding: calc(var(--dt-spacing-75) + var(--dt-spacing-1));
118
117
  background: var(--dt-color-surface-moderate-opaque);
119
- border: none;
118
+ border: var(--dt-size-border-100) solid var(--dt-color-neutral-transparent);
120
119
  border-radius: var(--dt-size-radius-circle);
121
120
  outline: none;
122
121
  cursor: pointer;
123
122
 
124
123
  &:hover {
125
- background: var(--dt-color-surface-bold);
124
+ border-color: var(--dt-color-border-subtle);
126
125
  }
127
126
  }
128
127
  }
@@ -144,7 +143,7 @@
144
143
  inline-size: 100%;
145
144
  margin: 0;
146
145
  padding: var(--dt-spacing-200) var(--dt-spacing-200) 0 var(--dt-spacing-200);
147
- background: var(--dt-color-surface-primary);
146
+ background: var(--dt-color-surface-overlay);
148
147
  }
149
148
 
150
149
  &__list {
@@ -118,6 +118,8 @@ fieldset {
118
118
  // ----------------------------------------------------------------------------
119
119
  .d-validation-message {
120
120
  --validation-color-text: var(--dt-color-foreground-tertiary);
121
+ --validation-size-icon: var(--dt-layout-25);
122
+ --validation-icon: initial;
121
123
 
122
124
  display: flex;
123
125
  gap: var(--dt-spacing-50);
@@ -129,14 +131,15 @@ fieldset {
129
131
  font-family: inherit;
130
132
  line-height: var(--dt-font-line-height-300);
131
133
 
132
- // Icon Slot
133
- &::before {
134
+ // Raw-HTML icon fallback — suppressed when a real .d-icon child is present
135
+ &:not(:has(.d-icon))::before {
134
136
  display: block;
135
137
  margin-block-start: var(--dt-spacing-25);
136
- inline-size: var(--dt-layout-25); // 16
137
- min-inline-size: var(--dt-layout-25); // 16
138
- block-size: var(--dt-layout-25); // 16
138
+ inline-size: var(--validation-size-icon);
139
+ min-inline-size: var(--validation-size-icon);
140
+ block-size: var(--validation-size-icon);
139
141
  background-color: var(--validation-color-text);
142
+ mask: var(--validation-icon);
140
143
  content: '';
141
144
  }
142
145
 
@@ -144,6 +147,13 @@ fieldset {
144
147
  display: flex;
145
148
  flex-direction: column;
146
149
  }
150
+
151
+ &__icon {
152
+ margin-block-start: calc(var(--dt-spacing-25) / 2);
153
+ color: var(--validation-color-text);
154
+ inline-size: var(--validation-size-icon);
155
+ block-size: var(--validation-size-icon);
156
+ }
147
157
  }
148
158
 
149
159
  // $$ VALIDATION STATES
@@ -151,27 +161,23 @@ fieldset {
151
161
 
152
162
  .d-validation-message--warning {
153
163
  --validation-color-text: var(--dt-color-foreground-warning);
154
-
155
- &::before {
156
- mask: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0ibm9uZSIgdmlld0JveD0iMCAwIDEyIDEyIj4gPHBhdGggZmlsbD0iIzY4M2UwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNS4yNCAxLjE5N2ExLjUgMS41IDAgMCAxIDIuMDYuNTU2bDMuOTk4IDYuOTk3YTEuNTA0IDEuNTA0IDAgMCAxIDAgMS41IDEuNSAxLjUgMCAwIDEtMS4yOTcuNzVIMi4wMDJhMS41IDEuNSAwIDAgMS0xLjMxLTIuMjQ5VjguNzVMNC42OSAxLjc1M2ExLjUgMS41IDAgMCAxIC41NS0uNTU2Wm0uNzU1Ljc5NmEuNS41IDAgMCAwLS40MzUuMjU0di4wMDFMMS41NTcgOS4yNWEuNS41IDAgMCAwIC40MzguNzVIMTBhLjUuNSAwIDAgMCAuNDMyLS43NWwtLjAwMS0uMDAyLTQtNy0uMDAxLS4wMDFhLjUuNSAwIDAgMC0uNDM1LS4yNTRaIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz4gPHBhdGggZmlsbD0iIzY4M2UwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNiA0YS41LjUgMCAwIDEgLjUuNXYyYS41LjUgMCAwIDEtMSAwdi0yQS41LjUgMCAwIDEgNiA0Wm0tLjUgNC41QS41LjUgMCAwIDEgNiA4aC4wMDVhLjUuNSAwIDAgMSAwIDFINmEuNS41IDAgMCAxLS41LS41WiIgY2xpcC1ydWxlPSJldmVub2RkIi8+IDwvc3ZnPg==') repeat;
157
- }
164
+ --validation-icon: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0ibm9uZSIgdmlld0JveD0iMCAwIDEyIDEyIj4gPHBhdGggZmlsbD0iIzY4M2UwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNS4yNCAxLjE5N2ExLjUgMS41IDAgMCAxIDIuMDYuNTU2bDMuOTk4IDYuOTk3YTEuNTA0IDEuNTA0IDAgMCAxIDAgMS41IDEuNSAxLjUgMCAwIDEtMS4yOTcuNzVIMi4wMDJhMS41IDEuNSAwIDAgMS0xLjMxLTIuMjQ5VjguNzVMNC42OSAxLjc1M2ExLjUgMS41IDAgMCAxIC41NS0uNTU2Wm0uNzU1Ljc5NmEuNS41IDAgMCAwLS40MzUuMjU0di4wMDFMMS41NTcgOS4yNWEuNS41IDAgMCAwIC40MzguNzVIMTBhLjUuNSAwIDAgMCAuNDMyLS43NWwtLjAwMS0uMDAyLTQtNy0uMDAxLS4wMDFhLjUuNSAwIDAgMC0uNDM1LS4yNTRaIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz4gPHBhdGggZmlsbD0iIzY4M2UwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNiA0YS41LjUgMCAwIDEgLjUuNXYyYS41LjUgMCAwIDEtMSAwdi0yQS41LjUgMCAwIDEgNiA0Wm0tLjUgNC41QS41LjUgMCAwIDEgNiA4aC4wMDVhLjUuNSAwIDAgMSAwIDFINmEuNS41IDAgMCAxLS41LS41WiIgY2xpcC1ydWxlPSJldmVub2RkIi8+IDwvc3ZnPg==') repeat;
158
165
  }
159
166
 
160
167
  .d-validation-message--critical,
161
168
  .d-validation-message--error {
162
169
  --validation-color-text: var(--dt-color-foreground-critical);
163
-
164
- &::before {
165
- mask: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0ibm9uZSIgdmlld0JveD0iMCAwIDEyIDEyIj4gPGcgY2xpcC1wYXRoPSJ1cmwoI2EpIj4gPHBhdGggZmlsbD0iI2VjMGUwZSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNiAxLjVhNC41IDQuNSAwIDEgMCAwIDkgNC41IDQuNSAwIDAgMCAwLTlaTS41IDZhNS41IDUuNSAwIDEgMSAxMSAwIDUuNSA1LjUgMCAwIDEtMTEgMFpNNiAzLjVhLjUuNSAwIDAgMSAuNS41djJhLjUuNSAwIDAgMS0xIDBWNGEuNS41IDAgMCAxIC41LS41Wk01LjUgOGEuNS41IDAgMCAxIC41LS41aC4wMDVhLjUuNSAwIDAgMSAwIDFINmEuNS41IDAgMCAxLS41LS41WiIgY2xpcC1ydWxlPSJldmVub2RkIi8+IDwvZz4gPGRlZnM+IDxjbGlwUGF0aCBpZD0iYSI+IDxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMTJ2MTJIMHoiLz4gPC9jbGlwUGF0aD4gPC9kZWZzPiA8L3N2Zz4=') no-repeat;
166
- }
170
+ --validation-icon: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0ibm9uZSIgdmlld0JveD0iMCAwIDEyIDEyIj4gPGcgY2xpcC1wYXRoPSJ1cmwoI2EpIj4gPHBhdGggZmlsbD0iI2VjMGUwZSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNiAxLjVhNC41IDQuNSAwIDEgMCAwIDkgNC41IDQuNSAwIDAgMCAwLTlaTS41IDZhNS41IDUuNSAwIDEgMSAxMSAwIDUuNSA1LjUgMCAwIDEtMTEgMFpNNiAzLjVhLjUuNSAwIDAgMSAuNS41djJhLjUuNSAwIDAgMS0xIDBWNGEuNS41IDAgMCAxIC41LS41Wk01LjUgOGEuNS41IDAgMCAxIC41LS41aC4wMDVhLjUuNSAwIDAgMSAwIDFINmEuNS41IDAgMCAxLS41LS41WiIgY2xpcC1ydWxlPSJldmVub2RkIi8+IDwvZz4gPGRlZnM+IDxjbGlwUGF0aCBpZD0iYSI+IDxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMTJ2MTJIMHoiLz4gPC9jbGlwUGF0aD4gPC9kZWZzPiA8L3N2Zz4=') no-repeat;
167
171
  }
168
172
 
169
173
  .d-validation-message--positive,
170
174
  .d-validation-message--success {
171
175
  --validation-color-text: var(--dt-color-foreground-positive);
176
+ --validation-icon: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0ibm9uZSIgdmlld0JveD0iMCAwIDEyIDEyIj4gPGcgY2xpcC1wYXRoPSJ1cmwoI2EpIj4gPHBhdGggZmlsbD0iIzAwNjcxZCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNLjUgNmE1LjUgNS41IDAgMSAxIDExIDAgNS41IDUuNSAwIDAgMS0xMSAwWk02IDEuNWE0LjUgNC41IDAgMSAwIDAgOSA0LjUgNC41IDAgMCAwIDAtOVptMS44NTQgMy4xNDZhLjUuNSAwIDAgMSAwIC43MDhsLTIgMmEuNS41IDAgMCAxLS43MDggMGwtMS0xYS41LjUgMCAxIDEgLjcwOC0uNzA4bC42NDYuNjQ3IDEuNjQ2LTEuNjQ3YS41LjUgMCAwIDEgLjcwOCAwWiIgY2xpcC1ydWxlPSJldmVub2RkIi8+IDwvZz4gPGRlZnM+IDxjbGlwUGF0aCBpZD0iYSI+IDxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMTJ2MTJIMHoiLz4gPC9jbGlwUGF0aD4gPC9kZWZzPiA8L3N2Zz4=') no-repeat;
177
+ }
172
178
 
173
- &::before {
174
- mask: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0ibm9uZSIgdmlld0JveD0iMCAwIDEyIDEyIj4gPGcgY2xpcC1wYXRoPSJ1cmwoI2EpIj4gPHBhdGggZmlsbD0iIzAwNjcxZCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNLjUgNmE1LjUgNS41IDAgMSAxIDExIDAgNS41IDUuNSAwIDAgMS0xMSAwWk02IDEuNWE0LjUgNC41IDAgMSAwIDAgOSA0LjUgNC41IDAgMCAwIDAtOVptMS44NTQgMy4xNDZhLjUuNSAwIDAgMSAwIC43MDhsLTIgMmEuNS41IDAgMCAxLS43MDggMGwtMS0xYS41LjUgMCAxIDEgLjcwOC0uNzA4bC42NDYuNjQ3IDEuNjQ2LTEuNjQ3YS41LjUgMCAwIDEgLjcwOCAwWiIgY2xpcC1ydWxlPSJldmVub2RkIi8+IDwvZz4gPGRlZnM+IDxjbGlwUGF0aCBpZD0iYSI+IDxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMTJ2MTJIMHoiLz4gPC9jbGlwUGF0aD4gPC9kZWZzPiA8L3N2Zz4=') no-repeat;
175
- }
179
+ .d-validation-message--info {
180
+ --validation-color-text: var(--dt-color-foreground-info);
181
+ --validation-icon: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0ibm9uZSIgdmlld0JveD0iMCAwIDEyIDEyIj4gPGcgY2xpcC1wYXRoPSJ1cmwoI2EpIj4gPHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNiAxLjVhNC41IDQuNSAwIDEgMCAwIDkgNC41IDQuNSAwIDAgMCAwLTlaTS41IDZhNS41IDUuNSAwIDEgMSAxMSAwIDUuNSA1LjUgMCAwIDEtMTEgMFptNS0yYS41LjUgMCAwIDEgLjUtLjVoLjAwNWEuNS41IDAgMCAxIDAgMUg2YS41LjUgMCAwIDEtLjUtLjVaTTYgNS41YS41LjUgMCAwIDEgLjUuNXYyYS41LjUgMCAwIDEtMSAwVjZhLjUuNSAwIDAgMSAuNS0uNVoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPiA8L2c+IDxkZWZzPiA8Y2xpcFBhdGggaWQ9ImEiPiA8cGF0aCBmaWxsPSIjZmZmIiBkPSJNMCAwaDEydjEySDB6Ii8+IDwvY2xpcFBhdGg+IDwvZGVmcz4gPC9zdmc+') no-repeat;
176
182
  }
177
183
  }
@@ -96,7 +96,7 @@
96
96
  // ------------------------------------------------------------------------
97
97
  --modal-backdrop-color-background: var(--dt-color-surface-backdrop);
98
98
  --modal-dialog-padding: var(--dt-spacing-400);
99
- --modal-dialog-color-background: var(--dt-color-surface-primary);
99
+ --modal-dialog-color-background: var(--dt-color-surface-overlay);
100
100
  --modal-dialog-color-border: var(--dt-color-border-subtle);
101
101
  --modal-dialog-color-text: var(--dt-color-foreground-primary);
102
102
  --modal-header-color-text: var(--dt-color-foreground-primary);
@@ -144,7 +144,7 @@
144
144
  }
145
145
 
146
146
  .d-modal--transparent {
147
- --modal-backdrop-color-background: var(--d-bgc-transparent);
147
+ --modal-backdrop-color-background: var(--dt-color-neutral-transparent);
148
148
 
149
149
  // If we don't set this the native app header region will override all click events on the modal overlay
150
150
  -webkit-app-region: no-drag;
@@ -158,6 +158,12 @@
158
158
  }
159
159
  }
160
160
 
161
+ // Not to be confused with .d-modal--transparent above — that one is used
162
+ // standalone (without .d-modal) by Popover/Tooltip.
163
+ .d-modal--transparent-backdrop {
164
+ --modal-backdrop-color-background: var(--dt-color-neutral-transparent);
165
+ }
166
+
161
167
  // $$ MODAL DIALOG
162
168
  // ----------------------------------------------------------------------------
163
169
  .d-modal__dialog {
@@ -44,6 +44,10 @@
44
44
  align-items: start;
45
45
  }
46
46
 
47
+ .d-toast {
48
+ --notice-color-background: var(--dt-color-surface-overlay);
49
+ }
50
+
47
51
  // ============================================================================
48
52
  // $ NOTICE AREAS
49
53
  // ============================================================================
@@ -25,7 +25,7 @@
25
25
  &__dialog {
26
26
  // $$ CSS CUSTOM PROPERTIES
27
27
  // ----------------------------------------------------------------------------
28
- --popover-color-background: var(--dt-color-surface-secondary);
28
+ --popover-color-background: var(--dt-color-surface-overlay);
29
29
  --popover-border-width: var(--dt-size-border-100);
30
30
  --popover-border-radius: var(--dt-size-radius-400);
31
31
  --popover-color-border: var(--dt-color-border-subtle);
@@ -12,11 +12,14 @@
12
12
  --presence-color-border-offline: var(--dt-presence-color-offline);
13
13
  --presence-color-background-active: var(--dt-presence-color-available);
14
14
  --presence-color-background-busy: var(--dt-presence-color-unavailable);
15
+ --presence-color-border-dnd: var(--dt-presence-color-unavailable);
15
16
  --presence-color-background-away: var(--dt-presence-color-busy);
16
17
  --presence-color-background-offline: var(--dt-color-surface-primary);
17
18
  --presence-border-radius: calc(var(--presence-size) * 0.208);
18
- --presence-border-inner-width: calc(calc(var(--presence-size) - calc(var(--presence-size) * 0.556)) / 2);
19
+ --presence-border-inner-width: calc(calc(var(--presence-size) - calc(var(--presence-size) * 0.556)) / 3);
19
20
  --presence-size: var(--dt-spacing-150);
21
+ --presence-icon-size: var(--dt-layout-100-percent);
22
+ --presence-icon-color: var(--dt-color-foreground-primary-inverted);
20
23
 
21
24
  display: inline-block;
22
25
 
@@ -29,11 +32,13 @@
29
32
  }
30
33
 
31
34
  &__inner {
35
+ display: grid;
32
36
  box-sizing: border-box;
33
- inline-size: var(--presence-size);
34
- block-size: var(--presence-size);
35
37
  border: none;
36
38
  border-radius: var(--presence-border-radius);
39
+ inline-size: var(--presence-size);
40
+ block-size: var(--presence-size);
41
+ place-items: center;
37
42
 
38
43
  &--active {
39
44
  background-color: var(--presence-color-background-active);
@@ -52,6 +57,21 @@
52
57
  border-style: solid;
53
58
  border-width: var(--presence-border-inner-width);
54
59
  }
60
+
61
+ &--dnd {
62
+ --presence-icon-color: var(--presence-color-border-dnd);
63
+
64
+ border-color: var(--presence-color-border-dnd);
65
+ border-style: solid;
66
+ border-width: var(--presence-border-inner-width);
67
+ }
68
+ }
69
+
70
+ &__icon {
71
+ display: block;
72
+ color: var(--presence-icon-color);
73
+ block-size: var(--presence-icon-size);
74
+ inline-size: var(--presence-icon-size);
55
75
  }
56
76
  }
57
77
  }
@@ -30,6 +30,7 @@
30
30
  --presence-color-background-active: var(--dt-shell-presence-color-available);
31
31
  --presence-color-background-busy: var(--dt-shell-presence-color-unavailable);
32
32
  --presence-color-background-away: var(--dt-shell-presence-color-busy);
33
+ --presence-color-border-dnd: var(--dt-shell-presence-color-unavailable);
33
34
  }
34
35
 
35
36
  // ============================================================================