# Transitions
A transition eases a property to each new value over a fixed time, with an
easing curve. It is declared on the value itself, with `.transition(..)`.
## Declaring one
```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
# let value = Color::WHITE;
# let timing = TimingFunction::EaseOut;
# let duration_ms = 200.0;
# let _: Animated<Color> =
value.transition(Transition::new(duration_ms, timing))
# ;
# }
```
- `duration_ms` - Animation duration in milliseconds
- `timing` - Easing curve for the animation
A bare number is the short form: `.transition(200.0)` is 200ms eased out.
## Examples
### Background Animation
```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
container()
.background(Color::rgb(0.3, 0.5, 0.8).transition(200.0))
.when_hovered(|s| s.lighter(0.15))
# ;
# }
```
### Border Animation
A border is declared as a pair and each half carries its own timing, so the
width can spring while the colour eases:
```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
container()
.border(
1.0.transition(150.0),
Color::rgb(0.3, 0.3, 0.4).transition(150.0),
)
.when_hovered(|s| s.border(2.0, Color::rgb(0.5, 0.5, 0.6)))
# ;
# }
```
### Transform Animation
```rust
# extern crate guido;
# use guido::prelude::*;
# fn main() {
container()
.scale(Scale::NONE.transition(Transition::new(300.0, TimingFunction::EaseOut)))
.when_pressed(|s| s.scale(0.98))
# ;
# }
```
The resting value is what the property is when no state layer overrides it —
here `Scale::NONE`, the size the press shrinks away from.
## Duration Guidelines
| 100-150ms | Quick feedback (button press) |
| 150-200ms | State changes (hover) |
| 200-300ms | Content changes (expand/collapse) |
| 300-500ms | Major transitions (page changes) |
## Combining with State Layers
A state layer supplies a value for a property somebody else declared, and
carries no timing of its own. The property eases whatever supplies its value:
```rust
# extern crate guido;
# use guido::prelude::*;
# const FLAT: Shadow = Shadow::none();
# const LOW: Shadow = Shadow::simple((0.0, 1.0), 3.0, Color::rgba(0.0, 0.0, 0.0, 0.12));
# const RAISED: Shadow = Shadow::simple((0.0, 3.0), 6.0, Color::rgba(0.0, 0.0, 0.0, 0.19));
# fn main() {
container()
.background(Color::rgb(0.2, 0.2, 0.3).transition(200.0))
.shadow(LOW.transition(200.0))
// State changes trigger the animations declared above
.when_hovered(|s| s.lighter(0.1).shadow(RAISED))
.when_pressed(|s| s.darker(0.05).shadow(FLAT))
# ;
# }
```
Writing a timing on the override does not compile — it would be a declaration
that is legal and does nothing:
```rust,ignore
# // not compiled: the line is the mistake the paragraph above names.
.when_hovered(|s| s.background(HOT.transition(900.0))) // error
```
## Complete Example
```rust
# extern crate guido;
# use guido::prelude::*;
# const LOW: Shadow = Shadow::simple((0.0, 1.0), 3.0, Color::rgba(0.0, 0.0, 0.0, 0.12));
# const RAISED: Shadow = Shadow::simple((0.0, 3.0), 6.0, Color::rgba(0.0, 0.0, 0.0, 0.19));
# const HIGH: Shadow = Shadow::simple((0.0, 6.0), 10.0, Color::rgba(0.0, 0.0, 0.0, 0.22));
fn animated_card() -> Container {
container()
.padding(20.0)
.background(Color::rgb(0.15, 0.15, 0.2).transition(200.0))
.corners(12.0)
.border(
1.0.transition(150.0),
Color::rgb(0.25, 0.25, 0.3).transition(150.0),
)
.shadow(RAISED.transition(250.0))
// State layers
.when_hovered(|s| s
.lighter(0.05)
.border(2.0, Color::rgb(0.4, 0.6, 0.9))
.shadow(HIGH)
)
.when_pressed(|s| s
.darker(0.02)
.shadow(LOW)
)
.child(container().child(text("Hover me!").color(Color::WHITE)))
}
# fn main() {}
```
## API Reference
```text
/// Ease to each new value this holds
value.transition(transition: impl Into<TransitionConfig>) -> Animated<T>;
/// A bare number is milliseconds, eased out
Transition::new(duration_ms: f32, timing: TimingFunction) -> Transition;
/// Create a spring-based transition
Transition::spring(config: SpringConfig) -> Transition
```