add popover

This commit is contained in:
2026-10-29 18:13:39 +07:00
parent 2ecde30ae2
commit 8fffbdcecb
9 changed files with 198 additions and 5 deletions
+53 -1
View File
@@ -1,7 +1,7 @@
use crate::definition::ThemeDefinition;
use crate::ramps::{AccentShades, Oklch, contrast_foreground, derive_shades, mix};
use crate::system::SystemTheme;
use crate::{ColorTokens, Radius, SizeTable, ThemeVariant};
use crate::{ColorTokens, Elevations, Motion, Radius, SizeTable, ThemeVariant};
use gpui::px;
/// Derived state shades for the colors that get pressed and hovered.
@@ -19,6 +19,8 @@ pub struct ResolvedTheme {
pub colors: ColorTokens,
pub ramps: Ramps,
pub radius: Radius,
pub elevations: Elevations,
pub motion: Motion,
/// The platform's native root font size; the fallback theme uses 16.
pub root_font_size: gpui::Pixels,
pub sizes: SizeTable,
@@ -123,6 +125,11 @@ pub(crate) fn resolve(
system_palette.selection,
base.selection,
),
overlay: pick(
def_color(|d| d.overlay()),
system_palette.overlay,
base.overlay,
),
};
let accessibility = system.accessibility;
@@ -172,6 +179,8 @@ pub(crate) fn resolve(
},
colors,
radius,
elevations: Elevations::default(),
motion: Motion::default(),
root_font_size,
sizes,
accessibility,
@@ -274,6 +283,49 @@ mod tests {
assert!((resolved.sizes.small.input_height - expected_small).abs() < px(0.01));
}
#[test]
fn overlay_is_translucent_and_overridable() {
let light = resolve(
&system(ThemeVariant::Light, PartialPalette::default(), None),
None,
None,
);
let dark = resolve(
&system(ThemeVariant::Dark, PartialPalette::default(), None),
None,
None,
);
// Both scrims are translucent black; dark is denser for contrast.
assert!(light.colors.overlay.a > 0.0 && light.colors.overlay.a < 0.5);
assert!(dark.colors.overlay.a > light.colors.overlay.a);
let def = ThemeDefinition::parse_toml("overlay = \"#000000\"").unwrap();
let overridden = resolve(
&system(ThemeVariant::Light, PartialPalette::default(), None),
Some(&def),
None,
);
assert_eq!(overridden.colors.overlay, hsla(0x000000));
assert_eq!(overridden.colors.overlay.a, 1.0);
}
#[test]
fn elevations_and_motion_resolve_with_defaults() {
let resolved = resolve(
&system(ThemeVariant::Dark, PartialPalette::default(), None),
None,
None,
);
// The popover shadow is softer and tighter than the dialog's.
assert!(resolved.elevations.popover.blur_radius < resolved.elevations.dialog.blur_radius);
assert!(resolved.motion.overlay > std::time::Duration::ZERO);
let shadows = resolved.elevations.popover.shadows();
assert_eq!(shadows.len(), 1);
assert!(!shadows[0].inset);
}
#[test]
fn system_colors_override_the_base_but_leave_the_rest_intact() {
let palette = PartialPalette {