How to create a counter with button click?
how would a hello world look like? I want a counter that increase upon button click
I'll help you understand how a "Hello World" with a counter would look like in the Freya framework. Let me first explore the repository structure to find relevant examples.
Perfect! I can see there's a counter.rs example. Let me read that:
Perfect! Here's what a Hello World counter application would look like in Freya. This is the actual example from the repository:
##Counter Example
use freya::prelude::*;
fn main() {
launch(LaunchConfig::new().with_window(WindowConfig::new(app).with_size(500., 450.)))
}
fn app() -> impl IntoElement {
let mut count = use_state(|| 4);
let counter = rect()
.width(Size::fill())
.height(Size::percent(50.))
.center()
.color((255, 255, 255))
.background((15, 163, 242))
.font_weight(FontWeight::BOLD)
.font_size(75.)
.shadow((0., 4., 20., 4., (0, 0, 0, 80)))
.child(count.read().to_string());
let actions = rect()
.horizontal()
.width(Size::fill())
.height(Size::percent(50.))
.center()
.spacing(8.0)
.child(
Button::new()
.on_press(move |_| {
*count.write() += 1;
})
.child("Increase"),
)
.child(
Button::new()
.on_press(move |_| {
*count.write() -= 1;
})
.child("Decrease"),
);
rect().child(counter).child(actions)
}
##Key Concepts:
-
State Management:
use_state(|| 4)creates a reactive state initialized to 4count.read()- reads the valuecount.write()- writes/mutates the value
-
UI Building: Using a declarative builder pattern with chainable methods
rect()- creates rectangular containers.horizontal()- layout direction.child()- adds children elements
-
Event Handling:
Button::new().on_press(move |_| { ... })handles button clicks- Closure captures
countwithmove - Updates state inside the closure
- Closure captures
-
Styling:
- Colors:
(R, G, B)or(R, G, B, A) - Size:
Size::fill(),Size::percent(50.) - Typography: font size, weight
- Effects: shadows, spacing
- Colors:
The app displays the counter in the upper half (50% height) with large text, and two buttons in the lower half that increment/decrement the counter!
how could I also render a progress bar alongside the buttons
Let me look at the progress bar component example to see how it's used:
Great! Now I can show you how to integrate a progress bar with the counter. Here's the modified code:
use freya::prelude::*;
fn main() {
launch(LaunchConfig::new().with_window(WindowConfig::new(app).with_size(500., 450.)))
}
fn app() -> impl IntoElement {
let mut count = use_state(|| 4);
let counter = rect()
.width(Size::fill())
.height(Size::percent(50.))
.center()
.color((255, 255, 255))
.background((15, 163, 242))
.font_weight(FontWeight::BOLD)
.font_size(75.)
.shadow((0., 4., 20., 4., (0, 0, 0, 80)))
.child(count.read().to_string());
let progress_value = (*count.read() as f32 / 100.0 * 100.0).min(100.0).max(0.0);
let actions = rect()
.vertical()
.width(Size::fill())
.height(Size::percent(50.))
.padding(16.0)
.spacing(8.0)
.child(
rect()
.horizontal()
.width(Size::fill())
.spacing(8.0)
.child(
Button::new()
.on_press(move |_| {
*count.write() += 1;
})
.child("Increase"),
)
.child(
Button::new()
.on_press(move |_| {
*count.write() -= 1;
})
.child("Decrease"),
),
)
.child(
ProgressBar::new(progress_value)
.width(Size::fill())
);
rect().child(counter).child(actions)
}
##Key Changes:
-
Progress Bar Value: Calculate progress based on the counter
let progress_value = (*count.read() as f32 / 100.0 * 100.0).min(100.0).max(0.0);This maps the counter value to a 0-100% range (clamped)
-
Layout: Changed
actionsto use.vertical()instead of.horizontal()to stack buttons and progress bar -
Added padding and spacing for better visual separation
-
Progress bar child: Added alongside buttons
ProgressBar::new(progress_value) .width(Size::fill())
Now the progress bar will update as you click the buttons! You can adjust the progress calculation to match whatever range you want. For example, if you want it to go from 0-100 on the counter directly, you could simplify it to just *count.read() as f32 and adjust your button logic accordingly.
END OF POST
Claude Haiku 4.5