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> </script>
{#if (show || menuOpen) && rect} {#if (show || menuOpen) && rect}
{#if inGutter || menuOpen} <!-- No hover overlay on the block: the active-block marker is a gutter
<!-- Active-block marker: a vertical accent BAR in the gutter (left rail driven by `[data-words-active]` (see words.css), so it tracks the
margin), spanning the block's height. NOT an overlay on the block CLICKED block, not the hovered one. -->
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}
<!-- Center the handle vertically against the block's height: position <!-- Center the handle vertically against the block's height: position
it at the block midpoint and let `transform: translateY(-50%)` it at the block midpoint and let `transform: translateY(-50%)`
in CSS pull it up by half its own height. The previous 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), transform var(--words-transition-duration) var(--words-transition-ease),
color 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 */ /* The grip is AMBIENT — no `:hover` transform. The old `scale(1.18)` grew the
[data-words-block-gutter] [data-words-block-handle]:hover { button under the cursor, which shifted its hitbox and produced a hover↔scale
color: var(--words-content-color); jitter ("the grip trembles"). */
transform: translateX(1px) scale(1.18);
}
/* Active-block marker — a vertical accent rail in the GUTTER (left margin), /* Fade-in for the active-block gutter rail (the `[data-words-active]::before`
NOT on the block. Only top/height come from the block (set inline); the marker further down). */
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);
}
@keyframes words-outline-in { @keyframes words-outline-in {
from { from {
opacity: 0; opacity: 0;
@ -1080,20 +1067,20 @@ button[data-words-breadcrumb-crumb]:focus-visible {
[data-words-content] [data-words-active] { [data-words-content] [data-words-active] {
position: relative; position: relative;
} }
/* The selection ring is a PSEUDO-ELEMENT with its OWN fixed radius — NOT an /* The active-block marker lives in the GUTTER, not on the block: a vertical
`outline` / `box-shadow` on the block. Outline and box-shadow both inherit accent rail in the left margin (`::before`, just left of the block) spanning
the element's `border-radius`, so a block the user rounded to e.g. 24px the block height. Depth-coloured via `--_words-active-outline`. The block
would get a 24px-rounded selection ring — which reads as wrong (the ring stays `position: relative` so the rail anchors to it. */
should be a stable indicator, independent of the block's own corner [data-words-content] [data-words-active]::before {
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 {
content: ''; content: '';
position: absolute; position: absolute;
inset: -3px; inset-block: 0;
border: 1.5px dotted var(--_words-active-outline, var(--color-primary-solid)); inset-inline-start: -0.7rem;
border-radius: 4px; inline-size: 3px;
border-radius: 2px;
background: var(--_words-active-outline, var(--color-primary-solid));
pointer-events: none; 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'] { [data-words-content] [data-words-active][data-words-depth='2'] {
--_words-active-outline: var(--color-affirm-solid); /* teal — column level */ --_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 { [data-words-content] [data-words-block='columns'] [data-words-column]:focus-within {
border-color: var(--words-content-color); 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 /* Reset the universal block-rhythm `margin-block` for the FIRST nested
block of each column — otherwise that extra gap pushes the column block of each column — otherwise that extra gap pushes the column
contents down relative to the column's frame, breaking vertical contents down relative to the column's frame, breaking vertical

Loading…
Cancel
Save

Powered by TurnKey Linux.