178 lines
5.5 KiB
Rust
178 lines
5.5 KiB
Rust
use gpui::Hsla;
|
|
|
|
/// A collection of colors that are used to style the UI.
|
|
///
|
|
/// Each step has a semantic meaning, and is used to style different parts of the UI.
|
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
|
|
pub struct ColorScaleStep(usize);
|
|
|
|
impl ColorScaleStep {
|
|
pub const EIGHT: Self = Self(8);
|
|
pub const ELEVEN: Self = Self(11);
|
|
pub const FIVE: Self = Self(5);
|
|
pub const FOUR: Self = Self(4);
|
|
pub const NINE: Self = Self(9);
|
|
pub const ONE: Self = Self(1);
|
|
pub const SEVEN: Self = Self(7);
|
|
pub const SIX: Self = Self(6);
|
|
pub const TEN: Self = Self(10);
|
|
pub const THREE: Self = Self(3);
|
|
pub const TWELVE: Self = Self(12);
|
|
pub const TWO: Self = Self(2);
|
|
}
|
|
|
|
/// A scale of colors for a given [`ColorScaleSet`].
|
|
///
|
|
/// Each [`ColorScale`] contains exactly 12 colors. Refer to
|
|
/// [`ColorScaleStep`] for a reference of what each step is used for.
|
|
pub struct ColorScale(Vec<Hsla>);
|
|
|
|
impl FromIterator<Hsla> for ColorScale {
|
|
fn from_iter<T: IntoIterator<Item = Hsla>>(iter: T) -> Self {
|
|
Self(Vec::from_iter(iter))
|
|
}
|
|
}
|
|
|
|
impl ColorScale {
|
|
/// Returns the specified step in the [`ColorScale`].
|
|
#[inline]
|
|
pub fn step(&self, step: ColorScaleStep) -> Hsla {
|
|
// Steps are one-based, so we need convert to the zero-based vec index.
|
|
self.0[step.0 - 1]
|
|
}
|
|
|
|
/// `Step 1` - Used for main application backgrounds.
|
|
///
|
|
/// This step provides a neutral base for any overlaying components, ideal for applications' main backdrop or empty spaces such as canvas areas.
|
|
///
|
|
#[inline]
|
|
pub fn step_1(&self) -> Hsla {
|
|
self.step(ColorScaleStep::ONE)
|
|
}
|
|
|
|
/// `Step 2` - Used for both main application backgrounds and subtle component backgrounds.
|
|
///
|
|
/// Like `Step 1`, this step allows variations in background styles, from striped tables, sidebar backgrounds, to card backgrounds.
|
|
#[inline]
|
|
pub fn step_2(&self) -> Hsla {
|
|
self.step(ColorScaleStep::TWO)
|
|
}
|
|
|
|
/// `Step 3` - Used for UI component backgrounds in their normal states.
|
|
///
|
|
/// This step maintains accessibility by guaranteeing a contrast ratio of 4.5:1 with steps 11 and 12 for text. It could also suit hover states for transparent components.
|
|
#[inline]
|
|
pub fn step_3(&self) -> Hsla {
|
|
self.step(ColorScaleStep::THREE)
|
|
}
|
|
|
|
/// `Step 4` - Used for UI component backgrounds in their hover states.
|
|
///
|
|
/// Also suited for pressed or selected states of components with a transparent background.
|
|
#[inline]
|
|
pub fn step_4(&self) -> Hsla {
|
|
self.step(ColorScaleStep::FOUR)
|
|
}
|
|
|
|
/// `Step 5` - Used for UI component backgrounds in their pressed or selected states.
|
|
#[inline]
|
|
pub fn step_5(&self) -> Hsla {
|
|
self.step(ColorScaleStep::FIVE)
|
|
}
|
|
|
|
/// `Step 6` - Used for subtle borders on non-interactive components.
|
|
///
|
|
/// Its usage spans from sidebars' borders, headers' dividers, cards' outlines, to alerts' edges and separators.
|
|
#[inline]
|
|
pub fn step_6(&self) -> Hsla {
|
|
self.step(ColorScaleStep::SIX)
|
|
}
|
|
|
|
/// `Step 7` - Used for subtle borders on interactive components.
|
|
///
|
|
/// This step subtly delineates the boundary of elements users interact with.
|
|
#[inline]
|
|
pub fn step_7(&self) -> Hsla {
|
|
self.step(ColorScaleStep::SEVEN)
|
|
}
|
|
|
|
/// `Step 8` - Used for stronger borders on interactive components and focus rings.
|
|
///
|
|
/// It strengthens the visibility and accessibility of active elements and their focus states.
|
|
#[inline]
|
|
pub fn step_8(&self) -> Hsla {
|
|
self.step(ColorScaleStep::EIGHT)
|
|
}
|
|
|
|
/// `Step 9` - Used for solid backgrounds.
|
|
///
|
|
/// `Step 9` is the most saturated step, having the least mix of white or black.
|
|
///
|
|
/// Due to its high chroma, `Step 9` is versatile and particularly useful for semantic colors such as
|
|
/// error, warning, and success indicators.
|
|
#[inline]
|
|
pub fn step_9(&self) -> Hsla {
|
|
self.step(ColorScaleStep::NINE)
|
|
}
|
|
|
|
/// `Step 10` - Used for hovered or active solid backgrounds, particularly when `Step 9` is their normal state.
|
|
///
|
|
/// May also be used for extremely low contrast text. This should be used sparingly, as it may be difficult to read.
|
|
#[inline]
|
|
pub fn step_10(&self) -> Hsla {
|
|
self.step(ColorScaleStep::TEN)
|
|
}
|
|
|
|
/// `Step 11` - Used for text and icons requiring low contrast or less emphasis.
|
|
#[inline]
|
|
pub fn step_11(&self) -> Hsla {
|
|
self.step(ColorScaleStep::ELEVEN)
|
|
}
|
|
|
|
/// `Step 12` - Used for text and icons requiring high contrast or prominence.
|
|
#[inline]
|
|
pub fn step_12(&self) -> Hsla {
|
|
self.step(ColorScaleStep::TWELVE)
|
|
}
|
|
}
|
|
|
|
/// Provides groups of [`ColorScale`]s for light and dark themes, as well as transparent versions of each scale.
|
|
pub struct ColorScaleSet {
|
|
light: ColorScale,
|
|
dark: ColorScale,
|
|
light_alpha: ColorScale,
|
|
dark_alpha: ColorScale,
|
|
}
|
|
|
|
impl ColorScaleSet {
|
|
pub(crate) fn new(
|
|
light: ColorScale,
|
|
light_alpha: ColorScale,
|
|
dark: ColorScale,
|
|
dark_alpha: ColorScale,
|
|
) -> Self {
|
|
Self {
|
|
light,
|
|
light_alpha,
|
|
dark,
|
|
dark_alpha,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn light(&self) -> &ColorScale {
|
|
&self.light
|
|
}
|
|
|
|
pub(crate) fn light_alpha(&self) -> &ColorScale {
|
|
&self.light_alpha
|
|
}
|
|
|
|
pub(crate) fn dark(&self) -> &ColorScale {
|
|
&self.dark
|
|
}
|
|
|
|
pub(crate) fn dark_alpha(&self) -> &ColorScale {
|
|
&self.dark_alpha
|
|
}
|
|
}
|