Allow specifying a custom `Frame` on each widget and container
- Dominant language
- Rust
- Stars
- 30.6k
- Forks
- 2.1k
- Avg merge
- 1d 9h
- Merged PRs (30d)
- 72
Description
## Related
* Part of https://github.com/emilk/egui/issues/3284
* Unblocks https://github.com/emilk/egui/issues/5605
* https://github.com/emilk/egui/issues/4019
## Description
It's very useful to be able to set an inner and outer margin on any one widget or container. For instance: add some inner margin to a `ScrollArea`, or an outer margin to a `Button`.
In the limit we would like to do so via some style engine plugin (https://github.com/emilk/egui/issues/3284), but being able to just set a `Frame` on a `ScrollArea` etc explicitly or in a hard-coded `Style` would already be a very useful feature.
## Making `Frame` and `UiBuilder` compose
Adding a `UiBuilder::frame(…)` would be very useful.
## Example code (copied from #4019)
Add a `min_size` to `Frame`
```rs
/// A frame around some content, including margin and border colors.
///
/// The total (outer) size of a frame is
/// `content_size + inner_margin + border.stroke.width + outer_margin`.
///
/// Everything within the border stroke is filled with the border fill color (if any).
///
/// ```
/// +---------------^-------------------------------+
/// | | outer_margin |
/// | +-----------v----^-----------------------+ |
/// | | | border stroke width | |
/// | | +-------------v---^----------------+ | |
/// | | | | inner_margin | | |
/// | | | +--------------v-------------+ | | |
/// | | | | | | | |
/// | | | | | | | |
/// | | | | content rect | | | |
/// | | | +----------------------------+ | | |
/// | | | | | |
/// | | +----------------------------------+ | |
/// | | widget rect | |
/// | +----------------------------------------+ |
/// | outer rect |
/// +-----------------------------------------------+
/// ```
///
/// `widget rect` is the interactive part of the widget (what sense clicks etc),
/// and is what is returned by [`Response::rect`].
struct Frame {
/// Inner spacing. Called `padding` in CSS.
pub inner_margin: Margin,
/// Stroke, fill color etc.
///
/// The width of the border is counted as part of the size of the frame.
pub border: Border,
/// Optional drop-shadow.
/// Does not affect margins or sizes.
pub shadow: Shadow,
/// Outer spacing. Called `margin` in CSS.
///
/// This does NOT do "Margin Collapse" like in CSS,
/// i.e. when placing two frames next to each other,
/// the distance between their borders is the SUM
/// of their other margin.
/// In CSS the distance would be the MAX of their outer margins.
///
/// Supporting margin collapse is difficult, and would
/// requires complicating the already complicated egui layout code.
///
/// Consider using [`egui::Spacing::item_spacing`] instead
/// for adding space between widgets.
pub outer_margin: Margin,
/// The inner rectangle must be at least this size.
pub min_size: Vec2,
}
/// Stroke, fill, rounding, etc.
///
/// Controls the look of widgets and [`RectShape`].
///
/// Similar to a CSS border.
struct Border {
/// Fills the content and inner padding of a [`Frame`].
///
/// In CSS this is called `background`.
pub fill: Color32,
pub stroke: Stroke,
pub rounding: Rounding,
// TODO: add texturing here eventually
}
struct RectShape {
/// The rectangle on which edge the border stroke is painted.
pub rect: Rect,
pub border: Border,
// TODO: consider moving these into `Border`.
// Care must be taken so that `Border` and `Frame` doesn't become too huge in common cases,
// i.e. when there is no texture, and the rounding is uniform.
pub fill_texture_id: TextureId,
pub uv: Rect,
}
```
Contributor guide
Research direction
Start by reviewing the existing Frame and UiBuilder APIs, then read the related issues #3284, #5605, and #4019 for the intended design. Trace how containers such as ScrollArea and widgets currently handle layout margins. Done should include a coherent way to specify a custom Frame per widget or container, including UiBuilder composition and the requested sizing behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- frontend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 28/100