@@ -0,0 +1,284 @@
|
||||
use gpui::Hsla;
|
||||
use refineable::Refineable;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{PlayerColors, StatusColors, SyntaxTheme, SystemColors};
|
||||
|
||||
#[derive(Refineable, Clone, Debug)]
|
||||
#[refineable(Debug, serde::Deserialize)]
|
||||
pub struct ThemeColors {
|
||||
pub border: Hsla,
|
||||
/// Border color. Used for deemphasized borders, like a visual divider between two sections
|
||||
pub border_variant: Hsla,
|
||||
/// Border color. Used for focused elements, like keyboard focused list item.
|
||||
pub border_focused: Hsla,
|
||||
/// Border color. Used for selected elements, like an active search filter or selected checkbox.
|
||||
pub border_selected: Hsla,
|
||||
/// Border color. Used for transparent borders. Used for placeholder borders when an element gains a border on state change.
|
||||
pub border_transparent: Hsla,
|
||||
/// Border color. Used for disabled elements, like a disabled input or button.
|
||||
pub border_disabled: Hsla,
|
||||
/// Border color. Used for elevated surfaces, like a context menu, popup, or dialog.
|
||||
pub elevated_surface_background: Hsla,
|
||||
/// Background Color. Used for grounded surfaces like a panel or tab.
|
||||
pub surface_background: Hsla,
|
||||
/// Background Color. Used for the app background and blank panels or windows.
|
||||
pub background: Hsla,
|
||||
/// Background Color. Used for the background of an element that should have a different background than the surface it's on.
|
||||
///
|
||||
/// Elements might include: Buttons, Inputs, Checkboxes, Radio Buttons...
|
||||
///
|
||||
/// For an element that should have the same background as the surface it's on, use `ghost_element_background`.
|
||||
pub element_background: Hsla,
|
||||
/// Background Color. Used for the hover state of an element that should have a different background than the surface it's on.
|
||||
///
|
||||
/// Hover states are triggered by the mouse entering an element, or a finger touching an element on a touch screen.
|
||||
pub element_hover: Hsla,
|
||||
/// Background Color. Used for the active state of an element that should have a different background than the surface it's on.
|
||||
///
|
||||
/// Active states are triggered by the mouse button being pressed down on an element, or the Return button or other activator being pressd.
|
||||
pub element_active: Hsla,
|
||||
/// Background Color. Used for the selected state of an element that should have a different background than the surface it's on.
|
||||
///
|
||||
/// Selected states are triggered by the element being selected (or "activated") by the user.
|
||||
///
|
||||
/// This could include a selected checkbox, a toggleable button that is toggled on, etc.
|
||||
pub element_selected: Hsla,
|
||||
/// Background Color. Used for the disabled state of an element that should have a different background than the surface it's on.
|
||||
///
|
||||
/// Disabled states are shown when a user cannot interact with an element, like a disabled button or input.
|
||||
pub element_disabled: Hsla,
|
||||
/// Background Color. Used for the area that shows where a dragged element will be dropped.
|
||||
pub drop_target_background: Hsla,
|
||||
/// Border Color. Used to show the area that shows where a dragged element will be dropped.
|
||||
// pub drop_target_border: Hsla,
|
||||
/// Used for the background of a ghost element that should have the same background as the surface it's on.
|
||||
///
|
||||
/// Elements might include: Buttons, Inputs, Checkboxes, Radio Buttons...
|
||||
///
|
||||
/// For an element that should have a different background than the surface it's on, use `element_background`.
|
||||
pub ghost_element_background: Hsla,
|
||||
/// Background Color. Used for the hover state of a ghost element that should have the same background as the surface it's on.
|
||||
///
|
||||
/// Hover states are triggered by the mouse entering an element, or a finger touching an element on a touch screen.
|
||||
pub ghost_element_hover: Hsla,
|
||||
/// Background Color. Used for the active state of a ghost element that should have the same background as the surface it's on.
|
||||
///
|
||||
/// Active states are triggered by the mouse button being pressed down on an element, or the Return button or other activator being pressd.
|
||||
pub ghost_element_active: Hsla,
|
||||
/// Background Color. Used for the selected state of a ghost element that should have the same background as the surface it's on.
|
||||
///
|
||||
/// Selected states are triggered by the element being selected (or "activated") by the user.
|
||||
///
|
||||
/// This could include a selected checkbox, a toggleable button that is toggled on, etc.
|
||||
pub ghost_element_selected: Hsla,
|
||||
/// Background Color. Used for the disabled state of a ghost element that should have the same background as the surface it's on.
|
||||
///
|
||||
/// Disabled states are shown when a user cannot interact with an element, like a disabled button or input.
|
||||
pub ghost_element_disabled: Hsla,
|
||||
/// Text Color. Default text color used for most text.
|
||||
pub text: Hsla,
|
||||
/// Text Color. Color of muted or deemphasized text. It is a subdued version of the standard text color.
|
||||
pub text_muted: Hsla,
|
||||
/// Text Color. Color of the placeholder text typically shown in input fields to guide the user to enter valid data.
|
||||
pub text_placeholder: Hsla,
|
||||
/// Text Color. Color used for text denoting disabled elements. Typically, the color is faded or grayed out to emphasize the disabled state.
|
||||
pub text_disabled: Hsla,
|
||||
/// Text Color. Color used for emphasis or highlighting certain text, like an active filter or a matched character in a search.
|
||||
pub text_accent: Hsla,
|
||||
/// Fill Color. Used for the default fill color of an icon.
|
||||
pub icon: Hsla,
|
||||
/// Fill Color. Used for the muted or deemphasized fill color of an icon.
|
||||
///
|
||||
/// This might be used to show an icon in an inactive pane, or to demphasize a series of icons to give them less visual weight.
|
||||
pub icon_muted: Hsla,
|
||||
/// Fill Color. Used for the disabled fill color of an icon.
|
||||
///
|
||||
/// Disabled states are shown when a user cannot interact with an element, like a icon button.
|
||||
pub icon_disabled: Hsla,
|
||||
/// Fill Color. Used for the placeholder fill color of an icon.
|
||||
///
|
||||
/// This might be used to show an icon in an input that disappears when the user enters text.
|
||||
pub icon_placeholder: Hsla,
|
||||
/// Fill Color. Used for the accent fill color of an icon.
|
||||
///
|
||||
/// This might be used to show when a toggleable icon button is selected.
|
||||
pub icon_accent: Hsla,
|
||||
|
||||
// ===
|
||||
// UI Elements
|
||||
// ===
|
||||
pub status_bar_background: Hsla,
|
||||
pub title_bar_background: Hsla,
|
||||
pub toolbar_background: Hsla,
|
||||
pub tab_bar_background: Hsla,
|
||||
pub tab_inactive_background: Hsla,
|
||||
pub tab_active_background: Hsla,
|
||||
pub search_match_background: Hsla,
|
||||
pub panel_background: Hsla,
|
||||
pub panel_focused_border: Hsla,
|
||||
pub pane_focused_border: Hsla,
|
||||
/// The color of the scrollbar thumb.
|
||||
pub scrollbar_thumb_background: Hsla,
|
||||
/// The color of the scrollbar thumb when hovered over.
|
||||
pub scrollbar_thumb_hover_background: Hsla,
|
||||
/// The border color of the scrollbar thumb.
|
||||
pub scrollbar_thumb_border: Hsla,
|
||||
/// The background color of the scrollbar track.
|
||||
pub scrollbar_track_background: Hsla,
|
||||
/// The border color of the scrollbar track.
|
||||
pub scrollbar_track_border: Hsla,
|
||||
// /// The opacity of the scrollbar status marks, like diagnostic states and git status.
|
||||
// todo!()
|
||||
// pub scrollbar_status_opacity: Hsla,
|
||||
|
||||
// ===
|
||||
// Editor
|
||||
// ===
|
||||
pub editor_foreground: Hsla,
|
||||
pub editor_background: Hsla,
|
||||
// pub editor_inactive_background: Hsla,
|
||||
pub editor_gutter_background: Hsla,
|
||||
pub editor_subheader_background: Hsla,
|
||||
pub editor_active_line_background: Hsla,
|
||||
pub editor_highlighted_line_background: Hsla,
|
||||
/// Text Color. Used for the text of the line number in the editor gutter.
|
||||
pub editor_line_number: Hsla,
|
||||
/// Text Color. Used for the text of the line number in the editor gutter when the line is highlighted.
|
||||
pub editor_active_line_number: Hsla,
|
||||
/// Text Color. Used to mark invisible characters in the editor.
|
||||
///
|
||||
/// Example: spaces, tabs, carriage returns, etc.
|
||||
pub editor_invisible: Hsla,
|
||||
pub editor_wrap_guide: Hsla,
|
||||
pub editor_active_wrap_guide: Hsla,
|
||||
/// Read-access of a symbol, like reading a variable.
|
||||
///
|
||||
/// A document highlight is a range inside a text document which deserves
|
||||
/// special attention. Usually a document highlight is visualized by changing
|
||||
/// the background color of its range.
|
||||
pub editor_document_highlight_read_background: Hsla,
|
||||
/// Read-access of a symbol, like reading a variable.
|
||||
///
|
||||
/// A document highlight is a range inside a text document which deserves
|
||||
/// special attention. Usually a document highlight is visualized by changing
|
||||
/// the background color of its range.
|
||||
pub editor_document_highlight_write_background: Hsla,
|
||||
|
||||
// ===
|
||||
// Terminal
|
||||
// ===
|
||||
/// Terminal Background Color
|
||||
pub terminal_background: Hsla,
|
||||
/// Bright Black Color for ANSI Terminal
|
||||
pub terminal_ansi_bright_black: Hsla,
|
||||
/// Bright Red Color for ANSI Terminal
|
||||
pub terminal_ansi_bright_red: Hsla,
|
||||
/// Bright Green Color for ANSI Terminal
|
||||
pub terminal_ansi_bright_green: Hsla,
|
||||
/// Bright Yellow Color for ANSI Terminal
|
||||
pub terminal_ansi_bright_yellow: Hsla,
|
||||
/// Bright Blue Color for ANSI Terminal
|
||||
pub terminal_ansi_bright_blue: Hsla,
|
||||
/// Bright Magenta Color for ANSI Terminal
|
||||
pub terminal_ansi_bright_magenta: Hsla,
|
||||
/// Bright Cyan Color for ANSI Terminal
|
||||
pub terminal_ansi_bright_cyan: Hsla,
|
||||
/// Bright White Color for ANSI Terminal
|
||||
pub terminal_ansi_bright_white: Hsla,
|
||||
/// Black Color for ANSI Terminal
|
||||
pub terminal_ansi_black: Hsla,
|
||||
/// Red Color for ANSI Terminal
|
||||
pub terminal_ansi_red: Hsla,
|
||||
/// Green Color for ANSI Terminal
|
||||
pub terminal_ansi_green: Hsla,
|
||||
/// Yellow Color for ANSI Terminal
|
||||
pub terminal_ansi_yellow: Hsla,
|
||||
/// Blue Color for ANSI Terminal
|
||||
pub terminal_ansi_blue: Hsla,
|
||||
/// Magenta Color for ANSI Terminal
|
||||
pub terminal_ansi_magenta: Hsla,
|
||||
/// Cyan Color for ANSI Terminal
|
||||
pub terminal_ansi_cyan: Hsla,
|
||||
/// White Color for ANSI Terminal
|
||||
pub terminal_ansi_white: Hsla,
|
||||
|
||||
// ===
|
||||
// UI/Rich Text
|
||||
// ===
|
||||
pub link_text_hover: Hsla,
|
||||
}
|
||||
|
||||
#[derive(Refineable, Clone)]
|
||||
pub struct ThemeStyles {
|
||||
pub system: SystemColors,
|
||||
/// An array of colors used for theme elements that iterrate through a series of colors.
|
||||
///
|
||||
/// Example: Player colors, rainbow brackets and indent guides, etc.
|
||||
pub accents: Vec<Hsla>,
|
||||
|
||||
#[refineable]
|
||||
pub colors: ThemeColors,
|
||||
pub status: StatusColors,
|
||||
pub player: PlayerColors,
|
||||
pub syntax: Arc<SyntaxTheme>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::json;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn override_a_single_theme_color() {
|
||||
let mut colors = ThemeColors::light();
|
||||
|
||||
let magenta: Hsla = gpui::rgb(0xff00ff);
|
||||
|
||||
assert_ne!(colors.text, magenta);
|
||||
|
||||
let overrides = ThemeColorsRefinement {
|
||||
text: Some(magenta),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
colors.refine(&overrides);
|
||||
|
||||
assert_eq!(colors.text, magenta);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn override_multiple_theme_colors() {
|
||||
let mut colors = ThemeColors::light();
|
||||
|
||||
let magenta: Hsla = gpui::rgb(0xff00ff);
|
||||
let green: Hsla = gpui::rgb(0x00ff00);
|
||||
|
||||
assert_ne!(colors.text, magenta);
|
||||
assert_ne!(colors.background, green);
|
||||
|
||||
let overrides = ThemeColorsRefinement {
|
||||
text: Some(magenta),
|
||||
background: Some(green),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
colors.refine(&overrides);
|
||||
|
||||
assert_eq!(colors.text, magenta);
|
||||
assert_eq!(colors.background, green);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_theme_colors_refinement_from_json() {
|
||||
let colors: ThemeColorsRefinement = serde_json::from_value(json!({
|
||||
"background": "#ff00ff",
|
||||
"text": "#ff0000"
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(colors.background, Some(gpui::rgb(0xff00ff)));
|
||||
assert_eq!(colors.text, Some(gpui::rgb(0xff0000)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
use gpui::Hsla;
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
use crate::{amber, blue, jade, lime, orange, pink, purple, red};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, Default)]
|
||||
pub struct PlayerColor {
|
||||
pub cursor: Hsla,
|
||||
pub background: Hsla,
|
||||
pub selection: Hsla,
|
||||
}
|
||||
|
||||
/// A collection of colors that are used to color players in the editor.
|
||||
///
|
||||
/// The first color is always the local player's color, usually a blue.
|
||||
///
|
||||
/// The rest of the default colors crisscross back and forth on the
|
||||
/// color wheel so that the colors are as distinct as possible.
|
||||
#[derive(Clone, Deserialize)]
|
||||
pub struct PlayerColors(pub Vec<PlayerColor>);
|
||||
|
||||
impl Default for PlayerColors {
|
||||
/// Don't use this!
|
||||
/// We have to have a default to be `[refineable::Refinable]`.
|
||||
/// todo!("Find a way to not need this for Refinable")
|
||||
fn default() -> Self {
|
||||
Self::dark()
|
||||
}
|
||||
}
|
||||
|
||||
impl PlayerColors {
|
||||
pub fn dark() -> Self {
|
||||
Self(vec![
|
||||
PlayerColor {
|
||||
cursor: blue().dark().step_9(),
|
||||
background: blue().dark().step_5(),
|
||||
selection: blue().dark().step_3(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: orange().dark().step_9(),
|
||||
background: orange().dark().step_5(),
|
||||
selection: orange().dark().step_3(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: pink().dark().step_9(),
|
||||
background: pink().dark().step_5(),
|
||||
selection: pink().dark().step_3(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: lime().dark().step_9(),
|
||||
background: lime().dark().step_5(),
|
||||
selection: lime().dark().step_3(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: purple().dark().step_9(),
|
||||
background: purple().dark().step_5(),
|
||||
selection: purple().dark().step_3(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: amber().dark().step_9(),
|
||||
background: amber().dark().step_5(),
|
||||
selection: amber().dark().step_3(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: jade().dark().step_9(),
|
||||
background: jade().dark().step_5(),
|
||||
selection: jade().dark().step_3(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: red().dark().step_9(),
|
||||
background: red().dark().step_5(),
|
||||
selection: red().dark().step_3(),
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
pub fn light() -> Self {
|
||||
Self(vec![
|
||||
PlayerColor {
|
||||
cursor: blue().light().step_9(),
|
||||
background: blue().light().step_4(),
|
||||
selection: blue().light().step_3(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: orange().light().step_9(),
|
||||
background: orange().light().step_4(),
|
||||
selection: orange().light().step_3(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: pink().light().step_9(),
|
||||
background: pink().light().step_4(),
|
||||
selection: pink().light().step_3(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: lime().light().step_9(),
|
||||
background: lime().light().step_4(),
|
||||
selection: lime().light().step_3(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: purple().light().step_9(),
|
||||
background: purple().light().step_4(),
|
||||
selection: purple().light().step_3(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: amber().light().step_9(),
|
||||
background: amber().light().step_4(),
|
||||
selection: amber().light().step_3(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: jade().light().step_9(),
|
||||
background: jade().light().step_4(),
|
||||
selection: jade().light().step_3(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: red().light().step_9(),
|
||||
background: red().light().step_4(),
|
||||
selection: red().light().step_3(),
|
||||
},
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
impl PlayerColors {
|
||||
pub fn local(&self) -> PlayerColor {
|
||||
// todo!("use a valid color");
|
||||
*self.0.first().unwrap()
|
||||
}
|
||||
|
||||
pub fn absent(&self) -> PlayerColor {
|
||||
// todo!("use a valid color");
|
||||
*self.0.last().unwrap()
|
||||
}
|
||||
|
||||
pub fn color_for_participant(&self, participant_index: u32) -> PlayerColor {
|
||||
let len = self.0.len() - 1;
|
||||
self.0[(participant_index as usize % len) + 1]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
use gpui::Hsla;
|
||||
use refineable::Refineable;
|
||||
|
||||
use crate::{blue, grass, neutral, red, yellow};
|
||||
|
||||
#[derive(Refineable, Clone, Debug)]
|
||||
#[refineable(Debug, serde::Deserialize)]
|
||||
pub struct StatusColors {
|
||||
/// Indicates some kind of conflict, like a file changed on disk while it was open, or
|
||||
/// merge conflicts in a Git repository.
|
||||
pub conflict: Hsla,
|
||||
pub conflict_background: Hsla,
|
||||
pub conflict_border: Hsla,
|
||||
|
||||
/// Indicates something new, like a new file added to a Git repository.
|
||||
pub created: Hsla,
|
||||
pub created_background: Hsla,
|
||||
pub created_border: Hsla,
|
||||
|
||||
/// Indicates that something no longer exists, like a deleted file.
|
||||
pub deleted: Hsla,
|
||||
pub deleted_background: Hsla,
|
||||
pub deleted_border: Hsla,
|
||||
|
||||
/// Indicates a system error, a failed operation or a diagnostic error.
|
||||
pub error: Hsla,
|
||||
pub error_background: Hsla,
|
||||
pub error_border: Hsla,
|
||||
|
||||
/// Represents a hidden status, such as a file being hidden in a file tree.
|
||||
pub hidden: Hsla,
|
||||
pub hidden_background: Hsla,
|
||||
pub hidden_border: Hsla,
|
||||
|
||||
/// Indicates a hint or some kind of additional information.
|
||||
pub hint: Hsla,
|
||||
pub hint_background: Hsla,
|
||||
pub hint_border: Hsla,
|
||||
|
||||
/// Indicates that something is deliberately ignored, such as a file or operation ignored by Git.
|
||||
pub ignored: Hsla,
|
||||
pub ignored_background: Hsla,
|
||||
pub ignored_border: Hsla,
|
||||
|
||||
/// Represents informational status updates or messages.
|
||||
pub info: Hsla,
|
||||
pub info_background: Hsla,
|
||||
pub info_border: Hsla,
|
||||
|
||||
/// Indicates a changed or altered status, like a file that has been edited.
|
||||
pub modified: Hsla,
|
||||
pub modified_background: Hsla,
|
||||
pub modified_border: Hsla,
|
||||
|
||||
/// Indicates something that is predicted, like automatic code completion, or generated code.
|
||||
pub predictive: Hsla,
|
||||
pub predictive_background: Hsla,
|
||||
pub predictive_border: Hsla,
|
||||
|
||||
/// Represents a renamed status, such as a file that has been renamed.
|
||||
pub renamed: Hsla,
|
||||
pub renamed_background: Hsla,
|
||||
pub renamed_border: Hsla,
|
||||
|
||||
/// Indicates a successful operation or task completion.
|
||||
pub success: Hsla,
|
||||
pub success_background: Hsla,
|
||||
pub success_border: Hsla,
|
||||
|
||||
/// Indicates some kind of unreachable status, like a block of code that can never be reached.
|
||||
pub unreachable: Hsla,
|
||||
pub unreachable_background: Hsla,
|
||||
pub unreachable_border: Hsla,
|
||||
|
||||
/// Represents a warning status, like an operation that is about to fail.
|
||||
pub warning: Hsla,
|
||||
pub warning_background: Hsla,
|
||||
pub warning_border: Hsla,
|
||||
}
|
||||
|
||||
impl Default for StatusColors {
|
||||
/// Don't use this!
|
||||
/// We have to have a default to be `[refineable::Refinable]`.
|
||||
/// todo!("Find a way to not need this for Refinable")
|
||||
fn default() -> Self {
|
||||
Self::dark()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DiagnosticColors {
|
||||
pub error: Hsla,
|
||||
pub warning: Hsla,
|
||||
pub info: Hsla,
|
||||
}
|
||||
|
||||
pub struct GitStatusColors {
|
||||
pub created: Hsla,
|
||||
pub deleted: Hsla,
|
||||
pub modified: Hsla,
|
||||
pub renamed: Hsla,
|
||||
pub conflict: Hsla,
|
||||
pub ignored: Hsla,
|
||||
}
|
||||
|
||||
impl StatusColors {
|
||||
pub fn dark() -> Self {
|
||||
Self {
|
||||
conflict: red().dark().step_9(),
|
||||
conflict_background: red().dark().step_9(),
|
||||
conflict_border: red().dark().step_9(),
|
||||
created: grass().dark().step_9(),
|
||||
created_background: grass().dark().step_9(),
|
||||
created_border: grass().dark().step_9(),
|
||||
deleted: red().dark().step_9(),
|
||||
deleted_background: red().dark().step_9(),
|
||||
deleted_border: red().dark().step_9(),
|
||||
error: red().dark().step_9(),
|
||||
error_background: red().dark().step_9(),
|
||||
error_border: red().dark().step_9(),
|
||||
hidden: neutral().dark().step_9(),
|
||||
hidden_background: neutral().dark().step_9(),
|
||||
hidden_border: neutral().dark().step_9(),
|
||||
hint: blue().dark().step_9(),
|
||||
hint_background: blue().dark().step_9(),
|
||||
hint_border: blue().dark().step_9(),
|
||||
ignored: neutral().dark().step_9(),
|
||||
ignored_background: neutral().dark().step_9(),
|
||||
ignored_border: neutral().dark().step_9(),
|
||||
info: blue().dark().step_9(),
|
||||
info_background: blue().dark().step_9(),
|
||||
info_border: blue().dark().step_9(),
|
||||
modified: yellow().dark().step_9(),
|
||||
modified_background: yellow().dark().step_9(),
|
||||
modified_border: yellow().dark().step_9(),
|
||||
predictive: neutral().dark_alpha().step_9(),
|
||||
predictive_background: neutral().dark_alpha().step_9(),
|
||||
predictive_border: neutral().dark_alpha().step_9(),
|
||||
renamed: blue().dark().step_9(),
|
||||
renamed_background: blue().dark().step_9(),
|
||||
renamed_border: blue().dark().step_9(),
|
||||
success: grass().dark().step_9(),
|
||||
success_background: grass().dark().step_9(),
|
||||
success_border: grass().dark().step_9(),
|
||||
unreachable: neutral().dark().step_10(),
|
||||
unreachable_background: neutral().dark().step_10(),
|
||||
unreachable_border: neutral().dark().step_10(),
|
||||
warning: yellow().dark().step_9(),
|
||||
warning_background: yellow().dark().step_9(),
|
||||
warning_border: yellow().dark().step_9(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn light() -> Self {
|
||||
Self {
|
||||
conflict: red().light().step_9(),
|
||||
conflict_background: red().light().step_9(),
|
||||
conflict_border: red().light().step_9(),
|
||||
created: grass().light().step_9(),
|
||||
created_background: grass().light().step_9(),
|
||||
created_border: grass().light().step_9(),
|
||||
deleted: red().light().step_9(),
|
||||
deleted_background: red().light().step_9(),
|
||||
deleted_border: red().light().step_9(),
|
||||
error: red().light().step_9(),
|
||||
error_background: red().light().step_9(),
|
||||
error_border: red().light().step_9(),
|
||||
hidden: neutral().light().step_9(),
|
||||
hidden_background: neutral().light().step_9(),
|
||||
hidden_border: neutral().light().step_9(),
|
||||
hint: blue().light().step_9(),
|
||||
hint_background: blue().light().step_9(),
|
||||
hint_border: blue().light().step_9(),
|
||||
ignored: neutral().light().step_9(),
|
||||
ignored_background: neutral().light().step_9(),
|
||||
ignored_border: neutral().light().step_9(),
|
||||
info: blue().light().step_9(),
|
||||
info_background: blue().light().step_9(),
|
||||
info_border: blue().light().step_9(),
|
||||
modified: yellow().light().step_9(),
|
||||
modified_background: yellow().light().step_9(),
|
||||
modified_border: yellow().light().step_9(),
|
||||
predictive: neutral().light_alpha().step_9(),
|
||||
predictive_background: neutral().light_alpha().step_9(),
|
||||
predictive_border: neutral().light_alpha().step_9(),
|
||||
renamed: blue().light().step_9(),
|
||||
renamed_background: blue().light().step_9(),
|
||||
renamed_border: blue().light().step_9(),
|
||||
success: grass().light().step_9(),
|
||||
success_background: grass().light().step_9(),
|
||||
success_border: grass().light().step_9(),
|
||||
unreachable: neutral().light().step_10(),
|
||||
unreachable_background: neutral().light().step_10(),
|
||||
unreachable_border: neutral().light().step_10(),
|
||||
warning: yellow().light().step_9(),
|
||||
warning_background: yellow().light().step_9(),
|
||||
warning_border: yellow().light().step_9(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn diagnostic(&self) -> DiagnosticColors {
|
||||
DiagnosticColors {
|
||||
error: self.error,
|
||||
warning: self.warning,
|
||||
info: self.info,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn git(&self) -> GitStatusColors {
|
||||
GitStatusColors {
|
||||
created: self.created,
|
||||
deleted: self.deleted,
|
||||
modified: self.modified,
|
||||
renamed: self.renamed,
|
||||
conflict: self.conflict,
|
||||
ignored: self.ignored,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
use gpui::prelude::*;
|
||||
use gpui::{div, px, ViewContext};
|
||||
use story::Story;
|
||||
|
||||
use crate::{default_color_scales, ColorScaleStep};
|
||||
|
||||
pub struct ColorsStory;
|
||||
|
||||
impl Render for ColorsStory {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let color_scales = default_color_scales();
|
||||
|
||||
Story::container().child(Story::title("Colors")).child(
|
||||
div()
|
||||
.id("colors")
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_1()
|
||||
.overflow_y_scroll()
|
||||
.text_color(gpui::white())
|
||||
.children(color_scales.into_iter().map(|scale| {
|
||||
div()
|
||||
.flex()
|
||||
.child(
|
||||
div()
|
||||
.w(px(75.))
|
||||
.line_height(px(24.))
|
||||
.child(scale.name().clone()),
|
||||
)
|
||||
.child(
|
||||
div().flex().gap_1().children(
|
||||
ColorScaleStep::ALL
|
||||
.map(|step| div().flex().size_6().bg(scale.step(cx, step))),
|
||||
),
|
||||
)
|
||||
})),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
mod color;
|
||||
mod players;
|
||||
|
||||
pub use color::*;
|
||||
pub use players::*;
|
||||
@@ -0,0 +1,145 @@
|
||||
use gpui::{div, img, px, IntoElement, ParentElement, Render, Styled, ViewContext};
|
||||
use story::Story;
|
||||
|
||||
use crate::{ActiveTheme, PlayerColors};
|
||||
|
||||
pub struct PlayerStory;
|
||||
|
||||
impl Render for PlayerStory {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
Story::container().child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_4()
|
||||
.child(Story::title_for::<PlayerColors>())
|
||||
.child(Story::label("Player Colors"))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_1()
|
||||
.child(
|
||||
div().flex().gap_1().children(
|
||||
cx.theme()
|
||||
.players()
|
||||
.0
|
||||
.clone()
|
||||
.iter_mut()
|
||||
.map(|player| div().w_8().h_8().rounded_md().bg(player.cursor)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div().flex().gap_1().children(
|
||||
cx.theme().players().0.clone().iter_mut().map(|player| {
|
||||
div().w_8().h_8().rounded_md().bg(player.background)
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div().flex().gap_1().children(
|
||||
cx.theme().players().0.clone().iter_mut().map(|player| {
|
||||
div().w_8().h_8().rounded_md().bg(player.selection)
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(Story::label("Avatar Rings"))
|
||||
.child(div().flex().gap_1().children(
|
||||
cx.theme().players().0.clone().iter_mut().map(|player| {
|
||||
div()
|
||||
.my_1()
|
||||
.rounded_full()
|
||||
.border_2()
|
||||
.border_color(player.cursor)
|
||||
.child(
|
||||
img("https://avatars.githubusercontent.com/u/1714999?v=4")
|
||||
.rounded_full()
|
||||
.size_6()
|
||||
.bg(gpui::red()),
|
||||
)
|
||||
}),
|
||||
))
|
||||
.child(Story::label("Player Backgrounds"))
|
||||
.child(div().flex().gap_1().children(
|
||||
cx.theme().players().0.clone().iter_mut().map(|player| {
|
||||
div()
|
||||
.my_1()
|
||||
.rounded_xl()
|
||||
.flex()
|
||||
.items_center()
|
||||
.h_8()
|
||||
.py_0p5()
|
||||
.px_1p5()
|
||||
.bg(player.background)
|
||||
.child(
|
||||
div()
|
||||
.relative()
|
||||
.neg_mx_1()
|
||||
.rounded_full()
|
||||
.z_index(3)
|
||||
.border_2()
|
||||
.border_color(player.background)
|
||||
.size(px(28.))
|
||||
.child(
|
||||
img("https://avatars.githubusercontent.com/u/1714999?v=4")
|
||||
.rounded_full()
|
||||
.size(px(24.))
|
||||
.bg(gpui::red()),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.relative()
|
||||
.neg_mx_1()
|
||||
.rounded_full()
|
||||
.z_index(2)
|
||||
.border_2()
|
||||
.border_color(player.background)
|
||||
.size(px(28.))
|
||||
.child(
|
||||
img("https://avatars.githubusercontent.com/u/1714999?v=4")
|
||||
.rounded_full()
|
||||
.size(px(24.))
|
||||
.bg(gpui::red()),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.relative()
|
||||
.neg_mx_1()
|
||||
.rounded_full()
|
||||
.z_index(1)
|
||||
.border_2()
|
||||
.border_color(player.background)
|
||||
.size(px(28.))
|
||||
.child(
|
||||
img("https://avatars.githubusercontent.com/u/1714999?v=4")
|
||||
.rounded_full()
|
||||
.size(px(24.))
|
||||
.bg(gpui::red()),
|
||||
),
|
||||
)
|
||||
}),
|
||||
))
|
||||
.child(Story::label("Player Selections"))
|
||||
.child(div().flex().flex_col().gap_px().children(
|
||||
cx.theme().players().0.clone().iter_mut().map(|player| {
|
||||
div()
|
||||
.flex()
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_none()
|
||||
.rounded_sm()
|
||||
.px_0p5()
|
||||
.text_color(cx.theme().colors().text)
|
||||
.bg(player.selection)
|
||||
.child("The brown fox jumped over the lazy dog."),
|
||||
)
|
||||
.child(div().flex_1())
|
||||
}),
|
||||
)),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
use gpui::{HighlightStyle, Hsla};
|
||||
|
||||
use crate::{
|
||||
blue, cyan, gold, indigo, iris, jade, lime, mint, neutral, orange, plum, purple, red, sky,
|
||||
tomato, yellow,
|
||||
};
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct SyntaxTheme {
|
||||
pub highlights: Vec<(String, HighlightStyle)>,
|
||||
}
|
||||
|
||||
impl SyntaxTheme {
|
||||
pub fn light() -> Self {
|
||||
Self {
|
||||
highlights: vec![
|
||||
("attribute".into(), cyan().light().step_11().into()),
|
||||
("boolean".into(), tomato().light().step_11().into()),
|
||||
("comment".into(), neutral().light().step_10().into()),
|
||||
("comment.doc".into(), iris().light().step_11().into()),
|
||||
("constant".into(), red().light().step_9().into()),
|
||||
("constructor".into(), red().light().step_9().into()),
|
||||
("embedded".into(), red().light().step_9().into()),
|
||||
("emphasis".into(), red().light().step_9().into()),
|
||||
("emphasis.strong".into(), red().light().step_9().into()),
|
||||
("enum".into(), red().light().step_9().into()),
|
||||
("function".into(), red().light().step_9().into()),
|
||||
("hint".into(), red().light().step_9().into()),
|
||||
("keyword".into(), orange().light().step_9().into()),
|
||||
("label".into(), red().light().step_9().into()),
|
||||
("link_text".into(), red().light().step_9().into()),
|
||||
("link_uri".into(), red().light().step_9().into()),
|
||||
("number".into(), purple().light().step_10().into()),
|
||||
("operator".into(), red().light().step_9().into()),
|
||||
("predictive".into(), red().light().step_9().into()),
|
||||
("preproc".into(), red().light().step_9().into()),
|
||||
("primary".into(), red().light().step_9().into()),
|
||||
("property".into(), red().light().step_9().into()),
|
||||
("punctuation".into(), neutral().light().step_11().into()),
|
||||
(
|
||||
"punctuation.bracket".into(),
|
||||
neutral().light().step_11().into(),
|
||||
),
|
||||
(
|
||||
"punctuation.delimiter".into(),
|
||||
neutral().light().step_10().into(),
|
||||
),
|
||||
(
|
||||
"punctuation.list_marker".into(),
|
||||
blue().light().step_11().into(),
|
||||
),
|
||||
("punctuation.special".into(), red().light().step_9().into()),
|
||||
("string".into(), jade().light().step_9().into()),
|
||||
("string.escape".into(), red().light().step_9().into()),
|
||||
("string.regex".into(), tomato().light().step_9().into()),
|
||||
("string.special".into(), red().light().step_9().into()),
|
||||
(
|
||||
"string.special.symbol".into(),
|
||||
red().light().step_9().into(),
|
||||
),
|
||||
("tag".into(), red().light().step_9().into()),
|
||||
("text.literal".into(), red().light().step_9().into()),
|
||||
("title".into(), red().light().step_9().into()),
|
||||
("type".into(), cyan().light().step_9().into()),
|
||||
("variable".into(), red().light().step_9().into()),
|
||||
("variable.special".into(), red().light().step_9().into()),
|
||||
("variant".into(), red().light().step_9().into()),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dark() -> Self {
|
||||
Self {
|
||||
highlights: vec![
|
||||
("attribute".into(), tomato().dark().step_11().into()),
|
||||
("boolean".into(), tomato().dark().step_11().into()),
|
||||
("comment".into(), neutral().dark().step_11().into()),
|
||||
("comment.doc".into(), iris().dark().step_12().into()),
|
||||
("constant".into(), orange().dark().step_11().into()),
|
||||
("constructor".into(), gold().dark().step_11().into()),
|
||||
("embedded".into(), red().dark().step_11().into()),
|
||||
("emphasis".into(), red().dark().step_11().into()),
|
||||
("emphasis.strong".into(), red().dark().step_11().into()),
|
||||
("enum".into(), yellow().dark().step_11().into()),
|
||||
("function".into(), blue().dark().step_11().into()),
|
||||
("hint".into(), indigo().dark().step_11().into()),
|
||||
("keyword".into(), plum().dark().step_11().into()),
|
||||
("label".into(), red().dark().step_11().into()),
|
||||
("link_text".into(), red().dark().step_11().into()),
|
||||
("link_uri".into(), red().dark().step_11().into()),
|
||||
("number".into(), red().dark().step_11().into()),
|
||||
("operator".into(), red().dark().step_11().into()),
|
||||
("predictive".into(), red().dark().step_11().into()),
|
||||
("preproc".into(), red().dark().step_11().into()),
|
||||
("primary".into(), red().dark().step_11().into()),
|
||||
("property".into(), red().dark().step_11().into()),
|
||||
("punctuation".into(), neutral().dark().step_11().into()),
|
||||
(
|
||||
"punctuation.bracket".into(),
|
||||
neutral().dark().step_11().into(),
|
||||
),
|
||||
(
|
||||
"punctuation.delimiter".into(),
|
||||
neutral().dark().step_11().into(),
|
||||
),
|
||||
(
|
||||
"punctuation.list_marker".into(),
|
||||
blue().dark().step_11().into(),
|
||||
),
|
||||
("punctuation.special".into(), red().dark().step_11().into()),
|
||||
("string".into(), lime().dark().step_11().into()),
|
||||
("string.escape".into(), orange().dark().step_11().into()),
|
||||
("string.regex".into(), tomato().dark().step_11().into()),
|
||||
("string.special".into(), red().dark().step_11().into()),
|
||||
(
|
||||
"string.special.symbol".into(),
|
||||
red().dark().step_11().into(),
|
||||
),
|
||||
("tag".into(), red().dark().step_11().into()),
|
||||
("text.literal".into(), purple().dark().step_11().into()),
|
||||
("title".into(), sky().dark().step_11().into()),
|
||||
("type".into(), mint().dark().step_11().into()),
|
||||
("variable".into(), red().dark().step_11().into()),
|
||||
("variable.special".into(), red().dark().step_11().into()),
|
||||
("variant".into(), red().dark().step_11().into()),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
// TOOD: Get this working with `#[cfg(test)]`. Why isn't it?
|
||||
pub fn new_test(colors: impl IntoIterator<Item = (&'static str, Hsla)>) -> Self {
|
||||
SyntaxTheme {
|
||||
highlights: colors
|
||||
.into_iter()
|
||||
.map(|(key, color)| {
|
||||
(
|
||||
key.to_owned(),
|
||||
HighlightStyle {
|
||||
color: Some(color),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, name: &str) -> HighlightStyle {
|
||||
self.highlights
|
||||
.iter()
|
||||
.find_map(|entry| if entry.0 == name { Some(entry.1) } else { None })
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn color(&self, name: &str) -> Hsla {
|
||||
self.get(name).color.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
use gpui::{hsla, Hsla};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SystemColors {
|
||||
pub transparent: Hsla,
|
||||
pub mac_os_traffic_light_red: Hsla,
|
||||
pub mac_os_traffic_light_yellow: Hsla,
|
||||
pub mac_os_traffic_light_green: Hsla,
|
||||
}
|
||||
|
||||
impl Default for SystemColors {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
transparent: hsla(0.0, 0.0, 0.0, 0.0),
|
||||
mac_os_traffic_light_red: hsla(0.0139, 0.79, 0.65, 1.0),
|
||||
mac_os_traffic_light_yellow: hsla(0.114, 0.88, 0.63, 1.0),
|
||||
mac_os_traffic_light_green: hsla(0.313, 0.49, 0.55, 1.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user