Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions packages/raystack/components/color-picker/color-picker-alpha.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
'use client';

import { Slider } from '@base-ui/react/slider';
import { cx } from 'class-variance-authority';
import { Slider } from 'radix-ui';
import { type ComponentProps } from 'react';
import { useColorPicker } from './color-picker-root';
import styles from './color-picker.module.css';
import { useColorPicker } from './color-picker-root';

export type ColorPickerAlphaProps = ComponentProps<typeof Slider.Root>;
export type ColorPickerAlphaProps = Slider.Root.Props;

export const ColorPickerAlpha = ({
className,
Expand All @@ -17,16 +16,19 @@ export const ColorPickerAlpha = ({
<Slider.Root
className={cx(styles.sliderRoot, className)}
max={100}
onValueChange={([alpha]) => setColor({ alpha: alpha / 100 })}
onValueChange={value => setColor({ alpha: (value as number) / 100 })}
step={1}
value={[alpha * 100]}
value={alpha * 100}
thumbAlignment='edge'
{...props}
>
<Slider.Track className={cx(styles.sliderTrack, styles.alphaTrack)}>
<div className={styles.alphaTrackGradient} />
<Slider.Range className={styles.sliderRange} />
</Slider.Track>
<Slider.Thumb className={styles.sliderThumb} />
<Slider.Control className={styles.sliderControl}>
<Slider.Track className={cx(styles.sliderTrack, styles.alphaTrack)}>
<div className={styles.alphaTrackGradient} />
<Slider.Indicator className={styles.sliderRange} />
<Slider.Thumb className={styles.sliderThumb} aria-label='Alpha' />
</Slider.Track>
</Slider.Control>
Comment on lines +19 to +31
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Base UI Slider onValueChange callback value type documentation

💡 Result:

In Base UI’s Slider (Slider.Root), the onValueChange callback receives the new value as:

  • number | number[] (an array is used for range sliders)

Signature (from the API docs):

  • onValueChange?: (value: number | number[], eventDetails: Slider.Root.ChangeEventDetails) => void [1]

Base UI change handlers also always receive an eventDetails object as the second argument (with fields like reason, event, cancel(), etc.) [2].

Sources: [1], [2]


🏁 Script executed:

# Find and examine the color-picker-alpha.tsx file
fd -t f "color-picker-alpha.tsx" --exec cat -n {} \;

Repository: raystack/apsara

Length of output: 1373


🏁 Script executed:

# Check the package.json to see Base UI version
cat package.json | grep -A 5 -B 5 "@base-ui" || cat package.json | grep -i slider

Repository: raystack/apsara

Length of output: 41


🏁 Script executed:

# Search for any range prop configuration in color-picker components
fd -t f "color-picker.*\\.tsx" --exec grep -l "range" {} \;

Repository: raystack/apsara

Length of output: 41


🏁 Script executed:

# Check for any constraints or configuration preventing range in Slider.Root
rg "range" packages/raystack/components/color-picker/ -A 2 -B 2

Repository: raystack/apsara

Length of output: 41


🏁 Script executed:

# Look for Base UI version in lock files or any config
fd -t f "package-lock.json|yarn.lock|pnpm-lock.yaml" --exec grep -A 1 "@base-ui/react" {} \; | head -20

Repository: raystack/apsara

Length of output: 376


Guard against range values in onValueChange.

Base UI's Slider can emit number | number[] in the onValueChange callback. Since ColorPickerAlphaProps exposes the full Slider.Root.Props, a consumer could pass range={true}, causing the value to be an array. The current cast to number would produce NaN if an array is passed. Add a guard to handle both cases:

♻️ Suggested guard for single-value normalization
-      onValueChange={value => setColor({ alpha: (value as number) / 100 })}
+      onValueChange={value => {
+        const next = Array.isArray(value) ? value[0] : value;
+        if (typeof next === 'number') {
+          setColor({ alpha: next / 100 });
+        }
+      }}
🤖 Prompt for AI Agents
In `@packages/raystack/components/color-picker/color-picker-alpha.tsx` around
lines 19 - 31, The Slider.onValueChange currently casts value to number which
will yield NaN when Base UI emits a range (number[]) — update the onValueChange
handler in the ColorPickerAlpha component to normalize the input: detect
Array.isArray(value) and extract a single numeric value (e.g., value[0]) or
otherwise coerce to a number, then compute alpha as that number / 100 and call
setColor({ alpha }). Ensure this change is applied where onValueChange is
defined and reference the ColorPickerAlphaProps/Slider.Root.Props types so the
handler safely supports both number and number[] inputs.

</Slider.Root>
);
};
22 changes: 12 additions & 10 deletions packages/raystack/components/color-picker/color-picker-hue.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
'use client';

import { Slider } from '@base-ui/react/slider';
import { cx } from 'class-variance-authority';
import { Slider } from 'radix-ui';
import { type ComponentProps } from 'react';
import { useColorPicker } from './color-picker-root';
import styles from './color-picker.module.css';
import { useColorPicker } from './color-picker-root';

export type ColorPickerHueProps = ComponentProps<typeof Slider.Root>;
export type ColorPickerHueProps = Slider.Root.Props;
export const ColorPickerHue = ({
className,
...props
Expand All @@ -16,15 +15,18 @@ export const ColorPickerHue = ({
<Slider.Root
className={cx(styles.sliderRoot, className)}
max={360}
onValueChange={([hue]) => setColor({ h: hue })}
onValueChange={value => setColor({ h: value as number })}
step={1}
value={[hue]}
value={hue}
thumbAlignment='edge'
{...props}
>
<Slider.Track className={cx(styles.sliderTrack, styles.hueTrack)}>
<Slider.Range className={styles.sliderRange} />
</Slider.Track>
<Slider.Thumb className={styles.sliderThumb} />
<Slider.Control className={styles.sliderControl}>
<Slider.Track className={cx(styles.sliderTrack, styles.hueTrack)}>
<Slider.Indicator className={styles.sliderRange} />
<Slider.Thumb className={styles.sliderThumb} aria-label='Hue' />
</Slider.Track>
</Slider.Control>
</Slider.Root>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
user-select: none;
align-items: center;
}
.sliderControl {
display: flex;
align-items: center;
width: 100%;
}
.sliderRange {
position: absolute;
height: 100%;
Expand Down Expand Up @@ -33,6 +38,7 @@
}

.sliderThumb {
position: absolute;
display: block;
height: 12px;
width: 12px;
Expand Down