@nextclaw/ui 0.21.0 → 0.22.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.
Files changed (98) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/assets/{api-DNLQPHfQ.js → api-m33O1Kb0.js} +3 -3
  3. package/dist/assets/{appearance-settings-page-BlAFMOGV.js → appearance-settings-page-x4Vjnfmz.js} +1 -1
  4. package/dist/assets/{book-open-BryfPTTa.js → book-open-BHiasMCg.js} +1 -1
  5. package/dist/assets/{channels-list-page-Cfbgubyv.js → channels-list-page-DOxJZeXq.js} +1 -1
  6. package/dist/assets/{config-split-page-Dd8xG0Jk.js → config-split-page-DBnMEP1o.js} +1 -1
  7. package/dist/assets/{confirm-dialog-CZIWjnJ6.js → confirm-dialog-f5NKLh5I.js} +2 -2
  8. package/dist/assets/{createLucideIcon-BxwVe8ZD.js → createLucideIcon-CHALGA42.js} +1 -1
  9. package/dist/assets/{desktop-capabilities-page-C6YxsHeV.js → desktop-capabilities-page-DixayAe6.js} +1 -1
  10. package/dist/assets/{desktop-update-config-BVN4QPJn.js → desktop-update-config-ChhfeOHj.js} +1 -1
  11. package/dist/assets/{dist-Cd8Nm3BW.js → dist-_UMsWSY0.js} +1 -1
  12. package/dist/assets/{dist-BRloKr3S.js → dist-sD6V4nHX.js} +1 -1
  13. package/dist/assets/doc-browser-Bq7LJsQY.js +1 -0
  14. package/dist/assets/doc-browser-BuDgpY2e.js +1 -0
  15. package/dist/assets/{doc-browser-context-3JGufiMA.js → doc-browser-context-Capim3og.js} +1 -1
  16. package/dist/assets/{extensions-Dedd2oDI.js → extensions-Bdclr3Wr.js} +1 -1
  17. package/dist/assets/{form-actions-FWCEof3V.js → form-actions-CH0kWhEt.js} +1 -1
  18. package/dist/assets/index-BjxnLYE3.js +109 -0
  19. package/dist/assets/index-CBmwJjwE.css +1 -0
  20. package/dist/assets/loader-circle-CH_0iPLy.js +1 -0
  21. package/dist/assets/{mcp-marketplace-page-e9Rmfz-d.js → mcp-marketplace-page-BUsxLVB5.js} +2 -2
  22. package/dist/assets/mcp-marketplace-page-GPRV3fB0.js +1 -0
  23. package/dist/assets/{model-config-page-C173Ssil.js → model-config-page-CIevwqp4.js} +1 -1
  24. package/dist/assets/{navigation-link-DTPOvGGL.js → navigation-link-CAUiM3zS.js} +1 -1
  25. package/dist/assets/plus-B3obD55V.js +1 -0
  26. package/dist/assets/{privacy-settings-page-CRserBVF.js → privacy-settings-page-CNKfZsYH.js} +1 -1
  27. package/dist/assets/{providers-config-page-C8jUtnZb.js → providers-config-page-DAah2NIS.js} +1 -1
  28. package/dist/assets/{react-BAzO6LZS.js → react-Co6JiC1n.js} +1 -1
  29. package/dist/assets/{refresh-cw-BCj-yjde.js → refresh-cw-BG_LX3SS.js} +1 -1
  30. package/dist/assets/remote-DuscgfvR.js +1 -0
  31. package/dist/assets/{rotate-cw-BPnW4qUl.js → rotate-cw-Cz7I_m7O.js} +1 -1
  32. package/dist/assets/{runtime-config-page-aeQ1Dryz.js → runtime-config-page-Cl1RpmSC.js} +1 -1
  33. package/dist/assets/{save-KT0MumfJ.js → save-BiHnb8ps.js} +1 -1
  34. package/dist/assets/{search-Cv1Hx_nx.js → search-C47TyRg0.js} +1 -1
  35. package/dist/assets/{search-config-page-b283V-fo.js → search-config-page-BAIzd6gN.js} +1 -1
  36. package/dist/assets/{secrets-config-page-ss7x3BOo.js → secrets-config-page-Ddi-n43R.js} +1 -1
  37. package/dist/assets/security-config-C8MHnE1r.js +1 -0
  38. package/dist/assets/{select-BVgD4EpG.js → select-BzQKfW1e.js} +2 -2
  39. package/dist/assets/skeleton-BXFAE9SE.js +1 -0
  40. package/dist/assets/{tag-chip-DZ4ircUB.js → tag-chip-C3K814HZ.js} +1 -1
  41. package/dist/assets/x-C1r9IXet.js +1 -0
  42. package/dist/index.html +29 -21
  43. package/dist/themes/island/island-atmosphere.webp +0 -0
  44. package/index.html +8 -0
  45. package/package.json +4 -4
  46. package/public/themes/island/island-atmosphere.webp +0 -0
  47. package/src/app/components/layout/header.tsx +4 -1
  48. package/src/app/components/layout/page-layout.tsx +4 -1
  49. package/src/app/components/layout/sidebar.tsx +1 -0
  50. package/src/app/styles/island-theme.css +542 -0
  51. package/src/features/chat/components/conversation/__tests__/chat-conversation-header.test.tsx +1 -0
  52. package/src/features/chat/components/conversation/chat-conversation-header.tsx +5 -1
  53. package/src/features/chat/components/conversation/chat-conversation-panel.tsx +4 -1
  54. package/src/features/chat/components/layout/__tests__/chat-sidebar-toolbar.test.tsx +10 -0
  55. package/src/features/chat/components/layout/chat-page-shell.tsx +4 -1
  56. package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +2 -0
  57. package/src/features/chat/components/layout/chat-sidebar.tsx +1 -0
  58. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel.test.tsx +1 -0
  59. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +1 -0
  60. package/src/features/chat/features/workspace/components/chat-session-workspace-panel.tsx +1 -0
  61. package/src/features/pwa/managers/__tests__/pwa-shell-theme.manager.test.ts +9 -0
  62. package/src/features/pwa/managers/pwa-shell-theme.manager.ts +1 -0
  63. package/src/features/service-apps/components/__tests__/service-apps-panel.test.tsx +35 -1
  64. package/src/features/service-apps/components/service-action-row.tsx +130 -0
  65. package/src/features/service-apps/components/service-app-list-item.tsx +11 -66
  66. package/src/features/service-apps/components/service-apps-panel.tsx +12 -0
  67. package/src/features/service-apps/hooks/use-service-apps.ts +20 -1
  68. package/src/features/settings/pages/__tests__/appearance-settings-page.test.tsx +2 -2
  69. package/src/features/side-dock/components/side-dock.tsx +1 -0
  70. package/src/index.css +1 -0
  71. package/src/platforms/desktop/components/__tests__/desktop-app-shell.test.tsx +8 -0
  72. package/src/platforms/desktop/components/desktop-app-shell.tsx +56 -2
  73. package/src/platforms/desktop/components/desktop-window-chrome.tsx +1 -0
  74. package/src/shared/components/doc-browser/__tests__/doc-browser.test.tsx +3 -0
  75. package/src/shared/components/doc-browser/doc-browser.tsx +2 -0
  76. package/src/shared/components/ui/context-menu/context-menu.tsx +1 -0
  77. package/src/shared/components/ui/dialog.tsx +2 -0
  78. package/src/shared/components/ui/overlays/sheet.tsx +2 -0
  79. package/src/shared/components/ui/popover.tsx +1 -0
  80. package/src/shared/components/ui/select.tsx +1 -0
  81. package/src/shared/components/ui/tooltip.tsx +1 -0
  82. package/src/shared/lib/i18n/locales/en-US/core.json +1 -0
  83. package/src/shared/lib/i18n/locales/en-US/doc-browser.json +1 -0
  84. package/src/shared/lib/i18n/locales/zh-CN/core.json +1 -0
  85. package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +1 -0
  86. package/src/shared/lib/theme/index.test.ts +9 -0
  87. package/src/shared/lib/theme/index.ts +2 -0
  88. package/dist/assets/doc-browser-Bzgqmmiu.js +0 -1
  89. package/dist/assets/doc-browser-D0qI0Z_R.js +0 -1
  90. package/dist/assets/index-CXkHcESm.css +0 -1
  91. package/dist/assets/index-D25tRg1p.js +0 -109
  92. package/dist/assets/loader-circle-BoyCoFps.js +0 -1
  93. package/dist/assets/mcp-marketplace-page-Cn-9CDh3.js +0 -1
  94. package/dist/assets/plus-D1R4Vipq.js +0 -1
  95. package/dist/assets/remote-6BHWP5zi.js +0 -1
  96. package/dist/assets/security-config-HHz62oxH.js +0 -1
  97. package/dist/assets/skeleton-ChUmcyys.js +0 -1
  98. package/dist/assets/x-BWDRfVWL.js +0 -1
@@ -0,0 +1,542 @@
1
+ @layer base {
2
+ :root[data-theme="island"] {
3
+ color-scheme: light;
4
+
5
+ /* Sea-glass actions over sun-warmed paper. */
6
+ --brand-50: 152 38% 94%;
7
+ --brand-100: 153 36% 88%;
8
+ --brand-200: 154 34% 79%;
9
+ --brand-300: 155 35% 66%;
10
+ --brand-400: 156 39% 49%;
11
+ --brand-500: 157 50% 34%;
12
+ --brand-600: 158 53% 28%;
13
+ --brand-700: 159 55% 22%;
14
+ --brand-800: 160 52% 17%;
15
+ --brand-900: 162 48% 12%;
16
+
17
+ /* Cream paper and green-black ink. */
18
+ --gray-50: 45 48% 93%;
19
+ --gray-100: 44 38% 89%;
20
+ --gray-200: 42 32% 84%;
21
+ --gray-300: 40 22% 74%;
22
+ --gray-400: 75 8% 56%;
23
+ --gray-500: 104 8% 43%;
24
+ --gray-600: 128 10% 32%;
25
+ --gray-700: 142 14% 24%;
26
+ --gray-800: 68 16% 22%;
27
+ --gray-900: 160 25% 11%;
28
+
29
+ --background: var(--gray-50);
30
+ --background-secondary: var(--gray-100);
31
+ --background-tertiary: var(--gray-200);
32
+ --foreground: var(--gray-800);
33
+ --foreground-secondary: var(--gray-700);
34
+ --foreground-tertiary: var(--gray-500);
35
+ --foreground-muted: var(--gray-400);
36
+ --link-foreground: 158 58% 28%;
37
+ --link-foreground-hover: 160 62% 20%;
38
+ --primary: var(--brand-500);
39
+ --primary-hover: var(--brand-600);
40
+ --primary-active: var(--brand-700);
41
+ --primary-foreground: 45 67% 97%;
42
+ --secondary: var(--gray-100);
43
+ --secondary-hover: 151 25% 86%;
44
+ --secondary-foreground: var(--gray-800);
45
+ --accent: 151 28% 88%;
46
+ --accent-foreground: var(--brand-800);
47
+ --interaction-hover: hsl(151 25% 86% / 0.72);
48
+ --interaction-selection: hsl(153 35% 80% / 0.82);
49
+ --interaction-selection-border: hsl(157 37% 58% / 0.88);
50
+ --muted: var(--gray-100);
51
+ --muted-foreground: var(--gray-500);
52
+ --destructive: 5 61% 47%;
53
+ --destructive-foreground: 45 67% 97%;
54
+ --success: 157 50% 34%;
55
+ --success-foreground: 45 67% 97%;
56
+ --warning: 35 74% 45%;
57
+ --warning-foreground: 160 25% 11%;
58
+ --card: 45 46% 93%;
59
+ --card-foreground: var(--gray-800);
60
+ --card-border: 40 28% 78%;
61
+ --popover: 45 46% 95%;
62
+ --popover-foreground: var(--gray-800);
63
+ --border: 40 27% 78%;
64
+ --border-hover: 150 18% 62%;
65
+ --border-active: var(--brand-500);
66
+ --input: 45 44% 94%;
67
+ --input-border: 40 27% 78%;
68
+ --input-focus: var(--brand-500);
69
+ --ring: var(--brand-500);
70
+ --ring-offset: var(--gray-50);
71
+
72
+ --radius: 0.4rem;
73
+ --radius-sm: 3px;
74
+ --radius-md: 5px;
75
+ --radius-lg: 7px;
76
+ --radius-xl: 10px;
77
+ --radius-2xl: 14px;
78
+ --radius-3xl: 18px;
79
+
80
+ --font-sans:
81
+ "American Typewriter", "Courier New", "Noto Sans Mono", monospace;
82
+ --font-mono:
83
+ "American Typewriter", "Courier New", "Noto Sans Mono", monospace;
84
+ --island-font-display:
85
+ "American Typewriter", "Hannotate SC", "HanziPen SC", "Kaiti SC", STKaiti,
86
+ KaiTi, serif;
87
+ --shadow-xs: 0 1px 2px rgb(44 57 36 / 0.05);
88
+ --shadow-sm:
89
+ 0 1px 3px rgb(44 57 36 / 0.07), 0 1px 2px -1px rgb(44 57 36 / 0.06);
90
+ --shadow-md:
91
+ 0 8px 20px -14px rgb(35 67 47 / 0.28), 0 3px 8px -6px rgb(82 65 37 / 0.18);
92
+ --shadow-lg:
93
+ 0 16px 32px -20px rgb(35 67 47 / 0.32),
94
+ 0 7px 14px -10px rgb(82 65 37 / 0.2);
95
+ --shadow-xl: 0 24px 44px -26px rgb(35 67 47 / 0.36);
96
+ --shadow-2xl: 0 30px 56px -30px rgb(35 67 47 / 0.4);
97
+ --shadow-card:
98
+ 0 0 0 1px hsl(var(--border) / 0.46),
99
+ 0 14px 34px -28px rgb(42 75 52 / 0.42);
100
+ --shadow-card-hover:
101
+ 0 0 0 1px hsl(var(--border-hover) / 0.62),
102
+ 0 18px 42px -28px rgb(42 75 52 / 0.5);
103
+ }
104
+
105
+ :root[data-theme="island"] ::selection {
106
+ background: hsl(155 42% 68% / 0.52);
107
+ color: hsl(var(--gray-900));
108
+ }
109
+
110
+ :root[data-theme="island"]
111
+ :is(.chat-markdown-assistant, .chat-markdown-user) {
112
+ --md-text: hsl(var(--foreground));
113
+ --md-muted: hsl(var(--foreground-tertiary));
114
+ --md-border: hsl(var(--border-hover) / 0.62);
115
+ --md-link: hsl(var(--link-foreground));
116
+ --md-inline-code-bg: hsl(151 24% 84% / 0.72);
117
+ --md-inline-code-color: hsl(var(--gray-800));
118
+ --md-blockquote-border: hsl(var(--brand-400) / 0.58);
119
+ --md-blockquote-bg: hsl(151 28% 88% / 0.66);
120
+ --md-code-surface: hsl(157 26% 12%);
121
+ --md-code-toolbar-bg: hsl(157 23% 16%);
122
+ --md-code-toolbar-border: hsl(151 18% 32% / 0.78);
123
+ --md-code-text: #ebead8;
124
+ --md-code-muted: #9cac9a;
125
+ --md-code-keyword: #d8b487;
126
+ --md-code-title: #91c8b1;
127
+ --md-code-string: #b8d69e;
128
+ --md-code-number: #e2c078;
129
+ --md-code-comment: #829787;
130
+ --md-code-attr: #8bc6bd;
131
+ --md-code-meta: #cfaa9c;
132
+ --md-code-deletion: #dfa69a;
133
+ --md-code-addition: #a8d394;
134
+ --md-table-head-bg: hsl(151 22% 84% / 0.6);
135
+ }
136
+
137
+ :root[data-theme="island"] .chat-terminal-surface {
138
+ --terminal-surface: hsl(157 26% 12%);
139
+ --terminal-border: hsl(151 18% 32% / 0.78);
140
+ --terminal-text: #ebead8;
141
+ --terminal-muted: #9cac9a;
142
+ --terminal-prompt: #8fc8a8;
143
+ --terminal-caret: #a8d394;
144
+ --terminal-error-border: rgba(199, 110, 93, 0.56);
145
+ --terminal-error-bg: rgba(111, 42, 31, 0.2);
146
+ --terminal-error-text: #efb8aa;
147
+ }
148
+ }
149
+
150
+ @layer utilities {
151
+ :is(
152
+ [data-theme-decoration="island-paper"],
153
+ [data-theme-decoration="island-palm"]
154
+ ) {
155
+ display: none;
156
+ }
157
+
158
+ :root[data-theme="island"] [data-theme-surface="app-shell"] {
159
+ isolation: isolate;
160
+ position: relative;
161
+ background-color: hsl(var(--background));
162
+ background-image: none;
163
+ font-variant-ligatures: none;
164
+ letter-spacing: 0.006em;
165
+ text-shadow:
166
+ 0.022em 0 hsl(166 34% 25% / 0.055),
167
+ -0.016em 0 hsl(26 35% 36% / 0.05);
168
+ }
169
+
170
+ :root[data-theme="island"] [data-theme-decoration="island-paper"] {
171
+ background: url("/themes/island/island-atmosphere.webp") center top / cover
172
+ no-repeat;
173
+ display: block;
174
+ inset: 0;
175
+ opacity: 0.94;
176
+ pointer-events: none;
177
+ position: absolute;
178
+ z-index: 0;
179
+ }
180
+
181
+ :root[data-theme="island"] [data-theme-decoration="island-palm"] {
182
+ display: block;
183
+ inset: 0;
184
+ opacity: 1;
185
+ pointer-events: none;
186
+ position: absolute;
187
+ z-index: 0;
188
+ }
189
+
190
+ :root[data-theme="island"]
191
+ [data-theme-decoration="island-palm"]
192
+ [data-island-palm-part] {
193
+ background: url("/themes/island/island-atmosphere.webp") center top / cover
194
+ no-repeat;
195
+ clip-path: polygon(46% 0, 100% 0, 100% 61%, 62% 55%);
196
+ inset: 0;
197
+ mask-image: radial-gradient(
198
+ ellipse at 88% 17%,
199
+ black 0 43%,
200
+ rgb(0 0 0 / 0.86) 51%,
201
+ transparent 72%
202
+ );
203
+ position: absolute;
204
+ will-change: filter;
205
+ }
206
+
207
+ :root[data-theme="island"]
208
+ [data-theme-decoration="island-palm"]
209
+ [data-island-palm-part="frond-wind"] {
210
+ filter: url("#island-wind-filter");
211
+ opacity: 1;
212
+ }
213
+
214
+ :root[data-theme="island"] [data-theme-surface="navigation"] {
215
+ background: transparent;
216
+ border-right: 1px solid hsl(var(--border) / 0.56);
217
+ }
218
+
219
+ :root[data-theme="island"]
220
+ :is(
221
+ [data-theme-surface="workspace"],
222
+ [data-theme-surface="settings-workspace"]
223
+ ) {
224
+ background: transparent;
225
+ }
226
+
227
+ :root[data-theme="island"] [data-theme-surface="utility-rail"] {
228
+ background: transparent;
229
+ border-color: hsl(var(--border) / 0.58);
230
+ }
231
+
232
+ :root[data-theme="island"]
233
+ :is(
234
+ [data-theme-surface="workspace-panel"],
235
+ [data-theme-surface="doc-browser"]
236
+ ) {
237
+ -webkit-backdrop-filter: none;
238
+ backdrop-filter: none;
239
+ background-color: transparent;
240
+ border-color: hsl(var(--border) / 0.54);
241
+ }
242
+
243
+ :root[data-theme="island"]
244
+ [data-theme-surface="workspace-panel"]
245
+ :is(.bg-white, .bg-background),
246
+ :root[data-theme="island"]
247
+ [data-theme-surface="doc-browser"]
248
+ :is(.bg-white, .bg-background) {
249
+ background-color: transparent;
250
+ }
251
+
252
+ :root[data-theme="island"]
253
+ [data-theme-surface="workspace-panel"]
254
+ :is(.bg-card, .bg-muted) {
255
+ background-color: hsl(var(--card) / 0.52);
256
+ }
257
+
258
+ :root[data-theme="island"]
259
+ [data-theme-surface="doc-browser"]
260
+ .bg-card {
261
+ background-color: hsl(var(--card) / 0.22);
262
+ }
263
+
264
+ :root[data-theme="island"]
265
+ [data-theme-surface="doc-browser"]
266
+ .bg-muted {
267
+ background-color: hsl(var(--card) / 0.28);
268
+ }
269
+
270
+ :root[data-theme="island"] [data-theme-surface="workspace-explorer"] {
271
+ background-color: hsl(var(--card) / 0.16);
272
+ border-color: hsl(var(--border) / 0.48);
273
+ }
274
+
275
+ :root[data-theme="island"]
276
+ [data-theme-surface="workspace-panel"]
277
+ :is(
278
+ [data-file-code-surface="true"],
279
+ [data-file-code-canvas="true"]
280
+ ),
281
+ :root[data-theme="island"]
282
+ [data-theme-surface="workspace-panel"]
283
+ [data-file-code-canvas="true"]
284
+ > .bg-card,
285
+ :root[data-theme="island"]
286
+ [data-theme-surface="workspace-panel"]
287
+ [data-file-code-row="true"].bg-card {
288
+ background-color: transparent;
289
+ }
290
+
291
+ :root[data-theme="island"]
292
+ [data-theme-surface="workspace-panel"]
293
+ [data-file-code-gutter="true"]
294
+ :is([data-file-line-number-cell="true"].bg-muted, .bg-muted) {
295
+ background-color: hsl(var(--card) / 0.12);
296
+ }
297
+
298
+ :root[data-theme="island"]
299
+ [data-theme-surface="workspace-panel"]
300
+ [data-file-target-line="true"]
301
+ [data-file-code-row="true"],
302
+ :root[data-theme="island"]
303
+ [data-theme-surface="workspace-panel"]
304
+ [data-file-line-number-cell="true"][aria-current="location"] {
305
+ background-color: hsl(var(--brand-200) / 0.28);
306
+ }
307
+
308
+ :root[data-theme="island"]
309
+ [data-theme-surface="doc-browser"]
310
+ .doc-browser-tab-scrollbar {
311
+ background-color: transparent;
312
+ }
313
+
314
+ :root[data-theme="island"]
315
+ :is(
316
+ [data-theme-overlay="popover"],
317
+ [data-theme-overlay="menu"],
318
+ [data-theme-overlay="select"],
319
+ .bg-popover,
320
+ [role="menu"].bg-popover,
321
+ [role="listbox"].bg-popover
322
+ ) {
323
+ -webkit-backdrop-filter: blur(18px) saturate(0.9);
324
+ backdrop-filter: blur(18px) saturate(0.9);
325
+ background-color: hsl(var(--popover) / 0.9);
326
+ border-color: hsl(var(--border) / 0.7);
327
+ box-shadow: 0 18px 42px -24px hsl(158 27% 20% / 0.46);
328
+ }
329
+
330
+ :root[data-theme="island"] [data-theme-overlay="tooltip"] {
331
+ -webkit-backdrop-filter: blur(14px) saturate(0.9);
332
+ backdrop-filter: blur(14px) saturate(0.9);
333
+ background-color: hsl(var(--popover) / 0.94);
334
+ border-color: hsl(var(--border) / 0.72);
335
+ box-shadow: 0 10px 24px -18px hsl(158 27% 20% / 0.42);
336
+ }
337
+
338
+ :root[data-theme="island"]
339
+ :is([data-theme-overlay="dialog"], [data-theme-overlay="sheet"]) {
340
+ -webkit-backdrop-filter: blur(24px) saturate(0.88);
341
+ backdrop-filter: blur(24px) saturate(0.88);
342
+ background-color: hsl(var(--popover) / 0.94);
343
+ border-color: hsl(var(--border) / 0.72);
344
+ box-shadow: 0 32px 80px -32px hsl(158 31% 17% / 0.58);
345
+ }
346
+
347
+ :root[data-theme="island"] [data-theme-overlay="modal-backdrop"] {
348
+ -webkit-backdrop-filter: blur(3px) saturate(0.82);
349
+ backdrop-filter: blur(3px) saturate(0.82);
350
+ background-color: hsl(158 22% 16% / 0.24);
351
+ }
352
+
353
+ :root[data-theme="island"]
354
+ [data-theme-surface="app-shell"]
355
+ :is(h1, h2, h3, button, [role="tab"], [aria-current="page"]) {
356
+ font-family: var(--island-font-display);
357
+ letter-spacing: 0.025em;
358
+ }
359
+
360
+ :root[data-theme="island"] [data-theme-surface="header"] {
361
+ background-color: transparent;
362
+ background-image: none;
363
+ backdrop-filter: none;
364
+ }
365
+
366
+ :root[data-theme="island"]
367
+ :is([data-theme-surface="navigation"], [data-theme-surface="header"])
368
+ :is(.bg-secondary, .bg-background) {
369
+ background-color: transparent;
370
+ }
371
+
372
+ :root[data-theme="island"] .nextclaw-chat-composer-surface {
373
+ background-color: hsl(var(--card) / 0.86);
374
+ border-color: hsl(var(--border) / 0.7);
375
+ backdrop-filter: blur(18px) saturate(0.88);
376
+ }
377
+
378
+ :root[data-theme="island"] [data-theme-control="chat-search"] {
379
+ background-color: transparent;
380
+ border: 1px solid transparent;
381
+ }
382
+
383
+ :root[data-theme="island"] [data-theme-control="chat-search"]:hover {
384
+ background-color: hsl(var(--background) / 0.22);
385
+ }
386
+
387
+ :root[data-theme="island"] [data-theme-control="chat-search"]:focus {
388
+ background-color: hsl(var(--background) / 0.28);
389
+ border-color: hsl(var(--brand-500) / 0.58);
390
+ }
391
+
392
+ :root[data-theme="island"] .nextclaw-chat-input-bar-surface {
393
+ background-color: transparent;
394
+ background-image: none;
395
+ }
396
+
397
+ :root[data-theme="island"] .nextclaw-chat-composer:focus {
398
+ caret-color: hsl(var(--brand-500));
399
+ text-shadow:
400
+ 0.055em 0 hsl(163 44% 35% / 0.12),
401
+ -0.035em 0 hsl(28 42% 38% / 0.1);
402
+ }
403
+
404
+ :root[data-theme="island"] .chat-markdown[data-stream-phase="0"] {
405
+ animation: island-ink-echo-a 240ms ease-out;
406
+ }
407
+
408
+ :root[data-theme="island"] .chat-markdown[data-stream-phase="1"] {
409
+ animation: island-ink-echo-b 260ms ease-out;
410
+ }
411
+
412
+ :root[data-theme="island"] .chat-markdown[data-stream-phase="2"] {
413
+ animation: island-ink-echo-c 220ms ease-out;
414
+ }
415
+
416
+ :root[data-theme="island"] .nextclaw-chat-message-user {
417
+ -webkit-backdrop-filter: blur(12px) saturate(0.88);
418
+ backdrop-filter: blur(12px) saturate(0.88);
419
+ background-color: hsl(151 28% 87% / 0.5);
420
+ border-color: hsl(153 22% 62% / 0.42);
421
+ color: hsl(var(--gray-800));
422
+ box-shadow:
423
+ inset 0 1px 0 hsl(45 70% 98% / 0.52),
424
+ 0 9px 22px -20px rgb(42 75 52 / 0.52);
425
+ }
426
+
427
+ :root[data-theme="island"] .nextclaw-chat-message-avatar-user {
428
+ -webkit-backdrop-filter: blur(10px) saturate(0.86);
429
+ backdrop-filter: blur(10px) saturate(0.86);
430
+ background-color: hsl(45 58% 94% / 0.46);
431
+ color: hsl(var(--brand-700));
432
+ box-shadow:
433
+ inset 0 0 0 1px hsl(var(--brand-500) / 0.34),
434
+ 0 5px 14px -12px rgb(42 75 52 / 0.48);
435
+ }
436
+
437
+ :root[data-theme="island"]
438
+ [data-theme-control="process-icon"].bg-card {
439
+ background-color: transparent;
440
+ color: hsl(var(--brand-700) / 0.82);
441
+ }
442
+
443
+ :root[data-theme="island"] [data-reasoning-scroll="true"] {
444
+ background-color: transparent;
445
+ border-left: 1px solid hsl(var(--brand-600) / 0.28);
446
+ border-radius: 0;
447
+ }
448
+
449
+ :root[data-theme="island"]
450
+ [data-theme-surface="navigation"]
451
+ :is([aria-current="page"], [aria-selected="true"], [data-state="active"]),
452
+ :root[data-theme="island"]
453
+ [data-theme-surface="utility-rail"]
454
+ :is([aria-pressed="true"], [data-state="active"]) {
455
+ background-color: hsl(151 27% 84% / 0.68);
456
+ color: hsl(var(--brand-800));
457
+ }
458
+
459
+ :root[data-theme="island"]
460
+ :is(
461
+ .custom-scrollbar,
462
+ .workspace-horizontal-scrollbar,
463
+ .doc-browser-tab-scrollbar
464
+ ) {
465
+ scrollbar-color: hsl(var(--brand-400) / 0.35) transparent;
466
+ }
467
+
468
+ :root[data-theme="island"] .custom-scrollbar::-webkit-scrollbar-thumb,
469
+ :root[data-theme="island"]
470
+ .workspace-horizontal-scrollbar::-webkit-scrollbar-thumb,
471
+ :root[data-theme="island"]
472
+ .doc-browser-tab-scrollbar::-webkit-scrollbar-thumb {
473
+ background: hsl(var(--brand-400) / 0.3);
474
+ }
475
+
476
+ @media (max-width: 760px) {
477
+ :root[data-theme="island"] [data-theme-surface="app-shell"] {
478
+ background-image: none;
479
+ }
480
+
481
+ :root[data-theme="island"] [data-theme-decoration="island-palm"] {
482
+ inset: 0;
483
+ }
484
+ }
485
+
486
+ @media (prefers-reduced-motion: reduce) {
487
+ :root[data-theme="island"] .chat-markdown[data-stream-phase] {
488
+ animation: none;
489
+ }
490
+
491
+ :root[data-theme="island"]
492
+ [data-theme-decoration="island-palm"]
493
+ [data-island-palm-part] {
494
+ display: none;
495
+ }
496
+ }
497
+
498
+ @media (prefers-reduced-transparency: reduce) {
499
+ :root[data-theme="island"]
500
+ :is(
501
+ .nextclaw-chat-composer-surface,
502
+ .nextclaw-chat-message-user,
503
+ .nextclaw-chat-message-avatar-user,
504
+ [data-theme-surface="workspace-panel"],
505
+ [data-theme-surface="doc-browser"]
506
+ ) {
507
+ -webkit-backdrop-filter: none;
508
+ backdrop-filter: none;
509
+ }
510
+
511
+ :root[data-theme="island"] .nextclaw-chat-message-user {
512
+ background-color: hsl(151 28% 87% / 0.9);
513
+ }
514
+
515
+ :root[data-theme="island"] .nextclaw-chat-message-avatar-user {
516
+ background-color: hsl(45 58% 94% / 0.9);
517
+ }
518
+ }
519
+ }
520
+
521
+ @keyframes island-ink-echo-a {
522
+ from {
523
+ opacity: 0.9;
524
+ text-shadow: 0.08em 0 hsl(163 45% 34% / 0.28);
525
+ }
526
+ }
527
+
528
+ @keyframes island-ink-echo-b {
529
+ from {
530
+ opacity: 0.92;
531
+ text-shadow: -0.065em 0 hsl(27 42% 38% / 0.24);
532
+ }
533
+ }
534
+
535
+ @keyframes island-ink-echo-c {
536
+ from {
537
+ opacity: 0.91;
538
+ text-shadow:
539
+ 0.05em 0 hsl(163 45% 34% / 0.2),
540
+ -0.035em 0 hsl(27 42% 38% / 0.18);
541
+ }
542
+ }
@@ -38,6 +38,7 @@ describe("ChatConversationHeader", () => {
38
38
 
39
39
  const header = screen.getByTestId("chat-conversation-header");
40
40
 
41
+ expect(header.getAttribute("data-theme-surface")).toBe("header");
41
42
  expect(header?.className).toContain("h-[52px]");
42
43
  expect(header?.className).not.toContain("border-b");
43
44
  expect(header?.className).not.toContain("transition-all");
@@ -16,7 +16,10 @@ export function ChatParentSessionBanner({
16
16
  }
17
17
  const trimmedLabel = parentSessionLabel.trim();
18
18
  return (
19
- <div className="bg-background/75 px-4 py-2 backdrop-blur-sm sm:px-5">
19
+ <div
20
+ data-theme-surface="header"
21
+ className="bg-background/75 px-4 py-2 backdrop-blur-sm sm:px-5"
22
+ >
20
23
  <button
21
24
  type="button"
22
25
  onClick={onGoToParentSession}
@@ -58,6 +61,7 @@ export function ChatConversationHeader({
58
61
  return (
59
62
  <div
60
63
  data-testid="chat-conversation-header"
64
+ data-theme-surface="header"
61
65
  className={cn(
62
66
  "bg-background/80 backdrop-blur-sm flex items-center justify-between shrink-0 overflow-hidden transition-colors duration-200",
63
67
  isMobileLayout ? "px-3 sm:px-3" : "px-4 sm:px-5",
@@ -20,7 +20,10 @@ export function ChatConversationPanel({
20
20
  );
21
21
 
22
22
  return (
23
- <section className="relative flex-1 min-h-0 flex overflow-hidden bg-background">
23
+ <section
24
+ data-theme-surface="workspace"
25
+ className="relative flex-1 min-h-0 flex overflow-hidden bg-background"
26
+ >
24
27
  <div className="flex min-h-0 flex-1 flex-col overflow-hidden">
25
28
  <ChatConversationParentBanner />
26
29
  <ChatConversationHeaderSection
@@ -40,6 +40,11 @@ describe("ChatSidebarToolbar", () => {
40
40
  expect(
41
41
  screen.getByPlaceholderText("Search conversations...").className,
42
42
  ).toContain("border-0");
43
+ expect(
44
+ screen
45
+ .getByPlaceholderText("Search conversations...")
46
+ .getAttribute("data-theme-control"),
47
+ ).toBe("chat-search");
43
48
  });
44
49
 
45
50
  it("keeps mobile search icon transparent to pointer input", () => {
@@ -49,5 +54,10 @@ describe("ChatSidebarToolbar", () => {
49
54
  expect(
50
55
  screen.getByPlaceholderText("Search conversations...").className,
51
56
  ).toContain("border-0");
57
+ expect(
58
+ screen
59
+ .getByPlaceholderText("Search conversations...")
60
+ .getAttribute("data-theme-control"),
61
+ ).toBe("chat-search");
52
62
  });
53
63
  });
@@ -53,7 +53,10 @@ export function ChatPageLayout({ view, confirmDialog }: ChatPageLayoutProps) {
53
53
  {view === "chat" ? (
54
54
  isMobile ? <ChatMobileShell /> : <ChatConversationPanel />
55
55
  ) : (
56
- <section className="flex-1 min-h-0 overflow-hidden bg-background">
56
+ <section
57
+ data-theme-surface="workspace"
58
+ className="flex-1 min-h-0 overflow-hidden bg-background"
59
+ >
57
60
  {view === "inbox" ? (
58
61
  <div className={`mx-auto flex h-full min-h-0 w-full flex-col py-4 sm:px-6 sm:py-5 ${MANAGEMENT_PAGE_CANVAS_WIDTH_CLASS}`}>
59
62
  <InboxPage />
@@ -194,6 +194,7 @@ export function ChatSidebarDesktopToolbar(props: ChatSidebarToolbarProps) {
194
194
  <div className="relative">
195
195
  <Search className="pointer-events-none absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground/60" />
196
196
  <Input
197
+ data-theme-control="chat-search"
197
198
  value={query}
198
199
  onChange={(event) => onQueryChange(event.target.value)}
199
200
  placeholder={t("chatSidebarSearchPlaceholder")}
@@ -223,6 +224,7 @@ export function ChatSidebarMobileToolbar(props: ChatSidebarToolbarProps) {
223
224
  <div className="relative min-w-0 flex-1">
224
225
  <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground/70" />
225
226
  <Input
227
+ data-theme-control="chat-search"
226
228
  value={query}
227
229
  onChange={(event) => onQueryChange(event.target.value)}
228
230
  placeholder={t("chatSidebarSearchPlaceholder")}
@@ -279,6 +279,7 @@ export function ChatSidebar({
279
279
 
280
280
  return (
281
281
  <aside
282
+ data-theme-surface="navigation"
282
283
  className={cn(
283
284
  "flex h-full min-h-0 flex-col bg-secondary transition-[width] duration-200 ease-out",
284
285
  isMobileVariant
@@ -163,6 +163,7 @@ describe("ChatSessionWorkspacePanel", () => {
163
163
 
164
164
  const panel = screen.getByTestId("chat-session-workspace-panel");
165
165
  expect(panel.className).not.toContain("absolute");
166
+ expect(panel.getAttribute("data-theme-surface")).toBe("workspace-panel");
166
167
 
167
168
  await user.click(
168
169
  screen.getByRole("button", { name: "Maximize workspace panel" }),
@@ -363,6 +363,7 @@ export function ChatSessionWorkspacePanelContent({
363
363
  ) : null}
364
364
  <div
365
365
  data-testid="workspace-shared-explorer"
366
+ data-theme-surface="workspace-explorer"
366
367
  data-mode={projectFilesActive ? 'full' : explorerOverlay ? 'overlay' : 'side'}
367
368
  className={cn(
368
369
  'relative min-h-0 shrink-0 flex-col border-r border-gray-200/80 bg-white',
@@ -187,6 +187,7 @@ export function ChatSessionWorkspacePanel({
187
187
  return (
188
188
  <ResizableRightPanel
189
189
  data-testid="chat-session-workspace-panel"
190
+ data-theme-surface="workspace-panel"
190
191
  className={cn(
191
192
  isOverlayPanel
192
193
  ? "bg-white"
@@ -100,6 +100,15 @@ describe('PwaShellThemeManager', () => {
100
100
  expect(document.documentElement.style.colorScheme).toBe('dark');
101
101
  });
102
102
 
103
+ it('applies island shell colors and light color scheme', () => {
104
+ pwaShellThemeManager.syncTheme('island');
105
+
106
+ const meta = document.querySelector('meta[name="theme-color"]');
107
+ expect(meta?.getAttribute('content')).toBe('#FBF8ED');
108
+ expect(document.body.style.backgroundColor).toBe('rgb(251, 248, 237)');
109
+ expect(document.documentElement.style.colorScheme).toBe('light');
110
+ });
111
+
103
112
  it('maps the legacy leaf theme to warm shell colors', () => {
104
113
  document.documentElement.setAttribute('data-theme', 'leaf');
105
114