Tiles resize from anywhere, so nothing marks the spots

Every edge and both bottom corners resize now, so the little marks that used
to appear on hover were pointing at the whole rim. They are gone — corners,
edges and the seam pill alike — and the cursor over an edge is what says it
can be dragged, the way a window's own edges do it. The seam still shows
itself while it is actually being dragged, which says what is moving rather
than where you may push.

With nothing drawn, the grips could be made to cover the rim properly: the
top strip now runs corner to corner instead of stopping 24px short, the
sides run from it down to the bottom corners, and the bottom strip fills
between those. No dead spots left along an edge.

The side grips also stopped standing down at a seam. They only did so to
avoid stacking three marks in one place, and it cost real ground: a tile
taller than its neighbour lost its whole side, not just the part the seam
covers. The seam sits above them anyway, so it still wins where it exists
and the rest of the edge now works.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Waters Church
2026-09-17 11:52:45 -04:00
co-authored by Claude Opus 5
parent 8e579ecb34
commit 68f0ba806d
3 changed files with 70 additions and 191 deletions
+46 -127
View File
@@ -464,146 +464,67 @@ body.fullscreen .tile.head-peek .tile-notch { top: 32px; }
overflow: hidden;
}
.tile-resize,
.tile-resize-left {
position: absolute;
bottom: 0;
width: 20px;
height: 20px;
touch-action: none;
z-index: 5;
color: var(--muted);
opacity: 0; /* corner indicators only show while hovering the tile */
transition: opacity 0.15s ease;
}
.tile-resize { right: 0; cursor: nwse-resize; }
.tile-resize-left { left: 0; cursor: nesw-resize; }
.tile:hover .tile-resize,
.tile:hover .tile-resize-left { opacity: 0.6; }
.tile .tile-resize:hover,
.tile .tile-resize-left:hover { opacity: 1; color: var(--text); }
.tile-resize::after,
.tile-resize-left::after {
content: "";
position: absolute;
bottom: 4px;
width: 9px;
height: 9px;
border-bottom: 2px solid currentColor;
}
.tile-resize::after {
right: 4px;
border-right: 2px solid currentColor;
border-radius: 0 0 3px 0;
}
.tile-resize-left::after {
left: 4px;
border-left: 2px solid currentColor;
border-radius: 0 0 0 3px;
}
/* ── resizing: the whole rim of a tile, drawn nowhere ────────────────
Every edge and both bottom corners resize, so there is nothing to point
at — the grips are invisible and the cursor says what each one does, the
way a window's own edges do. Together they tile the tile's outer 8px
without a gap: the top strip runs corner to corner, the sides run between
it and the bottom corners, and the bottom strip fills between those. */
/* bottom edge: drag to move the tile's bottom edge (height only). Drawn as
the same 2px line as the corner handles it sits between, on the same
4px inset, so the three read as one set of marks along the bottom. */
.tile-resize-bottom {
position: absolute;
left: 24px;
right: 24px;
bottom: 0;
height: 10px;
z-index: 5;
display: flex;
align-items: flex-end;
justify-content: center;
cursor: ns-resize;
touch-action: none;
color: var(--muted);
opacity: 0;
transition: opacity 0.15s ease;
}
.tile-resize-bottom::after {
content: "";
width: 44px;
max-width: 60%;
height: 0;
margin-bottom: 4px;
border-bottom: 2px solid currentColor;
}
/* the other three edges: the same mark, turned to face its own side. Each
stops short of the corners so the corner grips keep their full 20px. */
.tile-resize,
.tile-resize-left,
.tile-resize-bottom,
.tile-resize-top,
.tile-resize-right,
.tile-resize-side {
position: absolute;
z-index: 6;
display: flex;
align-items: center;
justify-content: center;
z-index: 5;
touch-action: none;
color: var(--muted);
opacity: 0;
transition: opacity 0.15s ease;
}
/* the two bottom corners: both directions at once */
.tile-resize,
.tile-resize-left {
bottom: 0;
width: 20px;
height: 20px;
}
.tile-resize { right: 0; cursor: nwse-resize; }
.tile-resize-left { left: 0; cursor: nesw-resize; }
/* top and bottom: height only */
.tile-resize-top,
.tile-resize-bottom {
height: 8px;
cursor: ns-resize;
}
.tile-resize-top {
top: 0;
left: 24px;
right: 24px;
height: 10px;
align-items: flex-start;
cursor: ns-resize;
/* Above a revealed title bar: the bar slides in under the pointer here, and
this strip has to stay the top edge rather than become part of it. */
left: 0;
right: 0;
/* Above a revealed title bar: the bar slides in under the pointer here,
and this strip has to stay the top edge rather than become part of it. */
z-index: 8;
}
.tile-resize-bottom { bottom: 0; left: 20px; right: 20px; }
/* left and right: width only, between the top strip and the bottom corners */
.tile-resize-right,
.tile-resize-side {
top: 24px;
bottom: 24px;
width: 10px;
top: 8px;
bottom: 20px;
width: 8px;
cursor: ew-resize;
}
.tile-resize-right { right: 0; justify-content: flex-end; }
.tile-resize-side { left: 0; justify-content: flex-start; }
.tile-resize-top::after,
.tile-resize-right::after,
.tile-resize-side::after {
content: "";
border-radius: 999px;
}
.tile-resize-top::after {
width: 44px;
max-width: 60%;
height: 0;
margin-top: 4px;
border-top: 2px solid currentColor;
}
.tile-resize-right::after,
.tile-resize-side::after {
width: 0;
height: 44px;
max-height: 60%;
}
.tile-resize-right::after { margin-right: 4px; border-right: 2px solid currentColor; }
.tile-resize-side::after { margin-left: 4px; border-left: 2px solid currentColor; }
/* A side that meets another tile belongs to the seam pill between them. */
.tile.seam-left .tile-resize-side,
.tile.seam-right .tile-resize-right { display: none; }
.tile:hover .tile-resize-top,
.tile:hover .tile-resize-right,
.tile:hover .tile-resize-side { opacity: 0.6; }
.tile .tile-resize-top:hover,
.tile .tile-resize-right:hover,
.tile .tile-resize-side:hover { opacity: 1; color: var(--text); }
.tile:hover .tile-resize-bottom { opacity: 0.6; }
.tile .tile-resize-bottom:hover,
.tile.resizing .tile-resize-bottom { opacity: 1; color: var(--text); }
.tile-resize-right { right: 0; }
.tile-resize-side { left: 0; }
/* ── seam divider between adjacent tiles ───────────────────────────── */
/* When two tiles share a vertical edge, an invisible strip sits on the seam;
hovering reveals a small macOS-split-view-style grab pill. Dragging it
trades width between the two tiles. */
/* When two tiles share a vertical edge, an invisible strip sits on the seam.
Dragging it trades width between the two tiles rather than resizing one,
so it sits above their own edge grips. Like them it draws nothing at rest
— only while it is being dragged, to show which seam is moving. */
.tile-divider {
position: absolute;
width: 14px;
@@ -627,18 +548,16 @@ body.fullscreen .tile.head-peek .tile-notch { top: 32px; }
transition: opacity 0.15s ease, background 0.15s ease;
}
.tile-divider:hover::after,
.tile-divider.linked::after { opacity: 0.7; }
.tile-divider.active::after { opacity: 1; background: var(--text); }
/* Hide the pills while a tile itself is being moved or corner-resized —
they're rebuilt for the new geometry on release. */
/* Drop the seams while a tile itself is being moved or resized — they're
rebuilt for the new geometry on release. */
#grid.no-dividers .tile-divider { display: none; }
/* ── fullscreen mode ───────────────────────────────────────────────── */
/* Fullscreen is a viewing mode: the layout auto-fits the screen, so the
editing affordances (corner handles, seam pills) are parked. */
editing affordances (the rim grips and the seams) are parked. */
body.fullscreen .tile-resize,
body.fullscreen .tile-resize-left,
body.fullscreen .tile-resize-bottom,