Skip to content

feat(fuselage)!: Render message mentions as plain text instead of pills - #2155

Open
ivans-netto wants to merge 5 commits into
RocketChat:mainfrom
ivans-netto:mention-layout-unification
Open

feat(fuselage)!: Render message mentions as plain text instead of pills#2155
ivans-netto wants to merge 5 commits into
RocketChat:mainfrom
ivans-netto:mention-layout-unification

Conversation

@ivans-netto

@ivans-netto ivans-netto commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Proposed changes (including videos or screenshots)

Mentions are rendered inconsistently between the Web and Mobile clients: Web draws them as a coloured pill, Mobile renders them as ordinary text in a distinct colour. This aligns Web with the Mobile approach — the same treatment WhatsApp uses — so a mention reads as part of the sentence instead of as a badge dropped into it.

MessageHighlight now renders regular text: no background, no border radius, no horizontal padding. Each variant keeps its meaning through colour and a medium (p2m) weight.

Variant Used for Colour
critical mentions of you, highlighted words status-font-on-danger (red)
relevant @all / @here status-font-on-service-1 (orange)
link rooms / channels status-font-on-info (blue)
other mentions of other users status-font-on-warning (amber)

All four resolve through semantic tokens, so light, dark and high-contrast themes each get their own shade instead of a single hardcoded value.

Before

before

After

after

Both images are the committed visual-regression baselines, so they are exactly what CI renders. The wording differs between them because the story itself was reworked in this PR — it used to repeat the same critical mention five times and never showed @here.

With and without @ # symbols

A new With Mentions story writes the same sentence twice, with the mentions rendered without and with their @/# symbols — the two states the mention symbol setting toggles between:

with mentions

Also in here

  • Spacing around a mention is now font-derived. Two things were adding fixed space to something that should just be text. display: inline-block contributed the element's border to the line box, so a line containing a mention was ~1.5px taller than a line without one; it is display: inline now, and the Default story's body measures exactly 4 × 20px of line-height. And templates.focus-state reserved a 1px transparent border to keep the focus ring from shifting layout, which on an inline run put a fixed 1px on each side of every mention — the ring is drawn with an outline instead, which paints outside the box without taking up space. Each highlight box now matches its text width exactly, focused or not.
  • The link variant gets its own theme variable. It declared the theme key message-highlight-colors-other-color — the same one the other variant uses — so setting that custom property recoloured both at once. Harmless while both variants shared the same pill, but they are now visually distinct and need to be themable independently. It reads message-highlight-colors-link-color from this PR on.
  • The Message stories gain the With Mentions story above, and the Default story now shows one mention per variant instead of repeating the same one five times. It also stops labelling the channel mention as other, adds the missing @here, renames highlighted text to highlighted word to match the feature name, and restores the spaces the pill padding used to fake.

Breaking: the message-highlight-colors-background-* and message-highlight-border-radius theme variables no longer exist, since nothing paints a background anymore. Nothing in the Rocket.Chat codebase reads them.

Issue(s)

DSN-186

Further comments

Why colour + weight rather than a lighter pill. A pill competes with the message text for attention and forces vertical padding into a line box that is only 20px tall, which is what made mentions push their line taller. Colour plus medium weight carries the same "this is a mention" signal at text weight, and it is what Mobile already does, so the two clients stop diverging.

Accessibility. Removing the pill means the mention colour is now read against the room surface rather than against a solid badge, so I checked every combination. All pass WCAG AA for body text in both themes; the tightest is 5.34:1 (other on light).

Variant Light Dark
critical 8.35:1 5.90:1
relevant 6.47:1 5.82:1
link 6.17:1 5.77:1
other 5.34:1 7.04:1

Those figures are the palette values that actually apply at runtime. Worth flagging separately: colors.status-font(on-warning) falls back to y800 (#AC892F, 3.29:1 on white) when the palette custom properties are absent, because of the pre-existing TODO(design) in styles/colors.scss where the SCSS fallback and the token disagree (y800 vs y900). That fallback only shows up for a consumer loading fuselage.css without the palette, and it is not introduced here, but other is the first mention variant to depend on that particular token.

Visual regression. Ran the full suite in the CI Playwright container without --update-snapshots first, then regenerated only the affected baselines with --grep: the Default one, plus a new baseline for the With Mentions story. No other story produced a pixel diff. A handful of stories fail locally by timing out while loading, never by pixel difference, and the failing set changes between runs — local flakiness rather than regression. Layout/PositionAnimated Left Start did diff once by ~1px on an animated element and passed on other runs, so I left its baseline alone.

Follow-up outside this repo. Highlighted words are not rendered by Fuselage: the web client wraps them in <mark class="highlight-text">, styled in apps/meteor/app/theme/client/imports/general/base_old.css, and they are still a white-on-red pill. They need the same treatment in Rocket.Chat for the change to be consistent end to end.

@changeset-bot

changeset-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bb5a202

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@rocket.chat/fuselage Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

ivans-netto and others added 2 commits August 11, 2026 15:11
Align the Web mention layout with Mobile: drop the background pill and
render mentions as regular text with a distinct font color and medium
(p2m) weight, using the status-font tokens so both themes get proper
shades (critical/@me on-danger, relevant/@all-@here on-service-1,
link/rooms on-info, other keeps the default font color).

Highlights become display: inline, so a line containing a mention is no
longer taller than a line without one.

BREAKING CHANGE: the message-highlight-colors-background-* and
message-highlight-border-radius theme variables no longer exist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The link variant declared the theme key 'message-highlight-colors-other-color',
the same one used by the other variant, so setting that custom property
recolored both at once. Harmless while both variants shared the same pill
styling; now that link is blue and other uses the default font color, they
need to be themable independently.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ivans-netto
ivans-netto force-pushed the mention-layout-unification branch 2 times, most recently from 413f9aa to 358ca3e Compare August 11, 2026 18:29
ivans-netto and others added 3 commits August 12, 2026 14:19
…space

templates.focus-state keeps a 1px transparent border on the element so the
ring does not shift layout when it appears. On an inline run that border
sits inside the line, so every mention carried a fixed 1px on each side —
2px of spacing that does not come from the font. Invisible while the pill
painted its own box, noticeable once mentions are plain text.

Draw the ring with an outline instead: it paints outside the box without
taking up space, so focus still cannot shift layout and the gap around a
mention is now font-derived. Measured on the With Mentions story: each
highlight box matches its text width exactly, focused or not.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add a 'With Mentions' story that writes the same sentence twice, once with
the mentions rendered without their @/# symbols and once with them — the
two states the mention symbol setting toggles between. Every variant shows
up once in each, so the plain-text treatment can be judged in context.

Also fix the Default story, which repeated the same critical mention five
times and mislabeled the channel mention as the other variant — that one
renders in the other-user colour, not the link blue gazzodown uses for
channels. Keep one mention per variant, add the missing @here, rename
'highlighted text' to 'highlighted word' to match the feature name, and
add the spaces the removed pill padding used to fake.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Regenerated with the CI Playwright container for the new mention rendering,
the reworked stories and the font-derived spacing, plus a new baseline for
the With Mentions story. No other story produced a pixel diff.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ivans-netto
ivans-netto force-pushed the mention-layout-unification branch from 358ca3e to bb5a202 Compare August 12, 2026 17:20
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