Skip to content

Render selected skills as composer pills - #422

Merged
maxwellpeterson merged 3 commits into
mainfrom
balint/composer-skill-pill
Sep 4, 2026
Merged

Render selected skills as composer pills#422
maxwellpeterson merged 3 commits into
mainfrom
balint/composer-skill-pill

Conversation

@FBalint

@FBalint FBalint commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Render a selected skill as a lightweight inline treatment while preserving the composer's existing textarea/mirror geometry. The command remains literal /name text at the textarea's inherited font size and wrapping behavior; the mirror adds only paint-only background, rounding, and hover treatment.

The informational hover tooltip remains, including the skill description and provider/resource details.

Rescope

The original implementation replaced /name with opaque backing text and overlaid an icon, resized label, padding, and nowrap pill. Review exposed that this can diverge from native textarea layout for long or unusual provider-supplied names, especially in narrow composers. Once the textarea and mirror wrap differently, following text, caret placement, scrolling, and pointer hit-testing no longer align.

This PR is therefore deliberately narrowed to visual treatment that does not alter text metrics or editor behavior:

  • Keep the exact /name text in both the textarea and mirror
  • Keep inherited font size, weight, line height, and wrapping
  • Add the pill-like fill and rounding without layout-affecting padding
  • Keep the delayed skill details tooltip
  • Use native text editing and clipboard behavior

Removed From Scope

  • Icon and replacement label inside the selected command
  • Opaque/non-breaking backing text
  • Atomic command deletion and replacement handling
  • Custom rich copy, cut, and paste behavior
  • Width reservation, truncation, and nowrap command layout

Those richer editor semantics should be revisited with an editor implementation that owns text layout rather than layering presentation over a native textarea.

Testing

  • 50 frontend test files pass (329 tests)
  • Workshop frontend application and Vite TypeScript checks pass

Devin Review

@github-actions github-actions Bot added the workshop/frontend Changes to the Workshop frontend label Sep 2, 2026
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Preview: pr422-balint-compos-9ca4629c

https://pr422-balint-compos-9ca4629c-router.cloudflare-os-previews.workers.dev

Dashboard · deleted when this PR closes

devin-ai-integration[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 2, 2026

Copy link
Copy Markdown

Findings

  1. High: Replacing a selected skill pill deletes the replacement text. composerDocument.ts:304-319 removes through newEnd, swallowing typed or pasted content.
  2. High: ChatComposer.tsx:862-900 trusts pasted command IDs without resolving them against the destination catalog. Cross-workspace paste can invoke the wrong provider; /compact can also bypass new-chat filtering.
  3. Medium: composerClipboard.ts:64-68 serializes plain text as review, not /review. Losing the custom MIME type therefore loses skill semantics.
  4. Medium: ComposerMirror.module.css:44-64 uses different font metrics and wrapping from the textarea, causing gaps, overlap, or incorrect caret geometry for long/hyphenated skills, especially at mobile’s 16px textarea size.
  5. High: The added draft test fails consistently at ChatComposer.test.tsx:188; CI likewise reports 334/335 tests passing. Command-only restoration waits on an unexecuted animation frame.

TypeScript validation passes.

github run

devin-ai-integration[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 2, 2026

Copy link
Copy Markdown

Findings

  1. High: ChatComposer.tsx:876-918 prevents paste before async catalog resolution. Typing or sending meanwhile invalidates the snapshot, silently losing the paste or sending the pre-paste prompt.
  2. Medium: ChatComposer.tsx:894-912 directly splices pasted pills without token spacing normalization. Pasting inside a word creates an abutting token and rejoins surrounding arguments on submission.
  3. Medium: ComposerMirror.tsx:134-165,231-253 exposes skill tooltips only through mouse hit-testing. Sighted keyboard users cannot open the provider/resource details.

github run

@FBalint FBalint mentioned this pull request Sep 2, 2026
ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 2, 2026

Copy link
Copy Markdown

Submitted 4 actionable inline findings.

github run

devin-ai-integration[bot]

This comment was marked as resolved.

ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 2, 2026

Copy link
Copy Markdown

Submitted 4 actionable inline findings.

github run

devin-ai-integration[bot]

This comment was marked as resolved.

ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 2, 2026

Copy link
Copy Markdown

Submitted 1 actionable inline finding.

github run

@FBalint
FBalint force-pushed the balint/composer-skill-pill branch from bc4298d to 2bd6550 Compare September 2, 2026 15:08
@FBalint

FBalint commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Scope reset: #422 is now a focused presentation change (412 additions). The custom rich clipboard format, pasted-command catalog validation, asynchronous paste coordination, and send waiting were removed. The visual pill and its informational hover tooltip remain in scope. Earlier findings that apply only to the deleted validation and paste paths are obsolete; please review the current branch for pill rendering, tooltip details, minimal backing-text mechanics, draft restoration, submission normalization, and plain copy/cut support.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 2, 2026

Copy link
Copy Markdown

Submitted 2 actionable inline findings.

github run

@ask-bonk

ask-bonk Bot commented Sep 2, 2026

Copy link
Copy Markdown

@FBalint Bonk workflow failed. Check the logs for details.

View workflow run · To retry, trigger Bonk again.

@maxwellpeterson
maxwellpeterson force-pushed the balint/composer-skill-pill branch from 3e89d93 to b81a15e Compare September 2, 2026 18:30
@ask-bonk

ask-bonk Bot commented Sep 2, 2026

Copy link
Copy Markdown

LGTM!

github run

Comment thread packages/workshop-frontend/src/features/chat/composer/draft/composerDraft.ts Outdated
@ask-bonk

ask-bonk Bot commented Sep 2, 2026

Copy link
Copy Markdown

Submitted 1 actionable inline finding.

github run

Base automatically changed from balint/composer-correctness to main September 2, 2026 18:49
@maxwellpeterson
maxwellpeterson force-pushed the balint/composer-skill-pill branch from b81a15e to 376790a Compare September 2, 2026 18:49
@maxwellpeterson
maxwellpeterson self-requested a review September 2, 2026 18:54
Comment thread packages/workshop-frontend/src/components/chat/composer-tokens.ts Outdated
Comment thread packages/workshop-frontend/src/features/chat/composer/composerDocument.ts Outdated
@ask-bonk

ask-bonk Bot commented Sep 2, 2026

Copy link
Copy Markdown

Submitted 2 actionable inline findings. Frontend tests and type checks pass.

github run

@maxwellpeterson maxwellpeterson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably want to differentiate built-in slash commands (right now just /compact) from skills:

Image

This could be as simple as changing the pill icon to match the compaction marker in chat history:

Image

@ndisidore

Copy link
Copy Markdown
Member

Initial pass with gpt findings. Happy to pressure test when this is ready to roll

 Findings

 1. [P2] Replacement text is discarded when replacing a skill pill
    packages/workshop-frontend/src/features/chat/composer/composerDocument.ts:304-319
    Selecting the pill in try <pill> today and typing run produces try  today. The atomic-range cleanup removes both the pill and newly inserted replacement. Preserve text in [editStart, newEnd) while removing only surviving pill fragments.
 2. [P2] Deleting a selection before a pill returns a stale caret position
    packages/workshop-frontend/src/features/chat/composer/composerDocument.ts:339-340
    Deleting try <pill> from try <pill> today produces  today but returns caret offset 4, placing subsequent input inside today. Derive the caret from the adjusted edit/deletion start, bounded by the resulting text.
 3. [P2] Custom pill cuts cannot be undone
    packages/workshop-frontend/src/features/chat/composer/ChatComposer.tsx:859-869
    The handler prevents the native cut and updates the controlled value programmatically. That update is absent from the browser editing history, so Ctrl/Cmd+Z cannot restore the pill or any ordinary text selected with it. Use an undo-integrated edit operation or maintain document-level undo state.
 4. [P2] Long skill pills break textarea/mirror geometry
    packages/workshop-frontend/src/features/chat/composer/inline-items/ComposerMirror.module.css:43-47
    The textarea wraps long unbreakable content, while .command is a nowrap inline block. On narrow composers, the mirror remains one overflowing line while the real caret moves across wrapped lines; hit-testing and following text no longer align. Preserve identical wrapping geometry or constrain the
    visible pill without changing backing-text layout.
 5. [P2] Skill names retain tabs, newlines, and other whitespace
    packages/workshop-frontend/src/components/chat/composer-tokens.ts:12
    Only ASCII spaces become non-breaking spaces. SlashCommandDescriptor.name has no whitespace constraint, so provider-supplied tabs/newlines remain in the backing textarea while the visible pill is nowrap, again desynchronizing layout and hit-testing. Normalize all whitespace or validate names at the
    catalog boundary.
 6. [P2] Long provider labels overflow the tooltip footer
    packages/workshop-frontend/src/features/chat/composer/inline-items/SkillTooltipContent.tsx:32
    providerLabelis unbounded but rendered shrink-0 inside a max-w-64 popup. Long Gatekeeper titles overflow or displace the resource label. Give the provider label a bounded, truncating flex treatment.
 7. [P3] Expanded mirror clipping exposes scrolled-off content
    packages/workshop-frontend/src/features/chat/composer/inline-items/ComposerMirror.module.css:2-6
    Extending the clip four pixels beyond the textarea allows glyphs or pill backgrounds to remain visible in surrounding padding after scrolling. Keep an exact textarea viewport clip and accommodate decoration inside it.

@FBalint
FBalint force-pushed the balint/composer-skill-pill branch from 376790a to b611811 Compare September 4, 2026 10:24
@FBalint

FBalint commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Rescope note on mirror geometry: the transparent native textarea remains the source of truth for glyph widths, wrapping, caret movement, selection, and scrolling. The mirror must lay out the exact same text with the same typography. Adding an icon, real padding, a resized replacement label, non-breaking backing text, or nowrap makes the mirror consume different width from the textarea; with long names or narrow composers, subsequent text and hit-testing drift onto different lines. This revision therefore keeps literal /name text and uses only paint-only background, rounding, and box-shadow. The tooltip is portaled and does not participate in composer layout. A richer atomic pill should wait for an editor implementation that owns layout rather than overlays a textarea.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

2 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)

Devin Review

Comment thread packages/workshop-frontend/src/features/chat/composer/ChatComposer.tsx Outdated
@ask-bonk

ask-bonk Bot commented Sep 4, 2026

Copy link
Copy Markdown
  1. P2 ChatComposer.tsx:764: spellCheck={false} disables browser spell checking for all prompt prose, introducing an unrelated composer regression. Keep spell checking enabled while styling selected commands.

github run

@ask-bonk

ask-bonk Bot commented Sep 4, 2026

Copy link
Copy Markdown

LGTM!

github run

@maxwellpeterson
maxwellpeterson merged commit cff8cf5 into main Sep 4, 2026
17 checks passed
@maxwellpeterson
maxwellpeterson deleted the balint/composer-skill-pill branch September 4, 2026 21:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

workshop/frontend Changes to the Workshop frontend

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants