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
- Render
<ColorPicker> with a color whose saturation (or alpha) is 0.
- Inspect the slider
<input> for that channel in DevTools.
- 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
Component
ColorPicker (Preview)
Package version
@fluentui/react-color-picker9.3.0React version
18.3.1
Environment
Current Behavior
packages/react-components/react-color-picker/library/src/utils/adjustChannel.ts:32selects theper-channel action with a logical OR:
actions[channel]is a defined function for every valid channel, so the|| actions.huearm waspresumably 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
0takes 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
with the thumb painted at 210% — off the end of the track.
Expected Behavior
A channel valued
0is an ordinary, in-range value and must resolve to its own action. Thefallback should be reached only when the channel key is genuinely absent.
Reproduction
Render a
ColorPickerand drive any non-hue channel (saturation, value, alpha) to0— forexample by supplying a fully-desaturated or zero-alpha color — then inspect the corresponding
slider's
value/maxattributes.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
<ColorPicker>with a color whose saturation (or alpha) is0.<input>for that channel in DevTools.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-componentstwin at the pixel level, and a channel-sweep probe over ColorPickerput 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-pickerutility. 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:
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 tosplit 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