Skip to content

feat(composer): ghost-text completion of the highlighted command item - #35

Merged
rpvilo merged 7 commits into
feature/composer-editorfrom
feature/composer-suggestion-ghost
Jul 10, 2026
Merged

feat(composer): ghost-text completion of the highlighted command item#35
rpvilo merged 7 commits into
feature/composer-editorfrom
feature/composer-suggestion-ghost

Conversation

@rpvilo

@rpvilo rpvilo commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Notion-style inline completion, stacked on #33: while the command popup is open, the highlighted item's remaining label renders as ghost text after the query — @Te shows st Document faded; Tab/Enter accepts as before.

Zero new API, zero engine changes:

  • suggestionRemainder(query, label) — pure helper in fuzzy.ts: completes only case-insensitive prefix matches (inline-completing a fuzzy hit would read as broken); empty query → full label; exact match → nothing.
  • ComposerCommand stamps data-command-suggestion onto the badge span via a layout effect (same badge-query pattern as the popover anchor). Re-stamping survives badge rewraps because those always coincide with a query/highlight re-render.
  • Ghost is pure CSS: ::after { content: attr(data-command-suggestion) } in the styled layer — no real DOM, so the caret, reader, selection, and IME are untouched by construction. A double-attribute rule outranks the "Type to filter" hint when both apply.
  • On TextareaLegacy the ghost degrades gracefully (PM recreates decoration spans on selection-only transactions without a React re-render) — not a target; the legacy editor is a frozen baseline.

Manual checks

  • @ with items → highlighted item's label ghosts after the caret (replaces "Type to filter")
  • Typing a prefix (@Te) → ghost shows the remainder; a fuzzy-only match shows no ghost
  • Arrow through items → ghost follows the highlight
  • Tab/Enter accepts; Escape dismisses and the ghost disappears
  • Ghost never becomes selectable/copyable text (it's ::after content)

@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
intentface-chat Ready Ready Preview, Comment Jul 10, 2026 2:06pm

Request Review

@rpvilo

rpvilo commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator Author

Reworked how the badge hints render, per DX feedback: the ::after/attr()/specificity-ladder CSS is gone. The badge now hosts one real span[data-slot="command-hint"] carrying either the ghost completion or the empty-query placeholder — exclusivity is a plain ?? chain in code, and styling is one ordinary slot rule (**:data-[slot=command-hint]:text-ink-tertiary …). The reader and position mappers treat non-editable non-chip elements as zero-width presentation (pure-tested), so the hint can never leak into the model; syncBadge drops it on unwrap and excludes it from the token-length fast path. data-command-suggestion (never released) is removed from the contract; data-slot="command-hint" replaces it in the docs.

@rpvilo
rpvilo merged commit a42f658 into feature/composer-editor Jul 10, 2026
2 checks passed
rpvilo added a commit that referenced this pull request Jul 10, 2026
…#35)

* feat(composer): ghost-text completion of the highlighted command item

* style(composer): borderless chip + badge surface in the input

* feat(composer): per-prefix suggestion flag gating ghost-text completion

* feat(composer): per-prefix command placeholder, exclusive with suggestion

* refactor(composer): badge hints as a real command-hint slot element, replacing ::after attribute CSS
rpvilo added a commit that referenced this pull request Jul 10, 2026
…33) (#37)

* feat(composer): hand-rolled contenteditable editor engine; TipTap becomes Composer.TextareaLegacy

* feat(composer): editable-routed event callbacks with consumer-first override semantics

* fix(composer): hide placeholder during IME composition; add native placeholder prop

* refactor(composer): single-writer hasContent; placeholder gates on engine isComposing

* feat(composer): submitOn prop for Enter/Shift+Enter mapping; soft break dismisses active trigger token

* fix(composer): repaint on br-count drift — collapse on emptied editor + phantom newlines

* fix(composer): whitespace-only docs count as content — placeholder no longer overlays line breaks

* feat(composer): ghost-text completion of the highlighted command item (#35)

* feat(composer): ghost-text completion of the highlighted command item

* style(composer): borderless chip + badge surface in the input

* feat(composer): per-prefix suggestion flag gating ghost-text completion

* feat(composer): per-prefix command placeholder, exclusive with suggestion

* refactor(composer): badge hints as a real command-hint slot element, replacing ::after attribute CSS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant