egui layout patterns

Guide for egui layout patterns

Egui Layout Patterns

Fixing Vertical Text Wrapping

Problem

When using egui::Area with anchoring, text can wrap vertically if the available width is insufficient. This creates a poor user experience where text like "Next Milestone" appears as a vertical column of letters.
Example of the issue:
N
e
x
t

M
i
l
e
s
t
o
n
e

Root Cause

Egui's automatic layout system may not allocate sufficient horizontal space when:
  • Using ui.vertical() without explicit width constraints
  • Content is placed in anchored areas with limited space
  • Parent containers don't specify minimum dimensions

Solution: Use allocate_ui() with Explicit Dimensions

Before (Broken):
ui.vertical(|ui| {
    ui.label(egui::RichText::new("Next Milestone")
        .size(10.0)
        .color(egui::Color32::LIGHT_GRAY));
    ui.label(egui::RichText::new(format!("{} Lv{}", skill, level))
        .size(14.0)
        .strong()
        .color(egui::Color32::GOLD));
});
After (Fixed):
ui.allocate_ui(egui::vec2(100.0, 40.0), |ui| {
    ui.vertical(|ui| {
        ui.label(egui::RichText::new("Next Milestone")
            .size(10.0)
            .color(egui::Color32::LIGHT_GRAY));
        ui.label(egui::RichText::new(format!("{} Lv{}", skill, level))
            .size(14.0)
            .strong()
            .color(egui::Color32::GOLD));
    });
});
Key Changes:
  1. Wrap content in ui.allocate_ui(egui::vec2(width, height), |ui| { ... })
  2. Specify explicit width (100.0) to prevent text wrapping
  3. Specify explicit height (40.0) to reserve vertical space

When to Use This Pattern

Use allocate_ui() when:
  • Text is wrapping unexpectedly in anchored areas
  • Content needs guaranteed minimum dimensions
  • Layout is unpredictable due to dynamic content

Alternative Solutions

1. Use ui.horizontal() for single-line content:
ui.horizontal(|ui| {
    ui.label("Next Milestone:");
    ui.label(format!("{} Lv{}", skill, level));
});
2. Set minimum width on parent frame:
egui::Frame::none()
    .inner_margin(egui::Margin::same(12.0))
    .show(ui, |ui| {
        ui.set_min_width(120.0);
        ui.vertical(|ui| {
            // Content here
        });
    });
3. Use ui.with_layout() with explicit sizing:
ui.with_layout(egui::Layout::top_down(egui::Align::LEFT).with_main_wrap(false), |ui| {
    ui.set_width(100.0);
    // Content here
});

Best Practices

  1. Always test UI with varying content lengths to catch wrapping issues
  2. Use allocate_ui() for critical UI elements that must maintain specific dimensions
  3. Prefer explicit sizing over automatic layout for anchored areas
  4. Consider responsive design - use percentages or dynamic calculations for different screen sizes
  • src/systems/ui/progression_tracker.rs (line 70) - Fixed vertical text wrapping in XP tracker
  • src/systems/ui/mod.rs - Main UI layout system

References