ui focus
This commit is contained in:
+49
-4
@@ -1,9 +1,12 @@
|
||||
use bevy::{
|
||||
color::palettes::tailwind::SLATE_900,
|
||||
input_focus::tab_navigation::TabIndex,
|
||||
input_focus::{
|
||||
AutoFocus, InputFocus,
|
||||
tab_navigation::{TabGroup, TabIndex},
|
||||
},
|
||||
prelude::*,
|
||||
text::{EditableText, EditableTextFilter, TextCursorStyle},
|
||||
ui::Checked,
|
||||
ui::{Checked, auto_directional_navigation::AutoDirectionalNavigation},
|
||||
ui_widgets::{Activate, Button, RadioButton, RadioGroup, ValueChange},
|
||||
};
|
||||
|
||||
@@ -83,6 +86,7 @@ impl Plugin for LobbyPlugin {
|
||||
session_visuals,
|
||||
sync_lobby_fields,
|
||||
style_privacy_options,
|
||||
style_lobby_focus,
|
||||
)
|
||||
.chain(),
|
||||
);
|
||||
@@ -101,6 +105,7 @@ fn setup_lobby(mut commands: Commands) {
|
||||
commands.spawn_scene(bsn! {
|
||||
#LobbyUiRoot
|
||||
LobbyUiRoot
|
||||
TabGroup::default()
|
||||
DespawnOnExit::<AppState>(AppState::Lobby)
|
||||
Node {
|
||||
width: percent(100),
|
||||
@@ -148,6 +153,8 @@ fn build_lobby_ui(mut commands: Commands, root_ui: Single<Entity, With<LobbyUiRo
|
||||
),
|
||||
(
|
||||
RadioGroup
|
||||
AutoFocus
|
||||
AutoDirectionalNavigation::default()
|
||||
Node {
|
||||
display: Display::Flex,
|
||||
flex_direction: FlexDirection::Row,
|
||||
@@ -183,6 +190,8 @@ fn build_lobby_ui(mut commands: Commands, root_ui: Single<Entity, With<LobbyUiRo
|
||||
(
|
||||
Button
|
||||
ResetPortButton
|
||||
AutoDirectionalNavigation::default()
|
||||
TabIndex(2)
|
||||
Node {
|
||||
width: px(600),
|
||||
height: px(130),
|
||||
@@ -230,6 +239,8 @@ fn build_lobby_ui(mut commands: Commands, root_ui: Single<Entity, With<LobbyUiRo
|
||||
BorderColor::from(Color::BLACK)
|
||||
InteractionColors::GOOD
|
||||
Interaction
|
||||
AutoDirectionalNavigation::default()
|
||||
TabIndex(4)
|
||||
on(|_event: On<Activate>, mut lobby: ResMut<LobbyUiState>| {
|
||||
info!("Session clicked!");
|
||||
lobby.session_active = !lobby.session_active;
|
||||
@@ -313,7 +324,8 @@ fn port_field() -> impl Scene {
|
||||
TextCursorStyle {
|
||||
color: Color::BLACK,
|
||||
}
|
||||
TabIndex(0)
|
||||
AutoDirectionalNavigation::default()
|
||||
TabIndex(1)
|
||||
BackgroundColor(TEXT_INPUT_BACKGROUND)
|
||||
}
|
||||
}
|
||||
@@ -339,7 +351,8 @@ fn password_field() -> impl Scene {
|
||||
TextCursorStyle {
|
||||
color: Color::BLACK,
|
||||
}
|
||||
TabIndex(1)
|
||||
AutoDirectionalNavigation::default()
|
||||
TabIndex(3)
|
||||
BackgroundColor(TEXT_INPUT_BACKGROUND)
|
||||
}
|
||||
}
|
||||
@@ -494,6 +507,28 @@ fn style_privacy_options(
|
||||
}
|
||||
}
|
||||
|
||||
fn style_lobby_focus(
|
||||
input_focus: Res<InputFocus>,
|
||||
mut options: Query<
|
||||
(&ChildOf, &mut BorderColor),
|
||||
(With<LobbyPrivacyOption>, Without<InteractionColors>),
|
||||
>,
|
||||
) {
|
||||
let focused_entity = input_focus.get();
|
||||
|
||||
for (parent, mut border_color) in &mut options {
|
||||
let color = if focused_entity == Some(parent.parent()) {
|
||||
OPTION_TEXT_COLOR
|
||||
} else {
|
||||
OPTION_BORDER_COLOR
|
||||
};
|
||||
let new_border_color = BorderColor::all(color);
|
||||
if *border_color != new_border_color {
|
||||
*border_color = new_border_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -506,6 +541,16 @@ mod tests {
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn autofocus_claims_initial_lobby_focus() {
|
||||
let mut world = World::new();
|
||||
world.insert_resource(InputFocus::default());
|
||||
|
||||
let radio_group = world.spawn((RadioGroup, AutoFocus)).id();
|
||||
|
||||
assert_eq!(world.resource::<InputFocus>().get(), Some(radio_group));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checked_option_is_styled() {
|
||||
let mut world = World::new();
|
||||
|
||||
Reference in New Issue
Block a user