Skip to content

fix: model selector tooltip renders raw HTML tags instead of text#489

Draft
laileni-aws wants to merge 3 commits into
aws:mainfrom
laileni-aws:fix/model-selector-tooltip-html-tags
Draft

fix: model selector tooltip renders raw HTML tags instead of text#489
laileni-aws wants to merge 3 commits into
aws:mainfrom
laileni-aws:fix/model-selector-tooltip-html-tags

Conversation

@laileni-aws

Copy link
Copy Markdown
Contributor

Summary

The model selector's hover tooltip displayed raw HTML tags (e.g. <strong> and <br>) as literal text instead of a formatted label and description. This makes the tooltip look broken to users. This PR fixes the tooltip to render correctly and adds unit tests to guard against regression.

Problem

When hovering over a select form item that has options with a description (such as the model selector in chat), the tooltip showed something like:

<strong>Claude Sonnet 4</strong><br>Hybrid reasoning and coding for regular use

instead of a bold label followed by its description.

Root cause

SelectInternal.getCurrentTooltip() in src/components/form-items/select.ts built the tooltip content using raw HTML tags:

return `<strong>${selectedOption.label}</strong><br>${selectedOption.description}`;

That string is passed to showTooltip(), which renders it through a CardBody. CardBody renders its body via the markdown parser (parseMarkdown), and the parser's HTML renderer is configured to escape raw HTML:

// src/helper/marked.ts -> configureMarked()
html: ({ text }) => escapeHTML(text),

As a result, the raw <strong> / <br> tags were escaped and shown to the user verbatim.

Fix

Use markdown syntax instead of raw HTML so the content renders correctly through the same parser:

return `**${selectedOption.label}**\n${selectedOption.description}`;

CardBody already invokes the parser with line breaks enabled (includeLineBreaks: true), so the newline becomes a line break and **…** renders as bold — producing the intended "bold label + description" tooltip without any raw HTML.

Testing

  • Added unit tests in src/__test__/components/form-items/select.spec.ts covering the tooltip content path:
    • the tooltip renders as markdown (a real <strong> element) and never leaks literal <strong> / <br> text;
    • the tooltip reflects the currently selected option;
    • it falls back to the base tooltip when the selected option has no description.
  • The new tests were confirmed to fail against the previous (raw-HTML) implementation and pass with this change.
  • Full unit test suite passes (npx jest): 72 suites / 845 tests.
  • eslint and prettier --check pass; production build (npm run build) succeeds.

Additional change

  • ui-tests/__test__/flows/quick-action-commands-header.ts: replaced an implicit truthiness check on an any-typed value with an explicit boolean comparison to satisfy @typescript-eslint/strict-boolean-expressions. This was a pre-existing lint error unrelated to the tooltip fix; correcting it keeps the lint gate green.

Notes

  • Change is limited to tooltip content generation; no public API changes.

The select component built its hover tooltip using raw HTML tags
(<strong> and <br>), but tooltip content is rendered through the
markdown parser (via CardBody), which escapes raw HTML. As a result
the literal tags were shown to users instead of a formatted label
and description.

Use markdown syntax (bold + line break) so the selected option's
label and description render as intended. Adds unit tests covering
the rendered tooltip content.
Use an explicit boolean comparison for the value returned by the
Playwright evaluate call, which is typed as any. Fixes an eslint
error that blocked the pre-push lint hook.
Wrap the Playwright evaluate result in Boolean() so the value is a
genuine boolean in every toolchain. This satisfies strict-boolean-
expressions without introducing an unnecessary boolean-literal
comparison, keeping the lint gate green across environments.
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