react-dockable-desktop 1.0.0 → 1.2.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/dist/styles.css CHANGED
@@ -1,3 +1,11 @@
1
+ /*
2
+ * @file index.css
3
+ * @description Core stylesheet for the react-dockable-desktop layout engine.
4
+ * Contains the styling variables for design system tokens (Nord, Tokyo Night, macOS skins),
5
+ * layout splits, resizers, floating window shadows, sidebars, modal rendering,
6
+ * and specialized scaling overrides for embedded web canvases.
7
+ */
8
+
1
9
  :root {
2
10
  --bg-primary: #090b11;
3
11
  --bg-workspace: #0f111a;
@@ -8,6 +16,7 @@
8
16
  --border-color: rgba(255, 255, 255, 0.08);
9
17
  --accent-color: #38bdf8; /* Modern Cyan/Sky-blue accent */
10
18
  --accent-glow: rgba(56, 189, 248, 0.15);
19
+ --header-button-gap: 4px; /* Configurable gap spacing between titlebar action buttons */
11
20
  /* Window skins variables */
12
21
  --window-bg: rgba(20, 22, 28, var(--window-opacity, 0.85));
13
22
  --window-border: rgba(255, 255, 255, 0.08);
@@ -28,6 +37,13 @@
28
37
  --close-btn-hover-color: #ffffff;
29
38
  --close-btn-color: #858b99;
30
39
  --close-btn-active-color: #e2e8f0;
40
+ /* Tab focus states */
41
+ --tab-indicator-focused: var(--accent-color, #38bdf8);
42
+ --tab-indicator-unfocused: rgba(255, 255, 255, 0.3);
43
+ --tab-bg-active-focused: var(--bg-panel);
44
+ --tab-bg-active-unfocused: rgba(20, 23, 34, 0.55);
45
+ --tab-text-active-focused: var(--text-tab-active, #ffffff);
46
+ --tab-text-active-unfocused: rgba(255, 255, 255, 0.65);
31
47
  --resizer-bg: rgba(255, 255, 255, 0.08);
32
48
  --custom-btn-bg: rgba(255, 255, 255, 0.03);
33
49
  --custom-btn-border: rgba(255, 255, 255, 0.05);
@@ -100,6 +116,10 @@ body,
100
116
  background-color: var(--bg-panel);
101
117
  border: 1px solid var(--border-panel);
102
118
  box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.15);
119
+ width: 100%;
120
+ height: 100%;
121
+ display: flex;
122
+ flex-direction: column;
103
123
  }
104
124
 
105
125
  /* Tab Headers Bar */
@@ -107,6 +127,10 @@ body,
107
127
  background-color: var(--bg-tab-bar);
108
128
  border-bottom: 1px solid var(--border-panel);
109
129
  padding: 0 4px;
130
+ display: flex;
131
+ flex-direction: row;
132
+ justify-content: space-between;
133
+ align-items: center;
110
134
  }
111
135
 
112
136
  /* Tab Headers Container */
@@ -118,6 +142,8 @@ body,
118
142
  padding-left: 6px;
119
143
  position: relative;
120
144
  margin-bottom: -1px;
145
+ flex-grow: 1;
146
+ overflow-x: auto;
121
147
  }
122
148
 
123
149
  /* Premium Tab styling (VS Code Style) */
@@ -127,7 +153,7 @@ body,
127
153
  color: var(--text-tab-inactive) !important; /* Clear readable gray */
128
154
  border: none !important;
129
155
  border-right: 1px solid var(--border-panel) !important; /* crisp separator */
130
- padding: 0 8px 0 16px !important;
156
+ padding: 0 6px 0 14px !important;
131
157
  font-size: 0.75rem;
132
158
  transition: background-color 0.1s ease, color 0.1s ease;
133
159
  display: flex;
@@ -141,6 +167,10 @@ body,
141
167
  box-sizing: border-box;
142
168
  }
143
169
 
170
+ .workspace-tab > .text-truncate {
171
+ margin-right: 12px;
172
+ }
173
+
144
174
  /* Remove original after element separator */
145
175
  .workspace-tab:not(.active):not(:last-child)::after {
146
176
  display: none !important;
@@ -151,28 +181,47 @@ body,
151
181
  color: var(--text-tab-hover) !important;
152
182
  }
153
183
 
154
- /* Active tab */
155
- .workspace-tab.active {
156
- background-color: var(--bg-panel) !important; /* matches panel content area */
157
- color: var(--text-tab-active) !important;
184
+ /* Active tab (focused) */
185
+ .workspace-tab.active.workspace-tab-active-focused {
186
+ background-color: var(--tab-bg-active-focused) !important;
187
+ color: var(--tab-text-active-focused) !important;
158
188
  font-weight: 500;
159
189
  border-right: 1px solid var(--border-panel) !important;
160
190
  z-index: 2;
161
191
  }
162
192
 
163
- /* Top accent line on active tab (VS Code style indicator) */
164
- .workspace-tab.active::before {
193
+ .workspace-tab.active.workspace-tab-active-focused::before {
165
194
  content: '';
166
195
  position: absolute;
167
196
  top: 0;
168
197
  left: 0;
169
198
  right: 0;
170
199
  height: 2px;
171
- background-color: var(--accent-color);
200
+ background-color: var(--tab-indicator-focused) !important;
172
201
  border-radius: 0 !important;
173
202
  box-shadow: 0 1px 4px var(--accent-glow);
174
203
  }
175
204
 
205
+ /* Active tab (unfocused/inactive group) */
206
+ .workspace-tab.active.workspace-tab-active-unfocused {
207
+ background-color: var(--tab-bg-active-unfocused) !important;
208
+ color: var(--tab-text-active-unfocused) !important;
209
+ font-weight: 500;
210
+ border-right: 1px solid var(--border-panel) !important;
211
+ z-index: 2;
212
+ }
213
+
214
+ .workspace-tab.active.workspace-tab-active-unfocused::before {
215
+ content: '';
216
+ position: absolute;
217
+ top: 0;
218
+ left: 0;
219
+ right: 0;
220
+ height: 2px;
221
+ background-color: var(--tab-indicator-unfocused) !important;
222
+ border-radius: 0 !important;
223
+ }
224
+
176
225
  .workspace-tab-inactive {
177
226
  color: var(--close-btn-color) !important;
178
227
  }
@@ -214,14 +263,66 @@ body,
214
263
 
215
264
  /* Drag resizer split bars */
216
265
  .resizer-bar {
217
- background-color: var(--resizer-bg) !important;
218
- transition: background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1) !important;
266
+ background-color: var(--border-panel, rgba(255, 255, 255, 0.08)) !important;
267
+ transition: background-color 0.15s ease, transform 0.15s ease !important;
268
+ position: relative;
269
+ z-index: 21;
219
270
  }
220
271
 
272
+ /* Invisible 8px hit-box overlay to make grabbing easy */
273
+ .resizer-bar::before {
274
+ content: '';
275
+ position: absolute;
276
+ z-index: 22;
277
+ }
278
+
279
+ /* Grab hit-box for columns (cursor: col-resize) */
280
+ .resizer-bar[style*="cursor: col-resize"]::before {
281
+ top: 0;
282
+ bottom: 0;
283
+ left: -3px;
284
+ width: 8px;
285
+ height: 100%;
286
+ }
287
+
288
+ /* Grab hit-box for rows (cursor: row-resize) */
289
+ .resizer-bar[style*="cursor: row-resize"]::before {
290
+ left: 0;
291
+ right: 0;
292
+ top: -3px;
293
+ height: 8px;
294
+ width: 100%;
295
+ }
296
+
297
+ /* Highlight state (on hover or active drag) */
221
298
  .resizer-bar:hover,
222
299
  .resizer-bar.active {
223
- background-color: var(--accent-color) !important;
224
- box-shadow: 0 0 8px var(--accent-glow);
300
+ background-color: color-mix(in srgb, var(--accent-color) 35%, transparent) !important;
301
+ box-shadow: none !important;
302
+ z-index: 25 !important;
303
+ }
304
+
305
+ .resizer-bar[style*="cursor: col-resize"]:hover,
306
+ .resizer-bar[style*="cursor: col-resize"].active {
307
+ transform: scaleX(2);
308
+ }
309
+
310
+ .resizer-bar[style*="cursor: row-resize"]:hover,
311
+ .resizer-bar[style*="cursor: row-resize"].active {
312
+ transform: scaleY(2);
313
+ }
314
+
315
+ /* Global body cursor overrides during active resize drag to prevent cursor flickering */
316
+ body.resizing-active {
317
+ user-select: none !important;
318
+ }
319
+ body.resizing-row-active,
320
+ body.resizing-row-active * {
321
+ cursor: row-resize !important;
322
+ }
323
+ body.resizing-col-active,
324
+ body.resizing-col-active * {
325
+ cursor: col-resize !important;
225
326
  }
226
327
 
227
328
  /* Control buttons inside tabs/windows */
@@ -255,10 +356,25 @@ body,
255
356
  border-top: 1px solid var(--taskbar-border) !important;
256
357
  backdrop-filter: blur(12px) saturate(180%);
257
358
  -webkit-backdrop-filter: blur(12px) saturate(180%);
359
+ flex-shrink: 0;
360
+ width: 100%;
361
+ display: flex;
362
+ flex-direction: row;
363
+ align-items: center;
364
+ justify-content: center;
365
+ padding: 0 1rem;
258
366
  }
259
367
 
260
368
  .taskbar-nav-btn {
261
369
  color: var(--taskbar-nav-color) !important;
370
+ background: transparent;
371
+ border: none;
372
+ cursor: pointer;
373
+ font-family: monospace;
374
+ padding: 0;
375
+ text-decoration: none;
376
+ font-size: 0.875rem;
377
+ line-height: 1;
262
378
  }
263
379
 
264
380
  .taskbar-nav-btn:hover {
@@ -274,6 +390,11 @@ body,
274
390
  color: var(--taskbar-item-text) !important;
275
391
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
276
392
  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important;
393
+ display: flex;
394
+ align-items: center;
395
+ justify-content: center;
396
+ border-radius: 4px;
397
+ cursor: pointer;
277
398
  }
278
399
 
279
400
  .taskbar-glassmorphic-item:hover {
@@ -324,6 +445,7 @@ body,
324
445
  animation: tooltipFadeIn 0.15s cubic-bezier(0.4, 0, 0.2, 1) forwards;
325
446
  display: flex;
326
447
  flex-direction: column;
448
+ gap: 0.25rem;
327
449
  }
328
450
 
329
451
  /* Invisible bridge so mouse transitions smoothly to tooltip */
@@ -426,7 +548,6 @@ body,
426
548
  border-color: rgba(56, 189, 248, 0.25) !important;
427
549
  }
428
550
 
429
- /* Floating Windows customization styling */
430
551
  .floating-window {
431
552
  display: flex;
432
553
  flex-direction: column;
@@ -437,16 +558,20 @@ body,
437
558
  -webkit-backdrop-filter: blur(16px) saturate(180%);
438
559
  background-color: var(--window-bg);
439
560
  overflow: hidden;
440
- opacity: 0.88;
441
- transition: opacity 0.2s, box-shadow 0.2s, border-color 0.2s;
561
+ transition: box-shadow 0.2s, border-color 0.2s;
442
562
  }
443
563
 
444
564
  .floating-window.v2-window-focused {
445
- opacity: 1;
446
565
  box-shadow: var(--window-shadow-focused), inset 0 1px 0 rgba(255, 255, 255, 0.08);
447
566
  border-color: var(--window-border-focused);
448
567
  }
449
568
 
569
+ /* Dim only titlebar when window is unfocused to keep panel content opaque */
570
+ .floating-window:not(.v2-window-focused) .floating-window-titlebar {
571
+ opacity: 0.65;
572
+ transition: opacity 0.2s ease;
573
+ }
574
+
450
575
  .floating-window.maximized {
451
576
  border-radius: 0;
452
577
  border: none;
@@ -479,6 +604,10 @@ body,
479
604
  background-color: var(--window-header-bg);
480
605
  border-bottom: 1px solid var(--window-border);
481
606
  min-height: 38px;
607
+ display: flex;
608
+ flex-direction: row;
609
+ justify-content: space-between;
610
+ align-items: center;
482
611
  }
483
612
 
484
613
  .floating-window-title {
@@ -487,6 +616,12 @@ body,
487
616
  font-weight: 600;
488
617
  color: var(--window-text);
489
618
  letter-spacing: 0.02em;
619
+ display: flex;
620
+ align-items: center;
621
+ overflow: hidden;
622
+ text-overflow: ellipsis;
623
+ white-space: nowrap;
624
+ margin-inline-end: 0.5rem;
490
625
  }
491
626
 
492
627
  .cursor-move {
@@ -633,6 +768,10 @@ body,
633
768
  .header-close-empty-group {
634
769
  opacity: 0 !important;
635
770
  transition: opacity 0.12s ease, background-color 0.12s ease, color 0.12s ease !important;
771
+ display: flex;
772
+ align-items: center;
773
+ justify-content: center;
774
+ margin-inline-end: 0.5rem;
636
775
  }
637
776
 
638
777
  .workspace-panel:hover .header-close-empty-group {
@@ -720,6 +859,12 @@ body,
720
859
  --close-btn-hover-color: #212529;
721
860
  --close-btn-color: #6c757d;
722
861
  --close-btn-active-color: #212529;
862
+ --tab-indicator-focused: #0066cc;
863
+ --tab-indicator-unfocused: rgba(0, 0, 0, 0.25);
864
+ --tab-bg-active-focused: var(--bg-panel);
865
+ --tab-bg-active-unfocused: rgba(220, 224, 230, 0.65);
866
+ --tab-text-active-focused: #212529;
867
+ --tab-text-active-unfocused: #6c757d;
723
868
  --resizer-bg: rgba(0, 0, 0, 0.08);
724
869
  --custom-btn-bg: rgba(0, 0, 0, 0.03);
725
870
  --custom-btn-border: rgba(0, 0, 0, 0.08);
@@ -845,21 +990,36 @@ body,
845
990
  }
846
991
  [data-workspace-skin="macos"] .floating-window-titlebar {
847
992
  flex-direction: row-reverse !important;
993
+ position: relative !important;
994
+ }
995
+ [data-workspace-skin="macos"] .floating-window-titlebar .floating-window-title {
996
+ position: absolute !important;
997
+ left: 0 !important;
998
+ right: 0 !important;
999
+ text-align: center !important;
1000
+ pointer-events: none !important;
1001
+ margin: 0 !important;
1002
+ justify-content: center !important;
1003
+ }
1004
+ [data-workspace-skin="macos"] .floating-window-titlebar .floating-window-title > * {
1005
+ pointer-events: auto;
848
1006
  }
849
- [data-workspace-skin="macos"] .floating-window-titlebar .d-flex.align-items-center {
1007
+ [data-workspace-skin="macos"] .floating-window-titlebar .fw-titlebar-actions {
850
1008
  flex-direction: row-reverse !important;
1009
+ position: relative !important;
1010
+ z-index: 1 !important;
851
1011
  }
852
1012
  [data-workspace-skin="macos"] .custom-tab-btn:not(.btn-anchor-tab) svg {
853
1013
  display: none !important;
854
1014
  }
855
1015
  [data-workspace-skin="macos"] .btn-close-tab {
856
- background-color: #ff5f56 !important;
1016
+ background-color: #ff5f56 !important; /* Red (Close) */
857
1017
  }
858
- [data-workspace-skin="macos"] .custom-tab-btn:nth-child(2) {
859
- background-color: #ffbd2e !important;
1018
+ [data-workspace-skin="macos"] .btn-minimize-tab {
1019
+ background-color: #ffbd2e !important; /* Yellow (Minimize) */
860
1020
  }
861
- [data-workspace-skin="macos"] .custom-tab-btn:nth-child(3) {
862
- background-color: #27c93f !important;
1021
+ [data-workspace-skin="macos"] .btn-maximize-tab {
1022
+ background-color: #27c93f !important; /* Green (Maximize) */
863
1023
  }
864
1024
  [data-workspace-skin="macos"] .btn-anchor-tab {
865
1025
  /* Default: Neutral Graphite/Slate dot when inactive */
@@ -1377,102 +1537,7 @@ html:not(.enable-animations) *::after {
1377
1537
  animation: none !important;
1378
1538
  }
1379
1539
 
1380
- /* Dirty Close Interception Warning Modal */
1381
- .close-warning-overlay {
1382
- position: absolute;
1383
- inset: 0;
1384
- background-color: rgba(9, 11, 17, 0.7);
1385
- backdrop-filter: blur(8px);
1386
- display: flex;
1387
- align-items: center;
1388
- justify-content: center;
1389
- z-index: 200000;
1390
- animation: fadeIn 0.2s ease-out;
1391
- }
1392
-
1393
- .close-warning-modal {
1394
- background: rgba(20, 23, 34, 0.95);
1395
- border: 1px solid rgba(255, 255, 255, 0.08);
1396
- box-shadow: 0 24px 48px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.05);
1397
- border-radius: 12px;
1398
- width: 420px;
1399
- max-width: 90%;
1400
- padding: 24px;
1401
- display: flex;
1402
- flex-direction: column;
1403
- gap: 20px;
1404
- font-family: 'Outfit', 'Inter', sans-serif;
1405
- color: var(--text-primary);
1406
- animation: scaleUp 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
1407
- }
1408
-
1409
- .close-warning-header {
1410
- display: flex;
1411
- align-items: center;
1412
- gap: 12px;
1413
- }
1414
1540
 
1415
- .close-warning-icon {
1416
- width: 40px;
1417
- height: 40px;
1418
- border-radius: 50%;
1419
- background-color: rgba(239, 68, 68, 0.1);
1420
- color: #ef4444;
1421
- display: flex;
1422
- align-items: center;
1423
- justify-content: center;
1424
- font-size: 1.25rem;
1425
- }
1426
-
1427
- .close-warning-title {
1428
- font-size: 1.1rem;
1429
- font-weight: 600;
1430
- margin: 0;
1431
- }
1432
-
1433
- .close-warning-message {
1434
- font-size: 0.88rem;
1435
- color: var(--text-secondary);
1436
- line-height: 1.5;
1437
- margin: 0;
1438
- }
1439
-
1440
- .close-warning-footer {
1441
- display: flex;
1442
- justify-content: flex-end;
1443
- gap: 12px;
1444
- }
1445
-
1446
- .btn-warning-action {
1447
- font-size: 0.82rem;
1448
- font-weight: 500;
1449
- padding: 8px 16px;
1450
- border-radius: 6px;
1451
- cursor: pointer;
1452
- transition: all 0.15s ease;
1453
- border: none;
1454
- font-family: inherit;
1455
- }
1456
-
1457
- .btn-warning-cancel {
1458
- background-color: rgba(255, 255, 255, 0.05);
1459
- color: var(--text-primary);
1460
- border: 1px solid rgba(255, 255, 255, 0.08);
1461
- }
1462
-
1463
- .btn-warning-cancel:hover {
1464
- background-color: rgba(255, 255, 255, 0.1);
1465
- }
1466
-
1467
- .btn-warning-discard {
1468
- background-color: #ef4444;
1469
- color: #ffffff;
1470
- }
1471
-
1472
- .btn-warning-discard:hover {
1473
- background-color: #dc2626;
1474
- box-shadow: 0 0 12px rgba(239, 68, 68, 0.3);
1475
- }
1476
1541
 
1477
1542
  @keyframes fadeIn {
1478
1543
  from { opacity: 0; }
@@ -1512,6 +1577,7 @@ html:not(.enable-animations) *::after {
1512
1577
  flex-direction: column;
1513
1578
  color: var(--text-primary);
1514
1579
  max-width: 90%;
1580
+ max-height: 90vh;
1515
1581
  animation: scaleUp 0.18s cubic-bezier(0.34, 1.56, 0.64, 1);
1516
1582
  overflow: hidden;
1517
1583
  }
@@ -1558,21 +1624,19 @@ html:not(.enable-animations) *::after {
1558
1624
 
1559
1625
  .v2-modal-body {
1560
1626
  padding: 10px;
1561
- overflow: auto;
1627
+ overflow-y: auto;
1628
+ max-height: calc(90vh - 70px);
1562
1629
  }
1563
1630
 
1564
1631
  /* Modal Sizes */
1565
1632
  .v2-modal-size-small {
1566
- width: 360px;
1567
- max-height: 270px; /* 4:3 aspect ratio */
1633
+ width: 420px;
1568
1634
  }
1569
1635
  .v2-modal-size-medium {
1570
1636
  width: 560px;
1571
- max-height: 420px; /* ~4:3 aspect ratio */
1572
1637
  }
1573
1638
  .v2-modal-size-large {
1574
1639
  width: 800px;
1575
- max-height: 500px; /* ~16:10 aspect ratio */
1576
1640
  }
1577
1641
  .v2-modal-size-fullscreen {
1578
1642
  width: 98vw;
@@ -1581,7 +1645,6 @@ html:not(.enable-animations) *::after {
1581
1645
  .v2-modal-size-auto {
1582
1646
  width: auto;
1583
1647
  min-width: 300px;
1584
- max-height: 80vh; /* Safe aspect ratio threshold for auto content */
1585
1648
  }
1586
1649
 
1587
1650
  /* Side Drawer Panels */
@@ -1762,5 +1825,402 @@ html:not(.enable-animations) *::after {
1762
1825
  height: 30%;
1763
1826
  }
1764
1827
 
1828
+ /*
1829
+ * Counteract scale for canvas and its siblings inside Luciad containers.
1830
+ *
1831
+ * When rendering a panel's mini hover-preview in the taskbar, the parent container
1832
+ * is scaled down using CSS transform scale(var(--preview-scale)). For standard HTML UI,
1833
+ * this works natively. However, for web maps (like WebGL / canvas-based engines such as
1834
+ * LuciadRIA), scaling down the browser container causes the rendering canvas and its absolute
1835
+ * siblings (e.g. HTML overlays, labels, shapes) to blur or offset.
1836
+ *
1837
+ * To counteract this, we apply a reverse scale transform (1 / scale) and multiply the size
1838
+ * of the canvas and its siblings by the scale factor. This forces the map engine to render
1839
+ * at full resolution inside the preview container without positioning glitches.
1840
+ */
1841
+ .taskbar-item-preview-host .luciad canvas,
1842
+ .taskbar-item-preview-host .luciad canvas ~ * {
1843
+ transform: scale(calc(1 / var(--preview-scale, 1))) !important;
1844
+ transform-origin: top left;
1845
+ width: calc(100% * var(--preview-scale, 1)) !important;
1846
+ height: calc(100% * var(--preview-scale, 1)) !important;
1847
+ }
1848
+
1849
+ /* ==========================================
1850
+ RTL (Right-to-Left) Support
1851
+ ========================================== */
1852
+
1853
+ [dir="rtl"] .workspace-tab-bar {
1854
+ flex-direction: row-reverse !important;
1855
+ }
1856
+
1857
+ [dir="rtl"] .tab-headers-container {
1858
+ flex-direction: row-reverse !important;
1859
+ }
1860
+
1861
+ [dir="rtl"] .workspace-tab {
1862
+ border-right: none !important;
1863
+ border-left: 1px solid var(--border-panel) !important;
1864
+ padding: 0 14px 0 6px !important;
1865
+ }
1765
1866
 
1867
+ [dir="rtl"] .workspace-tab > .text-truncate {
1868
+ margin-right: 0 !important;
1869
+ margin-left: 12px !important;
1870
+ }
1871
+
1872
+ [dir="rtl"] .workspace-tab-icon {
1873
+ margin-right: 0 !important;
1874
+ margin-left: 6px !important;
1875
+ }
1876
+
1877
+ [dir="rtl"] .tab-header-actions {
1878
+ margin-left: 0 !important;
1879
+ margin-right: auto !important;
1880
+ }
1881
+
1882
+ [dir="rtl"] .close-tab-x {
1883
+ margin-left: 0 !important;
1884
+ margin-right: auto !important;
1885
+ }
1886
+
1887
+ /* Floating window title bar adjustments */
1888
+ [dir="rtl"] [data-workspace-skin="vscode"] .floating-window-titlebar,
1889
+ [dir="rtl"] [data-workspace-skin="chrome"] .floating-window-titlebar,
1890
+ [dir="rtl"] [data-workspace-skin="slate"] .floating-window-titlebar {
1891
+ flex-direction: row-reverse !important;
1892
+ }
1893
+
1894
+ [dir="rtl"] [data-workspace-skin="vscode"] .floating-window-titlebar .fw-titlebar-actions,
1895
+ [dir="rtl"] [data-workspace-skin="chrome"] .floating-window-titlebar .fw-titlebar-actions,
1896
+ [dir="rtl"] [data-workspace-skin="slate"] .floating-window-titlebar .fw-titlebar-actions {
1897
+ flex-direction: row-reverse !important;
1898
+ }
1766
1899
 
1900
+ [dir="rtl"] .floating-window-title {
1901
+ margin-right: 0 !important;
1902
+ margin-left: auto !important;
1903
+ }
1904
+
1905
+ /* Side Panels transitions slide-in direction */
1906
+ [dir="rtl"] .v2-side-panel-left {
1907
+ left: auto !important;
1908
+ right: 0 !important;
1909
+ transform: translateX(100%) !important;
1910
+ }
1911
+ [dir="rtl"] .v2-side-panel-left.v2-side-panel-visible {
1912
+ transform: translateX(0) !important;
1913
+ border-right: none !important;
1914
+ border-left: 1px solid var(--border-panel, #3c3c3c) !important;
1915
+ }
1916
+
1917
+ [dir="rtl"] .v2-side-panel-right {
1918
+ right: auto !important;
1919
+ left: 0 !important;
1920
+ transform: translateX(-100%) !important;
1921
+ }
1922
+ [dir="rtl"] .v2-side-panel-right.v2-side-panel-visible {
1923
+ transform: translateX(0) !important;
1924
+ border-left: none !important;
1925
+ border-right: 1px solid var(--border-panel, #3c3c3c) !important;
1926
+ }
1927
+
1928
+ /* Minimize Taskbar adjustments */
1929
+ [dir="rtl"] .taskbar-footer-container {
1930
+ flex-direction: row-reverse !important;
1931
+ }
1932
+ [dir="rtl"] .taskbar-item-icon {
1933
+ margin-right: 0 !important;
1934
+ margin-left: 4px !important;
1935
+ }
1936
+
1937
+ /* macOS Skin - RTL floating window titlebar overrides
1938
+ Dots must stay on the LEFT in both LTR and RTL (real macOS behavior).
1939
+ Title is absolutely centered, so no direction-specific adjustment needed.
1940
+ In RTL, row-reverse naturally places the button group on the left. */
1941
+ [dir="rtl"][data-workspace-skin="macos"] .floating-window-titlebar {
1942
+ flex-direction: row-reverse !important;
1943
+ }
1944
+
1945
+ /* Button group: keep dots in correct visual order (Red → Yellow → Green)
1946
+ from left to right regardless of text direction */
1947
+ [dir="rtl"][data-workspace-skin="macos"] .floating-window-titlebar .fw-titlebar-actions {
1948
+ flex-direction: row !important;
1949
+ }
1950
+
1951
+ /* Mirror close-button margins for macOS tabs under RTL */
1952
+ [dir="rtl"][data-workspace-skin="macos"] .close-tab-x {
1953
+ margin-left: 0 !important;
1954
+ margin-right: 2px !important;
1955
+ }
1956
+
1957
+ /* ==========================================================================
1958
+ FRAMEWORK-AGNOSTIC UTILITY CLASSES
1959
+ (replaces Bootstrap utility class dependencies)
1960
+ ========================================================================== */
1961
+
1962
+ /* Text truncation (equivalent to Bootstrap .text-truncate) */
1963
+ .text-truncate {
1964
+ overflow: hidden;
1965
+ text-overflow: ellipsis;
1966
+ white-space: nowrap;
1967
+ }
1968
+
1969
+ /* Floating window titlebar button group */
1970
+ .fw-titlebar-actions {
1971
+ display: flex;
1972
+ align-items: center;
1973
+ }
1974
+
1975
+ /* Window custom header actions slot */
1976
+ .window-header-actions {
1977
+ display: flex;
1978
+ align-items: center;
1979
+ margin-inline-end: 0.25rem;
1980
+ gap: var(--header-button-gap, 4px);
1981
+ }
1982
+
1983
+ /* Tab header custom actions slot */
1984
+ .tab-header-actions {
1985
+ margin-inline-start: auto;
1986
+ display: flex;
1987
+ align-items: center;
1988
+ margin-inline-end: 0.25rem;
1989
+ gap: var(--header-button-gap, 4px);
1990
+ }
1991
+
1992
+ /* Panel body (tab content area / floating window content area) */
1993
+ .dw-panel-body {
1994
+ flex-grow: 1;
1995
+ width: 100%;
1996
+ height: 100%;
1997
+ }
1998
+
1999
+ /* Empty workspace section placeholder text */
2000
+ .empty-leaf-placeholder {
2001
+ width: 100%;
2002
+ height: 100%;
2003
+ display: flex;
2004
+ align-items: center;
2005
+ justify-content: center;
2006
+ font-family: monospace;
2007
+ font-size: 0.875rem;
2008
+ color: var(--text-secondary, #94a3b8);
2009
+ }
2010
+
2011
+ /* Empty workspace grid (no panels loaded) */
2012
+ .empty-workspace-grid {
2013
+ width: 100%;
2014
+ height: 100%;
2015
+ display: flex;
2016
+ align-items: center;
2017
+ justify-content: center;
2018
+ color: var(--text-secondary, #94a3b8);
2019
+ font-family: monospace;
2020
+ font-size: 0.875rem;
2021
+ }
2022
+
2023
+ /* Unregistered component error panel */
2024
+ .dw-unregistered-panel {
2025
+ width: 100%;
2026
+ height: 100%;
2027
+ display: flex;
2028
+ flex-direction: column;
2029
+ align-items: center;
2030
+ justify-content: center;
2031
+ background: transparent;
2032
+ color: #dc3545;
2033
+ font-family: monospace;
2034
+ padding: 1rem;
2035
+ text-align: center;
2036
+ box-sizing: border-box;
2037
+ }
2038
+
2039
+ /* Taskbar scrollable items row */
2040
+ .taskbar-items-container {
2041
+ display: flex;
2042
+ flex-direction: row;
2043
+ gap: 0.5rem;
2044
+ overflow-x: auto;
2045
+ align-items: center;
2046
+ margin: 0 0.5rem;
2047
+ padding: 2px 4px;
2048
+ scrollbar-width: none;
2049
+ scroll-snap-type: x mandatory;
2050
+ max-width: 800px;
2051
+ }
2052
+
2053
+ .taskbar-items-container::-webkit-scrollbar {
2054
+ display: none;
2055
+ }
2056
+
2057
+ /* Tooltip header row (title + close button) */
2058
+ .tooltip-header-row {
2059
+ display: flex;
2060
+ flex-direction: row;
2061
+ align-items: center;
2062
+ justify-content: space-between;
2063
+ width: 100%;
2064
+ gap: 0.75rem;
2065
+ padding: 0 0.25rem;
2066
+ }
2067
+
2068
+ /* Drag ghost tab preview (floating label while dragging) */
2069
+ .drag-ghost-tab {
2070
+ position: fixed;
2071
+ background: rgba(0, 0, 0, 0.8);
2072
+ border: 1px solid var(--accent-color, #38bdf8);
2073
+ border-left: 3px solid var(--accent-color, #38bdf8);
2074
+ border-radius: 4px;
2075
+ color: var(--accent-color, #38bdf8);
2076
+ font-family: monospace;
2077
+ padding: 0.375rem 1rem;
2078
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
2079
+ display: flex;
2080
+ align-items: center;
2081
+ gap: 0.5rem;
2082
+ font-size: 0.75rem;
2083
+ white-space: nowrap;
2084
+ pointer-events: none;
2085
+ }
2086
+
2087
+ /* ConfirmationForm component styles */
2088
+ .confirmation-form-body {
2089
+ padding: 0.75rem;
2090
+ display: flex;
2091
+ flex-direction: column;
2092
+ gap: 0.75rem;
2093
+ }
2094
+
2095
+ .confirmation-alert {
2096
+ display: flex;
2097
+ align-items: center;
2098
+ gap: 0.5rem;
2099
+ margin: 0;
2100
+ padding: 0.625rem;
2101
+ font-size: 0.875rem;
2102
+ border-radius: 0.375rem;
2103
+ }
2104
+
2105
+ .confirmation-alert-danger {
2106
+ background: rgba(220, 53, 69, 0.15);
2107
+ border: 1px solid rgba(220, 53, 69, 0.3);
2108
+ color: #f87171;
2109
+ }
2110
+
2111
+ .confirmation-alert-info {
2112
+ background: rgba(13, 202, 240, 0.15);
2113
+ border: 1px solid rgba(13, 202, 240, 0.3);
2114
+ color: #67e8f9;
2115
+ }
2116
+
2117
+ .confirmation-alert-warning {
2118
+ background: rgba(255, 193, 7, 0.15);
2119
+ border: 1px solid rgba(255, 193, 7, 0.3);
2120
+ color: #fbbf24;
2121
+ }
2122
+
2123
+ .confirmation-alert-success {
2124
+ background: rgba(25, 135, 84, 0.15);
2125
+ border: 1px solid rgba(25, 135, 84, 0.3);
2126
+ color: #4ade80;
2127
+ }
2128
+
2129
+ .confirmation-actions {
2130
+ display: flex;
2131
+ justify-content: flex-end;
2132
+ gap: 0.5rem;
2133
+ }
2134
+
2135
+ /* Sidebar drawer header */
2136
+ .sidebar-drawer-header {
2137
+ display: flex;
2138
+ align-items: center;
2139
+ justify-content: space-between;
2140
+ border-bottom: 1px solid var(--sidebar-border, rgba(255, 255, 255, 0.08));
2141
+ padding: 0 0.75rem;
2142
+ flex-shrink: 0;
2143
+ background: rgba(0, 0, 0, 0.08);
2144
+ min-height: 38px;
2145
+ }
2146
+
2147
+ /* Sidebar drawer close button */
2148
+ .sidebar-close-btn {
2149
+ background: transparent;
2150
+ border: none;
2151
+ padding: 0;
2152
+ color: var(--text-secondary, #94a3b8);
2153
+ display: flex;
2154
+ align-items: center;
2155
+ cursor: pointer;
2156
+ border-radius: 4px;
2157
+ transition: color 0.15s ease;
2158
+ text-decoration: none;
2159
+ }
2160
+
2161
+ .sidebar-close-btn:hover {
2162
+ color: var(--text-primary, #f1f5f9);
2163
+ }
2164
+
2165
+ /* Sidebar drawer content body */
2166
+ .sidebar-drawer-body {
2167
+ flex-grow: 1;
2168
+ overflow: auto;
2169
+ }
2170
+
2171
+ /* Button base — used in ConfirmationForm and similar dialogs */
2172
+ .dw-btn {
2173
+ display: inline-flex;
2174
+ align-items: center;
2175
+ justify-content: center;
2176
+ font-family: monospace;
2177
+ font-weight: 500;
2178
+ cursor: pointer;
2179
+ border-radius: 4px;
2180
+ transition: all 0.15s ease;
2181
+ white-space: nowrap;
2182
+ user-select: none;
2183
+ line-height: 1.2;
2184
+ }
2185
+
2186
+ .dw-btn-sm {
2187
+ padding: 0.25rem 0.75rem;
2188
+ font-size: 0.8125rem;
2189
+ }
2190
+
2191
+ .dw-btn-outline {
2192
+ background: transparent;
2193
+ border: 1px solid var(--text-secondary, #6c757d);
2194
+ color: var(--text-secondary, #6c757d);
2195
+ }
2196
+
2197
+ .dw-btn-outline:hover {
2198
+ background: rgba(255, 255, 255, 0.08);
2199
+ border-color: var(--text-primary, #f1f5f9);
2200
+ color: var(--text-primary, #f1f5f9);
2201
+ }
2202
+
2203
+ [data-bs-theme="light"] .dw-btn-outline {
2204
+ border-color: #6c757d;
2205
+ color: #6c757d;
2206
+ }
2207
+
2208
+ [data-bs-theme="light"] .dw-btn-outline:hover {
2209
+ background: rgba(0, 0, 0, 0.05);
2210
+ border-color: #495057;
2211
+ color: #495057;
2212
+ }
2213
+
2214
+ .dw-btn-primary {
2215
+ background: var(--accent-color, #38bdf8);
2216
+ border: 1px solid var(--accent-color, #38bdf8);
2217
+ color: #090b11;
2218
+ }
2219
+
2220
+ .dw-btn-primary:hover {
2221
+ filter: brightness(1.1);
2222
+ }
2223
+
2224
+ [data-bs-theme="light"] .dw-btn-primary {
2225
+ color: #ffffff;
2226
+ }