words: gutter rail tracks the ACTIVE block + grip jitter + preview columns

Four feedback fixes:

- Grip "trembles": the handle's `:hover` did `scale(1.18)`, which grew the
  button under the cursor and shifted its hitbox → a hover↔scale feedback
  loop. Removed the hover transform; the grip is ambient (per EV-G doctrine).
- Active-block marker was a box/rail tied to the HOVERED block. Moved it to a
  vertical accent rail in the GUTTER driven by `[data-words-active]::before`,
  so it tracks the CLICKED block (the inspector's target), 0.7rem left of the
  block, spanning its height, depth-coloured. Removed the gutter component's
  hover overlay div.
- Preview showed empty columns' dashed border + min-height (editing
  affordances). `[data-mode='preview']` now makes the column border
  transparent and min-height 0 — empty columns vanish in the read-only view.

Verified in-browser: active rail sits 11px left of the clicked block (violet,
3px, full height); column border is transparent + min-height 0 in preview;
grip has no hover transform. Check clean for the touched files.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
active-uix
dev 4 months ago
parent 91bab32bc2
commit 986d61bde6

@ -313,13 +313,10 @@
</script>
{#if (show || menuOpen) && rect}
{#if inGutter || menuOpen}
<!-- Active-block marker: a vertical accent BAR in the gutter (left
margin), spanning the block's height. NOT an overlay on the block
itself — the CSS pins it to the gutter column; only top/height
track the block. -->
<div data-words-block-outline style="top: {rect.top}px; height: {rect.height}px;"></div>
{/if}
<!-- No hover overlay on the block: the active-block marker is a gutter
rail driven by `[data-words-active]` (see words.css), so it tracks the
CLICKED block, not the hovered one. -->
<!-- Center the handle vertically against the block's height: position
it at the block midpoint and let `transform: translateY(-50%)`
in CSS pull it up by half its own height. The previous

@ -173,25 +173,12 @@
transform var(--words-transition-duration) var(--words-transition-ease),
color var(--words-transition-duration) var(--words-transition-ease);
}
/* subtle displacement when the cursor lands on the handle */
[data-words-block-gutter] [data-words-block-handle]:hover {
color: var(--words-content-color);
transform: translateX(1px) scale(1.18);
}
/* The grip is AMBIENT — no `:hover` transform. The old `scale(1.18)` grew the
button under the cursor, which shifted its hitbox and produced a hover↔scale
jitter ("the grip trembles"). */
/* Active-block marker — a vertical accent rail in the GUTTER (left margin),
NOT on the block. Only top/height come from the block (set inline); the
bar is pinned to the gutter column, just inside where the text begins. */
[data-words-block-outline] {
position: absolute;
inset-inline-start: calc(var(--_words-content-px) - 0.7rem);
z-index: 1;
inline-size: 3px;
border-radius: 2px;
background: color-mix(in srgb, var(--color-primary-solid) 55%, transparent);
pointer-events: none;
animation: words-outline-in var(--words-transition-duration) var(--words-transition-ease);
}
/* Fade-in for the active-block gutter rail (the `[data-words-active]::before`
marker further down). */
@keyframes words-outline-in {
from {
opacity: 0;
@ -1080,20 +1067,20 @@ button[data-words-breadcrumb-crumb]:focus-visible {
[data-words-content] [data-words-active] {
position: relative;
}
/* The selection ring is a PSEUDO-ELEMENT with its OWN fixed radius — NOT an
`outline` / `box-shadow` on the block. Outline and box-shadow both inherit
the element's `border-radius`, so a block the user rounded to e.g. 24px
would get a 24px-rounded selection ring — which reads as wrong (the ring
should be a stable indicator, independent of the block's own corner
radius). `inset: -3px` reproduces the old `outline-offset: 2px` gap;
`pointer-events: none` keeps the contenteditable text fully editable. */
[data-words-content] [data-words-active]::after {
/* The active-block marker lives in the GUTTER, not on the block: a vertical
accent rail in the left margin (`::before`, just left of the block) spanning
the block height. Depth-coloured via `--_words-active-outline`. The block
stays `position: relative` so the rail anchors to it. */
[data-words-content] [data-words-active]::before {
content: '';
position: absolute;
inset: -3px;
border: 1.5px dotted var(--_words-active-outline, var(--color-primary-solid));
border-radius: 4px;
inset-block: 0;
inset-inline-start: -0.7rem;
inline-size: 3px;
border-radius: 2px;
background: var(--_words-active-outline, var(--color-primary-solid));
pointer-events: none;
animation: words-outline-in var(--words-transition-duration) var(--words-transition-ease);
}
[data-words-content] [data-words-active][data-words-depth='2'] {
--_words-active-outline: var(--color-affirm-solid); /* teal — column level */
@ -1169,6 +1156,12 @@ button[data-words-breadcrumb-crumb]:focus-visible {
[data-words-content] [data-words-block='columns'] [data-words-column]:focus-within {
border-color: var(--words-content-color);
}
/* Preview is read-only — the dashed border + min-height are editing
affordances; an empty column shouldn't advertise itself. Hide them. */
[data-words][data-mode='preview'] [data-words-block='columns'] [data-words-column] {
border-color: transparent;
min-block-size: 0;
}
/* Reset the universal block-rhythm `margin-block` for the FIRST nested
block of each column — otherwise that extra gap pushes the column
contents down relative to the column's frame, breaking vertical

Loading…
Cancel
Save

Powered by TurnKey Linux.