From 33b3a580b7298092c88e0fd6e2290b1d73d3bb1a Mon Sep 17 00:00:00 2001 From: dev Date: Thu, 28 May 2026 00:24:57 +0200 Subject: [PATCH] feat(words): visible dotted band in the grip rail + trim to 1rem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two complaints from the user on the rail: 1. Still too wide at 1.5rem (~24px). 2. The band doesn't visually distinguish itself from the canvas so the grip + "+" look detached. Fixes: - **Rail trimmed to 1rem (~16px)** — combined with content-px gives a 32px total padding on the rail side. The 28×28 grip lands at content.left+0 → +28 with a 4px gap before the text. This is the minimum band width that still keeps the grip fully inside the editor's visible content area. - **Dotted pattern on the band** — `[data-words-content]::before` fills the rail's padding zone (32px wide, full height) with a radial-gradient dot pattern at 8×8 px tiles. Color is `status-color @ 40% opacity` so the dots read as a "this is a gutter" cue without competing with content. `pointer-events: none` and `z-index: 0` so they don't interfere with selection or caret. - **Flips with drawer side** — when `` the pseudo's inset moves to inline-end so the dotted band tracks the rail to the right side. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/uix/eidos/components/words/words.css | 38 +++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/uix/eidos/components/words/words.css b/src/uix/eidos/components/words/words.css index b93c3bff7..df2213008 100644 --- a/src/uix/eidos/components/words/words.css +++ b/src/uix/eidos/components/words/words.css @@ -6,10 +6,11 @@ --_words-content-min-block-size: var(--words-content-min-block-size-md); /* Gutter reserved for the block-handle grip + inserter "+" overlay. Content is padded by this much on the side OPPOSITE to the drawer - so the floating overlays have a visible band to land in. 1.5rem - (≈24px) added to the existing content-px (16px) gives ~40px total - on that side — just enough for a 28×28 hit area, no waste. */ - --_words-rail-px: 1.5rem; + so the floating overlays have a visible band to land in. 1rem + (≈16px) is the minimum: combined with the existing content-px + (16px) it gives a 32px band — wide enough for the 28px grip to + start at the editor edge and leave 4px before the text. */ + --_words-rail-px: 1rem; --_words-toolbar-px: var(--words-toolbar-px-md); --_words-toolbar-py: var(--words-toolbar-py-md); --_words-button-size: var(--words-button-size-md); @@ -1778,6 +1779,7 @@ } [data-words-content] { + position: relative; min-block-size: var(--_words-content-min-block-size); padding-block: var(--_words-content-py); /* Default (drawer on right): rail on the LEFT for the grip + "+". */ @@ -1792,6 +1794,34 @@ -webkit-user-select: text; } +/* Dotted band — fills the rail's padding zone so the user reads it as + a dedicated gutter (where grip + "+" overlays live) instead of empty + content padding. Pointer-events disabled so it doesn't intercept + clicks/selection. Pseudo-elements on a contenteditable don't affect + text selection or caret in modern browsers. */ +[data-words-content]::before { + content: ''; + position: absolute; + inset-block: 0; + inset-inline-start: 0; + inline-size: calc(var(--_words-rail-px) + var(--_words-content-px)); + background-image: radial-gradient( + circle 1px, + color-mix(in srgb, var(--words-status-color) 40%, transparent) 99%, + transparent 100% + ); + background-size: 8px 8px; + background-position: 50% 50%; + background-repeat: repeat; + pointer-events: none; + z-index: 0; +} + +[data-words]:has([data-words-drawer][data-side='left']) > [data-words-content]::before { + inset-inline-start: auto; + inset-inline-end: 0; +} + /* When the drawer lives on the LEFT, mirror: rail moves to the RIGHT so the grip + "+" don't fight the drawer's gutter. */ [data-words]:has([data-words-drawer][data-side='left']) > [data-words-content],