Modern Animated Blossom Color Picker with React & TailwindCSS

Compact color picker with radial petal design. Auto-shifts within viewport. Accepts hex, RGB, HSL formats. Built with React & TailwindCSS.

Blossom Color Picker is a React component that lets you pick colors in a radial petal layout, with color options arranged in nested layers around a central core.

The component has built-in viewport detection logic. If the expanded picker extends beyond the screen boundaries, it automatically shifts to remain visible. The arc slider repositions itself based on available space. The background applies a tinted overlay derived from the currently selected color. All positioning calculations happen at render time.

You can pass colors in multiple formats, including hex strings, RGB values, HSL strings, or HSL objects. The component parses each format and converts it internally for the geometric distribution algorithm. The state management supports both controlled and uncontrolled modes.

Features

📐 Geometric Nesting Algorithm: Uses trigonometric calculations to position petals in valley spaces between previous layers with zero gaps.

📱 Viewport Shifting: Detects screen boundaries and automatically shifts the expanded picker to prevent overflow on mobile devices.

🎯 Adaptive Arc Slider: Repositions the saturation slider to the side with maximum available space (top, bottom, left, or right).

🎨 Multi-Format Color Input: Accepts hex strings, RGB/RGBA, HSL/HSLA strings, space-separated HSL, and HSL objects in the same array.

⚙️ Controlled and Uncontrolled Modes: Supports both value prop for controlled state and defaultValue for uncontrolled initialization.

🌗 Theme-Aware Background: Applies a soft tinted overlay using the currently selected color for automatic dark mode compatibility.

⏱️ Configurable Animation: Adjusts blooming animation duration and supports hover-triggered expansion.

🔧 Fully Customizable: Exposes 16 props for core size, petal size, slider visibility, initial state, and positioning behavior.

How to Use It

Installation

Install the package from npm:

npm install @dayflow/blossom-color-picker

Basic Usage

Import the component and pass an onChange callback to handle color selection:

import { BlossomColorPicker } from '@dayflow/blossom-color-picker';
const MyComponent = () => {
  const handleColorChange = (color) => {
    console.log('Selected color:', color.hex);
    console.log('HSL format:', color.hsl);
    console.log('HSLA with alpha:', color.hsla);
  };
  return <BlossomColorPicker onChange={handleColorChange} />;
};

The onChange callback receives a complete color object containing hex, hsl, and hsla strings along with the raw hue, saturation, and alpha values.

Controlled Mode

Control the picker state externally by passing a value prop:

import { useState } from 'react';
import { BlossomColorPicker } from '@dayflow/blossom-color-picker';
const ControlledPicker = () => {
  const [color, setColor] = useState({
    hue: 210,
    saturation: 60,
    alpha: 100,
    layer: 'outer'
  });
  return (
    <BlossomColorPicker
      value={color}
      onChange={(newColor) => {
        setColor({
          hue: newColor.hue,
          saturation: newColor.saturation,
          alpha: newColor.alpha,
          layer: newColor.layer
        });
      }}
    />
  );
};

The value object requires hue (0-360), saturation (0-100), alpha (0-100), and layer (‘inner’ or ‘outer’) fields.

Custom Color Palette

Define your own color set using any supported format:

<BlossomColorPicker
  colors={[
    '#FF6B6B',
    '#4ECDC4',
    'rgb(107, 203, 119)',
    'rgba(65, 105, 225, 0.9)',
    'hsl(280, 70%, 55%)',
    'hsl(200 80% 60%)',
    { h: 45, s: 90, l: 65 },
    { h: 330, s: 85, l: 60 }
  ]}
  onChange={(color) => console.log(color)}
/>

The component automatically parses all formats and sorts colors by hue for optimal geometric distribution across layers.

Hover Interaction Mode

Trigger the bloom animation on hover instead of click:

<BlossomColorPicker
  openOnHover={true}
  initialExpanded={false}
  onChange={(color) => console.log(color)}
/>

This configuration works well in toolbars where users frequently switch between colors during active editing sessions.

Customized Layout

Adjust the core size, petal size, and animation timing:

<BlossomColorPicker
  coreSize={40}
  petalSize={36}
  animationDuration={500}
  showCoreColor={true}
  showAlphaSlider={true}
  sliderPosition="bottom"
  onChange={(color) => console.log(color)}
/>

The coreSize and petalSize props accept pixel values. The showCoreColor prop displays the selected color in the central circle while the picker remains expanded.

Disabled Positioning Features

Turn off adaptive positioning for fixed layout contexts:

<BlossomColorPicker
  adaptivePositioning={false}
  sliderPosition="right"
  onChange={(color) => console.log(color)}
/>

When adaptivePositioning is false, the picker maintains its default position regardless of viewport boundaries, and the slider stays at the specified position.

Collapse Callback

Handle the collapse event when the picker closes:

<BlossomColorPicker
  onChange={(color) => console.log('Color changed:', color.hex)}
  onCollapse={(color) => {
    console.log('Picker collapsed with final color:', color.hex);
    saveColorToDatabase(color.hex);
  }}
/>

The onCollapse callback fires when the user clicks outside the expanded picker or selects a final color and closes the interface.

API Reference

BlossomColorPickerProps

PropTypeDefaultDescription
valueBlossomColorPickerValueControlled value containing hue, saturation, alpha, and layer.
defaultValueBlossomColorPickerValue{ hue: 330, saturation: 70, alpha: 50, layer: 'outer' }Initial value for uncontrolled mode (pink color).
colorsColorInput[]18-color default setArray of colors automatically sorted and distributed into layers.
onChange(color: BlossomColorPickerColor) => voidCallback invoked when color changes.
onCollapse(color: BlossomColorPickerColor) => voidCallback invoked when picker collapses.
disabledbooleanfalseDisables all interactions when true.
openOnHoverbooleanfalseOpens picker on hover instead of click.
initialExpandedbooleanfalseStarts picker in expanded state.
animationDurationnumber300Duration of blooming animation in milliseconds.
showAlphaSliderbooleantrueShows or hides the saturation arc slider.
coreSizenumber32Diameter of central circle in pixels.
petalSizenumber32Diameter of individual color petals in pixels.
showCoreColorbooleantrueDisplays selected color in core while expanded.
sliderPosition'top' | 'bottom' | 'left' | 'right''right'Fixed position for arc slider.
adaptivePositioningbooleantrueAutomatically shifts picker within viewport and repositions slider.
classNamestring""Additional CSS class for container element.

BlossomColorPickerValue

FieldTypeDescription
huenumberHue angle from 0 to 360 degrees.
saturationnumberSlider position from 0 (bright) to 100 (dark).
lightnessnumber?HSL lightness auto-computed from slider if omitted.
originalSaturationnumber?Base saturation of selected petal.
alphanumberAlpha value from 0 to 100.
layer'inner' | 'outer'Layer identifier for selected petal.

BlossomColorPickerColor

Extends BlossomColorPickerValue with formatted color strings:

FieldTypeDescription
hexstringHex color string like “#6586E5”.
hslstringHSL string like “hsl(225, 71%, 65%)”.
hslastringHSLA string with alpha channel.

ColorInput Type

type ColorInput = string | { h: number; s: number; l: number };

Accepts hex strings, RGB/RGBA strings, HSL/HSLA strings (comma or space-separated), or HSL objects with h, s, and l properties.

Related Resources

FAQs

Q: How does the geometric nesting algorithm prevent gaps between petals?
A: The algorithm calculates the valley angle between adjacent petals in the previous layer and positions each new petal at that midpoint. It uses trigonometric functions to compute the exact radius offset needed for the petal edges to touch without overlapping. This creates a dense, gap-free structure regardless of how many colors you pass.

Q: What happens when adaptivePositioning is enabled on desktop screens?
A: The component still monitors viewport boundaries but rarely needs to shift since desktop screens provide more space. The adaptive slider positioning remains active and chooses the side with maximum available space. This prevents the slider from extending beyond the viewport when the picker sits near screen edges.

Q: Does the component support gradients or color mixing?
A: No. The picker handles solid colors with alpha transparency. Each petal represents a distinct color from your colors array. The saturation slider darkens or brightens the selected petal but does not blend multiple colors together.

Q: How do I disable the saturation arc slider completely?
A: Set the showAlphaSlider prop to false. This removes the arc slider from the UI entirely. Users can still select colors from the petals but cannot adjust the saturation value. The component returns the base saturation of each petal without modification.

DayFlow-JS

DayFlow-JS

Leave a Reply

Your email address will not be published. Required fields are marked *