swoop_ui/
lib.rs

1//! **Swoop UI** is a modular, ergonomic layout toolkit built on top of Bevy UI.
2//! It introduces expressive layout containers like `HStack`, `VStack`, `HGrid`, and `VGrid`,
3//! supporting fluent syntax for padding, spacing, border, and background styling.
4//! Now only some packaged candies are generated, no additional functions, maybe they will be added later,
5//! a plugin is reserved, but it has not been used yet
6//!
7//! Most methods implement Bundle and can be generated directly.
8//! However, some packaging requires multiple levels,
9//! so ViewToBundle is implemented and the pack() method is called to convert it into impl Bundle.
10//!
11//! # UI Layout Overview
12//!
13//! This crate defines a menu bar container using a horizontal stack layout:
14//!
15//! ```rust
16//! use bevy::prelude::*;
17//! use swoop_ui::prelude::*;
18//!
19//! fn setup(mut commands: Commands) {
20//!     commands.spawn((
21//!         HStack::new(AlignItems::Start, Val::Auto)
22//!             .background_color(Srgba::WHITE.into())
23//!             .justify_content(JustifyContent::Start)
24//!             .pack(),
25//!     ));
26//! }
27//! ```
28//!
29//! - `HStack` creates a horizontal layout with children aligned at the top.
30//! - The background color is set using the impl Into<Color> value.
31//! - Contents are left-aligned using `JustifyContent::Start`.
32//!
33//! Because the impl Bundle is implemented, it can be directly generated using commands.spawn
34
35use std::borrow::Cow;
36use std::fmt::Debug;
37
38use bevy_app::prelude::*;
39use bevy_ecs::prelude::*;
40use bevy_ui::prelude::*;
41
42// Background UI trait
43pub mod background;
44// Border UI trait
45pub mod border;
46// Shadow UI Trait
47pub mod shadow;
48// Absolute positioning
49pub mod position;
50
51/// Button
52pub mod button;
53/// Layouts and containers
54pub mod container;
55/// Text
56pub mod text;
57
58pub mod prelude {
59    pub use super::background::BackgroundView;
60    pub use super::border::BorderView;
61    pub use super::position::PositionView;
62    pub use super::shadow::{BoxShadowView, TextShadowView};
63    pub use super::{SwoopUiPlugin, View, ViewToBundle};
64
65    pub use super::button::prelude::*;
66    pub use super::container::prelude::*;
67    pub use super::text::prelude::*;
68}
69
70/// Reserved for future addition of system functions
71pub struct SwoopUiPlugin;
72
73/// Provides a builder-style trait for configuring UI elements
74/// using a fluent interface.
75///
76/// Types implementing `View` must define how to access their `Name`
77/// and `Node` components. This trait simplifies layout and styling
78/// tasks through expressive method chaining.
79pub trait View: Debug + Clone + Default {
80    /// Creates a new instance using the type's `Default` implementation.
81    ///
82    /// This is a convenient shorthand when no customization is needed.
83    fn new() -> Self {
84        Self::default()
85    }
86
87    /// Constructs a new instance and sets its `Name` component.
88    ///
89    /// # Arguments
90    /// * `name` - A name to assign to this instance, typically used for entity
91    ///   identification or debugging purposes.
92    fn from_name(name: impl Into<Cow<'static, str>>) -> Self {
93        let mut view = Self::default();
94        view.name_node().set(name);
95        view
96    }
97
98    /// Provides mutable access to the underlying `Name` component.
99    ///
100    /// This allows for direct manipulation or inspection of the `Name`.
101    fn name_node(&mut self) -> &mut Name;
102
103    /// Provides mutable access to the underlying `Node` component.
104    ///
105    /// Useful when applying layout or transform properties.
106    fn node_node(&mut self) -> &mut Node;
107
108    /// Sets the `Name` component of this instance.
109    ///
110    /// Helpful for tracking or debugging UI entities.
111    ///
112    /// # Arguments
113    /// * `name` - The name to assign, provided as a `&str`, `String`, or `Cow`.
114    fn name(mut self, name: impl Into<Cow<'static, str>>) -> Self {
115        self.name_node().set(name);
116        self
117    }
118
119    /// Sets the padding (insets) around the content of the `Node`.
120    ///
121    /// # Arguments
122    /// * `padding` - A `UiRect` defining spacing on all four sides.
123    fn padding(mut self, padding: UiRect) -> Self {
124        self.node_node().padding = padding;
125        self
126    }
127
128    /// Sets both the width and height of the `Node`.
129    ///
130    /// # Arguments
131    /// * `width` - The desired width using `Val::Px`, `Val::Percent`, etc.
132    /// * `height` - The desired height using the same `Val` enum.
133    fn frame(mut self, width: Val, height: Val) -> Self {
134        let node = self.node_node();
135        node.width = width;
136        node.height = height;
137        self
138    }
139
140    /// Sets the width of the `Node`.
141    ///
142    /// # Arguments
143    /// * `val` - The desired width value.
144    fn width(mut self, val: Val) -> Self {
145        self.node_node().width = val;
146        self
147    }
148
149    /// Sets the maximum width constraint of the `Node`.
150    ///
151    /// Prevents the node from expanding beyond this limit.
152    fn max_width(mut self, val: Val) -> Self {
153        self.node_node().max_width = val;
154        self
155    }
156
157    /// Sets the minimum width constraint of the `Node`.
158    ///
159    /// Ensures the node does not shrink below this value.
160    fn min_width(mut self, val: Val) -> Self {
161        self.node_node().min_width = val;
162        self
163    }
164
165    /// Sets the height of the `Node`.
166    ///
167    /// # Arguments
168    /// * `val` - The desired height value.
169    fn height(mut self, val: Val) -> Self {
170        self.node_node().height = val;
171        self
172    }
173
174    /// Sets the maximum height constraint of the `Node`.
175    ///
176    /// Prevents the node from growing beyond this value.
177    fn max_height(mut self, val: Val) -> Self {
178        self.node_node().max_height = val;
179        self
180    }
181
182    /// Sets the minimum height constraint of the `Node`.
183    ///
184    /// Ensures the node maintains at least this size.
185    fn min_height(mut self, val: Val) -> Self {
186        self.node_node().min_height = val;
187        self
188    }
189
190    /// Sets the `flex_grow` factor of the `Node`.
191    ///
192    /// Determines how much the node should grow relative to its siblings.
193    fn flex_grow(mut self, grow: f32) -> Self {
194        self.node_node().flex_grow = grow;
195        self
196    }
197
198    /// Sets the `flex_shrink` factor of the `Node`.
199    ///
200    /// Controls how much the node should shrink when space is constrained.
201    fn flex_shrink(mut self, shrink: f32) -> Self {
202        self.node_node().flex_shrink = shrink;
203        self
204    }
205
206    /// Assigns this node to a specific grid row in a grid layout.
207    ///
208    /// # Arguments
209    /// * `row` - The grid row position.
210    fn grid_row(mut self, row: GridPlacement) -> Self {
211        self.node_node().grid_row = row;
212        self
213    }
214
215    /// Assigns this node to a specific grid column in a grid layout.
216    ///
217    /// # Arguments
218    /// * `column` - The grid column position.
219    fn grid_column(mut self, column: GridPlacement) -> Self {
220        self.node_node().grid_column = column;
221        self
222    }
223}
224
225pub trait ViewToBundle: View {
226    fn pack(self) -> impl Bundle;
227}
228
229impl Plugin for SwoopUiPlugin {
230    fn build(&self, _: &mut App) {}
231}