Feathers toggle switches. (#19928)
# Objective This is the Feathers toggle switch widget (without animation). Part of #19236 ### Showcase <img width="143" alt="toggles" src="https://github.com/user-attachments/assets/c04afc06-5a57-4bc6-8181-99efbd1bebef" />
This commit is contained in:
parent
0adbacd4c2
commit
870490808d
@ -10,6 +10,7 @@ keywords = ["bevy"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# bevy
|
# bevy
|
||||||
|
bevy_a11y = { path = "../bevy_a11y", version = "0.17.0-dev" }
|
||||||
bevy_app = { path = "../bevy_app", version = "0.17.0-dev" }
|
bevy_app = { path = "../bevy_app", version = "0.17.0-dev" }
|
||||||
bevy_asset = { path = "../bevy_asset", version = "0.17.0-dev" }
|
bevy_asset = { path = "../bevy_asset", version = "0.17.0-dev" }
|
||||||
bevy_color = { path = "../bevy_color", version = "0.17.0-dev" }
|
bevy_color = { path = "../bevy_color", version = "0.17.0-dev" }
|
||||||
|
@ -26,4 +26,10 @@ pub mod size {
|
|||||||
|
|
||||||
/// Width and height of a radio button
|
/// Width and height of a radio button
|
||||||
pub const RADIO_SIZE: Val = Val::Px(18.0);
|
pub const RADIO_SIZE: Val = Val::Px(18.0);
|
||||||
|
|
||||||
|
/// Width of a toggle switch
|
||||||
|
pub const TOGGLE_WIDTH: Val = Val::Px(32.0);
|
||||||
|
|
||||||
|
/// Height of a toggle switch
|
||||||
|
pub const TOGGLE_HEIGHT: Val = Val::Px(18.0);
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,10 @@ pub struct CheckboxProps {
|
|||||||
pub on_change: Callback<In<bool>>,
|
pub on_change: Callback<In<bool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Marker for the checkbox frame (contains both checkbox and label)
|
||||||
|
#[derive(Component, Default, Clone)]
|
||||||
|
struct CheckboxFrame;
|
||||||
|
|
||||||
/// Marker for the checkbox outline
|
/// Marker for the checkbox outline
|
||||||
#[derive(Component, Default, Clone)]
|
#[derive(Component, Default, Clone)]
|
||||||
struct CheckboxOutline;
|
struct CheckboxOutline;
|
||||||
@ -68,6 +72,7 @@ pub fn checkbox<C: SpawnableList<ChildOf> + Send + Sync + 'static, B: Bundle>(
|
|||||||
CoreCheckbox {
|
CoreCheckbox {
|
||||||
on_change: props.on_change,
|
on_change: props.on_change,
|
||||||
},
|
},
|
||||||
|
CheckboxFrame,
|
||||||
Hovered::default(),
|
Hovered::default(),
|
||||||
CursorIcon::System(bevy_window::SystemCursorIcon::Pointer),
|
CursorIcon::System(bevy_window::SystemCursorIcon::Pointer),
|
||||||
TabIndex(0),
|
TabIndex(0),
|
||||||
@ -124,7 +129,7 @@ fn update_checkbox_styles(
|
|||||||
&ThemeFontColor,
|
&ThemeFontColor,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
With<CoreCheckbox>,
|
With<CheckboxFrame>,
|
||||||
Or<(Changed<Hovered>, Added<Checked>, Added<InteractionDisabled>)>,
|
Or<(Changed<Hovered>, Added<Checked>, Added<InteractionDisabled>)>,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
@ -173,7 +178,7 @@ fn update_checkbox_styles_remove(
|
|||||||
&Hovered,
|
&Hovered,
|
||||||
&ThemeFontColor,
|
&ThemeFontColor,
|
||||||
),
|
),
|
||||||
With<CoreCheckbox>,
|
With<CheckboxFrame>,
|
||||||
>,
|
>,
|
||||||
q_children: Query<&Children>,
|
q_children: Query<&Children>,
|
||||||
mut q_outline: Query<(&ThemeBackgroundColor, &ThemeBorderColor), With<CheckboxOutline>>,
|
mut q_outline: Query<(&ThemeBackgroundColor, &ThemeBorderColor), With<CheckboxOutline>>,
|
||||||
|
@ -5,17 +5,25 @@ mod button;
|
|||||||
mod checkbox;
|
mod checkbox;
|
||||||
mod radio;
|
mod radio;
|
||||||
mod slider;
|
mod slider;
|
||||||
|
mod toggle_switch;
|
||||||
|
|
||||||
pub use button::{button, ButtonPlugin, ButtonProps, ButtonVariant};
|
pub use button::{button, ButtonPlugin, ButtonProps, ButtonVariant};
|
||||||
pub use checkbox::{checkbox, CheckboxPlugin, CheckboxProps};
|
pub use checkbox::{checkbox, CheckboxPlugin, CheckboxProps};
|
||||||
pub use radio::{radio, RadioPlugin};
|
pub use radio::{radio, RadioPlugin};
|
||||||
pub use slider::{slider, SliderPlugin, SliderProps};
|
pub use slider::{slider, SliderPlugin, SliderProps};
|
||||||
|
pub use toggle_switch::{toggle_switch, ToggleSwitchPlugin, ToggleSwitchProps};
|
||||||
|
|
||||||
/// Plugin which registers all `bevy_feathers` controls.
|
/// Plugin which registers all `bevy_feathers` controls.
|
||||||
pub struct ControlsPlugin;
|
pub struct ControlsPlugin;
|
||||||
|
|
||||||
impl Plugin for ControlsPlugin {
|
impl Plugin for ControlsPlugin {
|
||||||
fn build(&self, app: &mut bevy_app::App) {
|
fn build(&self, app: &mut bevy_app::App) {
|
||||||
app.add_plugins((ButtonPlugin, CheckboxPlugin, RadioPlugin, SliderPlugin));
|
app.add_plugins((
|
||||||
|
ButtonPlugin,
|
||||||
|
CheckboxPlugin,
|
||||||
|
RadioPlugin,
|
||||||
|
SliderPlugin,
|
||||||
|
ToggleSwitchPlugin,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
249
crates/bevy_feathers/src/controls/toggle_switch.rs
Normal file
249
crates/bevy_feathers/src/controls/toggle_switch.rs
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
use accesskit::Role;
|
||||||
|
use bevy_a11y::AccessibilityNode;
|
||||||
|
use bevy_app::{Plugin, PreUpdate};
|
||||||
|
use bevy_core_widgets::{Callback, CoreCheckbox};
|
||||||
|
use bevy_ecs::{
|
||||||
|
bundle::Bundle,
|
||||||
|
children,
|
||||||
|
component::Component,
|
||||||
|
entity::Entity,
|
||||||
|
hierarchy::Children,
|
||||||
|
lifecycle::RemovedComponents,
|
||||||
|
query::{Added, Changed, Has, Or, With},
|
||||||
|
schedule::IntoScheduleConfigs,
|
||||||
|
spawn::SpawnRelated,
|
||||||
|
system::{Commands, In, Query},
|
||||||
|
world::Mut,
|
||||||
|
};
|
||||||
|
use bevy_input_focus::tab_navigation::TabIndex;
|
||||||
|
use bevy_picking::{hover::Hovered, PickingSystems};
|
||||||
|
use bevy_ui::{BorderRadius, Checked, InteractionDisabled, Node, PositionType, UiRect, Val};
|
||||||
|
use bevy_winit::cursor::CursorIcon;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
constants::size,
|
||||||
|
theme::{ThemeBackgroundColor, ThemeBorderColor},
|
||||||
|
tokens,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Parameters for the toggle switch template, passed to [`toggle_switch`] function.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ToggleSwitchProps {
|
||||||
|
/// Change handler
|
||||||
|
pub on_change: Callback<In<bool>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Marker for the toggle switch outline
|
||||||
|
#[derive(Component, Default, Clone)]
|
||||||
|
struct ToggleSwitchOutline;
|
||||||
|
|
||||||
|
/// Marker for the toggle switch slide
|
||||||
|
#[derive(Component, Default, Clone)]
|
||||||
|
struct ToggleSwitchSlide;
|
||||||
|
|
||||||
|
/// Template function to spawn a toggle switch.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
/// * `props` - construction properties for the toggle switch.
|
||||||
|
/// * `overrides` - a bundle of components that are merged in with the normal toggle switch components.
|
||||||
|
pub fn toggle_switch<B: Bundle>(props: ToggleSwitchProps, overrides: B) -> impl Bundle {
|
||||||
|
(
|
||||||
|
Node {
|
||||||
|
width: size::TOGGLE_WIDTH,
|
||||||
|
height: size::TOGGLE_HEIGHT,
|
||||||
|
border: UiRect::all(Val::Px(2.0)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
CoreCheckbox {
|
||||||
|
on_change: props.on_change,
|
||||||
|
},
|
||||||
|
ToggleSwitchOutline,
|
||||||
|
BorderRadius::all(Val::Px(5.0)),
|
||||||
|
ThemeBackgroundColor(tokens::SWITCH_BG),
|
||||||
|
ThemeBorderColor(tokens::SWITCH_BORDER),
|
||||||
|
AccessibilityNode(accesskit::Node::new(Role::Switch)),
|
||||||
|
Hovered::default(),
|
||||||
|
CursorIcon::System(bevy_window::SystemCursorIcon::Pointer),
|
||||||
|
TabIndex(0),
|
||||||
|
overrides,
|
||||||
|
children![(
|
||||||
|
Node {
|
||||||
|
position_type: PositionType::Absolute,
|
||||||
|
left: Val::Percent(0.),
|
||||||
|
top: Val::Px(0.),
|
||||||
|
bottom: Val::Px(0.),
|
||||||
|
width: Val::Percent(50.),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
BorderRadius::all(Val::Px(3.0)),
|
||||||
|
ToggleSwitchSlide,
|
||||||
|
ThemeBackgroundColor(tokens::SWITCH_SLIDE),
|
||||||
|
)],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_switch_styles(
|
||||||
|
q_switches: Query<
|
||||||
|
(
|
||||||
|
Entity,
|
||||||
|
Has<InteractionDisabled>,
|
||||||
|
Has<Checked>,
|
||||||
|
&Hovered,
|
||||||
|
&ThemeBackgroundColor,
|
||||||
|
&ThemeBorderColor,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
With<ToggleSwitchOutline>,
|
||||||
|
Or<(Changed<Hovered>, Added<Checked>, Added<InteractionDisabled>)>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
q_children: Query<&Children>,
|
||||||
|
mut q_slide: Query<(&mut Node, &ThemeBackgroundColor), With<ToggleSwitchSlide>>,
|
||||||
|
mut commands: Commands,
|
||||||
|
) {
|
||||||
|
for (switch_ent, disabled, checked, hovered, outline_bg, outline_border) in q_switches.iter() {
|
||||||
|
let Some(slide_ent) = q_children
|
||||||
|
.iter_descendants(switch_ent)
|
||||||
|
.find(|en| q_slide.contains(*en))
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
// Safety: since we just checked the query, should always work.
|
||||||
|
let (ref mut slide_style, slide_color) = q_slide.get_mut(slide_ent).unwrap();
|
||||||
|
set_switch_colors(
|
||||||
|
switch_ent,
|
||||||
|
slide_ent,
|
||||||
|
disabled,
|
||||||
|
checked,
|
||||||
|
hovered.0,
|
||||||
|
outline_bg,
|
||||||
|
outline_border,
|
||||||
|
slide_style,
|
||||||
|
slide_color,
|
||||||
|
&mut commands,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_switch_styles_remove(
|
||||||
|
q_switches: Query<
|
||||||
|
(
|
||||||
|
Entity,
|
||||||
|
Has<InteractionDisabled>,
|
||||||
|
Has<Checked>,
|
||||||
|
&Hovered,
|
||||||
|
&ThemeBackgroundColor,
|
||||||
|
&ThemeBorderColor,
|
||||||
|
),
|
||||||
|
With<ToggleSwitchOutline>,
|
||||||
|
>,
|
||||||
|
q_children: Query<&Children>,
|
||||||
|
mut q_slide: Query<(&mut Node, &ThemeBackgroundColor), With<ToggleSwitchSlide>>,
|
||||||
|
mut removed_disabled: RemovedComponents<InteractionDisabled>,
|
||||||
|
mut removed_checked: RemovedComponents<Checked>,
|
||||||
|
mut commands: Commands,
|
||||||
|
) {
|
||||||
|
removed_disabled
|
||||||
|
.read()
|
||||||
|
.chain(removed_checked.read())
|
||||||
|
.for_each(|ent| {
|
||||||
|
if let Ok((switch_ent, disabled, checked, hovered, outline_bg, outline_border)) =
|
||||||
|
q_switches.get(ent)
|
||||||
|
{
|
||||||
|
let Some(slide_ent) = q_children
|
||||||
|
.iter_descendants(switch_ent)
|
||||||
|
.find(|en| q_slide.contains(*en))
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
// Safety: since we just checked the query, should always work.
|
||||||
|
let (ref mut slide_style, slide_color) = q_slide.get_mut(slide_ent).unwrap();
|
||||||
|
set_switch_colors(
|
||||||
|
switch_ent,
|
||||||
|
slide_ent,
|
||||||
|
disabled,
|
||||||
|
checked,
|
||||||
|
hovered.0,
|
||||||
|
outline_bg,
|
||||||
|
outline_border,
|
||||||
|
slide_style,
|
||||||
|
slide_color,
|
||||||
|
&mut commands,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_switch_colors(
|
||||||
|
switch_ent: Entity,
|
||||||
|
slide_ent: Entity,
|
||||||
|
disabled: bool,
|
||||||
|
checked: bool,
|
||||||
|
hovered: bool,
|
||||||
|
outline_bg: &ThemeBackgroundColor,
|
||||||
|
outline_border: &ThemeBorderColor,
|
||||||
|
slide_style: &mut Mut<Node>,
|
||||||
|
slide_color: &ThemeBackgroundColor,
|
||||||
|
commands: &mut Commands,
|
||||||
|
) {
|
||||||
|
let outline_border_token = match (disabled, hovered) {
|
||||||
|
(true, _) => tokens::SWITCH_BORDER_DISABLED,
|
||||||
|
(false, true) => tokens::SWITCH_BORDER_HOVER,
|
||||||
|
_ => tokens::SWITCH_BORDER,
|
||||||
|
};
|
||||||
|
|
||||||
|
let outline_bg_token = match (disabled, checked) {
|
||||||
|
(true, true) => tokens::SWITCH_BG_CHECKED_DISABLED,
|
||||||
|
(true, false) => tokens::SWITCH_BG_DISABLED,
|
||||||
|
(false, true) => tokens::SWITCH_BG_CHECKED,
|
||||||
|
(false, false) => tokens::SWITCH_BG,
|
||||||
|
};
|
||||||
|
|
||||||
|
let slide_token = match disabled {
|
||||||
|
true => tokens::SWITCH_SLIDE_DISABLED,
|
||||||
|
false => tokens::SWITCH_SLIDE,
|
||||||
|
};
|
||||||
|
|
||||||
|
let slide_pos = match checked {
|
||||||
|
true => Val::Percent(50.),
|
||||||
|
false => Val::Percent(0.),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Change outline background
|
||||||
|
if outline_bg.0 != outline_bg_token {
|
||||||
|
commands
|
||||||
|
.entity(switch_ent)
|
||||||
|
.insert(ThemeBackgroundColor(outline_bg_token));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change outline border
|
||||||
|
if outline_border.0 != outline_border_token {
|
||||||
|
commands
|
||||||
|
.entity(switch_ent)
|
||||||
|
.insert(ThemeBorderColor(outline_border_token));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change slide color
|
||||||
|
if slide_color.0 != slide_token {
|
||||||
|
commands
|
||||||
|
.entity(slide_ent)
|
||||||
|
.insert(ThemeBackgroundColor(slide_token));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change slide position
|
||||||
|
if slide_pos != slide_style.left {
|
||||||
|
slide_style.left = slide_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Plugin which registers the systems for updating the toggle switch styles.
|
||||||
|
pub struct ToggleSwitchPlugin;
|
||||||
|
|
||||||
|
impl Plugin for ToggleSwitchPlugin {
|
||||||
|
fn build(&self, app: &mut bevy_app::App) {
|
||||||
|
app.add_systems(
|
||||||
|
PreUpdate,
|
||||||
|
(update_switch_styles, update_switch_styles_remove).in_set(PickingSystems::Last),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ pub fn create_dark_theme() -> ThemeProps {
|
|||||||
ThemeProps {
|
ThemeProps {
|
||||||
color: HashMap::from([
|
color: HashMap::from([
|
||||||
(tokens::WINDOW_BG.into(), palette::GRAY_0),
|
(tokens::WINDOW_BG.into(), palette::GRAY_0),
|
||||||
|
// Button
|
||||||
(tokens::BUTTON_BG.into(), palette::GRAY_3),
|
(tokens::BUTTON_BG.into(), palette::GRAY_3),
|
||||||
(
|
(
|
||||||
tokens::BUTTON_BG_HOVER.into(),
|
tokens::BUTTON_BG_HOVER.into(),
|
||||||
@ -40,6 +41,7 @@ pub fn create_dark_theme() -> ThemeProps {
|
|||||||
tokens::BUTTON_PRIMARY_TEXT_DISABLED.into(),
|
tokens::BUTTON_PRIMARY_TEXT_DISABLED.into(),
|
||||||
palette::WHITE.with_alpha(0.5),
|
palette::WHITE.with_alpha(0.5),
|
||||||
),
|
),
|
||||||
|
// Slider
|
||||||
(tokens::SLIDER_BG.into(), palette::GRAY_1),
|
(tokens::SLIDER_BG.into(), palette::GRAY_1),
|
||||||
(tokens::SLIDER_BAR.into(), palette::ACCENT),
|
(tokens::SLIDER_BAR.into(), palette::ACCENT),
|
||||||
(tokens::SLIDER_BAR_DISABLED.into(), palette::GRAY_2),
|
(tokens::SLIDER_BAR_DISABLED.into(), palette::GRAY_2),
|
||||||
@ -48,6 +50,7 @@ pub fn create_dark_theme() -> ThemeProps {
|
|||||||
tokens::SLIDER_TEXT_DISABLED.into(),
|
tokens::SLIDER_TEXT_DISABLED.into(),
|
||||||
palette::WHITE.with_alpha(0.5),
|
palette::WHITE.with_alpha(0.5),
|
||||||
),
|
),
|
||||||
|
// Checkbox
|
||||||
(tokens::CHECKBOX_BG.into(), palette::GRAY_3),
|
(tokens::CHECKBOX_BG.into(), palette::GRAY_3),
|
||||||
(tokens::CHECKBOX_BG_CHECKED.into(), palette::ACCENT),
|
(tokens::CHECKBOX_BG_CHECKED.into(), palette::ACCENT),
|
||||||
(
|
(
|
||||||
@ -74,6 +77,7 @@ pub fn create_dark_theme() -> ThemeProps {
|
|||||||
tokens::CHECKBOX_TEXT_DISABLED.into(),
|
tokens::CHECKBOX_TEXT_DISABLED.into(),
|
||||||
palette::LIGHT_GRAY_1.with_alpha(0.5),
|
palette::LIGHT_GRAY_1.with_alpha(0.5),
|
||||||
),
|
),
|
||||||
|
// Radio
|
||||||
(tokens::RADIO_BORDER.into(), palette::GRAY_3),
|
(tokens::RADIO_BORDER.into(), palette::GRAY_3),
|
||||||
(
|
(
|
||||||
tokens::RADIO_BORDER_HOVER.into(),
|
tokens::RADIO_BORDER_HOVER.into(),
|
||||||
@ -93,6 +97,31 @@ pub fn create_dark_theme() -> ThemeProps {
|
|||||||
tokens::RADIO_TEXT_DISABLED.into(),
|
tokens::RADIO_TEXT_DISABLED.into(),
|
||||||
palette::LIGHT_GRAY_1.with_alpha(0.5),
|
palette::LIGHT_GRAY_1.with_alpha(0.5),
|
||||||
),
|
),
|
||||||
|
// Toggle Switch
|
||||||
|
(tokens::SWITCH_BG.into(), palette::GRAY_3),
|
||||||
|
(tokens::SWITCH_BG_CHECKED.into(), palette::ACCENT),
|
||||||
|
(
|
||||||
|
tokens::SWITCH_BG_DISABLED.into(),
|
||||||
|
palette::GRAY_1.with_alpha(0.5),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
tokens::SWITCH_BG_CHECKED_DISABLED.into(),
|
||||||
|
palette::GRAY_3.with_alpha(0.5),
|
||||||
|
),
|
||||||
|
(tokens::SWITCH_BORDER.into(), palette::GRAY_3),
|
||||||
|
(
|
||||||
|
tokens::SWITCH_BORDER_HOVER.into(),
|
||||||
|
palette::GRAY_3.lighter(0.1),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
tokens::SWITCH_BORDER_DISABLED.into(),
|
||||||
|
palette::GRAY_3.with_alpha(0.5),
|
||||||
|
),
|
||||||
|
(tokens::SWITCH_SLIDE.into(), palette::LIGHT_GRAY_2),
|
||||||
|
(
|
||||||
|
tokens::SWITCH_SLIDE_DISABLED.into(),
|
||||||
|
palette::LIGHT_GRAY_2.with_alpha(0.3),
|
||||||
|
),
|
||||||
]),
|
]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,3 +99,24 @@ pub const RADIO_MARK_DISABLED: &str = "feathers.radio.mark.disabled";
|
|||||||
pub const RADIO_TEXT: &str = "feathers.radio.text";
|
pub const RADIO_TEXT: &str = "feathers.radio.text";
|
||||||
/// Radio label text (disabled)
|
/// Radio label text (disabled)
|
||||||
pub const RADIO_TEXT_DISABLED: &str = "feathers.radio.text.disabled";
|
pub const RADIO_TEXT_DISABLED: &str = "feathers.radio.text.disabled";
|
||||||
|
|
||||||
|
// Toggle Switch
|
||||||
|
|
||||||
|
/// Switch background around the checkmark
|
||||||
|
pub const SWITCH_BG: &str = "feathers.switch.bg";
|
||||||
|
/// Switch border around the checkmark (disabled)
|
||||||
|
pub const SWITCH_BG_DISABLED: &str = "feathers.switch.bg.disabled";
|
||||||
|
/// Switch background around the checkmark
|
||||||
|
pub const SWITCH_BG_CHECKED: &str = "feathers.switch.bg.checked";
|
||||||
|
/// Switch border around the checkmark (disabled)
|
||||||
|
pub const SWITCH_BG_CHECKED_DISABLED: &str = "feathers.switch.bg.checked.disabled";
|
||||||
|
/// Switch border around the checkmark
|
||||||
|
pub const SWITCH_BORDER: &str = "feathers.switch.border";
|
||||||
|
/// Switch border around the checkmark (hovered)
|
||||||
|
pub const SWITCH_BORDER_HOVER: &str = "feathers.switch.border.hover";
|
||||||
|
/// Switch border around the checkmark (disabled)
|
||||||
|
pub const SWITCH_BORDER_DISABLED: &str = "feathers.switch.border.disabled";
|
||||||
|
/// Switch slide
|
||||||
|
pub const SWITCH_SLIDE: &str = "feathers.switch.slide";
|
||||||
|
/// Switch slide (disabled)
|
||||||
|
pub const SWITCH_SLIDE_DISABLED: &str = "feathers.switch.slide.disabled";
|
||||||
|
@ -4,7 +4,8 @@ use bevy::{
|
|||||||
core_widgets::{Callback, CoreRadio, CoreRadioGroup, CoreWidgetsPlugin, SliderStep},
|
core_widgets::{Callback, CoreRadio, CoreRadioGroup, CoreWidgetsPlugin, SliderStep},
|
||||||
feathers::{
|
feathers::{
|
||||||
controls::{
|
controls::{
|
||||||
button, checkbox, radio, slider, ButtonProps, ButtonVariant, CheckboxProps, SliderProps,
|
button, checkbox, radio, slider, toggle_switch, ButtonProps, ButtonVariant,
|
||||||
|
CheckboxProps, SliderProps, ToggleSwitchProps,
|
||||||
},
|
},
|
||||||
dark_theme::create_dark_theme,
|
dark_theme::create_dark_theme,
|
||||||
rounded_corners::RoundedCorners,
|
rounded_corners::RoundedCorners,
|
||||||
@ -222,6 +223,36 @@ fn demo_root(commands: &mut Commands) -> impl Bundle {
|
|||||||
),
|
),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
Node {
|
||||||
|
display: Display::Flex,
|
||||||
|
flex_direction: FlexDirection::Row,
|
||||||
|
align_items: AlignItems::Center,
|
||||||
|
justify_content: JustifyContent::Start,
|
||||||
|
column_gap: Val::Px(8.0),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
children![
|
||||||
|
toggle_switch(
|
||||||
|
ToggleSwitchProps {
|
||||||
|
on_change: Callback::Ignore,
|
||||||
|
},
|
||||||
|
(),
|
||||||
|
),
|
||||||
|
toggle_switch(
|
||||||
|
ToggleSwitchProps {
|
||||||
|
on_change: Callback::Ignore,
|
||||||
|
},
|
||||||
|
InteractionDisabled,
|
||||||
|
),
|
||||||
|
toggle_switch(
|
||||||
|
ToggleSwitchProps {
|
||||||
|
on_change: Callback::Ignore,
|
||||||
|
},
|
||||||
|
(InteractionDisabled, Checked),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
slider(
|
slider(
|
||||||
SliderProps {
|
SliderProps {
|
||||||
max: 100.0,
|
max: 100.0,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
title: Bevy Feathers
|
title: Bevy Feathers
|
||||||
authors: ["@viridia", "@Atlas16A"]
|
authors: ["@viridia", "@Atlas16A"]
|
||||||
pull_requests: [19730, 19900]
|
pull_requests: [19730, 19900, 19928]
|
||||||
---
|
---
|
||||||
|
|
||||||
To make it easier for Bevy engine developers and third-party tool creators to make comfortable, visually cohesive tooling,
|
To make it easier for Bevy engine developers and third-party tool creators to make comfortable, visually cohesive tooling,
|
||||||
|
Loading…
Reference in New Issue
Block a user