Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(react-color-picker): Added transparent option to the AlphaSlider #33572

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
ValentinaKozlova marked this conversation as resolved.
Show resolved Hide resolved
"type": "patch",
"comment": "feat: Added `transparent` option to the AlphaSlider",
"packageName": "@fluentui/react-color-picker-preview",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ export type AlphaSliderSlots = ColorSliderSlots;
/**
* AlphaSlider Props
*/
export type AlphaSliderProps = ColorSliderProps;
export type AlphaSliderProps = ColorSliderProps & {
transparency?: boolean;
};

/**
* State used in rendering AlphaSlider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@ export const useAlphaSliderState_unstable = (state: AlphaSliderState, props: Alp
const { dir } = useFluent();
const onChangeFromContext = useColorPickerContextValue_unstable(ctx => ctx.requestChange);
const colorFromContext = useColorPickerContextValue_unstable(ctx => ctx.color);
const { color, onChange = onChangeFromContext } = props;
const { color, onChange = onChangeFromContext, transparency } = props;
const hsvColor = color || colorFromContext;
const hslColor = tinycolor(hsvColor).toHsl();

function adjustToTransparency(value: number) {
return transparency ? 100 - value : value;
}

const defaultState = props.defaultColor?.a !== undefined ? props.defaultColor.a * 100 : undefined;
const _state = hsvColor?.a !== undefined ? hsvColor.a * 100 : undefined;
dmytrokirpa marked this conversation as resolved.
Show resolved Hide resolved
const [currentValue, setCurrentValue] = useControllableState({
defaultState: props.defaultColor?.a ? props.defaultColor.a * 100 : undefined,
state: hsvColor?.a ? hsvColor.a * 100 : undefined,
defaultState: defaultState && adjustToTransparency(defaultState),
state: _state && adjustToTransparency(_state),
initialState: 100,
dmytrokirpa marked this conversation as resolved.
Show resolved Hide resolved
});
const clampedValue = clamp(currentValue, MIN, MAX);
Expand All @@ -30,15 +36,23 @@ export const useAlphaSliderState_unstable = (state: AlphaSliderState, props: Alp
const inputOnChange = state.input.onChange;

const _onChange: React.ChangeEventHandler<HTMLInputElement> = useEventCallback(event => {
const newValue = Number(event.target.value);
const newValue = adjustToTransparency(Number(event.target.value));
const newColor: HsvColor = { ...hsvColor, a: newValue / 100 };
setCurrentValue(newValue);
inputOnChange?.(event);
onChange?.(event, { type: 'change', event, color: newColor });
});

const sliderDirection = state.vertical
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider extracting this into a named utility function. This will enhance code readability and simplify unit testing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed. I was thinking about moving those functions to the separate files but then I'll need to pass plenty parameters there

Copy link
Contributor

Choose a reason for hiding this comment

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

I think pure functions with a few parameters are way better and easier to maintain than inner functions that rely on scope. If you have more than three arguments, it's a good idea to use an object for the parameters.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

moved functions to one file

? transparency
? '180deg'
: '0deg'
: dir === 'ltr' && !transparency
? '90deg'
: '-90deg';

const rootVariables = {
[alphaSliderCSSVars.sliderDirectionVar]: state.vertical ? '0deg' : dir === 'ltr' ? '90deg' : '-90deg',
[alphaSliderCSSVars.sliderDirectionVar]: sliderDirection,
[alphaSliderCSSVars.sliderProgressVar]: `${valuePercent}%`,
[alphaSliderCSSVars.thumbColorVar]: `transparent`,
[alphaSliderCSSVars.railColorVar]: `hsl(${hslColor.h} ${hslColor.s * 100}%, ${hslColor.l * 100}%)`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@ export const AlphaSliderExample = (props: Partial<AlphaSliderProps>) => {
const styles = useStyles();

const [color, setColor] = React.useState(COLOR);
const [transparancyColor, setTransparancyColor] = React.useState(COLOR);
const [value, setValue] = React.useState(COLOR.a * 100);
const onSliderChange: AlphaSliderProps['onChange'] = (_, data) => {
const alpha = data.color.a ?? 1;
setColor({ ...data.color, a: alpha });
setValue(alpha * 100);
};
const onTransparancySliderChange: AlphaSliderProps['onChange'] = (_, data) =>
setTransparancyColor({ ...data.color, a: data.color.a ?? 1 });
const resetSlider = () => setColor(COLOR);
const resetTransparencySlider = () => setTransparancyColor(COLOR);

return (
<div className={styles.example}>
Expand All @@ -48,6 +52,26 @@ export const AlphaSliderExample = (props: Partial<AlphaSliderProps>) => {
/>
<div className={styles.previewColor} style={{ backgroundColor: tinycolor(color).toRgbString() }} />
<Button onClick={resetSlider}>Reset</Button>
<h3>Transparency</h3>
<AlphaSlider
color={transparancyColor}
onChange={onTransparancySliderChange}
aria-valuetext={`${value}%`}
aria-label="Alpha"
transparency
{...props}
/>
<AlphaSlider
color={transparancyColor}
onChange={onTransparancySliderChange}
aria-valuetext={`${value}%`}
aria-label="Vertical alpha"
transparency
vertical
{...props}
/>
<div className={styles.previewColor} style={{ backgroundColor: tinycolor(transparancyColor).toRgbString() }} />
<Button onClick={resetTransparencySlider}>Reset</Button>
</div>
);
};
Expand Down
Loading