Color Field

Select two color dimensions on a rectangle, triangle, or wheel.

Try it

Drag within the saturation/value field to update the preview and committed color. This preview runs the exact code sample below.

Open example separately ↗

Basic use

Saturation/value field with named callbacks
use gpui::{AppContext, Context, Entity, Render, Window, prelude::*, px};
use xgpui_luma_color::color_field::{ColorFieldEventExt, ColorFieldState};
use xgpui_luma_color::color_slider::color_spec::Hsv;

struct Example {
    field: Entity<ColorFieldState>,
    preview: Hsv,
    committed: Hsv,
}
impl Example {
    fn new(cx: &mut Context<Self>) -> Self {
        let hsv = Hsv { h: 210.0, s: 0.7, v: 0.8, a: 1.0 };
        let field = cx.new(|_| {
            ColorFieldState::saturation_value_rect("sv", hsv, 16.0)
                .vector().size(px(220.0)).rounded(px(0.0))
                .keyboard_steps(0.01, 0.1)
        })
        .on_value_changed(cx, |owner: &mut Self, hsv, cx| {
            owner.preview = hsv;
            cx.notify();
        })
        .on_release(cx, |owner, hsv, cx| {
            owner.committed = hsv;
            cx.notify();
        });
        Self { field, preview: hsv, committed: hsv }
    }
}
impl Render for Example {
    fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
        self.field.clone()
    }
}

Planes and wheels

ConstructorInteraction
saturation_value_rectSaturation/value at fixed hue.
saturation_value_triangleSaturation/value within a triangle domain.
hue_saturation_wheelHue/saturation within a circle.
hue_saturationHue/saturation rectangle at fixed value.
hue_valueHue/value rectangle at fixed saturation.

Constructors return ColorFieldState; retain it with cx.new. Render the entity directly, or use ColorField::new(&state). Custom surfaces pair a FieldDomain2D with a ColorFieldModel2D through new, with_domain, and with_model.

Events and updates

Import ColorFieldEventExt and register named callbacks on the entity after cx.new. Each callback receives the owner, the payload below, and the owner context. Subscriptions are retained automatically for the field’s lifetime; the owner is held weakly. Use on_event or cx.subscribe for the full ColorFieldEvent stream.

EventPayloadHandling
ChangeHsvon_value_changed
Update the live preview.
ReleaseHsvon_release
Commit the final interaction value.
DragStarthsv: Hsvon_drag_start
Begin a pointer gesture.
DragEndhsv: Hsvon_drag_end
Finish a pointer gesture.
HoverChangedhovered: boolon_hover_changed
React to pointer hover.
EnabledChangedenabled: boolon_enabled_changed
React to enablement changes.

Use set_hsv or set_hsv_components to synchronize another color editor into the field. The field is an HSV editing view, not storage for an original Display P3 or Oklch source.

Keyboard and rendering

An enabled field is one Tab stop and focuses on pointer press by default. Arrows move spatially by 1%; Shift+Arrow uses 10%. keyboard_steps, tab_stop, and pointer_focus_policy customize this. A changed keyboard adjustment emits Change and one final Release, without pointer drag events. Wheel input passes through.

vector() paints the field directly. Raster rendering is the default; raster_image_prewarmed(width, height) prepares its cache. inside_field, edge_to_edge, and edge_to_edge_clipped control thumb placement. Focus does not add a visual focus treatment; screen-reader semantics remain a follow-up in the current implementation.

Source

Implementation · Picker composition