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}