feat(engine): duck the glass tab bar during card drags
While a drag is committed the floating bar slides below the screen edge (UiTransform translation - no layout dirtying, no fight with the safe-area anchor over Node::bottom) so it never occludes a drop target on the bottom tableau rows; it slides back on release. Same tween rate as the label reveal, snaps under reduce-motion. Desktop docked bar is untouched (no TabBarDuck component). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1014,6 +1014,54 @@ fn expansion_width_is_linear_in_progress() {
|
||||
assert_eq!(expansion_width(4, 16.0, 1.5), full);
|
||||
}
|
||||
|
||||
/// While a committed drag is active the bar must slide down (positive
|
||||
/// `UiTransform` y — off-screen) and return to identity once the drag
|
||||
/// ends. Manual time steps make the tween deterministic.
|
||||
#[test]
|
||||
fn tab_bar_ducks_during_committed_drag_and_returns() {
|
||||
use crate::resources::DragState;
|
||||
use bevy::ui::UiTransform;
|
||||
|
||||
let mut app = bar_only_app(true);
|
||||
set_manual_time_step(&mut app, 0.05);
|
||||
app.add_systems(Update, duck_tab_bar_during_drag);
|
||||
app.insert_resource(DragState {
|
||||
committed: true,
|
||||
..default()
|
||||
});
|
||||
|
||||
let translation_y_px = |app: &mut App| -> f32 {
|
||||
let world = app.world_mut();
|
||||
let mut q = world.query_filtered::<&UiTransform, With<HudActionBar>>();
|
||||
let t = q.single(world).expect("bar carries UiTransform");
|
||||
match t.translation.y {
|
||||
Val::Px(px) => px,
|
||||
other => panic!("duck must write Val::Px, got {other:?}"),
|
||||
}
|
||||
};
|
||||
|
||||
// 0.18s slide at 0.05s/frame: fully ducked within 5 frames.
|
||||
app.update();
|
||||
app.update();
|
||||
let mid = translation_y_px(&mut app);
|
||||
assert!(mid > 0.0, "bar must start sliding down: {mid}");
|
||||
for _ in 0..5 {
|
||||
app.update();
|
||||
}
|
||||
let ducked = translation_y_px(&mut app);
|
||||
assert!(
|
||||
ducked > TAB_BAR_CLEARANCE_PX,
|
||||
"fully ducked bar must clear its own floating footprint: {ducked}"
|
||||
);
|
||||
|
||||
// Drag ends → bar slides back to identity.
|
||||
app.world_mut().resource_mut::<DragState>().committed = false;
|
||||
for _ in 0..8 {
|
||||
app.update();
|
||||
}
|
||||
assert_eq!(translation_y_px(&mut app), 0.0);
|
||||
}
|
||||
|
||||
/// The tween must move at the `MOTION_SLIDE_SECS` rate, never overshoot,
|
||||
/// and snap instantly under reduce-motion.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user