ColorPicker
View .mdLets users browse and select a color across a spectrum. Subcomponents: ColorArea, ColorSlider, AlphaSlider.
Default
Loading interactive example. Full source is available below.
View example source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { useId } from "@coreai-ds/react-components";
import * as React from 'react';
import { tinycolor } from "@ctrl/tinycolor";
import type { ColorPickerProps } from "@coreai-ds/react-components";
import type { SpinButtonOnChangeData } from "@coreai-ds/react-components";
import type { SpinButtonChangeEvent } from "@coreai-ds/react-components";
import { ColorPicker } from "@coreai-ds/react-components";
import { ColorArea } from "@coreai-ds/react-components";
import { ColorSlider } from "@coreai-ds/react-components";
import { AlphaSlider } from "@coreai-ds/react-components";
import { Label } from "@coreai-ds/react-components";
import { Input } from "@coreai-ds/react-components";
import { SpinButton } from "@coreai-ds/react-components";
export const Default = () => {
type RgbKey = 'r' | 'g' | 'b';
const hexColorRegex = /^#?([0-9A-Fa-f]{0,8})$/;
const numberRegex = /^\d+$/;
const defaultColorHsv = { h: 109, s: 1, v: 0.9, a: 1 };
const hexId = useId('hex-input');
const redId = useId('red-input');
const greenId = useId('green-input');
const blueId = useId('blue-input');
const alphaId = useId('alpha-input');
const [color, setColor] = React.useState(defaultColorHsv);
const [hex, setHex] = React.useState(tinycolor(color).toHexString());
const [rgb, setRgb] = React.useState(tinycolor(color).toRgb());
const [alpha, setAlpha] = React.useState(color.a);
const [namedColor, setNamedColor] = React.useState('');
const handleChange: ColorPickerProps['onColorChange'] = (_, data) => {
setColor({ ...data.color, a: data.color.a ?? 1 });
setHex(tinycolor(data.color).toHexString());
setRgb(tinycolor(data.color).toRgb());
setAlpha(data.color.a ?? 1);
const nextNamedColor = tinycolor(`hsl(${data.color.h},100%,50%)`).toName();
if (nextNamedColor) {
setNamedColor(nextNamedColor);
}
};
const onRgbChange = (name: RgbKey, data: SpinButtonOnChangeData) => {
const value = data.value ?? parseFloat(data.displayValue ?? '');
if (value === null || Number.isNaN(value) || !numberRegex.test(value.toString())) {
return;
}
const newColor = tinycolor({ ...rgb, [name]: value });
if (newColor.isValid) {
setColor(newColor.toHsv());
setHex(newColor.toHex());
setRgb(newColor.toRgb());
}
};
const onAlphaChange = React.useCallback((_event: SpinButtonChangeEvent, data: SpinButtonOnChangeData) => {
const value = data.value ?? parseFloat(data.displayValue ?? '');
if (Number.isNaN(value) || value < 0 || value > 1) {
return;
}
const newColor = tinycolor({ ...color, a: value });
if (newColor.isValid) {
setColor(newColor.toHsv());
setHex(newColor.toHex());
setRgb(newColor.toRgb());
setAlpha(newColor.a);
}
}, [color]);
const handleOnBlur = (event: React.FocusEvent<HTMLInputElement>) => {
const value = tinycolor(event.target.value);
if (!value.isValid) {
event.target.setAttribute('aria-invalid', 'true');
}
else {
event.target.removeAttribute('aria-invalid');
}
};
const colorAriaAttributes = {
'aria-roledescription': '2D slider',
'aria-valuetext': `Saturation ${color.s * 100}, Brightness: ${color.v * 100}, ${namedColor}`,
};
const rgbFields: Array<{
id: string;
label: string;
name: RgbKey;
value: number;
}> = [
{ id: redId, label: 'Red', name: 'r', value: rgb.r },
{ id: greenId, label: 'Green', name: 'g', value: rgb.g },
{ id: blueId, label: 'Blue', name: 'b', value: rgb.b },
];
const styles = /* css */ `
.color-picker-default-example {
width: 300px;
display: flex;
flex-direction: column;
gap: 10px;
}
.color-picker-default-example__preview {
width: 50px;
height: 50px;
border-radius: var(--borderRadiusMedium);
border: 1px solid #ccc;
}
.color-picker-default-example__fields {
display: flex;
align-items: flex-end;
flex-direction: row;
gap: 10px;
}
.color-picker-default-example__field {
display: flex;
flex-direction: column;
gap: var(--spacingHorizontalSNudge);
}
.color-picker-default-example__hex-input {
width: 96px;
}
.color-picker-default-example__spin-button {
min-width: 60px;
}
@media (forced-colors: active) {
.color-picker-default-example__preview {
forced-color-adjust: none;
}
}
`;
return (<>
<style>{styles}</style>
<div className="color-picker-default-example">
<ColorPicker color={color} onColorChange={handleChange}>
<ColorArea inputX={{ 'aria-label': 'Saturation', ...colorAriaAttributes }} inputY={{ 'aria-label': 'Brightness', ...colorAriaAttributes }}/>
<ColorSlider aria-label="Hue" aria-valuetext={`${color.h}°, ${namedColor}`}/>
<AlphaSlider aria-label="Alpha" aria-valuetext={`${color.a * 100}%`}/>
</ColorPicker>
<div className="color-picker-default-example__fields">
<div className="color-picker-default-example__field">
<Label htmlFor={hexId}>Hex</Label>
<Input className="color-picker-default-example__hex-input" value={hex} id={hexId} onChange={(event) => {
const value = event.target.value;
const newColor = tinycolor(value);
if (newColor.isValid) {
setColor(newColor.toHsv());
setRgb(newColor.toRgb());
setAlpha(newColor.a);
}
setHex((oldValue) => (hexColorRegex.test(value) ? value : oldValue));
}} onBlur={handleOnBlur}/>
</div>
{rgbFields.map((field) => (<div className="color-picker-default-example__field" key={field.name}>
<Label htmlFor={field.id}>{field.label}</Label>
<SpinButton className="color-picker-default-example__spin-button" min={0} max={255} value={field.value} id={field.id} onChange={(_, data) => onRgbChange(field.name, data)} name={field.name}/>
</div>))}
<div className="color-picker-default-example__field">
<Label htmlFor={alphaId}>Alpha</Label>
<SpinButton min={0} max={1} className="color-picker-default-example__spin-button" value={alpha} step={0.01} onChange={onAlphaChange} id={alphaId}/>
</div>
</div>
<div className="color-picker-default-example__preview" style={{ backgroundColor: tinycolor(color).toRgbString() }}/>
</div>
</>);
};
export default Default;
API referenceGenerated CoreAI prop and type summaries
API
Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. ? means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.
ColorPicker API
ColorPicker component
interface ColorPickerProps {
as?: "div";
children?: any;
className?: string;
/**
* Selected color.
*/
color?: HsvColor;
/**
* Callback for when the user changes the color.
*/
onColorChange?: EventHandler<ColorPickerOnChangeData>;
ref?: Ref<HTMLDivElement>;
/**
* ColorPicker shape
*/
shape?: "rounded" | "square";
style?: CSSProperties;
}
AlphaSlider API
AlphaSlider component
interface AlphaSliderProps {
as?: "input";
children?: undefined;
className?: string;
/**
* Color of the ColorPicker
*/
color?: HsvColor;
/**
* The starting color for an uncontrolled ColorSlider.
*/
defaultColor?: HsvColor;
input?: ({ as?: "input"; } & Omit<Omit<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & { ref?: ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null; }, "children"> & { children?: undefined; }) | undefined;
/**
* Triggers a callback when the value has been changed. This will be called on every individual step.
*/
onChange?: EventHandler<SliderOnChangeData>;
rail?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;
ref?: Ref<HTMLInputElement>;
root?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;
/**
* ColorPicker shape
*/
shape?: "rounded" | "square";
style?: CSSProperties;
thumb?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;
/**
* The `transparency` property determines how the alpha channel is interpreted.
* - When `false`, the alpha channel represents the opacity of the color.
* - When `true`, the alpha channel represents the transparency of the color.
* For example, a 30% transparent color has 70% opacity.
*/
transparency?: boolean;
/**
* Render the Slider in a vertical orientation, smallest value on the bottom.
* @default `false`
*/
vertical?: boolean;
}
ColorArea API
ColorArea component
interface ColorAreaProps {
as?: "div";
children?: any;
className?: string;
/**
* The current color of the ColorArea.
*/
color?: HsvColor;
/**
* The starting value for an uncontrolled ColorArea.
*/
defaultColor?: HsvColor;
inputX?: ({ as?: "input"; } & Omit<Omit<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & { ref?: ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null; }, "children"> & { children?: undefined; }) | undefined;
inputY?: ({ as?: "input"; } & Omit<Omit<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & { ref?: ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null; }, "children"> & { children?: undefined; }) | undefined;
/**
* Triggers a callback when the value has been changed. This will be called on every individual step.
*/
onChange?: EventHandler<ColorAreaOnColorChangeData>;
ref?: Ref<HTMLDivElement>;
/**
* ColorPicker shape
*/
shape?: "rounded" | "square";
style?: CSSProperties;
thumb?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;
}
ColorSlider API
ColorSlider component
interface ColorSliderProps {
as?: "input";
/**
* Color channel of the Slider.
* @default `hue`
*/
channel?: "value" | "hue" | "saturation";
children?: undefined;
className?: string;
/**
* Color of the ColorPicker
*/
color?: HsvColor;
/**
* The starting color for an uncontrolled ColorSlider.
*/
defaultColor?: HsvColor;
input?: ({ as?: "input"; } & Omit<Omit<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & { ref?: ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null; }, "children"> & { children?: undefined; }) | undefined;
/**
* Triggers a callback when the value has been changed. This will be called on every individual step.
*/
onChange?: EventHandler<SliderOnChangeData>;
rail?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;
ref?: Ref<HTMLInputElement>;
root?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;
/**
* ColorPicker shape
*/
shape?: "rounded" | "square";
style?: CSSProperties;
thumb?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;
/**
* Render the Slider in a vertical orientation, smallest value on the bottom.
* @default `false`
*/
vertical?: boolean;
}
Implementation
CoreAI 0.12.0; Fluent 9.74.9.
Import components from @coreai-ds/react-components. CoreAI guidance above takes precedence over API demonstration examples.
Alpha Slider Default
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { AlphaSliderProps } from "@coreai-ds/react-components";
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';
import { AlphaSlider } from "@coreai-ds/react-components";
import { tinycolor } from "@ctrl/tinycolor";
import { Button } from "@coreai-ds/react-components";
const useStyles = makeStyles({
example: {
width: '300px',
display: 'flex',
flexDirection: 'column',
gap: '10px',
},
previewColor: {
width: '50px',
height: '50px',
borderRadius: '4px',
border: '1px solid #ccc',
'@media (forced-colors: active)': {
forcedColorAdjust: 'none',
},
},
});
const COLOR = { h: 96, s: 1, v: 0.9, a: 1 };
export const AlphaSliderDefault = (props: Partial<AlphaSliderProps>): JSXElement => {
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}>
<AlphaSlider color={color} onChange={onSliderChange} aria-valuetext={`${value}%`} aria-label="Alpha" {...props}/>
<AlphaSlider color={color} onChange={onSliderChange} aria-valuetext={`${value}%`} aria-label="Vertical alpha" vertical {...props}/>
<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>);
};
export default AlphaSliderDefault;
Color And Swatch Picker
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import { tinycolor } from "@ctrl/tinycolor";
import type { ColorPickerProps } from "@coreai-ds/react-components";
import type { SwatchPickerOnSelectEventHandler } from "@coreai-ds/react-components";
import { ColorPicker } from "@coreai-ds/react-components";
import { ColorArea } from "@coreai-ds/react-components";
import { ColorSlider } from "@coreai-ds/react-components";
import { AlphaSlider } from "@coreai-ds/react-components";
import { SwatchPicker } from "@coreai-ds/react-components";
import { ColorSwatch } from "@coreai-ds/react-components";
import { EmptySwatch } from "@coreai-ds/react-components";
import { Label } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
const useStyles = makeStyles({
example: {
width: '300px',
display: 'flex',
flexDirection: 'column',
gap: '10px',
},
previewColor: {
width: '50px',
height: '50px',
borderRadius: tokens.borderRadiusMedium,
border: `1px solid ${tokens.colorNeutralStroke1}`,
margin: `${tokens.spacingVerticalMNudge} 0`,
'@media (forced-colors: active)': {
forcedColorAdjust: 'none',
},
},
button: {
marginRight: tokens.spacingHorizontalS,
},
input: {
display: 'block',
margin: `${tokens.spacingVerticalSNudge} 0`,
},
row: {
display: 'flex',
gap: '10px',
justifyContent: 'space-between',
},
sliders: {
display: 'flex',
flexDirection: 'column',
width: '80%',
},
});
const DEFAULT_COLOR_HSV = { h: 109, s: 1, v: 0.9, a: 1 };
const DEFAULT_SELECTED_VALUE = '2be700';
const DEFAULT_SELECTED_COLOR = tinycolor(DEFAULT_COLOR_HSV).toHex();
const ITEMS_LIMIT = 8;
export const ColorAndSwatchPicker = (): JSXElement => {
const styles = useStyles();
const [color, setColor] = React.useState(DEFAULT_COLOR_HSV);
const [selectedValue, setSelectedValue] = React.useState(DEFAULT_SELECTED_VALUE);
const [selectedColor, setSelectedColor] = React.useState(DEFAULT_SELECTED_COLOR);
const colorFocusTargetRef = React.useRef<HTMLButtonElement>(null);
const [colorFocusTarget, setColorFocusTarget] = React.useState<string | null>(null);
const [items, setItems] = React.useState<Array<{
color: string;
value: string;
'aria-label': string;
}>>([]);
const emptyItems = new Array(ITEMS_LIMIT - items.length).fill(null);
const handleChange: ColorPickerProps['onColorChange'] = (_, data) => {
setColor({ ...data.color, a: data.color.a ?? 1 });
};
const handleSelect: SwatchPickerOnSelectEventHandler = (_, data) => {
setSelectedValue(data.selectedValue);
setSelectedColor(data.selectedSwatch);
};
const handleAddColor = () => {
const newColor = tinycolor(color).toRgbString();
const newValue = `custom-${newColor} [${items.length - ITEMS_LIMIT}]`;
setItems([...items, { color: newColor, value: newValue, 'aria-label': newColor }]);
setColorFocusTarget(newValue);
};
const resetColors = () => {
setItems([]);
setColorFocusTarget(null);
setSelectedValue(DEFAULT_SELECTED_VALUE);
setSelectedColor(DEFAULT_SELECTED_COLOR);
setColor(DEFAULT_COLOR_HSV);
};
React.useEffect(() => {
if (colorFocusTarget) {
colorFocusTargetRef.current?.focus();
}
}, [colorFocusTarget]);
return (<div className={styles.example}>
<ColorPicker color={color} onColorChange={handleChange}>
<ColorArea inputX={{ 'aria-label': 'Saturation' }} inputY={{ 'aria-label': 'Brightness' }}/>
<div className={styles.row}>
<div className={styles.sliders}>
<ColorSlider aria-label="Hue"/>
<AlphaSlider aria-label="Alpha"/>
</div>
<div className={styles.previewColor} style={{ backgroundColor: tinycolor(color).toRgbString() }}/>
</div>
</ColorPicker>
<SwatchPicker aria-label="SwatchPicker with empty swatches" selectedValue={selectedValue} onSelectionChange={handleSelect} shape="rounded">
{items.map(item => (<ColorSwatch key={item.value} ref={item.value === colorFocusTarget ? colorFocusTargetRef : null} {...item}/>))}
{emptyItems.map((_, index) => (<EmptySwatch disabled key={index} aria-label="empty swatch"/>))}
</SwatchPicker>
<Label>Selected color</Label>
<div className={styles.previewColor} style={{ backgroundColor: selectedColor }}/>
<Button id="components-colorpicker--color-and-swatch-picker-add-new-color" className={styles.button} appearance="primary" disabled={items.length >= ITEMS_LIMIT} onClick={handleAddColor}>
Add new color
</Button>
<Button id="components-colorpicker--color-and-swatch-picker-reset-example" className={styles.button} onClick={resetColors}>
Reset example
</Button>
</div>);
};
export default ColorAndSwatchPicker;
Color Area Default
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import type { ColorAreaProps } from "@coreai-ds/react-components";
import { tinycolor } from "@ctrl/tinycolor";
import { ColorArea } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
const useStyles = makeStyles({
example: {
width: '300px',
display: 'flex',
flexDirection: 'column',
gap: '10px',
},
previewColor: {
width: '50px',
height: '50px',
borderRadius: '4px',
border: `1px solid ${tokens.colorNeutralStroke1}`,
'@media (forced-colors: active)': {
forcedColorAdjust: 'none',
},
},
});
const DEFAULT_COLOR_HSV = { h: 324, s: 0.5, v: 0.5, a: 1 };
export const ColorAreaDefault = (): JSXElement => {
const styles = useStyles();
const [color, setColor] = React.useState(DEFAULT_COLOR_HSV);
const [namedColor, setNamedColor] = React.useState('');
const onChange: ColorAreaProps['onChange'] = (_, data) => {
setColor({ ...data.color, a: data.color.a ?? 1 });
const _namedColor = tinycolor(`hsl(${data.color.h},100%,50%)`).toName();
if (_namedColor) {
setNamedColor(_namedColor);
}
};
const resetSlider = () => setColor(DEFAULT_COLOR_HSV);
const ariaAttributes = {
'aria-roledescription': '2D slider',
'aria-valuetext': `Saturation ${color.s * 100}, Brightness: ${color.v * 100}, ${namedColor}`,
};
return (<div className={styles.example}>
<ColorArea color={color} onChange={onChange} inputX={{ 'aria-label': 'Saturation', ...ariaAttributes }} inputY={{ 'aria-label': 'Brightness', ...ariaAttributes }}/>
<div className={styles.previewColor} style={{ backgroundColor: tinycolor(color).toHexString() }}/>
<Button onClick={resetSlider}>Reset</Button>
</div>);
};
export default ColorAreaDefault;
Color Picker Popup
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';
import type { ColorPickerProps } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";
import { ColorPicker } from "@coreai-ds/react-components";
import { ColorArea } from "@coreai-ds/react-components";
import { ColorSlider } from "@coreai-ds/react-components";
import { AlphaSlider } from "@coreai-ds/react-components";
import { tinycolor } from "@ctrl/tinycolor";
const useStyles = makeStyles({
example: {
width: '300px',
display: 'flex',
flexDirection: 'column',
gap: '10px',
},
previewColor: {
margin: '10px 0',
width: '50px',
height: '50px',
borderRadius: '4px',
border: '1px solid #ccc',
'@media (forced-colors: active)': {
forcedColorAdjust: 'none',
},
},
row: {
display: 'flex',
gap: '10px',
},
sliders: {
display: 'flex',
flexDirection: 'column',
},
});
const DEFAULT_COLOR_HSV = { h: 109, s: 1, v: 0.9, a: 1 };
export const ColorPickerPopup = (): JSXElement => {
const styles = useStyles();
const [previewColor, setPreviewColor] = React.useState(DEFAULT_COLOR_HSV);
const [color, setColor] = React.useState(DEFAULT_COLOR_HSV);
const handleChange: ColorPickerProps['onColorChange'] = (_, data) => {
setPreviewColor({ ...data.color, a: data.color.a ?? 1 });
};
const [popoverOpen, setPopoverOpen] = React.useState(false);
return (<>
<Popover open={popoverOpen} trapFocus onOpenChange={(_, data) => setPopoverOpen(data.open)}>
<PopoverTrigger disableButtonEnhancement>
<Button>Choose color</Button>
</PopoverTrigger>
<PopoverSurface>
<ColorPicker color={previewColor} onColorChange={handleChange}>
<ColorArea inputX={{ 'aria-label': 'Saturation' }} inputY={{ 'aria-label': 'Brightness' }}/>
<div className={styles.row}>
<div className={styles.sliders}>
<ColorSlider aria-label="Hue"/>
<AlphaSlider aria-label="Alpha"/>
</div>
<div className={styles.previewColor} style={{ backgroundColor: tinycolor(previewColor).toRgbString() }}/>
</div>
</ColorPicker>
<div className={styles.row}>
<Button appearance="primary" onClick={() => {
setColor(previewColor);
setPopoverOpen(false);
}}>
Ok
</Button>
<Button onClick={() => {
setPopoverOpen(false);
}}>
Cancel
</Button>
</div>
</PopoverSurface>
</Popover>
<div className={styles.previewColor} style={{ backgroundColor: tinycolor(color).toRgbString() }}/>
</>);
};
export default ColorPickerPopup;
Color Picker Shape
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';
import type { ColorPickerProps } from "@coreai-ds/react-components";
import { ColorPicker } from "@coreai-ds/react-components";
import { ColorSlider } from "@coreai-ds/react-components";
import { AlphaSlider } from "@coreai-ds/react-components";
import { ColorArea } from "@coreai-ds/react-components";
import { tinycolor } from "@ctrl/tinycolor";
const useStyles = makeStyles({
example: {
width: '300px',
display: 'flex',
flexDirection: 'column',
gap: '10px',
},
previewColor: {
width: '50px',
height: '50px',
borderRadius: '4px',
border: '1px solid #ccc',
'@media (forced-colors: active)': {
forcedColorAdjust: 'none',
},
},
});
const DEFAULT_COLOR_HSV = { h: 109, s: 1, v: 0.91, a: 1 };
export const ColorPickerShape = (): JSXElement => {
const styles = useStyles();
const [color, setColor] = React.useState(DEFAULT_COLOR_HSV);
const handleChange: ColorPickerProps['onColorChange'] = (_, data) => setColor({ ...data.color, a: data.color.a ?? 1 });
return (<div className={styles.example}>
<h3>Rounded (default)</h3>
<ColorPicker color={color} onColorChange={handleChange}>
<ColorSlider aria-label="Hue"/>
<AlphaSlider aria-label="Alpha"/>
<ColorArea inputX={{ 'aria-label': 'Saturation' }} inputY={{ 'aria-label': 'Brightness' }}/>
</ColorPicker>
<h3>Square (default)</h3>
<ColorPicker shape="square" color={color} onColorChange={handleChange}>
<ColorArea />
<ColorSlider />
<AlphaSlider />
</ColorPicker>
<div className={styles.previewColor} style={{ backgroundColor: tinycolor(color).toRgbString() }}/>
</div>);
};
export default ColorPickerShape;
Color Slider Channels
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';
import { tinycolor } from "@ctrl/tinycolor";
import type { ColorSliderProps } from "@coreai-ds/react-components";
import { ColorSlider } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
const useStyles = makeStyles({
example: {
width: '300px',
display: 'flex',
flexDirection: 'column',
gap: '10px',
},
previewColor: {
width: '50px',
height: '50px',
borderRadius: '4px',
border: '1px solid #ccc',
},
});
const DEFAULT_COLOR_HSV = tinycolor('#2be700').toHsv();
export const ColorSliderChannels = (): JSXElement => {
const styles = useStyles();
const [color, setColor] = React.useState(DEFAULT_COLOR_HSV);
const onSliderChange: ColorSliderProps['onChange'] = (_, data) => {
setColor({ ...data.color, a: data.color.a ?? 1 });
};
const resetSlider = () => setColor(DEFAULT_COLOR_HSV);
return (<div className={styles.example}>
<h4>Hue</h4>
<ColorSlider color={color} onChange={onSliderChange}/>
<h4>Saturation</h4>
<ColorSlider color={color} channel="saturation" onChange={onSliderChange}/>
<h4>Value (Brightness)</h4>
<ColorSlider color={color} channel="value" onChange={onSliderChange}/>
<div className={styles.previewColor} style={{ backgroundColor: tinycolor(color).toHexString() }}/>
<Button onClick={resetSlider}>Reset</Button>
</div>);
};
export default ColorSliderChannels;
Color Slider Default
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { ColorSliderProps } from "@coreai-ds/react-components";
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';
import { tinycolor } from "@ctrl/tinycolor";
import { ColorSlider } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
const useStyles = makeStyles({
example: {
width: '300px',
display: 'flex',
flexDirection: 'column',
gap: '10px',
},
previewColor: {
width: '50px',
height: '50px',
borderRadius: '4px',
border: '1px solid #ccc',
'@media (forced-colors: active)': {
forcedColorAdjust: 'none',
},
},
});
const DEFAULT_COLOR_HSV = { h: 109, s: 1, v: 0.9, a: 1 };
export const ColorSliderDefault = (props: Partial<ColorSliderProps>): JSXElement => {
const styles = useStyles();
const [color, setColor] = React.useState(DEFAULT_COLOR_HSV);
const [hue, setHue] = React.useState(DEFAULT_COLOR_HSV.h);
const [namedColor, setNamedColor] = React.useState('');
const onSliderChange: ColorSliderProps['onChange'] = (_, data) => {
setColor({ ...data.color, a: data.color.a ?? 1 });
setHue(data.color.h);
const _namedColor = tinycolor(`hsl(${data.color.h},100%,50%)`).toName();
if (_namedColor) {
setNamedColor(_namedColor);
}
};
const resetSlider = () => setColor(DEFAULT_COLOR_HSV);
return (<div className={styles.example}>
<ColorSlider color={color} onChange={onSliderChange} aria-label="Hue" aria-valuetext={`${hue}°, ${namedColor}`} {...props}/>
<ColorSlider color={color} onChange={onSliderChange} vertical aria-label="Vertical Hue" aria-valuetext={`${hue}°, ${namedColor}`} {...props}/>
<div className={styles.previewColor} style={{ backgroundColor: tinycolor(color).toHexString() }}/>
<Button onClick={resetSlider}>Reset</Button>
</div>);
};
export default ColorSliderDefault;