PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 0.9.6
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v0.9.6
1.1.10 1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 0.8.8 0.8.7 All 34 releases
desktop-mode / assets / css / window-overview.css

window-overview.css in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 0.9.6, at assets/css/window-overview.css

477 lines 13.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Desktop Mode — Overview.
3 *
4 * Zoom-out grid view: windows transform into thumbnails, floating
5 * labels sit above them, and a top bar lists every virtual desktop
6 * with one tile per space plus a "+" to add a new one. The dock
7 * collapses in parallel with the enter transition.
8 *
9 * Windows keep their `left/top/width/height` intact; only `transform`
10 * animates (translate + scale) so the layout change is a GPU
11 * composite, not a reflow. `transform-origin: top left` makes
12 * translate + scale compose cleanly — a target coordinate maps to
13 * the window's top-left corner pre-scale. Iframes go
14 * `pointer-events: none` inside overview so clicks hit the window
15 * wrapper (and bubble to the desktop-area click handler) instead of
16 * the iframe content, which would otherwise eat the click.
17 *
18 * Base chrome lives in window-chrome.css; non-overview state classes
19 * live in window-states.css.
20 *
21 * @since 6.9.0
22 */
23 .desktop-mode-area--overview {
24 /* Darken the backdrop and tint it so windows feel like they're
25 * floating over a neutral canvas, not the wallpaper. */
26 background-color: rgba( 0, 0, 0, 0.45 );
27 transition: background-color 0.28s ease;
28 }
29
30 .desktop-mode-window--overview {
31 transform-origin: top left;
32 transition:
33 transform 0.28s cubic-bezier( 0.2, 0, 0.2, 1 ),
34 box-shadow 0.2s ease,
35 opacity 0.2s ease;
36 cursor: pointer;
37 /* Hover effects apply a thick outline rather than another
38 * transform (which would fight the layout's own transform).
39 * Box-shadow is composite-only, so it's cheap. */
40 box-shadow: 0 10px 30px rgba( 0, 0, 0, 0.35 );
41 /* Overview thumbnails are click targets, not reading surfaces —
42 * suppress text selection so a drag across a thumbnail doesn't
43 * highlight paragraphs inside the title bar / native body. */
44 user-select: none;
45 -webkit-user-select: none;
46 }
47
48 /*
49 * While in overview, treat each window as a single click target —
50 * every inner element (title bar, buttons, iframe, native body) goes
51 * transparent to pointer events so drags/taps never start a drag,
52 * trip a close button, or launch an in-iframe action. Only the
53 * window's root element receives pointer events; our desktop-level
54 * pointerdown/pointerup handlers drive selection from there.
55 */
56 .desktop-mode-window--overview * {
57 pointer-events: none;
58 }
59
60 .desktop-mode-window--overview {
61 pointer-events: auto;
62 }
63
64 .desktop-mode-window--overview:hover {
65 box-shadow:
66 0 14px 38px rgba( 0, 0, 0, 0.45 ),
67 0 0 0 3px var( --wp-admin-theme-color, #2271b1 );
68 z-index: 1;
69 }
70
71 /*
72 * Mission-Control-style dimming: once ANY window is hovered, every
73 * OTHER window dims and desaturates slightly — creating a clear
74 * focal point without needing the hovered one to grow or lift.
75 * `:has()` lands in every evergreen browser we target (Chrome 105,
76 * Safari 15.4, Firefox 121+); older engines miss the dimming but
77 * keep the accent-ring affordance, so it degrades gracefully.
78 */
79 .desktop-mode-area--overview:has( .desktop-mode-window--overview:hover )
80 .desktop-mode-window--overview:not( :hover ) {
81 opacity: 0.5;
82 filter: brightness( 0.75 );
83 transition:
84 transform 0.28s cubic-bezier( 0.2, 0, 0.2, 1 ),
85 opacity 0.18s ease,
86 filter 0.18s ease;
87 }
88
89 /*
90 * Dock slides out smoothly during overview — width collapses (the
91 * flex row reflows so the area grows into the freed space) while
92 * the dock itself slides left and fades. `display: none` would have
93 * been abrupt in both directions; animating the flex width does the
94 * heavy lifting and the user sees a single continuous motion.
95 *
96 * `pointer-events: none` comes in immediately on overview enter so
97 * stray clicks mid-animation can't open a window behind the user's
98 * back. `overflow: hidden` is scoped to the collapsed state so the
99 * shrinking dock doesn't leak icons past its boundary — outside
100 * overview, the dock keeps `overflow: visible` from dock.css so
101 * per-tile "+ open another" chips can float past the edge.
102 */
103 .desktop-mode-dock {
104 transition:
105 width 0.28s cubic-bezier( 0.2, 0, 0.2, 1 ),
106 min-width 0.28s cubic-bezier( 0.2, 0, 0.2, 1 ),
107 padding 0.28s cubic-bezier( 0.2, 0, 0.2, 1 ),
108 transform 0.28s cubic-bezier( 0.2, 0, 0.2, 1 ),
109 opacity 0.22s ease;
110 }
111
112 /*
113 * Collapse EVERY dock (bottom + side rails, Classic / Unified /
114 * Spatial layouts alike) when overview is active.
115 *
116 * The placement-specific width rules in dock.css —
117 * `.desktop-mode-dock[ data-desktop-mode-dock-placement="left" ]
118 * { width: var( --desktop-mode-dock-width ); }` — share equal
119 * specificity with `.desktop-mode-shell--overview .desktop-mode-dock`
120 * (two classes / class+attr) and load LATER in the cascade, so
121 * without `!important` the side rail keeps its placement width
122 * and stays visible during overview. The bottom dock happens to
123 * lack a placement-attr-keyed width override so it collapsed
124 * fine; the side rail did not — caught by the regression
125 * screenshot.
126 *
127 * `!important` is the right tool here: this rule is a transient,
128 * mode-scoped override (overview screen only) of a layout-mode
129 * default, and we want it to win unconditionally.
130 */
131 .desktop-mode-shell--overview .desktop-mode-dock,
132 .desktop-mode-shell--overview #desktop-mode-side-dock {
133 width: 0 !important;
134 min-width: 0 !important;
135 padding-inline: 0 !important;
136 padding-block: 0 !important;
137 transform: translateX( -16px );
138 opacity: 0;
139 overflow: hidden;
140 pointer-events: none;
141 transition:
142 width 0.28s cubic-bezier( 0.2, 0, 0.2, 1 ),
143 min-width 0.28s cubic-bezier( 0.2, 0, 0.2, 1 ),
144 padding 0.28s cubic-bezier( 0.2, 0, 0.2, 1 ),
145 transform 0.28s cubic-bezier( 0.2, 0, 0.2, 1 ),
146 opacity 0.22s ease;
147 }
148
149 @media ( prefers-reduced-motion: reduce ) {
150 .desktop-mode-dock {
151 transition-duration: 0.01ms;
152 }
153 }
154
155 /* ---------------------------------------------------------------
156 * Overview thumbnail labels.
157 *
158 * Sit outside each window's transform (as absolute-positioned
159 * siblings in the desktop area) so they stay readable at any
160 * thumbnail scale — an icon-sized thumbnail still has its
161 * full-size caption hovering above it.
162 *
163 * Layout: one line, icon + title (+ optional meta). Horizontal
164 * center-of-thumbnail alignment is handled via the label's
165 * own flex + width set in JS to match the scaled thumbnail.
166 * --------------------------------------------------------------- */
167 .desktop-mode-overview-label {
168 position: absolute;
169 height: 28px;
170 display: flex;
171 align-items: center;
172 justify-content: center;
173 gap: 6px;
174 padding: 0 10px;
175 color: #fff;
176 font-size: 13px;
177 font-weight: 500;
178 line-height: 1;
179 letter-spacing: 0.01em;
180 text-shadow: 0 1px 3px rgba( 0, 0, 0, 0.55 );
181 white-space: nowrap;
182 pointer-events: none;
183 opacity: 0;
184 transform: translateY( 4px );
185 transition:
186 opacity 0.22s ease 0.06s,
187 transform 0.28s cubic-bezier( 0.2, 0, 0.2, 1 ) 0.06s;
188 z-index: 2;
189 }
190
191 /*
192 * Active labels fade/slide in once the area enters overview mode.
193 * The short delay on `transition-*` lets the thumbnails start
194 * moving first, so labels appear to "catch up" rather than race
195 * ahead of their windows.
196 */
197 .desktop-mode-area--overview .desktop-mode-overview-label {
198 opacity: 1;
199 transform: translateY( 0 );
200 }
201
202 /* On exit, flip the animation off. */
203 .desktop-mode-overview-label--out {
204 opacity: 0 !important;
205 transform: translateY( -4px ) !important;
206 transition-delay: 0s !important;
207 }
208
209 .desktop-mode-overview-label__icon {
210 font-size: 16px;
211 width: 16px;
212 height: 16px;
213 line-height: 1;
214 flex-shrink: 0;
215 opacity: 0.9;
216 }
217
218 .desktop-mode-overview-label__title {
219 overflow: hidden;
220 text-overflow: ellipsis;
221 }
222
223 .desktop-mode-overview-label__meta {
224 color: rgba( 255, 255, 255, 0.7 );
225 font-weight: 400;
226 flex-shrink: 0;
227 }
228
229 /*
230 * Dim labels when another window is hovered. DOM order places
231 * each label immediately after its window, so the adjacent-
232 * sibling selector picks out exactly the label belonging to the
233 * hovered window and keeps it bright; all other labels fall under
234 * the `:has()` rule and dim.
235 */
236 .desktop-mode-area--overview:has( .desktop-mode-window--overview:hover )
237 .desktop-mode-overview-label {
238 opacity: 0.45;
239 transform: translateY( 0 );
240 }
241
242 .desktop-mode-window--overview:hover + .desktop-mode-overview-label {
243 opacity: 1 !important;
244 }
245
246 @media ( prefers-reduced-motion: reduce ) {
247 .desktop-mode-overview-label {
248 transition-duration: 0.01ms;
249 transition-delay: 0s;
250 }
251 }
252
253 /*
254 * Focused-window label overlay is not strictly needed — the title
255 * bar stays visible in the scaled thumbnail. If we later want a
256 * cleaner label (to combat tiny text on 8+-window grids), slot it
257 * in here via a ::after pseudo-element.
258 */
259
260 @media ( prefers-reduced-motion: reduce ) {
261 .desktop-mode-area--overview,
262 .desktop-mode-window--overview {
263 transition-duration: 0.01ms;
264 }
265 }
266
267 /* ---------------------------------------------------------------
268 * Overview top bar — virtual desktops ("Spaces") strip.
269 *
270 * Lives at the top of the desktop area while overview is active,
271 * stacked above the dimmed backdrop and below the window
272 * thumbnails. Each tile represents one desktop; clicking switches
273 * to it (and exits overview), the trailing "+" tile creates a new
274 * one, and per-tile X buttons close.
275 * --------------------------------------------------------------- */
276
277 .desktop-mode-overview-top-bar {
278 position: absolute;
279 top: 16px;
280 left: 50%;
281 transform: translateX( -50% );
282 z-index: 2;
283 opacity: 0;
284 pointer-events: none;
285 transition:
286 opacity 0.22s ease 0.06s,
287 transform 0.28s cubic-bezier( 0.2, 0, 0.2, 1 ) 0.06s;
288 }
289
290 .desktop-mode-area--overview .desktop-mode-overview-top-bar {
291 opacity: 1;
292 pointer-events: auto;
293 }
294
295 .desktop-mode-overview-top-bar--out {
296 opacity: 0 !important;
297 transform: translateX( -50% ) translateY( -6px ) !important;
298 transition-delay: 0s !important;
299 }
300
301 .desktop-mode-overview-top-bar__list {
302 display: flex;
303 flex-direction: row;
304 align-items: stretch;
305 gap: 12px;
306 padding: 8px 12px;
307 border-radius: 14px;
308 background-color: rgba( 0, 0, 0, 0.32 );
309 backdrop-filter: blur( 18px ) saturate( 140% );
310 -webkit-backdrop-filter: blur( 18px ) saturate( 140% );
311 box-shadow:
312 0 8px 28px rgba( 0, 0, 0, 0.35 ),
313 inset 0 0 0 1px rgba( 255, 255, 255, 0.08 );
314 }
315
316 .desktop-mode-overview-top-bar__tile {
317 position: relative;
318 display: flex;
319 flex-direction: column;
320 align-items: stretch;
321 justify-content: stretch;
322 width: 140px;
323 padding: 0;
324 margin: 0;
325 background: rgba( 255, 255, 255, 0.04 );
326 border: 2px solid rgba( 255, 255, 255, 0.18 );
327 border-radius: 10px;
328 color: #fff;
329 cursor: pointer;
330 overflow: hidden;
331 transition:
332 border-color 0.18s ease,
333 background-color 0.18s ease,
334 transform 0.18s ease;
335 font: inherit;
336 }
337
338 .desktop-mode-overview-top-bar__tile:hover {
339 border-color: rgba( 255, 255, 255, 0.4 );
340 background: rgba( 255, 255, 255, 0.08 );
341 }
342
343 .desktop-mode-overview-top-bar__tile:focus-visible {
344 outline: 2px solid var( --wp-admin-theme-color, #2271b1 );
345 outline-offset: 2px;
346 }
347
348 .desktop-mode-overview-top-bar__tile--active {
349 border-color: var( --wp-admin-theme-color, #2271b1 );
350 box-shadow: 0 0 0 1px var( --wp-admin-theme-color, #2271b1 );
351 }
352
353 .desktop-mode-overview-top-bar__tile-preview {
354 display: flex;
355 align-items: center;
356 justify-content: center;
357 height: 60px;
358 background: linear-gradient(
359 135deg,
360 rgba( 255, 255, 255, 0.04 ),
361 rgba( 255, 255, 255, 0.12 )
362 );
363 border-bottom: 1px solid rgba( 255, 255, 255, 0.08 );
364 }
365
366 .desktop-mode-overview-top-bar__tile-count {
367 font-size: 18px;
368 font-weight: 600;
369 color: rgba( 255, 255, 255, 0.7 );
370 letter-spacing: 0.02em;
371 }
372
373 .desktop-mode-overview-top-bar__tile-label {
374 display: block;
375 padding: 6px 10px 8px;
376 text-align: center;
377 font-size: 12px;
378 font-weight: 500;
379 color: rgba( 255, 255, 255, 0.85 );
380 white-space: nowrap;
381 overflow: hidden;
382 text-overflow: ellipsis;
383 }
384
385 .desktop-mode-overview-top-bar__tile-wrapper {
386 position: relative;
387 display: inline-block;
388 }
389
390 .desktop-mode-overview-top-bar__tile-close {
391 position: absolute;
392 top: 4px;
393 inset-inline-end: 4px;
394 width: 18px;
395 height: 18px;
396 display: flex;
397 align-items: center;
398 justify-content: center;
399 color: rgba( 255, 255, 255, 0.7 );
400 background: rgba( 0, 0, 0, 0.45 );
401 border-radius: 50%;
402 cursor: pointer;
403 opacity: 0;
404 transition:
405 opacity 0.15s ease,
406 background-color 0.15s ease,
407 color 0.15s ease;
408 border: none;
409 padding: 0;
410 }
411
412 .desktop-mode-overview-top-bar__tile-wrapper:hover
413 .desktop-mode-overview-top-bar__tile-close,
414 .desktop-mode-overview-top-bar__tile-wrapper:focus-within
415 .desktop-mode-overview-top-bar__tile-close,
416 .desktop-mode-overview-top-bar__tile-close:focus-visible {
417 opacity: 1;
418 }
419
420 .desktop-mode-overview-top-bar__tile-close:hover {
421 background: #d63638;
422 color: #fff;
423 }
424
425 /*
426 * Hide the close X when there's only one tile left — the tile
427 * list contains both desktop wrappers AND the trailing "+".
428 * So "only one desktop" means exactly one wrapper in the list.
429 */
430 .desktop-mode-overview-top-bar__list:has(
431 .desktop-mode-overview-top-bar__tile-wrapper:only-of-type
432 )
433 .desktop-mode-overview-top-bar__tile-close {
434 display: none;
435 }
436
437 .desktop-mode-overview-top-bar__tile--add {
438 width: 60px;
439 background: transparent;
440 border-style: dashed;
441 }
442
443 .desktop-mode-overview-top-bar__tile--add:hover {
444 background: rgba( 255, 255, 255, 0.08 );
445 }
446
447 /*
448 * Keyboard cursor parked on the "+" tile. Mirrors the visual weight
449 * of `--active` (solid accent border + halo) so the user sees at a
450 * glance "Enter will land here". The dashed border on the add tile
451 * flips to solid when the cursor lands, matching the desktop tiles'
452 * solid borders.
453 */
454 .desktop-mode-overview-top-bar__tile--add.desktop-mode-overview-top-bar__tile--cursor {
455 border-style: solid;
456 border-color: var( --wp-admin-theme-color, #2271b1 );
457 box-shadow: 0 0 0 1px var( --wp-admin-theme-color, #2271b1 );
458 background: rgba( 255, 255, 255, 0.08 );
459 }
460
461 .desktop-mode-overview-top-bar__tile-plus {
462 display: flex;
463 align-items: center;
464 justify-content: center;
465 flex: 1;
466 font-size: 28px;
467 font-weight: 200;
468 color: rgba( 255, 255, 255, 0.7 );
469 line-height: 1;
470 }
471
472 @media ( prefers-reduced-motion: reduce ) {
473 .desktop-mode-overview-top-bar {
474 transition-duration: 0.01ms;
475 }
476 }
477