# Widgets
Widgets are the building blocks of Guido UIs. Every visual element is a widget, from simple text to complex layouts.
## The Widget Trait
All widgets implement the `Widget` trait:
```rust,ignore
# // not compiled: a signature listing — these declarations have no bodies.
pub trait Widget {
fn layout(&mut self, ctx: &mut LayoutCtx, constraints: Constraints) -> Size;
fn paint(&self, ctx: &mut PaintContext);
fn event(&mut self, tree: &mut Tree, id: WidgetId, event: &Event) -> EventResponse;
}
```
### Methods
- **layout** - Calculate the widget's size given tree access, widget ID, and constraints
- **paint** - Draw the widget using tree for child access
- **event** - Handle input events with tree access
### Bounds and Origins
Widget bounds and origins are stored in the `Tree`, not on individual widgets:
- Use `tree.get_bounds(id)` to retrieve a widget's bounding rectangle for hit testing
- Use `tree.set_origin(id, x, y)` to position widgets during layout (called by parent layouts)
## Built-in Widgets
### Container
The primary widget for building UIs. Handles:
- Backgrounds (solid, gradient)
- Borders and corner radius
- Padding and sizing
- Layout of children
- Event handling
- State layers (hover/pressed)
- Transforms
See [Container](container.md) for details.
### Text
Renders text content:
```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
container().child(text("Hello, World!").font_size(16.0).color(Color::WHITE))
# ;
# }
```
See [Text](../building-ui/text.md) for styling options.
### TextInput
Single-line text editing with selection, clipboard, and undo/redo:
```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
let username = create_signal(String::new());
container().child(text_input(username).color(Color::WHITE).on_submit(|text| println!("Submitted: {}", text)))
# ;
# }
```
See [Text Input](../building-ui/text-input.md) for details.
## Composition
Guido UIs are built through composition - nesting widgets inside containers:
```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
container()
.layout(Flex::column().spacing(8.0))
.children([
container().child(text("Title").font_size(24.0)),
container()
.layout(Flex::row().spacing(4.0))
.children([
text("Item 1"),
text("Item 2"),
]),
])
# ;
# }
```
This creates:
```text
┌─────────────────┐
│ Title │
│ ┌─────┬───────┐ │
│ │Item1│ Item2 │ │
│ └─────┴───────┘ │
└─────────────────┘
```
## Widget Functions
Guido provides functions that return configured widgets:
```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
// Creates a Container
container();
// Creates a Text widget
text("content")
# ;
# }
```
These use the builder pattern for configuration:
```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
container()
.padding(16.0) // Returns Container
.background(Color::RED) // Returns Container
.corners(8.0) // Returns Container
# ;
# }
```
## The impl Widget Pattern
Functions often return `impl Widget` instead of concrete types:
```rust
# extern crate guido;
# use guido::prelude::*;
fn my_button(label: &str) -> impl Widget {
container()
.padding(12.0)
.background(Color::rgb(0.3, 0.5, 0.8))
.corners(8.0)
.child(container().child(text(label).color(Color::WHITE)))
}
# fn main() {}
```
This allows returning any widget type without exposing implementation details.
## Constraints and Sizing
During layout, parent widgets pass constraints to children:
```rust,ignore
# // not compiled: a listing of a type the crate owns — a copy of it declared
# // here would compile without checking the original.
pub struct Constraints {
pub min_width: f32,
pub max_width: f32,
pub min_height: f32,
pub max_height: f32,
}
```
Children choose a size within these constraints. This enables flexible layouts where widgets can expand to fill space or shrink to fit content.
### Size Modifiers
Control widget sizing with builder methods:
```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
container()
.width(100.0) // Fixed width
.height(50.0) // Fixed height
.width(at_least(50.0).at_most(200.0)) // Bounded instead
# ;
# }
```
## Event Flow
Events flow from the platform through the widget tree, and each one goes only
where it can matter:
1. Platform receives input (mouse, keyboard)
2. Event dispatched to the surface's root widget
3. A pointer event is passed down to the widgets that can be under its point,
and to those it still owes one — the widget the pointer just left, the one
a press landed on. A key is passed down to the focused widget and, if it
does not take it, to the containers listening for keys
4. Each widget handles the event or ignores it; the innermost hears it first
[Event Routing](../architecture/events.md#event-routing) has the whole of it.
```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
container()
.on_click(|| println!("Clicked!"))
.child(text("Click me"))
# ;
# }
```
The container receives clicks anywhere within its bounds, including over the text.
## Next Steps
- [Container](container.md) - Deep dive into the Container widget
- [Layout](layout.md) - Learn about flex layout
- [Interactivity](../interactivity/README.md) - Add event handling