use gpui::{App, Global, Pixels, px};
const STATUS_INDICATOR_SLOT: Pixels = px(12.);
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct SizeTokens {
control_sm: Pixels,
control_md: Pixels,
control_lg: Pixels,
control_padding_sm: Pixels,
control_padding_md: Pixels,
slot_xs: Pixels,
slot_sm: Pixels,
slot_md: Pixels,
}
impl Global for SizeTokens {}
impl Default for SizeTokens {
fn default() -> Self {
Self::DEFAULT
}
}
impl SizeTokens {
pub const DEFAULT: Self = Self {
control_sm: px(24.),
control_md: px(28.),
control_lg: px(32.),
control_padding_sm: px(12.),
control_padding_md: px(14.),
slot_xs: STATUS_INDICATOR_SLOT,
slot_sm: px(16.),
slot_md: px(20.),
};
pub fn read(cx: &App) -> &Self {
if cx.has_global::<Self>() {
cx.global::<Self>()
} else {
&Self::DEFAULT
}
}
pub fn set(self, cx: &mut App) {
cx.set_global(self);
}
pub const fn control_sm(&self) -> Pixels {
self.control_sm
}
pub const fn control_md(&self) -> Pixels {
self.control_md
}
pub const fn control_lg(&self) -> Pixels {
self.control_lg
}
pub const fn control_padding_sm(&self) -> Pixels {
self.control_padding_sm
}
pub const fn control_padding_md(&self) -> Pixels {
self.control_padding_md
}
pub const fn with_control_padding_sm(mut self, padding: Pixels) -> Self {
self.control_padding_sm = padding;
self
}
pub const fn with_control_padding_md(mut self, padding: Pixels) -> Self {
self.control_padding_md = padding;
self
}
pub const fn slot_xs(&self) -> Pixels {
self.slot_xs
}
pub const fn with_slot_xs(mut self, size: Pixels) -> Self {
self.slot_xs = size;
self
}
pub const fn slot_sm(&self) -> Pixels {
self.slot_sm
}
pub const fn slot_md(&self) -> Pixels {
self.slot_md
}
pub const fn with_control_sm(mut self, height: Pixels) -> Self {
self.control_sm = height;
self
}
pub const fn with_control_md(mut self, height: Pixels) -> Self {
self.control_md = height;
self
}
pub const fn with_control_lg(mut self, height: Pixels) -> Self {
self.control_lg = height;
self
}
pub const fn with_slot_sm(mut self, size: Pixels) -> Self {
self.slot_sm = size;
self
}
pub const fn with_slot_md(mut self, size: Pixels) -> Self {
self.slot_md = size;
self
}
}
pub(crate) fn install(cx: &mut App) {
if !cx.has_global::<SizeTokens>() {
SizeTokens::DEFAULT.set(cx);
}
}
pub(crate) fn control_sm(cx: &App) -> Pixels {
SizeTokens::read(cx).control_sm()
}
pub(crate) fn control_md(cx: &App) -> Pixels {
SizeTokens::read(cx).control_md()
}
pub(crate) fn control_lg(cx: &App) -> Pixels {
SizeTokens::read(cx).control_lg()
}
pub(crate) fn slot_xs(cx: &App) -> Pixels {
SizeTokens::read(cx).slot_xs()
}
pub(crate) fn slot_sm(cx: &App) -> Pixels {
SizeTokens::read(cx).slot_sm()
}
pub(crate) fn slot_md(cx: &App) -> Pixels {
SizeTokens::read(cx).slot_md()
}
#[cfg(test)]
mod tests {
use super::*;
use gpui::TestAppContext;
#[gpui::test]
fn install_respects_a_policy_the_application_chose_first(cx: &mut TestAppContext) {
cx.update(|cx| {
SizeTokens::default().with_control_lg(px(36.)).set(cx);
crate::init(cx);
assert_eq!(SizeTokens::read(cx).control_lg(), px(36.));
});
}
#[gpui::test]
fn install_provides_the_default_policy_when_none_was_chosen(cx: &mut TestAppContext) {
cx.update(|cx| {
crate::init(cx);
assert!(cx.has_global::<SizeTokens>());
assert_eq!(*SizeTokens::read(cx), SizeTokens::DEFAULT);
});
}
#[test]
fn the_default_tiers_are_ordered() {
let tokens = SizeTokens::DEFAULT;
assert!(tokens.control_sm() < tokens.control_md());
assert!(tokens.control_md() < tokens.control_lg());
assert!(tokens.slot_xs() < tokens.slot_sm());
assert!(tokens.slot_sm() < tokens.slot_md());
assert!(tokens.control_padding_sm() < tokens.control_padding_md());
}
}