Skip to content

Commit 574e935

Browse files
viridiakfc35
andauthored
Decorative widgets (#23804)
# Objective Part of #19236 ## Solution A bunch of new, decorative widgets - see release note. ## Testing Manual testing ## Showcase <img width="384" height="207" alt="panes" src="https://github.com/user-attachments/assets/0b0bb2ee-d520-4280-938e-e08d5c4e49d1" /> --------- Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
1 parent c0e8e29 commit 574e935

22 files changed

Lines changed: 979 additions & 415 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
title: "Feathers widgets moving to BSN"
3+
pull_requests: [23804]
4+
---
5+
6+
Going forward, BSN will be the primary means to create Feathers widgets. The old spawning
7+
functions have been renamed (`button` is now `button_bundle`), and will be removed in a future
8+
release.
9+
10+
Some of the BSN widgets are slightly different than before:
11+
12+
- `button` no longer automatically includes `flex_grow`. This was originally added due to the
13+
difficulty of overriding node styles when spawning, but in BSN that's no longer a problem.
14+
- `button`, `checkbox` and `radio` now accept a `caption` parameter which lets you specify
15+
the label directly instead of appending them via `Children`.
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
---
22
title: "Moar widgets!"
33
authors: ["@viridia"]
4-
pull_requests: [23645, 23707]
4+
pull_requests: [23645, 23707, 23788, 23787, 23804]
55
---
66

7-
Bevy Feathers, the opinionated UI widget collection, has added two new widgets: text input and
8-
dropdown menu buttons. Note that unlike the older widgets, these are _only_ available through
7+
Bevy Feathers, the opinionated UI widget collection, has added several new widgets:
8+
9+
- text input
10+
- dropdown menu buttons
11+
- icon (displays an image)
12+
- label (displays a text string in the standard font)
13+
- pane, subpane, and group (decorative frames which can be used in editors)
14+
15+
Note that unlike the older widgets, these are _only_ available through
916
BSN (which will be the primary access to feathers going forward).

crates/bevy_feathers/src/constants.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub mod icons {
2626

2727
/// Size constants
2828
pub mod size {
29+
use bevy_text::FontSize;
2930
use bevy_ui::Val;
3031

3132
/// Common row size for buttons, sliders, spinners, etc.
@@ -45,4 +46,13 @@ pub mod size {
4546

4647
/// Height of a toggle switch
4748
pub const TOGGLE_HEIGHT: Val = Val::Px(18.0);
49+
50+
/// Regular font size, used for most widget captions
51+
pub const MEDIUM_FONT: FontSize = FontSize::Px(14.0);
52+
53+
/// Slightly smaller font size, used for text inputs
54+
pub const COMPACT_FONT: FontSize = FontSize::Px(13.0);
55+
56+
/// Small font size
57+
pub const SMALL_FONT: FontSize = FontSize::Px(12.0);
4858
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use bevy_scene::{bsn, Scene};
2+
use bevy_ui::Node;
3+
4+
/// An invisible UI node that takes up space, and which has a positive `flex_grow` setting.
5+
/// This is normally used within containers to provide a gap.
6+
pub fn flex_spacer() -> impl Scene {
7+
bsn! {
8+
Node {
9+
flex_grow: 1.0,
10+
}
11+
}
12+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use bevy_scene::{bsn, Scene};
2+
use bevy_text::FontWeight;
3+
use bevy_ui::{px, AlignItems, Display, FlexDirection, JustifyContent, Node, UiRect, Val};
4+
5+
use crate::{
6+
constants::{fonts, size},
7+
font_styles::InheritableFont,
8+
rounded_corners::RoundedCorners,
9+
theme::{ThemeBackgroundColor, ThemeBorderColor, ThemeFontColor},
10+
tokens,
11+
};
12+
13+
/// Group
14+
pub fn group() -> impl Scene {
15+
bsn! {
16+
Node {
17+
display: Display::Flex,
18+
flex_direction: FlexDirection::Column,
19+
align_items: AlignItems::Stretch,
20+
}
21+
}
22+
}
23+
24+
/// Group header
25+
pub fn group_header() -> impl Scene {
26+
bsn! {
27+
Node {
28+
display: Display::Flex,
29+
flex_direction: FlexDirection::Row,
30+
align_items: AlignItems::Center,
31+
justify_content: JustifyContent::SpaceBetween,
32+
border: UiRect {
33+
left: Val::Px(1.0),
34+
top: Val::Px(1.0),
35+
right: Val::Px(1.0),
36+
bottom: Val::Px(0.0),
37+
},
38+
padding: UiRect::axes(Val::Px(10.0), Val::Px(0.0)),
39+
min_height: size::HEADER_HEIGHT,
40+
column_gap: Val::Px(4.0),
41+
border_radius: {RoundedCorners::Top.to_border_radius(4.0)}
42+
}
43+
ThemeBackgroundColor(tokens::GROUP_HEADER_BG)
44+
ThemeBorderColor(tokens::GROUP_HEADER_BORDER)
45+
ThemeFontColor(tokens::GROUP_HEADER_TEXT)
46+
InheritableFont {
47+
font: fonts::REGULAR,
48+
font_size: size::MEDIUM_FONT,
49+
weight: FontWeight::NORMAL,
50+
}
51+
}
52+
}
53+
54+
/// Group body
55+
pub fn group_body() -> impl Scene {
56+
bsn! {
57+
Node {
58+
display: Display::Flex,
59+
flex_direction: FlexDirection::Column,
60+
border: UiRect {
61+
left: Val::Px(1.0),
62+
top: Val::Px(0.0),
63+
right: Val::Px(1.0),
64+
bottom: Val::Px(1.0),
65+
},
66+
row_gap: px(4.0),
67+
padding: UiRect::axes(Val::Px(6.0), Val::Px(6.0)),
68+
border_radius: {RoundedCorners::Bottom.to_border_radius(4.0)}
69+
}
70+
ThemeBackgroundColor(tokens::GROUP_BODY_BG)
71+
ThemeBorderColor(tokens::GROUP_BODY_BORDER)
72+
InheritableFont {
73+
font: fonts::REGULAR,
74+
font_size: size::MEDIUM_FONT,
75+
weight: FontWeight::NORMAL,
76+
}
77+
}
78+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//! Meta-module containing all feathers containers: passive widgets that hold other widgets.
2+
mod flex_spacer;
3+
mod group;
4+
mod pane;
5+
mod subpane;
6+
7+
pub use flex_spacer::*;
8+
pub use group::*;
9+
pub use pane::*;
10+
pub use subpane::*;
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
use bevy_ecs::hierarchy::Children;
2+
use bevy_scene::{bsn, Scene};
3+
use bevy_text::FontWeight;
4+
use bevy_ui::{
5+
px, AlignItems, AlignSelf, Display, FlexDirection, JustifyContent, Node, PositionType, UiRect,
6+
Val,
7+
};
8+
9+
use crate::{
10+
constants::{fonts, size},
11+
font_styles::InheritableFont,
12+
rounded_corners::RoundedCorners,
13+
theme::{ThemeBackgroundColor, ThemeBorderColor, ThemeFontColor},
14+
tokens,
15+
};
16+
17+
/// A standard pane
18+
pub fn pane() -> impl Scene {
19+
bsn! {
20+
Node {
21+
display: Display::Flex,
22+
flex_direction: FlexDirection::Column,
23+
align_items: AlignItems::Stretch,
24+
}
25+
}
26+
}
27+
28+
/// Pane header
29+
pub fn pane_header() -> impl Scene {
30+
bsn! {
31+
Node {
32+
display: Display::Flex,
33+
flex_direction: FlexDirection::Row,
34+
align_items: AlignItems::Center,
35+
justify_content: JustifyContent::SpaceBetween,
36+
padding: UiRect::axes(Val::Px(6.0), Val::Px(6.0)),
37+
border: UiRect {
38+
left: Val::Px(1.0),
39+
top: Val::Px(1.0),
40+
right: Val::Px(1.0),
41+
bottom: Val::Px(0.0),
42+
},
43+
min_height: size::HEADER_HEIGHT,
44+
column_gap: Val::Px(6.0),
45+
border_radius: {RoundedCorners::Top.to_border_radius(4.0)},
46+
}
47+
ThemeBackgroundColor(tokens::PANE_HEADER_BG)
48+
ThemeBorderColor(tokens::PANE_HEADER_BORDER)
49+
ThemeFontColor(tokens::PANE_HEADER_TEXT)
50+
InheritableFont {
51+
font: fonts::REGULAR,
52+
font_size: size::MEDIUM_FONT,
53+
weight: FontWeight::NORMAL,
54+
}
55+
}
56+
}
57+
58+
/// Vertical divider between groups of widgets in pane headers
59+
pub fn pane_header_divider() -> impl Scene {
60+
bsn! {
61+
Node {
62+
width: Val::Px(1.0),
63+
align_self: AlignSelf::Stretch,
64+
}
65+
Children [(
66+
// Because we want to extend the divider into the header padding area, we'll use
67+
// an absolutely-positioned child.
68+
Node {
69+
position_type: PositionType::Absolute,
70+
left: px(0),
71+
right: px(0),
72+
top: {px(-6)},
73+
bottom: {px(-6)},
74+
}
75+
ThemeBackgroundColor(tokens::PANE_HEADER_DIVIDER)
76+
)]
77+
}
78+
}
79+
80+
/// Pane body
81+
pub fn pane_body() -> impl Scene {
82+
bsn! {
83+
Node {
84+
display: Display::Flex,
85+
flex_direction: FlexDirection::Column,
86+
row_gap: px(4.0),
87+
padding: UiRect::axes(Val::Px(6.0), Val::Px(6.0)),
88+
border_radius: {RoundedCorners::Bottom.to_border_radius(4.0)}
89+
}
90+
ThemeBackgroundColor(tokens::PANE_BODY_BG)
91+
}
92+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use bevy_scene::{bsn, Scene};
2+
use bevy_text::FontWeight;
3+
use bevy_ui::{px, AlignItems, Display, FlexDirection, JustifyContent, Node, UiRect, Val};
4+
5+
use crate::{
6+
constants::{fonts, size},
7+
font_styles::InheritableFont,
8+
rounded_corners::RoundedCorners,
9+
theme::{ThemeBackgroundColor, ThemeBorderColor, ThemeFontColor},
10+
tokens,
11+
};
12+
13+
/// Sub-pane
14+
pub fn subpane() -> impl Scene {
15+
bsn! {
16+
Node {
17+
display: Display::Flex,
18+
flex_direction: FlexDirection::Column,
19+
align_items: AlignItems::Stretch,
20+
}
21+
}
22+
}
23+
24+
/// Sub-pane header
25+
pub fn subpane_header() -> impl Scene {
26+
bsn! {
27+
Node {
28+
display: Display::Flex,
29+
flex_direction: FlexDirection::Row,
30+
align_items: AlignItems::Center,
31+
justify_content: JustifyContent::SpaceBetween,
32+
border: UiRect {
33+
left: Val::Px(1.0),
34+
top: Val::Px(1.0),
35+
right: Val::Px(1.0),
36+
bottom: Val::Px(0.0),
37+
},
38+
padding: UiRect::axes(Val::Px(10.0), Val::Px(0.0)),
39+
min_height: size::HEADER_HEIGHT,
40+
column_gap: Val::Px(4.0),
41+
border_radius: {RoundedCorners::Top.to_border_radius(4.0)}
42+
}
43+
ThemeBackgroundColor(tokens::SUBPANE_HEADER_BG)
44+
ThemeBorderColor(tokens::SUBPANE_HEADER_BORDER)
45+
ThemeFontColor(tokens::SUBPANE_HEADER_TEXT)
46+
InheritableFont {
47+
font: fonts::REGULAR,
48+
font_size: size::MEDIUM_FONT,
49+
weight: FontWeight::NORMAL,
50+
}
51+
}
52+
}
53+
54+
/// Sub-pane body
55+
pub fn subpane_body() -> impl Scene {
56+
bsn! {
57+
Node {
58+
display: Display::Flex,
59+
flex_direction: FlexDirection::Column,
60+
border: UiRect {
61+
left: Val::Px(1.0),
62+
top: Val::Px(0.0),
63+
right: Val::Px(1.0),
64+
bottom: Val::Px(1.0),
65+
},
66+
row_gap: px(4.0),
67+
padding: UiRect::axes(Val::Px(6.0), Val::Px(6.0)),
68+
border_radius: {RoundedCorners::Bottom.to_border_radius(4.0)}
69+
}
70+
ThemeBackgroundColor(tokens::SUBPANE_BODY_BG)
71+
ThemeBorderColor(tokens::SUBPANE_BODY_BORDER)
72+
InheritableFont {
73+
font: fonts::REGULAR,
74+
font_size: size::MEDIUM_FONT,
75+
weight: FontWeight::NORMAL,
76+
}
77+
}
78+
}

0 commit comments

Comments
 (0)