Skip to content

Releases: emilk/egui

0.32.0 - Atoms, popups, and better SVG support

10 Jul 15:04
fabd4aa
Compare
Choose a tag to compare

egui is an easy-to-use immediate mode GUI for Rust that runs on both web and native.

Try it now: https://www.egui.rs/

egui development is sponsored by Rerun, a startup building an SDK for visualizing streams of multimodal data.

egui 0.32.0 changelog

This is a big egui release, with several exciting new features!

  • Atoms are new layout primitives in egui, for text and images
  • Popups, tooltips and menus have undergone a complete rewrite
  • Much improved SVG support
  • Crisper graphics (especially text!)

Let's dive in!

⚛️ Atoms

egui::Atom is the new, indivisible building block of egui (hence the name).
It lets you mix images and text in many places where you would previously only be able to add text.

Atoms is the first step towards a more powerful layout engine in egui - more to come!

Right now an Atom is an enum that can be either WidgetText, Image, or Custom.

The new AtomLayout can be used within widgets to do basic layout.
The initial implementation is as minimal as possible, doing just enough to implement what Button could do before.
There is a new IntoAtoms trait that works with tuples of Atoms. Each atom can be customized with the AtomExt trait
which works on everything that implements Into<Atom>, so e.g. RichText or Image.
So to create a Button with text and image you can now do:

let image = include_image!("my_icon.png").atom_size(Vec2::splat(12.0));
ui.button((image, "Click me!"));

Anywhere you see impl IntoAtoms you can add any number of images and text, in any order.

As of 0.32, we have ported the Button, Checkbox, RadioButton to use atoms
(meaning they support adding Atoms and are built on top of AtomLayout).
The Button implementation is not only more powerful now, but also much simpler, removing ~130 lines of layout math.

In combination with ui.read_response, custom widgets are really simple now, here is a minimal button implementation:

pub struct ALButton<'a> {
    al: AtomLayout<'a>,
}

impl<'a> ALButton<'a> {
    pub fn new(content: impl IntoAtoms<'a>) -> Self {
        Self {
            al: AtomLayout::new(content.into_atoms()).sense(Sense::click()),
        }
    }
}

impl<'a> Widget for ALButton<'a> {
    fn ui(mut self, ui: &mut Ui) -> Response {
        let Self { al } = self;
        let response = ui.ctx().read_response(ui.next_auto_id());

        let visuals = response.map_or(&ui.style().visuals.widgets.inactive, |response| {
            ui.style().interact(&response)
        });

        let al = al.frame(
            Frame::new()
                .inner_margin(ui.style().spacing.button_padding)
                .fill(visuals.bg_fill)
                .stroke(visuals.bg_stroke)
                .corner_radius(visuals.corner_radius),
        );

        al.show(ui).response
    }
}

You can even use Atom::custom to add custom content to Widgets. Here is a button in a button:

Screen.Recording.2025-07-10.at.13.10.52.mov
let custom_button_id = Id::new("custom_button");
let response = Button::new((
    Atom::custom(custom_button_id, Vec2::splat(18.0)),
    "Look at my mini button!",
))
.atom_ui(ui);
if let Some(rect) = response.rect(custom_button_id) {
    ui.put(rect, Button::new("🔎").frame_when_inactive(false));
}

Currently, you need to use atom_ui to get a AtomResponse which will have the Rect to use, but in the future
this could be streamlined, e.g. by adding a AtomKind::Callback or by passing the Rects back with egui::Response.

Basing our widgets on AtomLayout also allowed us to improve Response::intrinsic_size, which will now report the
correct size even if widgets are truncated. intrinsic_size is the size that a non-wrapped, non-truncated,
non-justified version of the widget would have, and can be useful in advanced layout
calculations like egui_flex.

Details

❕ Improved popups, tooltips, and menus

Introduces a new egui::Popup api. Checkout the new demo on https://egui.rs:

Screen.Recording.2025-07-10.at.11.47.22.mov

We introduced a new RectAlign helper to align a rect relative to an other rect. The Popup will by default try to find the best RectAlign based on the source widgets position (previously submenus would annoyingly overlap if at the edge of the window):

Screen.Recording.2025-07-10.at.11.36.29.mov

Tooltip and menu have been rewritten based on the new Popup api. They are now compatible with each other, meaning you can just show a ui.menu_button() in any Popup to get a sub menu. There are now customizable MenuButton and SubMenuButton structs, to help with customizing your menu buttons. This means menus now also support PopupCloseBehavior so you can remove your close_menu calls from your click handlers!

The old tooltip and popup apis have been ported to the new api so there should be very little breaking changes. The old menu is still around but deprecated. ui.menu_button etc now open the new menu, if you can't update to the new one immediately you can use the old buttons from the deprecated egui::menu menu.

We also introduced ui.close() which closes the nearest container. So you can now conveniently close Windows, Collapsibles, Modals and Popups from within. To use this for your own containers, call UiBuilder::closable and then check for closing within that ui via ui.should_close().

Details

▲ Improved SVG support

You can render SVG in egui with

ui.add(egui::Image::new(egui::include_image!("icon.svg"));

(Requires the use of egui_extras, with the svg feature enabled and a call to install_image_loaders).

Previously this would sometimes result in a blurry SVG, epecially if the Image was set to be dynamically scale based on the size of the Ui that contained it. Now SVG:s are always pixel-perfect, for truly scalable graphics.

svg-scaling

Details

✨ Crisper graphics

Non-SVG icons are also rendered better, and text sharpness has been improved, especially in light mode.

image

Details
  • Improve text sharpness #5838 by @emilk
  • Improve text rendering in light mode #7290 by @emilk
  • Improve texture filtering by doing it in gamma space #7311 by @emilk
  • Make text underline and strikethrough pixel perfect crisp #5857 by @emilk

Migration guide

We have some silently breaking changes (code compiles fine but behavior changed) that require special care:

wgpu backend features

  • wgpu 25 made the gles and vulkan backends optional
    • We missed this, so for now you need to manually opt in to those backends. Add the following to you Cargo.toml
      wgpu = "25" # enables the wgpu default features so we get the default backends
      

Menus close on click by default

  • Previously menus would only close on click outside
  • Either
    • Remove the ui.close_menu() calls from button click handlers sinc...
Read more

0.31.1 - TextEdit and egui_kittest fixes

05 Mar 07:46
Compare
Choose a tag to compare

egui is an easy-to-use immediate mode GUI for Rust that runs on both web and native.

Try it now: https://www.egui.rs/

egui development is sponsored by Rerun, a startup building an SDK for visualizing streams of multimodal data.

egui

egui_extras

egui_kittest

epaint

  • Fix panic when rendering thin textured rectangles #5692 by @PPakalns

0.31.0 - Scene container, improved rendering quality

04 Feb 16:01
Compare
Choose a tag to compare

egui is an easy-to-use immediate mode GUI for Rust that runs on both web and native.

Try it now: https://www.egui.rs/

egui development is sponsored by Rerun, a startup building an SDK for visualizing streams of multimodal data.

Highlights ✨

Scene container

This release adds the Scene container to egui. It is a pannable, zoomable canvas that can contain Widgets and child Uis.
This will make it easier to e.g. implement a graph editor.

scene

Clearer, pixel perfect rendering

The tessellator has been updated for improved rendering quality and better performance. It will produce fewer vertices
and shapes will have less overdraw. We've also defined what CornerRadius (previously Rounding) means.

We've also added a tessellator test to the demo app, where you can play around with different
values to see what's produced:

tessellator-test.mp4

Check the PR for more details.

CornerRadius, Margin, Shadow size reduction

In order to pave the path for more complex and customizable styling solutions, we've reduced the size of
CornerRadius, Margin and Shadow values to i8 and u8.

Migration guide

  • Add a StrokeKind to all your Painter::rect calls #5648
  • StrokeKind::default was removed, since the 'normal' value depends on the context #5658
    • You probably want to use StrokeKind::Inside when drawing rectangles
    • You probably want to use StrokeKind::Middle when drawing open paths
  • Rename Rounding to CornerRadius #5673
  • CornerRadius, Margin and Shadow have been updated to use i8 and u8 #5563, #5567, #5568
    • Remove the .0 from your values
    • Cast dynamic values with as i8 / as u8 or as _ if you want Rust to infer the type
      • Rust will do a 'saturating' cast, so if your f32 value is bigger than 127 it will be clamped to 127
  • RectShape parameters changed #5565
    • Prefer to use the builder methods to create it instead of initializing it directly
  • Frame now takes the Stroke width into account for its sizing, so check all views of your app to make sure they still look right.
    Read the PR for more info.

⭐ Added

🔧 Changed

  • ⚠️ Frame now includes stroke width as part of padding #5575 by @emilk
  • Rename Rounding to CornerRadius #5673 by @emilk
  • Require a StrokeKind when painting rectangles with strokes #5648 by @emilk
  • Round widget coordinates to even multiple of 1/32 #5517 by @emilk
  • Make all lines and rectangles crisp #5518 by @emilk
  • Tweak window resize handles #5524 by @emilk

🔥 Removed

🐛 Fixed

  • Use correct minimum version of profiling crate #5494 by @lucasmerlin
  • Fix interactive widgets sometimes being incorrectly marked as hovered #5523 by @emilk
  • Fix panic due to non-total ordering in Area::compare_order() #5569 by @HactarCE
  • Fix hovering through custom menu button #5555 by @M4tthewDE

🚀 Performance

  • Use u8 in CornerRadius, and introduce CornerRadiusF32 #5563 by @emilk
  • Store Margin using i8 to reduce its size #5567 by @emilk
  • Shrink size of Shadow by using i8/u8 instead of f32 #5568 by @emilk
  • Avoid allocations for loader cache lookup #5584 by @mineichen
  • Use bitfield instead of bools in Response and Sense #5556 by @polwel

0.30.0 - egui_kittest and modals

16 Dec 17:11
Compare
Choose a tag to compare

egui is an easy-to-use immediate mode GUI for Rust that runs on both web and native.

Try it now: https://www.egui.rs/

egui development is sponsored by Rerun, a startup building an SDK for visualizing streams of multimodal data.

egui_kittest

This release welcomes a new crate to the family: egui_kittest.
egui_kittest is a testing framework for egui, allowing you to test both automation (simulated clicks and other events),
and also do screenshot testing (useful for regression tests).
egui_kittest is built using kittest, which is a general GUI testing framework that aims to work with any Rust GUI (not just egui!).
kittest uses the accessibility library AccessKit for automatation and to query the widget tree.

kittest and egui_kittest are written by @lucasmerlin.

Here's a quick example of how to use egui_kittest to test a checkbox:

use egui::accesskit::Toggled;
use egui_kittest::{Harness, kittest::Queryable};

fn main() {
    let mut checked = false;
    let app = |ui: &mut egui::Ui| {
        ui.checkbox(&mut checked, "Check me!");
    };

    let mut harness = egui_kittest::Harness::new_ui(app);

    let checkbox = harness.get_by_label("Check me!");
    assert_eq!(checkbox.toggled(), Some(Toggled::False));
    checkbox.click();

    harness.run();

    let checkbox = harness.get_by_label("Check me!");
    assert_eq!(checkbox.toggled(), Some(Toggled::True));

    // You can even render the ui and do image snapshot tests
    #[cfg(all(feature = "wgpu", feature = "snapshot"))]
    harness.wgpu_snapshot("readme_example");
}

egui changelog

✨ Highlights

⭐ Added

🔧 Changed

🐛 Fixed

eframe changelog

BREAKING: you now need to enable the wayland and/or x11 features to get Linux support, including getting it to work on most CI systems.

⭐ Added

🔧 Changed

🐛 Fixed

  • iOS: Support putting UI next to the dynamic island #5211 by @frederik-uni
  • Prevent panic when copying text outside of a secure context #5326 by @YgorSouza
  • Fix accidental change of FallbackEgl to PreferEgl #5408 by @e00E

0.29.1 - Bug fixes

01 Oct 08:12
Compare
Choose a tag to compare

egui is an easy-to-use immediate mode GUI for Rust that runs on both web and native.

Try it now: https://www.egui.rs/

egui development is sponsored by Rerun, a startup building an SDK for visualizing streams of multimodal data.

egui

  • Remove debug-assert triggered by with_layer_id/dnd_drag_source #5191 by @emilk
  • Fix id clash in Ui::response #5192 by @emilk
  • Do not round panel rectangles to pixel grid #5196 by @emilk

eframe

  • Linux: Disable IME to fix backspace/arrow keys #5188 by @emilk

0.29.0 - Multipass, `UiBuilder`, & visual improvements

26 Sep 13:35
Compare
Choose a tag to compare

egui is an easy-to-use immediate mode GUI for Rust that runs on both web and native.

Try it now: https://www.egui.rs/

egui development is sponsored by Rerun, a startup building an SDK for visualizing streams of multimodal data.

egui changelog

✨ Highlights

This release adds initial support for multi-pass layout, which is a tool to circumvent a common limitation of immediate mode.
You can use the new UiBuilder::sizing_pass (#4969) to instruct the Ui and widgets to shrink to their minimum size, then store that size.
Then call the new Context::request_discard (#5059) to discard the visual output and do another pass immediately after the current finishes.
Together, this allows more advanced layouts that is normally not possible in immediate mode.
So far this is only used by egui::Grid to hide the "first-frame jitters" that would sometimes happen before, but 3rd party libraries can also use it to do much more advanced things.

There is also a new UiBuilder for more flexible construction of Uis (#4969).
By specifying a sense for the Ui you can make it respond to clicks and drags, reading the result with the new Ui::response (#5054).
Among other things, you can use this to create buttons that contain arbitrary widgets.

0.29 also adds improve support for automatic switching between light and dark mode.
You can now set up a custom Style for both dark and light mode, and have egui follow the system preference (#4744 #4860).

There also has been several small improvements to the look of egui:

  • Fix vertical centering of text (e.g. in buttons) (#5117)
  • Sharper rendering of lines and outlines (#4943)
  • Nicer looking text selection, especially in light mode (#5017)

The new text selection

New text selection in light mode New text selection in dark mode

What text selection used to look like

Old text selection in light mode Old text selection in dark mode

🧳 Migration

  • id_source is now called id_salt everywhere (#5025)
  • Ui::new now takes a UiBuilder (#4969)
  • Deprecated (replaced with UiBuilder):
    • ui.add_visible_ui
    • ui.allocate_ui_at_rect
    • ui.child_ui
    • ui.child_ui_with_id_source
    • ui.push_stack_info

⭐ Added

🚀 Performance

🔧 Changed

🐛 Fixed

  • Prevent text shrinking in tooltips; round wrap-width to integer #5161 by @emilk
  • Fix bug causing tooltips with dynamic content to shrink #5168 by @emilk
  • Remove some debug asserts #4826 by @emilk
  • Handle the IME event first in TextEdit to fix some bugs #4794 by @rustbasic
  • Slider: round to decimals after applying step_by #4822 by @AurevoirXavier
  • Fix: hint text follows the alignment set on the TextEdit #4889 by @PrimmR
  • Request focus on a TextEdit when clicked #4991 by @Zoxc
  • Fix Id clash in Frame styling widget #4967 by @YgorSouza
  • Prevent ScrollArea contents from exceeding the container size #5006 by @DouglasDwyer
  • Fix bug in ...
Read more

0.28.1 - Tooltip tweaks

05 Jul 10:13
Compare
Choose a tag to compare

egui is an easy-to-use immediate mode GUI for Rust that runs on both web and native.

Try it now: https://www.egui.rs/

egui development is sponsored by Rerun, a startup building an SDK for visualizing streams of multimodal data.

egui changelog

⭐ Added

🔧 Changed

🐛 Fixed

  • Fix default height of top/bottom panels #4779 by @emilk
  • Show the innermost debug rectangle when pressing all modifier keys #4782 by @emilk
  • Fix occasional flickering of pointer-tooltips #4788 by @emilk

eframe changelog

0.28.0 - Sizing pass, and better eframe web

03 Jul 13:02
Compare
Choose a tag to compare

egui is an easy-to-use immediate mode GUI for Rust that runs on both web and native.

Try it now: https://www.egui.rs/

egui development is sponsored by Rerun, a startup building an SDK for visualizing streams of multimodal data.

egui changelog

✨ Highlights

🧳 Migration

  • Update MSRV to 1.76 (#4411)
  • The wrap/truncate functions on Label/Button/ComboBox no longer take bools as arguments. Use .wrap_mode(…) instead for more fine control (#4556)
  • Style::wrap has been deprecated in favor of Style::wrap_mode (#4556)
  • Ui::new and ui.child_ui now takes a new parameter for the UiStack (#4588)
  • The extra_asserts and extra_debug_asserts feature flags have been removed (#4478)
  • Remove Event::Scroll and handle it in egui. Use Event::MouseWheel instead (#4524)
  • Event::Zoom is no longer emitted on ctrl+scroll. Use InputState::smooth_scroll_delta instead (#4524)
  • ui.set_enabled and set_visbile have been deprecated (#4614)
  • DragValue::clamp_range renamed to range ((#4728)

⭐ Added

  • Overload operators for Rect + Margin, Rect - Margin etc #4277 by @emilk
  • Add Window::order #4301 by @alexparlett
  • Add a way to specify Undoer settings and construct Undoers more easily #4357 by @valadaptive
  • Add xtask crate #4293 by @YgorSouza
  • Add ViewportCommand::RequestCut, RequestCopy and RequestPaste to trigger clipboard actions #4035 by @bu5hm4nn
  • Added ability to define colors at UV coordinates along a path #4353 by @murl-digital
  • Add a Display impl for Vec2, Pos2, and Rect #4428 by @tgross35
  • Easing functions #4630 by @emilk
  • Add Options::line_scroll_speed and scroll_zoom_speed #4532 by @emilk
  • Add TextEdit::hint_text_font #4517 by @zaaarf
  • Add Options::reduce_texture_memory to free up RAM #4431 by @varphone
  • Add support for text truncation to egui::Style #4556 by @abey79
  • Add Response::show_tooltip_ui and show_tooltip_text #4580 by @emilk
  • Add opacity and multiply_opacity functions to Ui and Painter #4586 by @emilk
  • Add Key::Quote #4683 by @mkeeter
  • Improve backtraces when hovering widgets with modifiers pressed #4696 by @emilk
  • Add PopupCloseBehavior #4636 by @Umatriz
  • Add basic test for egui accesskit output #4716 by @Wcubed
  • Add clamp_to_range option to DragValue, rename clamp_range to range (deprecating the former) #4728 by @Wumpf
  • Add Style::number_formatter as the default used by DragValue #4740 by @emilk

🔧 Changed

  • Improve the UI for changing the egui theme #4257 by @emilk
  • Change the resize cursor when you reach the resize limit #4275 by @emilk
  • Make TextEdit an atomic widget #4276 by @emilk
  • Rename fn scroll2 to fn scroll #4282 by @emilk
  • Change Frame::multiply_with_opacity to multiply in gamma space #4283 by @emilk
  • Use parent Uis style for popups #4325 by @alexparlett
  • Take rounding into account when using Slider::trailing_fill #4308 by @rustbasic
  • Allow users to create viewports larger than monitor on Windows & macOS #4337 by @lopo12123
  • Improve ViewportBuilder::with_icon() documentation #4408 by @roccoblues
  • include_image! now accepts expressions #4521 by @YgorSouza
  • Remove scroll latency for smooth trackpads #4526 by @emilk
  • Smooth out zooming with discreet scroll wheel #4530 by @emilk
  • Make TextEdit::return_key optional #4543 by @doonv
  • Better spacing and sizes for (menu) buttons #4558 by @emilk
  • ComboBox: fix justified layout of popup if wider than parent button #4570 by @emilk
  • Make Area state public #4576 by @emilk
  • Don't persist Area size #4749 by @emilk
  • Round text galley sizes to nearest UI point size #4578 by @emilk
  • Once you have waited for a tooltip to show, show the next one right away #4585 by @emilk
  • Fade in windows, tooltips, popups, etc #4587 by @emilk
  • Make egu::menu types public #4544 by @sor-ca
  • The default constrain rect for Area/Window is now ctx.screen_rect #4590 by @emilk
  • Constrain Areas to screen by default #4591 by @emilk
  • Grid: set the sizing_pass flag during the initial sizing pass #4612 by @emilk
  • Remove special case for 0 in DragValue default formatter #4639 by @YgorSouza
  • Abort drags when pressing escape key #4678 by @emilk
  • Allow setting a layer as a sublayer of another #4690 by @YgorSouza
  • Close context menus with Escape #4711 by @emilk
  • Cancel DragValue edit if Escape is pressed #4713 by @YgorSouza
  • The default parser for DragValue and Slider now ignores whitespace #4739 by @emilk
  • Disabled widgets are now also disabled in the accesskit output #4750 by @Wcubed
  • Make it easier to grab the handle of a floating scroll bar #4754 by @emilk
  • When debugging widget rects on hover, show width and height #4762 by @emilk
  • Make sure all tooltips close if you open a menu in the same layer [#4766](https://github...
Read more

0.27.2 - Fix blurry text on web, and other bug fixes

02 Apr 16:17
Compare
Choose a tag to compare

egui is an easy-to-use immediate mode GUI for Rust that runs on both web and native.

Try it now: https://www.egui.rs/

egui development is sponsored by Rerun, a startup building an SDK for visualizing streams of multimodal data.

Changelogs

egui

  • Fix tooltips for non-interactive widgets #4291
  • Fix problem clicking the edge of a TextEdit #4272
  • Fix incorrect Response::interact_rect for Area/Window #4273
  • Fix: Response::clicked_elsewhere takes clip rect into account #4274
  • Allow disabling animations on a ScrollArea #4309 (thanks @lucasmerlin!)

eframe

  • Fix blurry rendering in some browsers #4299
  • Correctly identify if browser tab has focus #4280
  • Fix continuous repaint on Wayland when TextEdit is focused or IME output is set #4269 (thanks @white-axe!)
  • Remove a bunch of unwrap() #4285

egui_plot

  • Allow zoom/pan a plot as long as it contains the mouse cursor #4292
  • Prevent plot from resetting one axis while zooming/dragging the other #4252 (thanks @YgorSouza!)
  • Fix the same plot tick label being painted multiple times #4307

egui-winit

  • Fix continuous repaint on Wayland when TextEdit is focused or IME output is set #4269 (thanks @white-axe!)

0.27.1 - Bug fixes for shadows and touch input

29 Mar 11:57
Compare
Choose a tag to compare

egui is an easy-to-use immediate mode GUI for Rust that runs on both web and native.

Try it now: https://www.egui.rs/

egui development is sponsored by Rerun, a startup building an SDK for visualizing streams of multimodal data.

egui changelog

🐛 Fixed

  • Fix visual glitch on the right side of highly rounded rectangles #4244
  • Prevent visual glitch when shadow blur width is very high #4245
  • Fix InputState::any_touches and add InputState::has_touch_screen #4247
  • Fix Context::repaint_causes returning no causes #4248
  • Fix touch-and-hold to open context menu #4249
  • Hide shortcut text on zoom buttons if zoom_with_keyboard is false #4262

🔧 Changed

  • Don't apply a clip rect to the contents of an Area or Window #4258

eframe changelog