@tutti-os/workbench-surface 0.0.40 → 0.0.42

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.
@@ -195,10 +195,10 @@
195
195
  .workbench-window__header {
196
196
  display: flex;
197
197
  align-items: center;
198
- justify-content: space-between;
198
+ justify-content: flex-start;
199
199
  gap: 12px;
200
200
  height: var(--workbench-header-height);
201
- padding: 0 8px 0 12px;
201
+ padding: 0 12px 0 16px;
202
202
  border-bottom: 1px solid var(--border-1);
203
203
  background: var(--background-panel);
204
204
  cursor: grab;
@@ -221,6 +221,84 @@
221
221
  cursor: default;
222
222
  }
223
223
 
224
+ .workbench-window__title {
225
+ min-width: 0;
226
+ overflow: hidden;
227
+ color: var(--text-primary);
228
+ font-size: 15px;
229
+ font-weight: 600;
230
+ line-height: 20px;
231
+ text-overflow: ellipsis;
232
+ white-space: nowrap;
233
+ }
234
+
235
+ .workbench-window__traffic-light-actions,
236
+ .workbench-window-traffic-lights {
237
+ display: inline-flex;
238
+ flex: 0 0 auto;
239
+ align-items: center;
240
+ gap: 8px;
241
+ }
242
+
243
+ .workbench-window__traffic-light-actions {
244
+ cursor: default;
245
+ }
246
+
247
+ .workbench-window-traffic-lights {
248
+ pointer-events: auto;
249
+ }
250
+
251
+ .workbench-window-traffic-light {
252
+ position: relative;
253
+ display: inline-flex;
254
+ width: 20px;
255
+ height: 20px;
256
+ flex: 0 0 auto;
257
+ margin: -4px;
258
+ padding: 0;
259
+ border: 0;
260
+ border-radius: 999px;
261
+ background: transparent;
262
+ cursor: pointer;
263
+ opacity: 0.78;
264
+ transition: opacity 160ms ease;
265
+ }
266
+
267
+ .workbench-window-traffic-light::before {
268
+ position: absolute;
269
+ inset: 4px;
270
+ border-radius: inherit;
271
+ background-color: color-mix(in srgb, var(--text-tertiary) 72%, transparent);
272
+ content: "";
273
+ transition: background-color 160ms ease;
274
+ }
275
+
276
+ .workbench-window-traffic-light:hover,
277
+ .workbench-window-traffic-light:focus-visible {
278
+ opacity: 1;
279
+ outline: none;
280
+ }
281
+
282
+ .workbench-window-traffic-light[data-workbench-traffic-light="close"]:hover::before,
283
+ .workbench-window-traffic-light[data-workbench-traffic-light="close"]:focus-visible::before {
284
+ background-color: #ff5f57;
285
+ }
286
+
287
+ .workbench-window-traffic-light[data-workbench-traffic-light="minimize"]:hover::before,
288
+ .workbench-window-traffic-light[data-workbench-traffic-light="minimize"]:focus-visible::before {
289
+ background-color: #ffbd2e;
290
+ }
291
+
292
+ .workbench-window-traffic-light[data-workbench-traffic-light="maximize"]:hover::before,
293
+ .workbench-window-traffic-light[data-workbench-traffic-light="maximize"]:focus-visible::before {
294
+ background-color: #28c840;
295
+ }
296
+
297
+ .workbench-window-traffic-light:disabled {
298
+ cursor: default;
299
+ opacity: 0.38;
300
+ }
301
+
224
302
  [data-workbench-drag-handle="true"] {
225
303
  cursor: grab;
226
304
  user-select: none;
@@ -278,31 +356,33 @@
278
356
  .workbench-window__resize-handle[data-handle="north-west"],
279
357
  .workbench-window__resize-handle[data-handle="south-east"],
280
358
  .workbench-window__resize-handle[data-handle="south-west"] {
281
- width: 24px;
282
- height: 24px;
359
+ width: 16px;
360
+ height: 16px;
283
361
  }
284
362
 
285
363
  .workbench-window__resize-handle[data-handle="north-east"] {
286
364
  top: -8px;
287
365
  right: -8px;
366
+ width: 24px;
367
+ height: 24px;
288
368
  cursor: nesw-resize;
289
369
  }
290
370
 
291
371
  .workbench-window__resize-handle[data-handle="north-west"] {
292
- top: -8px;
293
- left: -8px;
372
+ top: -12px;
373
+ left: -12px;
294
374
  cursor: nwse-resize;
295
375
  }
296
376
 
297
377
  .workbench-window__resize-handle[data-handle="south-east"] {
298
- right: -8px;
299
- bottom: -8px;
378
+ right: -12px;
379
+ bottom: -12px;
300
380
  cursor: nwse-resize;
301
381
  }
302
382
 
303
383
  .workbench-window__resize-handle[data-handle="south-west"] {
304
- bottom: -8px;
305
- left: -8px;
384
+ bottom: -12px;
385
+ left: -12px;
306
386
  cursor: nesw-resize;
307
387
  }
308
388
 
@@ -12,6 +12,35 @@ test("floating window bodies do not reserve a right-side content margin", () =>
12
12
  );
13
13
  });
14
14
 
15
+ test("traffic lights keep visual layout while expanding the pointer hit area", () => {
16
+ const css = readFileSync(resolve("src/styles/workbench.css"), "utf8");
17
+
18
+ assert.match(
19
+ css,
20
+ /\.workbench-window-traffic-light\s*{[^}]*width:\s*20px;[^}]*height:\s*20px;[^}]*margin:\s*-4px;[^}]*cursor:\s*pointer;[^}]*transition:\s*opacity 160ms ease;/s
21
+ );
22
+ assert.match(
23
+ css,
24
+ /\.workbench-window-traffic-light::before\s*{[^}]*inset:\s*4px;[^}]*content:\s*"";[^}]*transition:\s*background-color 160ms ease;/s
25
+ );
26
+ });
27
+
28
+ test("floating window corner resize handles do not intrude further than the edge handles", () => {
29
+ const css = readFileSync(resolve("src/styles/workbench.css"), "utf8");
30
+
31
+ // Resize handles render outside `.workbench-window`, which keeps most of
32
+ // the corner hot zone outside the clipped window while still leaving a small
33
+ // diagonal resize target over the visible border.
34
+ assert.match(
35
+ css,
36
+ /\.workbench-window__resize-handle\[data-handle="north-east"\],\s*\.workbench-window__resize-handle\[data-handle="north-west"\],\s*\.workbench-window__resize-handle\[data-handle="south-east"\],\s*\.workbench-window__resize-handle\[data-handle="south-west"\]\s*{[^}]*width:\s*16px;[^}]*height:\s*16px;/s
37
+ );
38
+ assert.match(
39
+ css,
40
+ /\.workbench-window__resize-handle\[data-handle="south-west"\]\s*{[^}]*bottom:\s*-12px;[^}]*left:\s*-12px;/s
41
+ );
42
+ });
43
+
15
44
  test("mission control hidden presentation windows are invisible and inert", () => {
16
45
  const css = readFileSync(resolve("src/styles/workbench.css"), "utf8");
17
46
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tutti-os/workbench-surface",
3
- "version": "0.0.40",
3
+ "version": "0.0.42",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
@@ -34,10 +34,10 @@
34
34
  "@tutti-os/config-tsconfig": "0.0.0"
35
35
  },
36
36
  "dependencies": {
37
- "@tutti-os/ui-i18n-runtime": "0.0.40",
38
- "@tutti-os/ui-react-hooks": "0.0.40",
39
- "@tutti-os/workbench-snapshot": "0.0.40",
40
- "@tutti-os/ui-system": "0.0.40"
37
+ "@tutti-os/ui-i18n-runtime": "0.0.42",
38
+ "@tutti-os/ui-react-hooks": "0.0.42",
39
+ "@tutti-os/workbench-snapshot": "0.0.42",
40
+ "@tutti-os/ui-system": "0.0.42"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "react": "^19.1.0",