-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Goal
Build 4 composable vanilla-TS primitives + 1 inline gamut helper in packages/ui/src/primitives/ that together form a full OKLCH color picker. Each primitive follows the Rafters pattern (element in, cleanup out, SSR-safe, zero deps).
Architecture
See .github/color-picker-spec.md for the complete interface specification.
Primitives
| Primitive | File | Responsibility |
|---|---|---|
| oklch-gamut | oklch-gamut.ts |
Inline sRGB/P3 gamut classification (~30 lines of matrix math) |
| interactive | interactive.ts |
Pointer tracking surface (mouse/touch/keyboard -> normalized 0-1 coords) |
| color-area | color-area.ts |
2D canvas: Lightness x Chroma at fixed Hue, black for out-of-gamut |
| hue-bar | hue-bar.ts |
1D canvas: 0-360 hue spectrum at given L/C |
| color-input | color-input.ts |
Filtered numeric L/C/H input fields |
Shared Types (types.ts additions)
NormalizedPoint- {left, top} both 0-1MoveDelta- keyboard movement deltaInteractiveMode- '1d-horizontal' | '1d-vertical' | '2d'OklchColor/OklchColorAlpha- color triplets
Key Design Decisions
- Inline gamut math --
oklch-gamut.tsprovidesinSrgb(l,c,h)andinP3(l,c,h)via matrix multiplication (~30 lines). No external deps. - Canvas-based rendering for color-area and hue-bar (CSS gradients cannot represent OKLCH's irregular gamut boundary).
- interactive is color-agnostic -- same primitive tracks pointer on the 2D area and the 1D hue strip.
- color-swatch reused for thumb/pointer -- no separate color-pointer primitive. Caller adds positioning CSS.
- All primitives are copyable via
rafters add-- only import from sibling primitives, never workspace packages. - No Zod -- plain TS types (dep-free constraint).
- Gamut feedback is consumer concern -- primitives expose
inSrgb/inP3booleans, consumer shows sRGB/P3 icons with checkmark or !.
Composition
ColorPicker (consumer component)
+-- ColorArea (2D canvas, L x C at current H)
| +-- Interactive (pointer tracking, 2D mode)
| +-- ColorSwatch (thumb at current L,C -- already built)
|
+-- HueBar (1D canvas, 0-360)
| +-- Interactive (pointer tracking, 1D mode)
| +-- ColorSwatch (thumb at current H -- already built)
|
+-- ColorInput (L, C, H filtered fields)
+-- ColorSwatch (preview -- already built)
Sub-Issues
- Implement shared types - NormalizedPoint, MoveDelta, InteractiveMode, OklchColor additions to types.ts #786 - Shared types additions to types.ts
- Implement oklch-gamut.ts - inline sRGB/P3 gamut classification helper #787 - oklch-gamut.ts inline gamut helper
- Implement interactive primitive - pointer tracking surface #788 - interactive primitive (pointer tracking surface)
- Implement color-area primitive - 2D gamut-aware OKLCH canvas renderer #789 - color-area primitive (2D gamut-aware canvas)
- Implement hue-bar primitive - 1D OKLCH hue spectrum canvas renderer #790 - hue-bar primitive (1D hue spectrum)
- Implement color-input primitive - filtered numeric OKLCH input fields #791 - color-input primitive (filtered numeric inputs)
- feat(ui): add ColorPicker React component composing OKLCH primitives #798 - ColorPicker React component (composes all primitives)
Superseded Issues
Issues #780-785 were closed -- they used an outdated architecture (external gamut boundaries, separate color-pointer, workspace deps).
Prerequisite
- feat(color-utils): add three-tier gamut awareness utilities #776 - color-utils gamut awareness utilities
- feat(ui): add color-swatch primitive #777 - color-swatch primitive
Success Criteria
- All primitives implemented with tests
- Shared types added to types.ts
- TypeScript compiles without errors
- All tests pass (77 tests across 6 primitive files)
- Primitives compose correctly (verified by feat(ui): add ColorPicker React component composing OKLCH primitives #798 React component)
This issue is complete when: All sub-issues are closed and the primitives compose into a working color picker via #798.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request