Skip to content

[Bug]: ColorPicker sliders break for any channel whose value is 0 (|| fallthrough in adjustChannel) #36646

Description

Component

ColorPicker (Preview)

Package version

@fluentui/react-color-picker 9.3.0

React version

18.3.1

Environment

node v22.12.0
@fluentui/react-color-picker 9.3.0
Chrome 147

Current Behavior

packages/react-components/react-color-picker/library/src/utils/adjustChannel.ts:32 selects the
per-channel action with a logical OR:

const action = actions[channel] || actions.hue;

actions[channel] is a defined function for every valid channel, so the || actions.hue arm was
presumably meant as a default for an unknown channel. But the expression is evaluated on the
channel's value, not its presence, in the code path that reaches it — so a channel whose value
is 0
takes the falsy branch and is handled by the hue action instead of its own.

The visible symptom: the slider for that channel renders with hue's domain rather than its own. The
emitted element is

<input value="210" max="100">

with the thumb painted at 210% — off the end of the track.

Expected Behavior

A channel valued 0 is an ordinary, in-range value and must resolve to its own action. The
fallback should be reached only when the channel key is genuinely absent.

Reproduction

Render a ColorPicker and drive any non-hue channel (saturation, value, alpha) to 0 — for
example by supplying a fully-desaturated or zero-alpha color — then inspect the corresponding
slider's value / max attributes.

Happy to add a StackBlitz on request; the defect is a two-character source expression and the
attribute readout above is the whole observable.

Steps to reproduce

  1. Render <ColorPicker> with a color whose saturation (or alpha) is 0.
  2. Inspect the slider <input> for that channel in DevTools.
  3. Observe value="210" max="100" and the thumb positioned at 210%.

Discovery context

Found during pixel-level verification of a styling layer built over
@fluentui/react-headless-components-preview. That work diffs every component against its
@fluentui/react-components twin at the pixel level, and a channel-sweep probe over ColorPicker
put both libraries into the same broken state simultaneously.

That is the part worth emphasising for triage: this is not a styling-layer defect. The probe
reproduced it identically on both libraries, because both consume the same
@fluentui/react-color-picker utility. It is a live bug for any consumer of that package today.

Proposed fix

Use a nullish coalescing operator, so the fallback fires on an absent key rather than on a falsy
value:

const action = actions[channel] ?? actions.hue;

One character-class change in one file. No API change, no type change.

A working implementation is included in PR #[WINDMOD-PR-NUMBER] (commit 20924b8a1a); happy to
split it into a standalone PR against this issue.

Suggested severity

Medium - Has workaround (a consumer can avoid exactly-zero channel values, which is not a real
workaround for a color picker).

Are you willing to submit a PR to fix?

yes

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions