PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.10
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.10
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
← All changes | assets/css/window-states.css +166 -6 1.1.41.1.10 View file →
@@ -363,21 +363,32 @@
363 363 }
364 364 }
365 365
366 366 /*
367 - * Minimized state — fade + scale down.
368 - * Uses opacity + pointer-events instead of display: none so the
369 - * CSS transition can animate the change. The window is invisible
370 - * and non-interactive but stays in the DOM for a smooth restore.
367 + * Minimized state — window is hidden and non-interactive at the dock.
368 + * Uses opacity + pointer-events + transition: none so neither state
369 + * changes nor WAAPI animation teardown trigger accidental transitions.
371 370 */
372 371 .os-window--minimized {
373 372 opacity: 0;
374 - transform: scale(0.92) translateY(16px);
375 373 pointer-events: none;
376 - will-change: transform, opacity;
374 + transition: none !important;
377 375 }
378 376
379 377 /*
378 + * Genie helpers — active only during the WAAPI flight to/from the
379 + * dock. Disable the base `left/top/width/height/transform/opacity`
380 + * transition so the CSS transition doesn't fight the WAAPI
381 + * `element.animate()` that drives the scale-to-dock motion. The
382 + * minimized class is applied AFTER the minimizing flight lands, and
383 + * the restoring class is removed AFTER the restoring flight lands.
384 + */
385 +.os-window--minimizing,
386 +.os-window--restoring {
387 + transition: none !important;
388 +}
389 +
390 +/*
380 391 * `pointer-events: none` on the window root above is not enough on
381 392 * its own: a number of descendants (most notably `.os-
382 393 * file-tile`, but also other tile renderers) explicitly set
383 394 * `pointer-events: auto` so the wallpaper / folder layer doesn't
@@ -417,8 +428,13 @@
417 428 }
418 429 .os-window--opening {
419 430 animation-duration: 0.01ms !important;
420 431 }
432 + .os-window--minimizing,
433 + .os-window--restoring {
434 + animation: none !important;
435 + transition: none !important;
436 + }
421 437 }
422 438
423 439 /*
424 440 * RTL note: resize handles use physical `left` / `right` anchors
@@ -462,8 +478,152 @@
462 478 }
463 479
464 480 .os-snap-preview--visible {
465 481 opacity: 1;
482 +}
483 +
484 +/* ---------------------------------------------------------------
485 + * Grid snap — the 6×6 desk shown while Option / Alt is held during a
486 + * drag (see window-manager/grid-snap.ts).
487 + *
488 + * The overlay is the work area; the lines are one repeating gradient
489 + * sized to a cell, and a cell is a fraction of the overlay — so the
490 + * same rule draws the grid at any dimensions, on any display, and
491 + * follows the work area if the dock folds away mid-drag. The target
492 + * is the span the window will land on, in the same accent as the
493 + * edge-snap preview so both previews read as one vocabulary.
494 + * --------------------------------------------------------------- */
495 +.os-grid-snap {
496 + position: absolute;
497 + /* Same layer as the edge-snap preview: under the windows, so the
498 + one being dragged stays on top of its own landing zone. */
499 + z-index: 99;
500 + pointer-events: none;
501 + opacity: 0;
502 + transition: opacity 0.2s ease;
503 + --os-grid-snap-cols: 6;
504 + --os-grid-snap-rows: 6;
505 + --os-grid-snap-line: color-mix(
506 + in srgb,
507 + var( --wp-admin-theme-color, #2271b1 ) 55%,
508 + transparent
509 + );
510 + background-image:
511 + linear-gradient( to right, var( --os-grid-snap-line ) 1px, transparent 1px ),
512 + linear-gradient( to bottom, var( --os-grid-snap-line ) 1px, transparent 1px );
513 + background-size:
514 + calc( 100% / var( --os-grid-snap-cols ) ) 100%,
515 + 100% calc( 100% / var( --os-grid-snap-rows ) );
516 + /* The gradient draws a line at the START of every cell; the
517 + inset ring supplies the far edges so the grid is closed. */
518 + box-shadow: inset 0 0 0 1px var( --os-grid-snap-line );
519 +}
520 +
521 +.os-grid-snap--visible {
522 + opacity: 1;
523 +}
524 +
525 +.os-grid-snap__target {
526 + position: absolute;
527 + background: color-mix(
528 + in srgb,
529 + var( --wp-admin-theme-color, #2271b1 ) 16%,
530 + transparent
531 + );
532 + border: 2px solid var( --wp-admin-theme-color, #2271b1 );
533 + border-radius: 10px;
534 + box-shadow:
535 + 0 0 0 1px rgba( 255, 255, 255, 0.15 ) inset,
536 + 0 12px 36px rgba( 0, 0, 0, 0.22 );
537 + /* Geometry animates so a cell-to-cell change slides rather than
538 + jumps; short, so it never lags the pointer by a cell. */
539 + transition:
540 + left 0.12s cubic-bezier( 0.2, 0, 0.2, 1 ),
541 + top 0.12s cubic-bezier( 0.2, 0, 0.2, 1 ),
542 + width 0.12s cubic-bezier( 0.2, 0, 0.2, 1 ),
543 + height 0.12s cubic-bezier( 0.2, 0, 0.2, 1 );
544 +}
545 +
546 +/*
547 + * The span, as "cols × rows", in the MIDDLE of the target. A user
548 + * picking a 3×2 wants to know it is 3×2 before letting go; the count
549 + * is what makes the grid a tool rather than a decoration, but only
550 + * if it is read, and in the corner it was not. The pointer is
551 + * somewhere inside the target by definition, so the centre is the
552 + * shortest average trip for the eye; on a 2×5 the corner could be
553 + * several hundred pixels from the hand.
554 + *
555 + * Centred rather than pinned to the pointer on purpose: a badge that
556 + * tracked the cursor would rewrite its position every move, and a
557 + * number that slides while you read it is harder to read than one
558 + * that waits. It only moves when the span does.
559 + */
560 +.os-grid-snap__target::after {
561 + content: attr( data-cols ) ' × ' attr( data-rows );
562 + position: absolute;
563 + top: 50%;
564 + left: 50%;
565 + transform: translate( -50%, -50% );
566 + padding: 2px 7px;
567 + border-radius: 6px;
568 + background: var( --os-ui-scrim, rgba( 0, 0, 0, 0.55 ) );
569 + color: var( --os-ui-fg-on-accent, #fff );
570 + font-size: 11px;
571 + font-weight: 600;
572 + letter-spacing: 0.03em;
573 + font-variant-numeric: tabular-nums;
574 +}
575 +
576 +/*
577 + * The desk in grid mode. Every OTHER window recedes so the grid and
578 + * the landing zone read through them; the one in hand stays solid —
579 + * it is the thing being placed, and the user needs to see it, not
580 + * through it. Translucent enough that the grid shows, opaque enough
581 + * that the other windows are still recognisably where they are,
582 + * because "will this land on top of Posts?" is the question the grid
583 + * is there to answer.
584 + *
585 + * Opacity only: a blur or a desaturate on a live iframe is a
586 + * per-frame filter on a large surface, and the drag has to stay
587 + * pixel-accurate at 120Hz. Minimized windows are already hidden and
588 + * need no rule.
589 + */
590 +.os-area--grid-snapping .os-window:not( .os-window--grid-snapping ) {
591 + opacity: 0.45;
592 + transition: opacity 0.16s ease;
593 +}
594 +
595 +/* A shake moved the anchor: one pulse so the reset is seen, not inferred. */
596 +.os-grid-snap__target--reset {
597 + animation: os-grid-snap-reset 0.32s ease;
598 +}
599 +
600 +@keyframes os-grid-snap-reset {
601 + 0% {
602 + box-shadow:
603 + 0 0 0 1px rgba( 255, 255, 255, 0.15 ) inset,
604 + 0 0 0 0 var( --wp-admin-theme-color, #2271b1 );
605 + }
606 + 60% {
607 + box-shadow:
608 + 0 0 0 1px rgba( 255, 255, 255, 0.15 ) inset,
609 + 0 0 0 10px transparent;
610 + }
611 + 100% {
612 + box-shadow:
613 + 0 0 0 1px rgba( 255, 255, 255, 0.15 ) inset,
614 + 0 12px 36px rgba( 0, 0, 0, 0.22 );
615 + }
616 +}
617 +
618 +@media ( prefers-reduced-motion: reduce ) {
619 + .os-grid-snap,
620 + .os-grid-snap__target {
621 + transition: none;
622 + }
623 + .os-grid-snap__target--reset {
624 + animation: none;
625 + }
466 626 }
467 627
468 628 /*
469 629 * Snapped window state — `--snapped-left` / `--snapped-right` carry