Customizing React Color’s Sketch Picker to display recently used colors
Whenever I gather materials to start a new painting, I always reach for a palette to hold the paints I’ll be using. Most often it’s a well-used piece of palette paper covered with the last painting’s color scheme. The palette makes it easy to switch between core colors without having to remix a frequently used color for each new brush stroke.
For a recent art-themed React project, I wanted to emulate the benefits of a palette and allow users to easily access their recently used colors as they ‘painted’ a digital canvas. In this post, we’ll build out this functionality by customizing React Color’s
SketchPicker component. We’ll also explore other customizations available through the
SketchPicker API that make the component a flexible and helpful tool.
You can check out the frontend repo for the project this post is based on here if you’d like more context. Code samples in this post have been simplified so we can focus on our color picker customization.
Setting up SketchPicker with Core Props
React Color is a package you can install through npm that gives you access to 13 different color picker components for use in React, ranging from sliders and swatches to input fields. You can also use helper components to create your own picker if desired.
For this demo, we’ll work with the pre-built
SketchPicker component, so let’s install the package in our app’s directory with the command
npm install react-color — save.
Next we’ll import the
SketchPicker into a parent component in our app called
StudioPage, which will also render the
Canvas component our users will be painting. We’ll also set up local state in the parent component to manage the active color on the color picker.
You’ll notice that
SketchPicker is receiving two props from the parent component. Each React Color picker is prepared to receive at least two props,
color and a choice of either
As the React Color docs explain,
color controls the color picker’s active color. In the code snippet above, we’ve set an
activeColor value in local state that will display as the selected color when the
SketchPicker loads. For your
color prop, you can pass a hex code as a string or an object containing either RGB or HSL values. In this demo, we’ll work with hex colors.
Since the color picker’s selected/active color is controlled by the value of
activeColor in our parent component’s state, we need a way to update
activeColor each time a user selects a new color on the
To achieve this, React Color lets you pass the color picker a function to execute when a color change occurs. If you want the function to fire on every change (including drag events), pass your callback function via a prop called
onChange. If you want it to execute only once per core change, then pass your callback to
Note that if you use
onChangeComplete, you can drag your color selector (via the hue slider or saturation block) to a new position, but the selector will not move with your cursor as you drag it. It remains stationary until you release the drag motion. Then the selector will jump to the new position. The selector does follow your pointer in a visual dragging motion if you use
We’ll name our callback function
handleChangeComplete. Whatever callback you pass to
onChange complete can receive both the selected color and the event as arguments. For this demo, we only need color details, so we’ll just pass in color to our callback.
Inside this callback, we’ll update the value of
activeColor in our local state and set it equal to color’s hex value by calling
color.hex. You can also access the RGB or HSL values of the selected color via
color.hsl. Hex values can come through with lower or uppercase letters, so for consistency, we’ll save the values in uppercase format. This becomes important later when we build out our recent colors tracking feature.
Customizing the Color Picker
Now that we have the base functionality setup, let’s explore ways to customize the
Some of the color picker options come with their own APIs, which are outlined in the React Color docs. SketchPicker lets you pass additional props if desired, including:
Alpha describes the opacity of a color. If you don’t want to display alpha values on the color picker, pass disableAlpha the boolean value
true (set to false by default). Make sure to pass
true as a boolean value, not a string. Since opacity did not factor into the app I was working on, I chose to disable this feature.
SketchPicker’s width is set to 200px by default, but you can pass in a new value to change the width. I chose to use a percentage so the picker would scale with its container.
If you want to further adjust the component’s style, use the
className prop to pass in your own styles. Since we don’t have access to the picker’s styles, you might need to override them in your CSS if you want to change already set values.
You can customize the hover behavior of the
SketchPicker’s preset color swatches. Add an
onSwatchHover prop to your picker and pass it a callback function that executes your desired hover action. The callback function will be able to receive both
color (i.e. the selected color) and
event as arguments.
SketchPicker displays 15 color swatches by default, but you can pass your own set of colors as either hex codes or RGB/HSL objects. You can also pass in more or less than 15 options. We’ll use this prop to transform the color swatches section into our own paint palette that tracks recently used colors.
Tracking Recently Used Colors in our Picker
Returning to our original goal, if a user works with a custom color pulled from the slider or saturation block, we want to keep track of that color so they can easily return to it later and not have to place their slider/selector in the exact same location. It’s hard, I’ve tried it.
In the code sample above, you may have noticed we’re passing
this.state.presetColors as the
presetColors prop to our color picker.
In our parent component’s local state, we’ll add
presetColors and set it equal to the default
presetColor values provided by the
These 15 default colors provide a nice starting palette, but we’ll update this slice of state with each new color used so that it becomes a rotating color palette displaying recently used colors.
In the app I worked on, a user can click on shapes within an SVG, our
<Canvas /> component, to add colors. Each click triggers a callback action,
StudioPage that accepts the shape’s id and the currently active color. It then dispatches an action via a prop called
addColor that updates the shape’s color. Understanding this user interaction is relevant because it helps determine when a color becomes ‘recently used’. In this case, we can say a color becomes ‘recently used’ when a user adds it to a canvas shape, or in other words, when a click event happens on the canvas.
Now let’s take a look at the
handleClick function we’re passing to our
As mentioned above, this function accepts a shape/polygon id and the active color from our color picker. The first line handles updating our canvas and isn’t our focus here. Instead, let’s walk through the logic in the rest of the function.
Each time a user fills a shape with a color and triggers this function, we only want to add the color added to our swatch collection if it isn’t already present. To achieve this, we’ll use a conditional:
Remember when we made sure our active color was stored as a hex value in uppercase format? Since we know all our colors in our presetColors array are stored in the same format, we can check to see if the array contains the color that was just used on our canvas. If it doesn’t, then we move into the block to update state.
setState is a built-in React function that lets us update our state. Because we’ll need to build on the current values in our presetColors array, we’ll pass in a callback function to
setState. (If you’re updating state based on previous state, it’s best practice to use this format because of
setState’s asynchronous nature). When we pass a function to
setState, this function can access our component’s state (often called previous state) as an argument.
We’ll pass in an argument named
state to represent this previous state. Keeping with best practices, we’ll avoid mutating state directly and create a copy of our presetColors array for editing.
const colors = state.presetColors.slice(0)
Next we’ll add the used color to the beginning of our array and remove the last color so our array stays at a length of 15 colors.
Finally, we’ll return the updated value of presetColors, updating our local state. Because our SketchPicker relies on the value of presetColors, it will be re-rendered and the row of 15 swatches will now include the just-used color. Just what we want!
We now know how to customize the
SketchPicker component available through React Color. By providing ways to adjust preset colors, width, hover effects, and alpha features, the component becomes a flexible and easy-to-adapt interface for color selection. Other color pickers come with their own customizations, so browse the React Color docs to learn more. If you want to customize even further, check out the section about creating your own color picker using their helper components.