T00 foundation: theme, motion, assets, icon, buttons, gallery

Theme tokens in light and dark with high contrast, a palette cross-fade,
motion curves and a damped spring, embedded Lucide icons with Inter and
JetBrains Mono, Icon, Button, IconButton, and a gallery that captures
its own window. Reviewed by codex gpt-6-astra (max): PASS in round 3.
This commit is contained in:
ZacharyZhang-NY committed 2026-09-24 23:59:55 -04:00
commit abf4cbcfc6
258 files changed
+16908

No files matched your search

+78
View File
@@ -0,0 +1,78 @@
use std::time::Duration;
use gpui::App;
use crate::theme::ActiveTheme;
pub const FAST: Duration = Duration::from_millis(120);
pub const BASE: Duration = Duration::from_millis(200);
pub const SLOW: Duration = Duration::from_millis(320);
pub const THEME: Duration = Duration::from_millis(280);
const DAMPING: f32 = 0.75;
const OMEGA: f32 = 6.91 / DAMPING;
/// `base`, or one millisecond under reduced motion.
pub fn duration(base: Duration, cx: &App) -> Duration {
if cx.theme().reduced_motion {
Duration::from_millis(1)
} else {
base
}
}
pub fn lerp(from: f32, to: f32, t: f32) -> f32 {
from + (to - from) * t
}
pub fn ease_out_cubic(t: f32) -> f32 {
1.0 - (1.0 - t).powi(3)
}
pub fn ease_in_out_cubic(t: f32) -> f32 {
if t < 0.5 {
4.0 * t * t * t
} else {
1.0 - (-2.0 * t + 2.0).powi(3) / 2.0
}
}
/// Damped spring. Overshoots; not a gpui easing.
pub fn spring(t: f32) -> f32 {
if t >= 1.0 {
return 1.0;
}
let damped = OMEGA * (1.0 - DAMPING * DAMPING).sqrt();
let decay = (-DAMPING * OMEGA * t).exp();
1.0 - decay * ((damped * t).cos() + DAMPING * OMEGA / damped * (damped * t).sin())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn easings_pin_their_ends() {
for ease in [ease_out_cubic, ease_in_out_cubic, spring] {
assert!(ease(0.0).abs() < 1e-6);
assert_eq!(ease(1.0), 1.0);
}
}
#[test]
fn spring_overshoots_a_little_then_settles() {
let peak = (0..=100)
.map(|i| spring(i as f32 / 100.0))
.fold(0.0, f32::max);
assert!(peak > 1.01 && peak < 1.05, "peak {peak}");
assert!((spring(0.95) - 1.0).abs() < 0.01);
}
#[test]
fn ease_in_out_is_symmetric() {
for i in 0..=10 {
let t = i as f32 / 10.0;
assert!((ease_in_out_cubic(t) + ease_in_out_cubic(1.0 - t) - 1.0).abs() < 1e-5);
}
}
}
+3
View File
@@ -0,0 +1,3 @@
mod curve;
pub use curve::*;