Back to Blog

egui Theming: Custom Colors, Rounding & Spacing | Rust GUI Ep 26

Celest KimCelest Kim

Video: egui Theming: Custom Colors, Rounding & Spacing | Rust GUI Ep 26 by Taught by Celeste AI - AI Coding Coach

Watch full page →

egui Theming: Custom Colors, Rounding & Spacing

Learn how to create a customizable theme editor in egui that supports live preview of dark and light themes, accent colors, widget rounding, and spacing. This example demonstrates how to manipulate egui's Visuals and Style structures to build a dynamic UI with theme controls and instant feedback.

Code

use eframe::egui::{self, Color32, Rounding, Style, Visuals};

struct MyApp {
  dark_mode: bool,
  accent_color: Color32,
  rounding: f32,
  spacing: f32,
}

impl Default for MyApp {
  fn default() -> Self {
    Self {
      dark_mode: true,
      accent_color: Color32::from_rgb(100, 150, 250),
      rounding: 6.0,
      spacing: 8.0,
    }
  }
}

impl eframe::App for MyApp {
  fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
    // Choose base visuals: dark or light
    let mut visuals = if self.dark_mode {
      Visuals::dark()
    } else {
      Visuals::light()
    };

    // Set custom accent color for selection background
    visuals.selection.bg_fill = self.accent_color;

    // Clone current style and modify spacing and rounding
    let mut style: Style = (*ctx.style()).clone();
    style.visuals = visuals;
    style.spacing.item_spacing = egui::vec2(self.spacing, self.spacing);
    style.visuals.window_rounding = Rounding::same(self.rounding);
    style.visuals.widgets.inactive.rounding = Rounding::same(self.rounding);
    style.visuals.widgets.hovered.rounding = Rounding::same(self.rounding);
    style.visuals.widgets.active.rounding = Rounding::same(self.rounding);

    // Apply the updated style to the context
    ctx.set_style(style);

    // UI layout: Side panel for theme controls
    egui::SidePanel::left("theme_controls").show(ctx, |ui| {
      ui.heading("Theme Editor");

      ui.checkbox(&mut self.dark_mode, "Dark Mode");

      ui.horizontal(|ui| {
        ui.label("Accent Color:");
        ui.color_edit_button_rgb(&mut self.accent_color);
      });

      ui.add(egui::Slider::new(&mut self.rounding, 0.0..=20.0).text("Rounding"));
      ui.add(egui::Slider::new(&mut self.spacing, 0.0..=20.0).text("Spacing"));
    });

    // Central panel shows live preview of themed widgets
    egui::CentralPanel::default().show(ctx, |ui| {
      ui.heading("Live Preview");

      if ui.button("Button").clicked() {
        // Button clicked action
      }

      ui.checkbox(&mut self.dark_mode, "Checkbox");

      ui.label("This is a label with current theme.");
    });
  }
}

Key Points

  • Use Visuals::dark() and Visuals::light() as base themes for dark and light modes.
  • Customize accent colors by modifying visuals.selection.bg_fill with Color32 values.
  • Clone the current style with ctx.style().clone(), then adjust spacing and rounding properties.
  • Apply the modified style every frame using ctx.set_style() to enable live theme updates.
  • Use egui widgets like sliders, checkboxes, and color pickers in a SidePanel to control theme parameters dynamically.