Skip to content

Luminance Circular

The same nesting trick with a luminance ring instead of a hue one, wrapped around a <Panel3 /> wheel — two circular controls in one. thumbScaleAnimationValue={1} holds the ring's thumb at a fixed size while it is dragged.

Code

LuminanceCircular.tsx
import React, { useState } from 'react';
import { StyleSheet, View } from 'react-native';
import type { ColorFormatsObject } from 'reanimated-color-picker';
import ColorPicker, { LuminanceCircular, Panel3, PreviewText, Swatches, colorKit } from 'reanimated-color-picker';
import { useContainerBackgroundColor } from './components/BaseContainer';
import Divider from './components/Divider';
import { colorPickerStyle } from './components/colorPickerStyle';
// generate 6 random colors for swatches
const customSwatches = new Array(6).fill('#fff').map(() => colorKit.randomRgbColor().hex());
export default function Example() {
const [resultColor, setResultColor] = useState(customSwatches[0]);
const currentColor = useContainerBackgroundColor(customSwatches[0]);
// runs on the ui thread on color change
const onColorChange = (color: ColorFormatsObject) => {
'worklet';
currentColor.value = color.hex;
};
// runs on the js thread on color pick
const onColorPick = (color: ColorFormatsObject) => {
setResultColor(color.hex);
};
return (
<View style={colorPickerStyle.pickerContainer}>
<ColorPicker
value={resultColor}
sliderThickness={24}
thumbSize={24}
onChange={onColorChange}
onCompleteJS={onColorPick}
style={colorPickerStyle.picker}
adaptSpectrum
boundedThumb
>
<LuminanceCircular
containerStyle={styles.hueContainer}
thumbShape='circle'
thumbInnerStyle={styles.thumbInner}
thumbScaleAnimationValue={1}
>
<Panel3 style={styles.panelStyle} centerChannel='hsl-saturation' />
</LuminanceCircular>
<Divider />
<Swatches style={colorPickerStyle.swatchesContainer} swatchStyle={colorPickerStyle.swatchStyle} colors={customSwatches} />
<Divider />
<PreviewText style={colorPickerStyle.previewTxt} colorFormat='hsl' />
</ColorPicker>
</View>
);
}
const styles = StyleSheet.create({
hueContainer: {
justifyContent: 'center',
},
panelStyle: {
width: '90%',
height: '90%',
alignSelf: 'center',
borderRadius: 16,
},
thumbInner: {
borderWidth: 4,
},
});

The colorPickerStyle object is shared by every example. Divider is a 1px line, and useContainerBackgroundColor only tints the modal of the example app.

components/colorPickerStyle.ts
import { Platform, StyleSheet } from "react-native";
const shadow = Platform.select({
web: { boxShadow: "rgba(0, 0, 0, 0.3) 0px 0px 2px" },
default: {
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.2,
shadowRadius: 1.41,
elevation: 2,
},
});
export const colorPickerStyle = StyleSheet.create({
title: {
textAlign: "center",
fontFamily: "Quicksand",
fontWeight: "bold",
marginVertical: 20,
color: "gray",
},
picker: {
gap: 20,
},
pickerContainer: {
alignSelf: "center",
width: 300,
backgroundColor: "#eee",
padding: 20,
borderRadius: 20,
...shadow,
},
panelStyle: {
borderRadius: 16,
...shadow,
},
sliderStyle: {
borderRadius: 20,
...shadow,
},
sliderVerticalStyle: {
borderRadius: 20,
height: 300,
...shadow,
},
sliderTitle: {
color: "#000",
fontWeight: "bold",
marginBottom: 5,
paddingHorizontal: 4,
fontFamily: "Quicksand",
},
previewStyle: {
height: 40,
borderRadius: 14,
},
previewTxt: {
color: "#707070",
fontFamily: "Quicksand",
},
inputStyle: {
color: "#707070",
paddingVertical: 2,
borderColor: "#707070",
fontSize: 12,
marginLeft: 5,
},
swatchesContainer: {
alignItems: "center",
flexWrap: "nowrap",
gap: 10,
},
swatchStyle: {
borderRadius: 20,
height: 30,
width: 30,
margin: 0,
marginBottom: 0,
marginHorizontal: 0,
marginVertical: 0,
},
});