Color Slider

Edit hue, alpha, individual channels, or gradient positions on a color track.

Try it

Drag the hue slider to update the preview and committed hue. This preview runs the exact code sample below.

Open example separately ↗

Basic use

Hue slider with preview and commit
use gpui::{Context, Entity, Render, Window, div, prelude::*, px};
use xgpui_luma::controls::slider::{SliderControl, SliderEventExt};
use xgpui_luma_color::color_slider::ColorSliderBuilder;
use xgpui_luma::theme::ControlSize;

struct Example {
    control: Entity<SliderControl>,
    preview: f32,
    committed: f32,
}
impl Example {
    fn new(cx: &mut Context<Self>) -> Self {
        let control = ColorSliderBuilder::hue("hue", 210.0)
            .size(ControlSize::Sm).thumb_medium()
            .spawn(cx)
            .on_value_changed(cx, |owner: &mut Self, _, value, cx| {
                owner.preview = value;
                cx.notify();
            })
            .on_release(cx, |owner, _, value, cx| {
                owner.committed = value;
                cx.notify();
            });
        Self { control, preview: 210.0, committed: 210.0 }
    }
}
impl Render for Example {
    fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
        div().w(px(240.0)).child(self.control.clone())
    }
}

Channels and gradients

hue uses degrees (0..360); alpha uses 0..1 and a supplied color specification. channel looks up a named channel’s bounds and step from that specification and returns Result<_, String>. Gradient construction accepts retained ColorValue stops and returns anyhow::Result.

RGBA channel and source-color gradient
fn red_channel(cx: &mut gpui::Context<Example>)
    -> Result<gpui::Entity<SliderControl>, String> {
    use xgpui_luma_color::color_slider::RgbaSpec;
    let rgba = RgbaSpec { r: 0.8, g: 0.3, b: 0.2, a: 1.0 };
    Ok(ColorSliderBuilder::channel("red", rgba.r, rgba, RgbaSpec::RED)?.spawn(cx))
}

fn gradient(cx: &mut gpui::Context<Example>)
    -> Result<gpui::Entity<SliderControl>, Box<dyn std::error::Error + Send + Sync>> {
    use xgpui_luma::color::ColorValue;
    use xgpui_luma_color::color_slider::ColorInterpolation;
    Ok(ColorSliderBuilder::gradient("gradient", 0.5, vec![
        ColorValue::srgb(1.0, 0.0, 0.0, 1.0),
        ColorValue::srgb(0.0, 0.0, 1.0, 0.5),
    ])?.interpolation(ColorInterpolation::Lab).spawn(cx))
}

Events

EventPayloadCallback
Changethumb_id: ThumbId
value: f32
on_value_changed
Update the live preview.
Releasethumb_id: ThumbId
value: f32
on_release
Commit the interaction value.
DragStartthumb_id: ThumbIdon_drag_start
Begin a pointer gesture.
DragEndthumb_id: ThumbId
value: f32
on_drag_end
Finish a pointer gesture.
ThumbAddedthumb_id: ThumbId
value: f32
on_thumb_added
Track an added gradient stop.
ThumbRemovedthumb_id: ThumbIdon_thumb_removed
Track a removed stop.
ThumbSelectedthumb_id: ThumbIdon_thumb_selected
Update the selected thumb.
FocusChangedfocused: boolon_focus_changed
React to keyboard focus.
HoverChangedhovered: boolon_hover_changed
React to pointer hover.
EnabledChangedenabled: boolon_enabled_changed
React to enablement changes.

These are SDK SliderEvent callbacks, available through SliderEventExt. The builders return Entity<SliderControl>. Each callback receives the owner, the listed payload values, and the owner context. Register callbacks after spawn; use on_event or cx.subscribe for the full event stream. See Slider events.

Appearance and synchronization

Use horizontal/vertical, size(ControlSize), thumb_size(SliderThumbSize), thumb_square, thumb_bar, rounded, and edge_to_edge. Gradient interpolation supports RGB, HSL, and Lab. multi_stop, dual_stop, and thumb_policy configure multiple thumbs.

Capture domain_renderer() and track_context() before consuming the builder. When a base color changes, replace its delegate with update_domain_delegate and call refresh_color_slider to refresh thumb previews. ColorCompositionSync::sync_color_slider combines these updates. Changing only the numeric slider value does not replace a delegate’s color specification.

Custom thumb painting

Implement ColorSliderDelegate::thumb_painter(&self, context: &ColorSliderTrackContext, position: f32) -> Option<ColorThumbPainter> to supply a custom thumb background for a normalized track position. The default returns None, preserving the normal thumb preview. ColorSliderBuilder::new connects the delegate to the thumb template automatically; track painting and slider behavior remain owned by their existing delegate and SDK control.

ColorThumbPainter is an Arc callback that receives Bounds<Pixels>, a mutable Window, and a mutable App, and returns anyhow::Result<()>. The callback must be Send + Sync. The thumb invokes it inside an inset canvas over the normal background. Paint failures are currently discarded by the thumb renderer, so handle any required diagnostics in the callback.

For a custom template that constructs its own ColorThumb, attach the painter directly with background_painter:

Custom thumb template helper
fn custom_thumb(
    painter: xgpui_luma_color::color_slider::color_thumb::ColorThumbPainter,
) -> xgpui_luma_color::color_slider::color_thumb::ColorThumb {
    xgpui_luma_color::color_slider::color_thumb::ColorThumb::new(gpui::px(20.0))
        .background_painter(painter)
}

Source

Implementation · SDK Slider · Picker composition