Repository navigation
Description
Summary: The approved 2026-07-09 syntax-highlighting spec
called for the code-block language-selector chip to be visible on
caret-inside-block or pointer-hover-over-block. The shipped
slice is caret-only. This was a recorded, deliberate deviation at
ship time (hover needs block-targeted dispatch, which is cleanest
once code blocks carry a stable blockId at creation time — today
set_code_block creates the node with empty attrs). Filing this as
a tracked follow-up per the spec, along with two related chip
lifecycle rough edges noted during review.
Severity: S4 — latent/deferred-scope item. The caret-only chip
is fully functional for its primary use case (selecting a language
while editing inside the block); no current user-facing failure,
but it's a known gap against the approved spec and a plausible
source of "why doesn't hovering show the language" reports later.
Environment:
- Deploy: N/A (design/implementation gap, not an environment-
specific bug) - Commit:
code-blocks-syntax-highlightingbranch, as shipped - Browser: N/A
Repro steps:
- Open a document with a code block.
- Move the pointer over the code block without placing the caret
inside it (e.g., hover from outside, or hover a code block that
isn't the one currently focused). - Observe the chip does not appear.
Expected (per spec): The chip becomes visible on caret-inside
OR pointer-hover-over the code block.
Observed: Chip visibility is driven purely by caret position —
see refresh_code_lang_chip in
frontend/src/components/editor_component.rs, which recomputes
CodeLangChipState from EditorState/DOM-selection anchor only,
with the comment explicitly noting "Visibility + current are
caret-based." There is no pointer-hover listener feeding this
signal.
Related lifecycle rough edges noted during review (same
component, not yet independently confirmed as bugs — noting for
the same follow-up rather than filing as separate tickets, since
fixing hover-visibility is likely to touch the same dispatch
path):
- Blur-hide race: the chip may linger visible if the editor
blurs without an intervening state-change dispatch (a blur-hide
handler racing against the<select>'s own click, since clicking
the select itself blurs the contenteditable). Needs a considered
debounce/ownership approach, not a quick patch, per the review
note. - Rect-read scoping:
refresh_code_lang_chipreads
getBoundingClientRect()on every dispatch inside the effect
(guarded by an early return when there's no code block at the
caret). If profiling ever flags this path, consider scoping the
rect-reads to only fire on code-block-adjacent dispatches.
Suggested approach: Give code blocks a stable blockId at
creation (currently set_code_block in
frontend/src/editor/commands.rs creates the CodeBlock node with
attrs: HashMap::new(), i.e., no id). With a stable id, hover
detection can dispatch through the same
find_element_by_block_id-style lookup already used by
update_mermaid_source (both in
frontend/src/editor/commands.rs) instead of relying on
caret/selection state, which is the blocker noted at ship time.
Suspected area:
frontend/src/components/code_lang_chip.rs— chip componentfrontend/src/components/editor_component.rs—
refresh_code_lang_chip(visibility/lifecycle logic)frontend/src/editor/commands.rs—set_code_block(attrs
creation),find_element_by_block_id,update_mermaid_source
(precedent pattern for block-targeted dispatch)
Scope expansion suggested: None beyond what's already rolled
into this ticket; the two lifecycle notes above are included here
rather than split out because they're expected to be touched by
the same fix.
Activity
jjbaumert commentedon Jul 10, 2026
Closing as won't-fix (product decision, 2026-07-10).
Decision: Caret-only visibility for the code-block language chip is accepted as the intended design. The hover-to-reveal behavior from the spec is deliberately not being implemented.
Rationale:
<select>must be targeted by block identity — today it mutates whatever block the caret is in, so hover-select would otherwise silently change the wrong block. That targeting (either a DOM→model position map or adding a stableblockIdto code blocks, the latter a deliberate CRDT wire-shape + schema-duality change) is the bulk of the work.Lifecycle rough edges noted in this ticket: left unaddressed. The blur-hide lingering race is a genuine latent item but has no confirmed user-facing repro; if it ever actually manifests, file a narrow ticket for just that (caret-only, no hover targeting needed) rather than reopening this.
fix(mermaid): close the four remaining gallery minors (#16, #18, #20, #…