@dayflow/blossom-color-picker

中文文档
2.5.0发布于 2026/10/24MITTypeScriptESM + CJS零依赖近 30 天下载 7.7万

A beautiful, blooming color picker — standalone vanilla JS

原始使用文档
文档目录21 节
  1. Packages
  2. Installation
  3. Usage
  4. Vanilla JS
  5. React
  6. Vue 3
  7. Svelte
  8. Angular
  9. Options / Props
  10. CSS Variables
  11. Vanilla JS Methods
  12. Features
  13. Smart Shifter & Adaptive UI
  14. Geometric Nesting
  15. Type Reference
  16. BlossomColorPickerValue
  17. BlossomColorPickerColor
  18. ColorInput
  19. Color Formats
  20. Project Structure
  21. Keyboard interaction and state compatibility

Blossom Color Picker

npm version PRs Welcome GitHub license

A beautiful, blooming color picker for Web. Available as a standalone vanilla JS class, or as a thin React / Vue / Svelte / Angular wrapper.

https://github.com/user-attachments/assets/553ee0ff-1f52-497f-bc8f-cee9a7b91d66

Packages

PackageDescriptionVersion
@dayflow/blossom-color-pickerVanilla JS core (zero dependencies)2.0.0
@dayflow/blossom-color-picker-reactReact wrapper1.0.0
@dayflow/blossom-color-picker-vueVue 3 wrapper1.0.0
@dayflow/blossom-color-picker-svelteSvelte wrapper1.0.0
@dayflow/blossom-color-picker-angularAngular wrapper1.0.0

Installation

# Vanilla JS (core)
npm install @dayflow/blossom-color-picker

# React
npm install @dayflow/blossom-color-picker-react

# Vue 3
npm install @dayflow/blossom-color-picker-vue

# Svelte
npm install @dayflow/blossom-color-picker-svelte

# Angular
npm install @dayflow/blossom-color-picker-angular

Usage

Vanilla JS

import { BlossomColorPicker } from '@dayflow/blossom-color-picker';
import '@dayflow/blossom-color-picker/styles.css';

const picker = new BlossomColorPicker(document.getElementById('picker'), {
  onChange: color => console.log(color.hex),
});

// Programmatic control
picker.expand();
picker.collapse();
picker.toggle();
picker.setValue({ hue: 200, saturation: 50, alpha: 100, layer: 'outer' });
picker.setOptions({ disabled: true });
picker.destroy();

React

import { BlossomColorPicker } from '@dayflow/blossom-color-picker-react';

function App() {
  const [color, setColor] = useState({
    hue: 330,
    saturation: 70,
    alpha: 100,
    layer: 'outer' as const,
  });

  return <BlossomColorPicker value={color} onChange={c => setColor(c)} />;
}

Vue 3

<script setup>
import { ref } from 'vue';
import { BlossomColorPicker } from '@dayflow/blossom-color-picker-vue';

const color = ref({
  hue: 330,
  saturation: 70,
  alpha: 100,
  layer: 'outer',
});

function handleChange(c) {
  color.value = c;
}
</script>

<template>
  <BlossomColorPicker :value="color" @change="handleChange" />
</template>

Svelte

<script>
  import { BlossomColorPicker } from '@dayflow/blossom-color-picker-svelte';

  let color = $state({
    hue: 330, saturation: 70, alpha: 100, layer: 'outer',
  });

  function handleChange(newColor) {
    color = newColor;
  }
</script>

<BlossomColorPicker value={color} onchange={handleChange} />

Angular

import { Component } from '@angular/core';
import {
  BlossomColorPickerComponent,
  type BlossomColorPickerColor,
} from '@dayflow/blossom-color-picker-angular';

@Component({
  selector: 'app-root',
  imports: [BlossomColorPickerComponent],
  template: `
    <blossom-color-picker
      [value]="color"
      (colorChange)="onColorChange($event)"
    />
  `,
})
export class App {
  color = { hue: 330, saturation: 70, alpha: 100, layer: 'outer' as const };

  onColorChange(c: BlossomColorPickerColor) {
    this.color = c;
  }
}

Options / Props

All packages share the same set of options. In React they are passed as JSX props; in Vue as component props (with events via @change / @collapse); in Svelte as callback props (onchange / oncollapse); in Angular as @Input() bindings (with events via (colorChange) / (colorCollapse)).

OptionTypeDefaultDescription
valueBlossomColorPickerValue-Controlled value of the picker.
defaultValueBlossomColorPickerValue{ hue: 330, saturation: 70, alpha: 100, layer: 'outer' }Initial value for uncontrolled mode.
colorsColorInput[](Default 18-color set)Color list, automatically sorted and distributed into layers.
onChange(color: BlossomColorPickerColor) => void-Called when color changes. Vue: @change. Svelte: onchange. Angular: (colorChange).
onChangeComplete(color: BlossomColorPickerColor) => void-Called once after petal activation or a shade gesture ends. Vue: @change-complete. Svelte: onchangecomplete. Angular: (colorChangeComplete).
onCollapse(color: BlossomColorPickerColor) => void-Called when the picker collapses. Vue: @collapse. Svelte: oncollapse. Angular: (colorCollapse).
onHover(color: BlossomColorPickerColor | null) => void-Called with the color a petal would select when it is hovered or keyboard-focused, and with null when that ends. Vue: @hover. Svelte: onhover. Angular: (colorHover).
disabledbooleanfalseWhether the picker is disabled.
openOnHoverbooleanfalseIf true, opens the picker on hover instead of click.
initialExpandedbooleanfalseWhether the picker starts expanded.
animationDurationnumber280Base timing of the blooming animation in ms; every phase scales with it (at the default the bloom settles in about 550 ms).
showShadeSliderbooleantrueWhether to show the shade (brightness) arc slider.
showAlphaSliderbooleantrueDeprecated alias for showShadeSlider; the new name takes precedence when both are supplied.
coreSizenumber32Diameter of the central circle in px.
petalSizenumber32Diameter of individual color petals in px.
showCoreColorbooleanfalseWhen true, the core shows the selected color while expanded; otherwise it is white.
hoverPreviewbooleanfalseWhen true, the ring, core (with showCoreColor) and background show the hovered or focused petal's color before it is picked.
petalShape'circle' | 'sakura' | 'lotus' | 'pinwheel''circle'Petal outline. sakura: broad petals with a notched tip. lotus: round base drawn up into a pointed tip. pinwheel: tip swept to one side, so the bloom looks like it is turning. Shaped petals point away from the core, are lightly shaded from base to tip, and ignore --bcp-petal-shadow.
petalStyle'flat' | 'veined''flat'Surface detail on shaped petals. veined draws a midrib and side veins on each petal. Ignored when petalShape is circle.
sliderPosition'top' | 'bottom' | 'left' | 'right''right'Fixed position for the arc slider.
adaptivePositioningbooleantrueSmart Shifter: Automatically shifts the picker to stay within viewport and repositions the slider for best visibility.
className / classstring""Additional CSS class (React: className, Svelte: class).

CSS Variables

Set these on .bcp-root or any ancestor to theme the picker. Each one falls back to the default look, so leaving them unset changes nothing.

VariableDefaultStyles
--bcp-surface#FFFFFFBackground disc behind the petals.
--bcp-surface-shadowsoft drop shadowShadow of the background disc.
--bcp-tint-opacity0.15Strength of the selected-color tint on the disc.
--bcp-trackrgba(0, 0, 0, 0.06)Unfilled track of the ring and the shade slider.
--bcp-petal-shadownoneShadow under each petal.
--bcp-petal-shadow-hover--bcp-petal-shadowShadow under a hovered petal.
--bcp-petal-hover-scale1.1How much a hovered petal grows.
--bcp-petal-hover-brightness1.1How much a hovered petal brightens.
--bcp-petal-vein-color#fffColor of the vein lines with petalStyle: 'veined'.
--bcp-petal-vein-opacity0.5Opacity of the vein lines.
--bcp-core-bg#FFFFFFCore color while expanded, when showCoreColor is off.
--bcp-core-shadowsubtle ring + shadowShadow of the expanded core.
--bcp-trigger-shadow0 2px 8px rgba(0, 0, 0, 0.12)Shadow of the collapsed trigger.
--bcp-trigger-shadow-hover0 4px 14px rgba(0, 0, 0, 0.18)Shadow of the hovered trigger.
--bcp-handle-borderwhiteOutline of the shade slider handle.
--bcp-focus-ring#3b82f6Keyboard focus outline.
--bcp-focus-ring-gapwhiteGap between the core and its focus outline.
.my-dark-theme .bcp-root {
  --bcp-surface: #1e1b2e;
  --bcp-core-bg: #1e1b2e;
  --bcp-track: rgba(255, 255, 255, 0.12);
  --bcp-handle-border: #1e1b2e;
  --bcp-focus-ring-gap: #1e1b2e;
}

Vanilla JS Methods

The core class exposes these additional methods:

MethodDescription
setValue(value)Set the current color value.
getValue()Get the current color as a BlossomColorPickerColor.
expand()Open the picker.
collapse()Close the picker.
toggle()Toggle open/close.
setOptions(opts)Update any options at runtime.
destroy()Remove all DOM elements and event listeners.

Features

Smart Shifter & Adaptive UI

The picker is built for all screen sizes. When adaptivePositioning is enabled:

  • Viewport Shifting: If the expanded picker would overflow the screen edge (common on mobile), it automatically shifts itself into view.
  • Auto Slider Positioning: The Arc Slider automatically moves to the side with the most available space (Top, Bottom, Left, or Right).
  • Dark Mode Ready: The background automatically adapts to your theme, using a soft, tinted overlay of the currently selected color.

Geometric Nesting

Our "Bloom" algorithm uses trigonometric calculations to ensure:

  • Zero Gaps: Petals aggressively "hug" the core and nestle deep into the "valleys" of previous layers.
  • Staggered Layout: Adjacent layers are automatically staggered to create a dense, natural blossom effect regardless of the color count.

Type Reference

BlossomColorPickerValue

The value object used for controlled / uncontrolled state.

FieldTypeDescription
huenumberHue angle (0-360).
saturationnumberSlider position (0-100). 0 = bright, 100 = dark.
lightnessnumber?HSL lightness (auto-computed from slider if omitted).
originalSaturationnumber?Base saturation of the selected petal.
colorIndexnumber?Index in the original input palette; preserves petal identity across layout sorting. Reset it when replacing the palette.
alphanumberAlpha value (0-100).
layer'inner' | 'outer'Which layer the selected petal belongs to.

BlossomColorPickerColor

Extends BlossomColorPickerValue — returned by onChange and onCollapse.

FieldTypeDescription
hexstringHex color string, e.g. "#6586E5".
hslstringHSL string, e.g. "hsl(225, 71%, 65%)".
hslastringHSLA string with alpha.

ColorInput

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

Color Formats

The colors option accepts any of the following formats, and they can be mixed:

// Vanilla JS
const picker = new BlossomColorPicker(el, {
  colors: [
    '#FF6B6B', // hex
    'rgb(107, 203, 119)', // rgb()
    'rgba(65, 105, 225, 0.9)', // rgba()
    'hsl(280, 70%, 55%)', // hsl()
    'hsl(200 80% 60%)', // hsl() space-separated
    { h: 45, s: 90, l: 65 }, // HSL object
  ],
});
// React
<BlossomColorPicker
  colors={['#FF6B6B', 'rgb(107, 203, 119)', { h: 45, s: 90, l: 65 }]}
/>

Project Structure

This is a monorepo with five packages:

packages/
  core/      @dayflow/blossom-color-picker          — standalone vanilla JS class
  react/     @dayflow/blossom-color-picker-react     — thin React wrapper
  vue/       @dayflow/blossom-color-picker-vue       — thin Vue 3 wrapper
  svelte/    @dayflow/blossom-color-picker-svelte    — thin Svelte 5 wrapper
  angular/   @dayflow/blossom-color-picker-angular   — thin Angular wrapper

The React, Vue, Svelte and Angular adapters are lightweight wrappers (~2 KB each) that mount the core instance into a container element and sync framework props/events to it.

Made by Jayce Li, idea from @lichinlin.

Keyboard interaction and state compatibility

Tab enters the petal group at one focusable petal. Left/Right move counterclockwise/clockwise in the current ring; Up moves inward and Down outward, choosing the nearest angular position. Enter/Space select the focused petal. Escape closes a collapsible picker and restores trigger focus. A picker with collapsible: false stays open.

The shade slider exposes role="slider" and its current value. Arrow keys change it by 1, Shift+Arrow and PageUp/PageDown by 10; Home/End select 0/100. Increasing shade darkens the color. onChange runs during interaction; onChangeComplete runs once on pointer release/cancellation, or key release/blur, with the last proposed color. A canceled pointer gesture retains its last change. No completion is emitted when there was no change or the picker is destroyed.

In controlled mode, petal and shade interactions only propose colors through callbacks. Supply the accepted value through setValue or setOptions({ value }). Passing setOptions({ value: undefined }) returns to uncontrolled mode while preserving the current accepted value.

For compatibility, value.saturation still stores the shade position, not HSL saturation. originalSaturation stores the petal's HSL saturation. showAlphaSlider remains a deprecated name for the shade arc; use showShadeSlider in new code. The Blossom picker preserves an explicitly supplied alpha but has no opacity control; use ChromePicker for its opacity slider. The default alpha is now 100 (opaque); pass 50 explicitly to retain the previous translucent default.

版本与发布记录

@dayflow/blossom-color-picker 共发布 13 个版本,首次发布于 2026/02/05;过去 12 个月发布了 13 个版本。

版本发布日期距今
2.5.0latest2026/10/2418 天前
2.4.02026/10/1329 天前
2.3.02026/09/102 个月前
2.2.12026/05/056 个月前
2.2.02026/03/317 个月前
2.1.02026/03/048 个月前

关于 @dayflow/blossom-color-picker 的常见问题

@dayflow/blossom-color-picker 是什么?

A beautiful, blooming color picker — standalone vanilla JS

如何安装 @dayflow/blossom-color-picker?

在项目目录运行 npm install @dayflow/blossom-color-picker,或使用 pnpm add / yarn add / bun add。

@dayflow/blossom-color-picker 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@dayflow/blossom-color-picker 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@dayflow/blossom-color-picker 可以商用吗?

@dayflow/blossom-color-picker 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@dayflow/blossom-color-picker 的下载量有多少?

根据 npm 官方下载统计,@dayflow/blossom-color-picker 在 2026/10/12 – 2026/11/10 这 30 天内被下载 76,523 次,日均约 2,551 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@dayflow/blossom-color-picker 还在维护吗?

最新版本 2.5.0 发布于 2026/10/24(18 天前);至今共发布 13 个版本,其中过去 12 个月发布了 13 个;首次发布于 2026/02/05。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。