Select Color: aligned views, smaller mode buttons, compact interface picker

- The gradient view no longer shows the nearest index colour.
- Mode buttons are 44 x 24 and the pipette button matches their height.
- Slider rows are 14 px apart and the gradient field is 108 px tall, so
  the hex value sits on the same row in the HSB, RGB and gradient views.
- The interface colour picker (Options) shrinks to its content, ending
  just below the hex row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013rGmDUNr1hUf4zo1X3dak8
This commit is contained in:
Claude committed 2026-10-12 18:53:51 +00:00
1 parent c8c5f667f7
commit 936c3b91aa
2 files changed
+33 -25

No files matched your search

+24 -17
View File
@@ -15,7 +15,12 @@ use iced::{Background, Border, Color, Element, Gradient, Length, Radians, Theme}
const ROW_HEIGHT: f32 = 26.0; const ROW_HEIGHT: f32 = 26.0;
const TRACK: f32 = 18.0; const TRACK: f32 = 18.0;
const STRIP_WIDTH: f32 = 22.0; const STRIP_WIDTH: f32 = 22.0;
const FIELD_HEIGHT: f32 = 118.0; /// Gap between slider rows. Together with `FIELD_HEIGHT` it puts the hex row
/// at the same height in every mode: 3 × 26 + 2 × 14 + 12 = 108 + 10.
const ROW_GAP: f32 = 14.0;
const FIELD_HEIGHT: f32 = 108.0;
const MODE_WIDTH: f32 = 44.0;
const MODE_HEIGHT: f32 = 24.0;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum EditorMode { pub enum EditorMode {
@@ -149,8 +154,8 @@ impl ColorEditor {
let active = self.mode == mode; let active = self.mode == mode;
button(container(content).center(Length::Fill)) button(container(content).center(Length::Fill))
.on_press(msg(EditorMsg::Mode(mode))) .on_press(msg(EditorMsg::Mode(mode)))
.width(52) .width(MODE_WIDTH)
.height(28) .height(MODE_HEIGHT)
.padding(0) .padding(0)
.style(move |theme: &Theme, status| { .style(move |theme: &Theme, status| {
super::picker::toggle_style(theme, active, status) super::picker::toggle_style(theme, active, status)
@@ -159,7 +164,7 @@ impl ColorEditor {
// The field button is only its gradient, without a frame; it takes // The field button is only its gradient, without a frame; it takes
// colour when its mode is active and stays gray otherwise. // colour when its mode is active and stays gray otherwise.
let field_active = self.mode == EditorMode::Field; let field_active = self.mode == EditorMode::Field;
let field_button = button(Space::new().width(52).height(28)) let field_button = button(Space::new().width(MODE_WIDTH).height(MODE_HEIGHT))
.on_press(msg(EditorMsg::Mode(EditorMode::Field))) .on_press(msg(EditorMsg::Mode(EditorMode::Field)))
.padding(0) .padding(0)
.style(move |_theme: &Theme, _status| { .style(move |_theme: &Theme, _status| {
@@ -182,8 +187,8 @@ impl ColorEditor {
} }
}); });
let mut modes = row![ let mut modes = row![
mode_button(text("HSB").size(12).into(), EditorMode::Hsb), mode_button(text("HSB").size(11).into(), EditorMode::Hsb),
mode_button(text("RGB").size(12).into(), EditorMode::Rgb), mode_button(text("RGB").size(11).into(), EditorMode::Rgb),
field_button, field_button,
Space::new().width(Length::Fill), Space::new().width(Length::Fill),
] ]
@@ -232,7 +237,7 @@ impl ColorEditor {
EditorMsg::Brightness, EditorMsg::Brightness,
), ),
] ]
.spacing(10) .spacing(ROW_GAP)
.into(), .into(),
EditorMode::Rgb => { EditorMode::Rgb => {
let ends = |lo: (u8, u8, u8), hi: (u8, u8, u8)| { let ends = |lo: (u8, u8, u8), hi: (u8, u8, u8)| {
@@ -310,23 +315,25 @@ impl ColorEditor {
.spacing(10) .spacing(10)
.align_y(iced::Center), .align_y(iced::Center),
] ]
// 108 + 10 matches the slider views' 3 × 26 + 2 × 14 + 12.
.spacing(10) .spacing(10)
.into() .into()
} }
}; };
// Below the editor: the hex value (unless the field view already // The field view shows the hex value beside H, S and B and leaves out
// shows it) and, on the right, the nearest index colour. // the nearest index colour; the slider views end on a hex row.
let mut hex_row = row![].spacing(8).align_y(iced::Center); let mut view = column![modes, editor].spacing(12);
if !field_mode { if !field_mode {
hex_row = hex_row.push(hex_field()); let mut hex_row = row![hex_field(), Space::new().width(Length::Fill)]
.spacing(8)
.align_y(iced::Center);
if let Some(end) = hex_end {
hex_row = hex_row.push(end);
}
view = view.push(hex_row);
} }
hex_row = hex_row.push(Space::new().width(Length::Fill)); view.into()
if let Some(end) = hex_end {
hex_row = hex_row.push(end);
}
column![modes, editor, hex_row].spacing(12).into()
} }
} }
+9 -8
View File
@@ -20,8 +20,6 @@ const PANEL_WIDTH: f32 = 400.0;
/// fields instead of the dialogs and command line underneath. /// fields instead of the dialogs and command line underneath.
const PANEL_ID: &str = "select-color-panel"; const PANEL_ID: &str = "select-color-panel";
const BODY_HEIGHT: f32 = 352.0; const BODY_HEIGHT: f32 = 352.0;
/// The interface picker has no tabs or info line, only the editor.
const EDITOR_ONLY_HEIGHT: f32 = 258.0;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ColorPickerTab { pub enum ColorPickerTab {
@@ -179,8 +177,11 @@ impl ColorPicker {
self.index_tab() self.index_tab()
}; };
let mut body = column![body, Space::new().height(Length::Fill)].spacing(8); // The interface picker shrinks to the editor; the CAD panel keeps one
// height across its tabs, with the info line at the bottom.
let mut body = column![body].spacing(8);
if !editor_only { if !editor_only {
body = body.push(Space::new().height(Length::Fill));
let fill = let fill =
math::color_rgb(self.pending).map_or(Color::from_rgb8(128, 128, 128), rgb_color); math::color_rgb(self.pending).map_or(Color::from_rgb8(128, 128, 128), rgb_color);
body = body body = body
@@ -208,9 +209,9 @@ impl ColorPicker {
.padding(12) .padding(12)
.width(Length::Fill) .width(Length::Fill)
.height(if editor_only { .height(if editor_only {
EDITOR_ONLY_HEIGHT Length::Shrink
} else { } else {
BODY_HEIGHT Length::Fixed(BODY_HEIGHT)
}) })
.style(panel_style); .style(panel_style);
@@ -396,10 +397,10 @@ impl ColorPicker {
None None
} else { } else {
Some( Some(
button(crate::ui::icons::themed(crate::ui::icons::EYEDROPPER, 16.0)) button(crate::ui::icons::themed(crate::ui::icons::EYEDROPPER, 14.0))
.on_press(picker_msg(ColorPickerMsg::Eyedropper(EyedropperMsg::Start))) .on_press(picker_msg(ColorPickerMsg::Eyedropper(EyedropperMsg::Start)))
.height(28) .height(24)
.padding([0, 8]) .padding([0, 7])
.style(|theme: &Theme, status| toggle_style(theme, false, status)) .style(|theme: &Theme, status| toggle_style(theme, false, status))
.into(), .into(),
) )