Skip to content

feat(fuselage): Update input pseudo states - #2162

Merged
juliajforesti merged 4 commits into
mainfrom
feat/core-2375-input-pseudo-states
Aug 18, 2026
Merged

feat(fuselage): Update input pseudo states#2162
juliajforesti merged 4 commits into
mainfrom
feat/core-2375-input-pseudo-states

Conversation

@abhinavkrin

@abhinavkrin abhinavkrin commented Aug 13, 2026

Copy link
Copy Markdown
Member

Proposed changes (including videos or screenshots)

Updates the pseudo states of the input components to match the design spec.

  • Placeholder text now uses font-hint and value text font-titles-labels. The placeholder previously used font-annotation, which is ~2.6:1 against white and fails WCAG AA; font-hint is ~4.7:1 and passes. The value colour was darkened alongside it to keep the contrast relationship.
  • Disabled inputs use font-disabled instead of font-default, so disabled text is now visually distinct from enabled text.
  • Invalid inputs no longer tint their value text red; only the border stays red, per the design file.
  • Icons inside inputs follow the input's font colour in every state, including focus, where they were previously blue.
  • Adds a hover state. The on-hover hook already existed in the shared input primitive but resolved to the same colour as the resting border, so hovering was a no-op. It now resolves to stroke-dark.
  • Every input type now shares the same transition. The 0.18s fade comes from the animated Box prop, and only InputBox passed it, so Select, MultiSelect, AutoComplete and PaginatedSelect snapped between colours instantly. They inherit their border and colour tokens from %rcx-input-box through @extend, but @extend cannot reach .rcx-box--animated because that class is applied from JSX. Passing animated on the five outer boxes that carry the input border means all of them share one definition, including its prefers-reduced-motion guard, rather than a duplicated timing value.

Two related fixes found while working through the states matrix:

  • A pressed input no longer loses its state. active-border-color used the lighter stroke-medium, so pressing made the border lighter than hover, and an invalid input dropped its red border entirely while pressed.
  • The ::placeholder rule in InputBox/mixins.scss had been commented out behind a "fix placeholder performance issue" TODO since 2019, so native placeholders rendered in the browser's default colour and no placeholder token ever reached them. It is re-enabled; under plain SCSS it compiles to 8 rules totalling ~2.3KB.

Because InputBox is the base for the whole input family, the token changes apply to Select, MultiSelect, AutoComplete and PaginatedSelect as well. Those components set some colours from JSX props rather than the shared mixins, so five hardcoded default values were swapped to titles-labels to keep them consistent.

Issue(s)

CORE-2375

Further comments

A few token pairs now resolve to the same value. These are intentional, not oversights:

  • focus-icon-color equals the base text colour, because the ticket asks that icons follow the font colour "always" and the design file shows a dark icon in the focus row.
  • hover-border-color and active-border-color are both stroke-dark, and invalid-active-border-color matches the invalid border. The design file has no pressed state, and the alternative was letting a press downgrade the state the user is already in.

Known and deliberately out of scope, both pre-existing:

  • A disabled Select/AutoComplete does not dim its value text. Box's color prop emits !important, so the disabled token cannot win by specificity; fixing it means removing those props and wiring the tokens through .rcx-select. Worth its own PR.
  • with-icon-addon-colors on .rcx-select emits sibling selectors while the addon is a descendant, so it never matches, and .rcx-autocomplete__addon has no rule at all.

Because transition: all now applies to the Select family's outer box, a size change animates too. A MultiSelect growing as chips are added is the visible case. InputBox has always behaved this way, so this is the consistency the ticket asks for rather than a new effect, but it is the one change that goes beyond colour.

Visual regression: run locally in the Playwright Docker image. 15 baselines changed, all of them input stories, and they are committed here. Every diff is colour-only, with identical image dimensions before and after, so there is no layout shift. The full suite is green at 506 passed. The transition change adds no further baseline churn, since screenshots are taken with animations: 'disabled' and a transition only affects intermediate frames.

Downstream note: the equivalent placeholder colour in Rocket.Chat's MessageComposerInput is hardcoded to font-annotation and should move to font-hint when the version is bumped.

CORE-2375

DSN-200

Signed-off-by: Abhinav Kumar <abhinav@avitechlab.com>
@changeset-bot

changeset-bot Bot commented Aug 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 957e5cf

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

The input pseudo state token changes alter placeholder, value, disabled and
border colours across the input stories. Regenerated in the Playwright Docker
image; 15 baselines changed, all colour-only with no layout shift.

Signed-off-by: Abhinav Kumar <abhinav@avitechlab.com>
The 0.18s colour transition came from the `animated` Box prop, which only
InputBox passed. The Select family inherits its border and colour tokens from
%rcx-input-box via @extend, but @extend cannot reach .rcx-box--animated because
that class is applied from JSX, so those inputs changed colour instantly.

Passes `animated` on the five outer boxes that carry the input border, so every
input type shares a single transition definition and its reduced-motion guard.

Signed-off-by: Abhinav Kumar <abhinav@avitechlab.com>
@mergify

mergify Bot commented Aug 18, 2026

Copy link
Copy Markdown

Queued — the merge queue status continues in this comment ↓.

@mergify

mergify Bot commented Aug 18, 2026

Copy link
Copy Markdown

queue

⚠️ Configuration not compatible with a branch protection setting

Details

The branch protection setting Require branches to be up to date before merging is not compatible with draft PR checks. To keep this branch protection enabled, update your Mergify configuration to enable in-place checks: set merge_queue.max_parallel_checks: 1, set every queue rule batch_size: 1, and avoid two-step CI (make merge_conditions identical to queue_conditions). Otherwise, disable this branch protection.

@juliajforesti
juliajforesti merged commit cdc86c7 into main Aug 18, 2026
7 checks passed
@juliajforesti
juliajforesti deleted the feat/core-2375-input-pseudo-states branch August 18, 2026 19:47
@mergify

mergify Bot commented Aug 18, 2026

Copy link
Copy Markdown

Merge Queue Status

  • 🟠 Waiting for queue conditions
  • ⏳ Enter queue
  • ⏳ Run checks
  • ⏳ Merge
Waiting for
  • -closed [📌 queue requirement]
All conditions
  • -closed [📌 queue requirement]
  • -conflict [📌 queue requirement]
  • -draft [📌 queue requirement]
  • any of [📌 queue -> configuration change requirements]:
    • -mergify-configuration-changed
    • check-success = Configuration changed
  • any of [🔀 queue conditions]:
    • all of [📌 queue conditions of queue rule default]:
      • #review-threads-unresolved = 0 [🛡 GitHub branch protection]
      • github-review-approved [🛡 GitHub branch protection]
      • any of [🛡 GitHub branch protection]:
        • check-success = Build and Test
        • check-neutral = Build and Test
        • check-skipped = Build and Test
      • any of [🛡 GitHub branch protection]:
        • check-success = license/cla
        • check-neutral = license/cla
        • check-skipped = license/cla

@github-actions github-actions Bot mentioned this pull request Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants