words: active-block marker → the gutter (not the block) + no select in preview

Two fixes from feedback:

- The active/hovered-block marker belonged in the GUTTER, not as an overlay
  on the block. `[data-words-block-outline]` is now a thin (3px) vertical
  accent rail pinned to the gutter column (left margin, just left of where
  the text begins) spanning the block's height — only top/height track the
  block. Replaces the tinted fill that landed on the block content.
- Preview is read-only, but `WordsActivate` (click-to-select → the dotted
  active outline) still ran, so blocks could be selected in preview. Add an
  `enabled` prop (false in preview): no click-activation and the active stamp
  is cleared. `<Words>` passes `enabled={mode === 'edit'}`.

Verified in-browser: the gutter rail sits 8px left of the block text (not
over it), spanning the block height; clicking a block in preview no longer
stamps `data-words-active`. 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 be15bbe4f6
commit 91bab32bc2

@ -28,11 +28,15 @@
let {
api,
content,
dom
dom,
enabled = true
}: {
api: ProviderSnippetProps;
content: HTMLElement;
dom: ActiveDom;
/** When false (preview / read-only) block activation is off: no
* click-to-select and the active-block outline is cleared. */
enabled?: boolean;
} = $props();
// Build the MATERIALIZED-PATH id of the clicked block: walk the DOM up
@ -52,7 +56,7 @@
}
$effect(() => {
if (!content) return;
if (!content || !enabled) return;
const onPointerDown = (e: Event) => {
const target = e.target as HTMLElement | null;
if (!target) return;
@ -76,6 +80,7 @@
// are unique, so we match the LAST segment. The segment count is the
// nesting depth → `data-words-depth`.
$effect(() => {
const on = enabled; // re-run (and clear) when activation is turned off
const idPath = api.activeBlockId;
// Touch `html` so this effect re-runs after each re-render and
// re-stamps the (freshly recreated) element.
@ -88,7 +93,8 @@
prev.removeAttribute('data-words-active');
prev.removeAttribute('data-words-depth');
}
if (!idPath) return;
// Preview / read-only: stamps cleared above, never re-applied.
if (!on || !idPath) return;
const segments = idPath.split('/').filter(Boolean);
const localId = segments[segments.length - 1];
if (!localId) return;

@ -314,11 +314,11 @@
{#if (show || menuOpen) && rect}
{#if inGutter || menuOpen}
<div
data-words-block-outline
style="top: {rect.top - 3}px; left: {rect.left - 3}px; width: {rect.width +
6}px; height: {rect.height + 6}px;"
></div>
<!-- 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}
<!-- Center the handle vertically against the block's height: position
it at the block midpoint and let `transform: translateY(-50%)`

@ -179,16 +179,17 @@
transform: translateX(1px) scale(1.18);
}
/* Active-block highlight while the handle acts on a block: a faint tinted
fill + a solid accent bar on the left edge (toward the gutter grip). Reads
as "this is the block" far better than the old dashed outline. */
/* 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;
background: color-mix(in srgb, var(--color-primary-solid) 5%, transparent);
border-radius: var(--words-radius-sm);
box-shadow: inset 3px 0 0 color-mix(in srgb, var(--color-primary-solid) 40%, transparent);
animation: words-outline-in var(--words-transition-duration) var(--words-transition-ease);
}
@keyframes words-outline-in {

@ -109,7 +109,7 @@
<WordsBubble {api} />
{/if}
{#if contentEl}
<WordsActivate {api} content={contentEl} {dom} />
<WordsActivate {api} content={contentEl} {dom} enabled={mode === 'edit'} />
{#if mode === 'edit'}
<WordsBlockGutter {api} content={contentEl} {dom} />
<WordsBlockDrag {api} content={contentEl} {dom} />

Loading…
Cancel
Save

Powered by TurnKey Linux.