PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 0.9.1
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v0.9.1
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-states.css

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

395 lines 12.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Desktop Mode — Window state visuals.
3 *
4 * Every rule that keys off a `--state` modifier class: the resize
5 * handle + its overlay shield (drag/resize iframe-interception),
6 * maximize, fullscreen, the opening animation, minimize + closing
7 * fade-outs, reduced-motion scoped overrides, and the RTL cursor
8 * flip on the resize corner.
9 *
10 * Base chrome lives in window-chrome.css; the zoom-out grid lives
11 * in window-overview.css.
12 *
13 * @since 6.9.0
14 */
15
16 /*
17 * Resize handles — one per corner (NE / NW / SE / SW). Each is an
18 * invisible square hit-target whose cursor telegraphs the resize
19 * axis. SE keeps the legacy grip-lines glyph so the affordance is
20 * visible even without hover; the other three remain transparent
21 * (discoverable by cursor change only) to keep the window chrome
22 * clean.
23 *
24 * Hit-area is `--desktop-mode-resize-size` (20 px by default). The
25 * handles extend a few pixels OUTSIDE the window edge so a cursor
26 * landing just past the border still activates them — matches how
27 * native OS windows forgive edge-grabs.
28 */
29 .desktop-mode-window__resize-handle {
30 position: absolute;
31 width: var(--desktop-mode-resize-size);
32 height: var(--desktop-mode-resize-size);
33 z-index: 999;
34 }
35
36 .desktop-mode-window__resize-handle--se {
37 right: -3px;
38 bottom: -3px;
39 cursor: nwse-resize;
40 background: linear-gradient(
41 135deg,
42 transparent 30%,
43 var(--desktop-mode-resize-color) 30%,
44 var(--desktop-mode-resize-color) 40%,
45 transparent 40%,
46 transparent 55%,
47 var(--desktop-mode-resize-color) 55%,
48 var(--desktop-mode-resize-color) 65%,
49 transparent 65%,
50 transparent 80%,
51 var(--desktop-mode-resize-color) 80%
52 );
53 }
54
55 .desktop-mode-window__resize-handle--sw {
56 left: -3px;
57 bottom: -3px;
58 cursor: nesw-resize;
59 }
60
61 .desktop-mode-window__resize-handle--ne {
62 right: -3px;
63 top: -3px;
64 cursor: nesw-resize;
65 }
66
67 .desktop-mode-window__resize-handle--nw {
68 left: -3px;
69 top: -3px;
70 cursor: nwse-resize;
71 }
72
73 /*
74 * During drag/resize, overlay the iframe to prevent it from
75 * capturing pointer events and breaking the drag.
76 */
77 .desktop-mode-window--dragging .desktop-mode-window__body::after,
78 .desktop-mode-window--resizing .desktop-mode-window__body::after {
79 content: "";
80 position: absolute;
81 inset: 0;
82 z-index: 10;
83 }
84
85 /*
86 * Maximized state: the pixel geometry is applied inline from JS
87 * (matching the desktop area) so left/top/width/height can animate.
88 * Only cosmetic overrides here.
89 */
90 .desktop-mode-window--maximized {
91 border-radius: 0;
92 }
93
94 .desktop-mode-window--maximized .desktop-mode-window__resize-handle {
95 display: none;
96 }
97
98 /*
99 * Fullscreen ("focus") state — the window escapes the desktop area and
100 * covers the entire viewport, hiding the admin bar and dock behind
101 * it. Uses position: fixed so no ancestor overflow clips it, and
102 * a z-index above the admin bar (--desktop-mode-z-adminbar). Inline
103 * geometry set by toggleMaximize() is overridden with !important because
104 * we never want fullscreen to respect a saved x/y/width/height.
105 */
106 .desktop-mode-window--fullscreen {
107 position: fixed !important;
108 left: 0 !important;
109 top: 0 !important;
110 width: 100vw !important;
111 height: 100vh !important;
112 z-index: var(--desktop-mode-z-fullscreen) !important;
113 border-radius: 0 !important;
114 border: none;
115 }
116
117 .desktop-mode-window--fullscreen .desktop-mode-window__resize-handle {
118 display: none;
119 }
120
121 /*
122 * Opening animation — subtle scale-up + fade-in.
123 * The class is added on creation and removed after the animation ends.
124 */
125 @keyframes desktop-mode-window-open {
126 from {
127 opacity: 0;
128 transform: scale(0.92);
129 }
130 to {
131 opacity: 1;
132 transform: scale(1);
133 }
134 }
135
136 .desktop-mode-window--opening {
137 animation: desktop-mode-window-open 0.2s ease forwards;
138 }
139
140 /*
141 * Shake animation — used by `Window.shake()` for nudge / attention-
142 * grab affordances. The window briefly jiggles horizontally while
143 * keeping its position. Composes via CSS variable so the inline
144 * `left`/`top` written by the window manager keeps wining; the
145 * shake is a translate ON TOP of that.
146 *
147 * Reduced-motion fallback: a static accent ring for the same
148 * duration so users with prefers-reduced-motion still see the
149 * affordance without movement.
150 */
151 @keyframes desktop-mode-window-shake {
152 0%, 100% { transform: translateX( 0 ); }
153 8% { transform: translateX( -10px ); }
154 18% { transform: translateX( 9px ); }
155 28% { transform: translateX( -8px ); }
156 38% { transform: translateX( 7px ); }
157 48% { transform: translateX( -5px ); }
158 60% { transform: translateX( 4px ); }
159 72% { transform: translateX( -3px ); }
160 84% { transform: translateX( 2px ); }
161 }
162
163 .desktop-mode-window--shaking {
164 animation: desktop-mode-window-shake 0.6s cubic-bezier( 0.36, 0.07, 0.19, 0.97 ) both;
165 }
166
167 @media ( prefers-reduced-motion: reduce ) {
168 .desktop-mode-window--shaking {
169 animation: none;
170 outline: 3px solid var( --wp-admin-theme-color, #2271b1 );
171 outline-offset: 2px;
172 transition: outline 0.6s ease;
173 }
174 }
175
176 /*
177 * Desktop-switch slide — applied to `.desktop-mode-area` (the windows
178 * + widgets container) when the user moves between virtual desktops
179 * via arrow keys or any other directional caller. The wallpaper lives
180 * OUTSIDE this element (sibling under `.desktop-mode-shell`), so the
181 * slide reveals the wallpaper as a backdrop — no black flash, no
182 * awkward gap on the leading edge.
183 *
184 * `--sliding-from-right` plays when moving to the next desktop (the
185 * rightward arrow press): the new desktop's content rushes in from
186 * the right and settles to centre. `--sliding-from-left` mirrors it
187 * for the previous-desktop direction. Wrap-around presses (rightmost
188 * → first via ArrowRight) keep the direction the user perceived,
189 * not the index delta.
190 *
191 * Opacity tapers from 0.35 → 1 so the moving content visibly arrives
192 * rather than just sliding in at full strength, but the wallpaper
193 * stays at full opacity behind it for an anchored sense of place.
194 * Cubic-bezier ease-out lands cleanly without overshoot.
195 *
196 * `forwards` isn't needed — the JS strips the class on `animationend`
197 * so the element returns to its natural transform / opacity state.
198 */
199 @keyframes desktop-mode-area-slide-from-right {
200 from {
201 transform: translateX(64px);
202 opacity: 0.35;
203 }
204 to {
205 transform: translateX(0);
206 opacity: 1;
207 }
208 }
209
210 @keyframes desktop-mode-area-slide-from-left {
211 from {
212 transform: translateX(-64px);
213 opacity: 0.35;
214 }
215 to {
216 transform: translateX(0);
217 opacity: 1;
218 }
219 }
220
221 .desktop-mode-area--sliding-from-right {
222 animation: desktop-mode-area-slide-from-right 0.28s cubic-bezier( 0.2, 0.7, 0.2, 1 );
223 }
224
225 .desktop-mode-area--sliding-from-left {
226 animation: desktop-mode-area-slide-from-left 0.28s cubic-bezier( 0.2, 0.7, 0.2, 1 );
227 }
228
229 @media ( prefers-reduced-motion: reduce ) {
230 .desktop-mode-area--sliding-from-right,
231 .desktop-mode-area--sliding-from-left {
232 animation: none;
233 }
234 }
235
236 /*
237 * Minimized state — fade + scale down.
238 * Uses opacity + pointer-events instead of display: none so the
239 * CSS transition can animate the change. The window is invisible
240 * and non-interactive but stays in the DOM for a smooth restore.
241 */
242 .desktop-mode-window--minimized {
243 opacity: 0;
244 transform: scale(0.92) translateY(16px);
245 pointer-events: none;
246 will-change: transform, opacity;
247 }
248
249 /*
250 * `pointer-events: none` on the window root above is not enough on
251 * its own: a number of descendants (most notably `.desktop-mode-
252 * file-tile`, but also other tile renderers) explicitly set
253 * `pointer-events: auto` so the wallpaper / folder layer doesn't
254 * eat their clicks. That `auto` overrides the parent's `none`, and
255 * after "Show Desktop" minimizes every window, hovering the empty
256 * space where a tile used to sit would still trigger its tooltip
257 * / dock peek — the invisible-but-still-interactive bug.
258 *
259 * The universal selector is scoped INSIDE the minimized window so
260 * it doesn't touch anything else, and `!important` is required to
261 * win over the per-tile `pointer-events: auto`.
262 */
263 .desktop-mode-window--minimized *,
264 .desktop-mode-window--closing * {
265 pointer-events: none !important;
266 }
267
268 /*
269 * Closing animation — fade out + slight scale down.
270 * The JS waits for transitionend then removes the element.
271 */
272 .desktop-mode-window--closing {
273 opacity: 0;
274 transform: scale(0.95);
275 pointer-events: none;
276 will-change: transform, opacity;
277 }
278
279 /*
280 * Respect prefers-reduced-motion: collapse all durations to near-zero
281 * so state changes are instant but still technically transition
282 * (avoids layout jumps from display: none).
283 */
284 @media ( prefers-reduced-motion: reduce ) {
285 .desktop-mode-window {
286 transition-duration: 0.01ms !important;
287 }
288 .desktop-mode-window--opening {
289 animation-duration: 0.01ms !important;
290 }
291 }
292
293 /*
294 * RTL note: resize handles use physical `left` / `right` anchors
295 * (not logical `inset-inline-*`) so the four corners stay in the
296 * same physical positions under RTL. Each handle already has the
297 * correct cursor for its physical diagonal (SE + NW use
298 * `nwse-resize`, NE + SW use `nesw-resize`); no RTL override
299 * needed.
300 */
301
302 /* ---------------------------------------------------------------
303 * Snap zones — edge-snap preview rectangle + snapped-state chrome.
304 *
305 * Preview appears while the drag cursor is within SNAP_EDGE_THRESHOLD
306 * of the left/right edge (see window-manager/snap-zones.ts). It's a
307 * translucent accent-colored rectangle covering the target half, with
308 * a bright border so the user sees exactly where the window will land.
309 * --------------------------------------------------------------- */
310 .desktop-mode-snap-preview {
311 position: absolute;
312 background: color-mix(
313 in srgb,
314 var( --wp-admin-theme-color, #2271b1 ) 14%,
315 transparent
316 );
317 border: 2px solid var( --wp-admin-theme-color, #2271b1 );
318 border-radius: 12px;
319 box-shadow:
320 0 0 0 1px rgba( 255, 255, 255, 0.15 ) inset,
321 0 12px 36px rgba( 0, 0, 0, 0.22 );
322 pointer-events: none;
323 z-index: 99; /* Just under windows (which start at 100) so a */
324 /* still-dragging window renders on top. */
325 opacity: 0;
326 transition:
327 opacity 0.15s ease,
328 left 0.18s cubic-bezier( 0.2, 0, 0.2, 1 ),
329 top 0.18s cubic-bezier( 0.2, 0, 0.2, 1 ),
330 width 0.18s cubic-bezier( 0.2, 0, 0.2, 1 ),
331 height 0.18s cubic-bezier( 0.2, 0, 0.2, 1 );
332 }
333
334 .desktop-mode-snap-preview--visible {
335 opacity: 1;
336 }
337
338 /*
339 * Snapped window state — `--snapped-left` / `--snapped-right` carry
340 * cosmetic tweaks only. Resize handles stay visible and functional:
341 * the user can grab any corner to shrink the window back to floating
342 * (the pointer layer drops the snapped-* class on first resize so
343 * geometry stops pretending to be half-screen).
344 *
345 * Rounded-corner profile flattens the INNER edges (the ones that
346 * butt against the partner window) to match macOS split-view
347 * aesthetic.
348 *
349 * Shadows are dropped on both snapped variants. The default window
350 * drop shadow would render inside the opposite half — a dark vertical
351 * ghost line at the seam — and compete visually with the partner
352 * window. Flat edges + no shadow gives the two-up feel of a native
353 * split view: windows adjacent, no separator.
354 */
355 .desktop-mode-window--snapped-left,
356 .desktop-mode-window--snapped-right {
357 box-shadow: none;
358 }
359
360 /* Override the elevated shadow applied to `--focused` windows too —
361 the focused selector runs at equal specificity, so without this
362 rule the focus shadow would re-introduce the seam once the snapped
363 window is active. */
364 .desktop-mode-window--focused.desktop-mode-window--snapped-left,
365 .desktop-mode-window--focused.desktop-mode-window--snapped-right {
366 box-shadow: none;
367 }
368
369 .desktop-mode-window--snapped-left {
370 /* Inner (right) edge flush; outer corners keep the radius. */
371 border-top-right-radius: 0;
372 border-bottom-right-radius: 0;
373 }
374
375 .desktop-mode-window--snapped-right {
376 border-top-left-radius: 0;
377 border-bottom-left-radius: 0;
378 }
379
380 /*
381 * Split overview — a constrained variant of the full overview,
382 * scoped to the half opposite a just-snapped window. Uses the same
383 * thumbnail visuals as the main overview; only the backdrop tint is
384 * lighter (the anchor window still takes the other half, so we want
385 * the picker to feel "peripheral" not "modal").
386 */
387 .desktop-mode-area--split-overview {
388 background-color: rgba( 0, 0, 0, 0.28 );
389 transition: background-color 0.24s ease;
390 }
391
392 /* Toast styling moved into `<wpd-toast-container>` and `<wpd-toast>`
393 * (src/ui/components/wpd-toast/). The components own their shadow
394 * DOM styling; nothing at host level needs to reach inside. */
395