Color picker
The ColorPicker component is a powerful UI element designed for seamless color selection. It is ideal for applications such as design tools, image editors, or any interface requiring color customization.
As part of the complex components in Gameface UI, the ColorPicker combines multiple basic components to deliver advanced functionality. It enables users to adjust hue, saturation, brightness, and transparency, while providing a color preview area for visual feedback.
Internally, the component utilizes the following basic components:
- XYSlider for adjusting brightness and saturation.
- Slider for controlling hue and alpha (transparency).
- Segment for toggling the color preview mode between HEX and RGBA.
To use the ColorPicker component, simply import and render it as shown below:
import ColorPicker from '@components/Complex/ColorPicker/ColorPicker';
const App = () => { return ( <ColorPicker /> );};
export default App;| Prop Name | Type | Default | Description |
|---|---|---|---|
style | JSX.CSSProperties | {} | Inline styles to apply directly to the color picker’s wrapper element. |
class | string | "" | Additional CSS classes to apply to the color picker’s wrapper element. |
ref | ColorPickerRef | undefined | undefined | A reference to the component, providing access to its methods and the underlying HTML element. |
value | string | rgba(255, 0, 0, 1) | Initial value of the color picker. Accepts colors as strings in HEX or RGBA format. |
size | 'S' | 'M' | 'L' | 'XL' | 'L' | Sets the size of the color picker. The size affects the overall dimensions and font sizes within the component. Ideal for quick customization. |
onChange | (value: ColorData) => void | undefined | A callback function triggered whenever the color changes. It can be used to retrieve the updated color value. |
onAction | Record<string, (scope?: string, ...args: any[]) => void> | undefined | Allows you to add custom navigation action handlers to the color picker. See the Navigation component documentation for details. |
anchor | string | HTMLElement | undefined | Links navigation to another element. When the anchor element is focused, the color picker’s actions will execute. Can be a CSS selector or HTMLElement. |
Ref API
Section titled “Ref API”To interact with the ColorPicker programmatically, you can use the ColorPickerRef interface. This interface provides properties and methods to access and manipulate the component’s state.
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
element | HTMLDivElement | A reference to the color picker’s root HTML element, useful for DOM access or styling. |
Methods
Section titled “Methods”| Method | Parameters | Return Value | Description |
|---|---|---|---|
value | None | {rgba: string, hex: string} | Retrieves the currently selected color value from the color picker into rgba and hex format. |
changeColor | newColor: string | void | Updates the color picker programmatically with a new color. This method accepts color strings in either RGBA or HEX format, which are automatically converted to ColorData internally. |
ColorData Type
Section titled “ColorData Type”| Property | Type | Description |
|---|---|---|
h | number | Represents the hue of the color (0-360). |
s | number | Represents the saturation of the color (0-100). |
v | number | Represents the brightness of the color (0-100). |
a | number | Represents the alpha (transparency) of the color (0-1). |
Color Picker Utilities
Section titled “Color Picker Utilities”To simplify color format conversions, utility methods are available for translating between HSVA, RGBA, and HEX. These methods can be imported from @components/Complex/ColorPicker/colorPickerUtils:
import { RGBAOrHEXToHSVA, RGBAToHSVA, parseHSVAColor } from "@components/Complex/ColorPicker/colorPickerUtils";RGBAOrHEXToHSVA(color: string) => ColorData
Section titled “RGBAOrHEXToHSVA(color: string) => ColorData”Converts a color string in RGBA or HEX format to ColorData. The method automatically detects the input format and performs the conversion.
import { RGBAOrHEXToHSVA } from "@components/Complex/ColorPicker/colorPickerUtils";
RGBAOrHEXToHSVA('rgba(0, 0, 0, 0.5)'); // Returns ColorData: { h: 0, s: 0, v: 0, a: 0.5 }RGBAOrHEXToHSVA('#00000080'); // Returns ColorData: { h: 0, s: 0, v: 0, a: 0.5 }RGBAToHSVA(rgba: string) => ColorData
Section titled “RGBAToHSVA(rgba: string) => ColorData”Converts an RGBA color string to ColorData.
import { RGBAToHSVA } from "@components/Complex/ColorPicker/colorPickerUtils";
RGBAToHSVA('rgba(0, 0, 0, 0.5)'); // Returns ColorData: { h: 0, s: 0, v: 0, a: 0.5 }parseHSVAColor(color: ColorData) => string
Section titled “parseHSVAColor(color: ColorData) => string”Converts ColorData to a color string in RGBA or HEX format.
import { parseHSVAColor } from "@components/Complex/ColorPicker/colorPickerUtils";
parseHSVAColor({ h: 0, s: 0, v: 0, a: 1 }); // Returns { rgba: 'rgba(0, 0, 0, 1)', hex: '#000000FF' }Setting an initial value
Section titled “Setting an initial value”To initialize the color picker with a value other than the default rgba(255, 0, 0, 1), use the value prop. This prop accepts color strings in either RGBA or HEX format. Internally, the component converts the provided value to HSVA format for internal processing.
import ColorPicker from '@components/Complex/ColorPicker/ColorPicker';
const App = () => { return ( <ColorPicker value="rgba(0, 0, 0, 0.5)" /> // Or <ColorPicker value="#00000080" /> );};
export default App;Programmatically changing the color picker value
Section titled “Programmatically changing the color picker value”To update the color picker value programmatically, use the ref prop to access the component’s instance. The changeColor method allows you to set a new color. The method accepts string values in RGBA or HEX format, which are automatically converted to ColorData internally.
import ColorPicker from '@components/Complex/ColorPicker/ColorPicker';
const App = () => { let colorPickerRef!: ColorPickerRef;
const changeColor = () => { if (colorPickerRef) { // Update the color to rgba(0, 0, 0, 0.5) colorPickerRef.changeColor('rgba(0, 0, 0, 0.5)'); } };
return ( <> <ColorPicker ref={colorPickerRef} /> <button onClick={changeColor}>Change Color</button> </> );};Retrieve the color picker value
Section titled “Retrieve the color picker value”To access the current value of the color picker, use the ref prop to obtain a reference to the component instance. This reference provides methods for interacting with the color picker.
The value method retrieves the current color in {rgba: string, hex: string} format. If you need the color in HSVA format, use the RGBAOrHEXToHSVA utility method to convert the rgba or hex string to ColorData which represents the color in hue, saturation, value, and alpha components.
import ColorPicker from '@components/Complex/ColorPicker/ColorPicker';
const App = () => { let colorPickerRef!: ColorPickerRef;
const getColor = () => { if (colorPickerRef) { // Retrieve the current color value from the color picker const color = colorPickerRef.value(); console.log(color); // Logs the color in RGBA and HEX format // Example output: { rgba: 'rgba(0, 0, 0, 0.5)', hex: '#00000080' } } };
return ( <> <ColorPicker ref={colorPickerRef} /> <button onClick={getColor}>Get Color</button> </> );};Listen to color changes
Section titled “Listen to color changes”To respond to color changes in the ColorPicker, use the onChange prop. This prop accepts a callback function that receives the updated color value as an argument. The value is provided in ColorData format, which includes hue, saturation, brightness, and alpha components.
Because the provided value of the onChange callback is in ColorData format, you can use the parseHSVAColor utility method to convert it to a string in either RGBA or HEX format if needed.
import ColorPicker, { ColorData } from '@components/Complex/ColorPicker/ColorPicker';import { parseHSVAColor } from '@components/Complex/ColorPicker/colorPickerUtils';
const App = () => { const handleColorChange = (color: ColorData) => { console.log('Color changed:', color); // Example output: { h: 0, s: 0, v: 0, a: 0.5 } // Convert to RGBA or HEX string if needed const rgbaString = parseHSVAColor(color).rgba; // 'rgba(0, 0, 0, 0.5)' const hexString = parseHSVAColor(color).hex; // '#00000080' console.log('RGBA:', rgbaString); console.log('HEX:', hexString); };
return ( <ColorPicker onChange={handleColorChange} /> );};Customizing the component
Section titled “Customizing the component”The ColorPicker component can be tailored to fit your application’s design by using the style and class props. These props allow you to apply custom styles and CSS classes to the wrapper element of the color picker.
import ColorPicker from '@components/Complex/ColorPicker/ColorPicker';
const App = () => { return ( <ColorPicker style={{ width: '300px', height: '300px' }} class="custom-color-picker" /> );};export default App;Extending the Color Picker With Navigation 2.0.0
Section titled “Extending the Color Picker With Navigation ”2.0.0The ColorPicker component can be extended to work with the Navigation component to allow for keyboard or gamepad navigation.
Since the ColorPicker is built using basic components like XYSlider, Slider and Segment , which are compatible with the Navigation system, you can wrap the ColorPicker in a Navigation component to enable navigation support.
To achieve this, follow these steps:
- Make sure the
ColorPickeris a descendant of aNavigationcomponent in your component tree. - Wrap the components in the
ColorPickeryou wish to enable navigation for with theNavigation.Areacomponent. - Optionally, add focus styles for all components that will be navigable for visual indication.
Example setup
Section titled “Example setup”In this example we will modify the ColorPicker component to include Navigation.Area around the internal components that we want to be navigable.
The component’s internal navigation setup will handle the interactions out of the box!
const ColorPicker: ParentComponent<ColorPickerProps> = (props) => { // Existing color picker code... return ( <div ref={element} class={className()} style={inlineStyles()} use:forwardEvents={props} use:forwardAttrs={props}> <Navigation.Area name="color-picker" focused> <XYSlider ref={xySliderRef} value={{ x: initialValue.s, y: 100 - initialValue.v }} class={styles.XYSlider} onChange={handleXYChange}> <XYSlider.Background style={XYSliderBackground()} />17 collapsed lines
<XYSlider.Handle class={styles['XYSlider-handle']} style={{ "background-color": selectedColorNonTransparent() }}></XYSlider.Handle> </XYSlider>
<Slider ref={hueSliderRef} min={0} max={360} value={initialValue.h} onChange={handleHueChange} class={styles['hue-slider']}> <Slider.Track class={styles['hue-slider-track']} /> <Slider.Fill class={styles['slider-fill']}></Slider.Fill> <Slider.Handle class={styles['slider-handle']} style={{ background: selectedColorHue() }} /> </Slider>
<Slider ref={alphaSliderRef} value={initialValue.a * 100} onChange={handleAlphaChange} class={styles['alpha-slider']}> <Slider.Track class={styles['alpha-slider-track']} style={{ 'background-image': `linear-gradient(to right,transparent 0% , ${selectedColorNonTransparent()} 100% )` }} /> <Slider.Fill class={styles['slider-fill']}></Slider.Fill> <Slider.Handle class={styles['slider-handle']} style={{ background: selectedColor() }} /> </Slider>
<Segment class={styles.segment} onChange={(value) => setSelectedFormat(value)}> <Segment.Indicator class={styles['segment-indicator']}></Segment.Indicator> <Segment.Button class={styles['segment-button']} selected value="hex">HEX</Segment.Button> <Segment.Button class={styles['segment-button']} value="rgba">RGBA</Segment.Button> </Segment> </Navigation.Area> <div class={styles['color-preview-wrapper']}> <div class={styles['color-preview']}> <div class={styles['color-preview-box']} style={{ 'background-color': selectedColor() }}></div> </div> <TextInput class={styles['color-preview-text']} readonly value={colorTextValue()} /> </div> </div > );}CSS for focus styles
Section titled “CSS for focus styles”For the visual focus indication, in this example we add a border to the slider handles and a box-shadow to the segment when the components receive focus.
Since there are multiple sliders in the ColorPicker’s components, we can create a SCSS mixin to handle the focus styles for the slider handles. Here’s how you can implement it:
@mixin handle-focus($slider-name) { &:focus { .#{$slider-name} { border: 0.2vmax solid rgb(197, 197, 197); } }}
.XYSlider {5 collapsed lines
width: 100%; border: none; margin-bottom: 0.5em; height: 10em;
@include handle-focus('XYSlider-handle');5 collapsed lines
&-handle { width: 1.5em; height: 1.5em; }}
.hue-slider,.alpha-slider {7 collapsed lines
width: 85%; height: 0.75em; padding: 0; margin: 0; margin-top: 0.5em; margin-bottom: 0.5em; border-radius: 0.5em;
@include handle-focus('slider-handle');}
.segment { margin-top: 0.5em; margin-bottom: 0.5em;
&:focus { box-shadow: 0 0 0.5vmax rgba(0, 0, 0, 0.2); }}