reworked style tree to use colorScheme instead of old theme. Very limited style for now
This commit is contained in:
parent
0c4c5f9238
commit
56f9543a95
53 changed files with 1017 additions and 1734 deletions
17
Cargo.lock
generated
17
Cargo.lock
generated
|
@ -814,22 +814,6 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chat_panel"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"client",
|
||||
"editor",
|
||||
"gpui",
|
||||
"menu",
|
||||
"postage",
|
||||
"settings",
|
||||
"theme",
|
||||
"time 0.3.11",
|
||||
"util",
|
||||
"workspace",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
|
@ -7138,7 +7122,6 @@ dependencies = [
|
|||
"auto_update",
|
||||
"backtrace",
|
||||
"breadcrumbs",
|
||||
"chat_panel",
|
||||
"chrono",
|
||||
"cli",
|
||||
"client",
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
[package]
|
||||
name = "chat_panel"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
path = "src/chat_panel.rs"
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
client = { path = "../client" }
|
||||
editor = { path = "../editor" }
|
||||
gpui = { path = "../gpui" }
|
||||
menu = { path = "../menu" }
|
||||
settings = { path = "../settings" }
|
||||
theme = { path = "../theme" }
|
||||
util = { path = "../util" }
|
||||
workspace = { path = "../workspace" }
|
||||
postage = { version = "0.4.1", features = ["futures-traits"] }
|
||||
time = { version = "0.3", features = ["serde", "serde-well-known"] }
|
|
@ -1,433 +0,0 @@
|
|||
use client::{
|
||||
channel::{Channel, ChannelEvent, ChannelList, ChannelMessage},
|
||||
Client,
|
||||
};
|
||||
use editor::Editor;
|
||||
use gpui::{
|
||||
actions,
|
||||
elements::*,
|
||||
platform::CursorStyle,
|
||||
views::{ItemType, Select, SelectStyle},
|
||||
AnyViewHandle, AppContext, Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext,
|
||||
Subscription, Task, View, ViewContext, ViewHandle,
|
||||
};
|
||||
use menu::Confirm;
|
||||
use postage::prelude::Stream;
|
||||
use settings::{Settings, SoftWrap};
|
||||
use std::sync::Arc;
|
||||
use time::{OffsetDateTime, UtcOffset};
|
||||
use util::{ResultExt, TryFutureExt};
|
||||
|
||||
const MESSAGE_LOADING_THRESHOLD: usize = 50;
|
||||
|
||||
pub struct ChatPanel {
|
||||
rpc: Arc<Client>,
|
||||
channel_list: ModelHandle<ChannelList>,
|
||||
active_channel: Option<(ModelHandle<Channel>, Subscription)>,
|
||||
message_list: ListState,
|
||||
input_editor: ViewHandle<Editor>,
|
||||
channel_select: ViewHandle<Select>,
|
||||
local_timezone: UtcOffset,
|
||||
_observe_status: Task<()>,
|
||||
}
|
||||
|
||||
pub enum Event {}
|
||||
|
||||
actions!(chat_panel, [LoadMoreMessages]);
|
||||
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
cx.add_action(ChatPanel::send);
|
||||
cx.add_action(ChatPanel::load_more_messages);
|
||||
}
|
||||
|
||||
impl ChatPanel {
|
||||
pub fn new(
|
||||
rpc: Arc<Client>,
|
||||
channel_list: ModelHandle<ChannelList>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let input_editor = cx.add_view(|cx| {
|
||||
let mut editor =
|
||||
Editor::auto_height(4, Some(|theme| theme.chat_panel.input_editor.clone()), cx);
|
||||
editor.set_soft_wrap_mode(SoftWrap::EditorWidth, cx);
|
||||
editor
|
||||
});
|
||||
let channel_select = cx.add_view(|cx| {
|
||||
let channel_list = channel_list.clone();
|
||||
Select::new(0, cx, {
|
||||
move |ix, item_type, is_hovered, cx| {
|
||||
Self::render_channel_name(
|
||||
&channel_list,
|
||||
ix,
|
||||
item_type,
|
||||
is_hovered,
|
||||
&cx.global::<Settings>().theme.chat_panel.channel_select,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
})
|
||||
.with_style(move |cx| {
|
||||
let theme = &cx.global::<Settings>().theme.chat_panel.channel_select;
|
||||
SelectStyle {
|
||||
header: theme.header.container,
|
||||
menu: theme.menu,
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
let mut message_list = ListState::new(0, Orientation::Bottom, 1000., cx, {
|
||||
let this = cx.weak_handle();
|
||||
move |_, ix, cx| {
|
||||
let this = this.upgrade(cx).unwrap().read(cx);
|
||||
let message = this.active_channel.as_ref().unwrap().0.read(cx).message(ix);
|
||||
this.render_message(message, cx)
|
||||
}
|
||||
});
|
||||
message_list.set_scroll_handler(|visible_range, cx| {
|
||||
if visible_range.start < MESSAGE_LOADING_THRESHOLD {
|
||||
cx.dispatch_action(LoadMoreMessages);
|
||||
}
|
||||
});
|
||||
let _observe_status = cx.spawn_weak(|this, mut cx| {
|
||||
let mut status = rpc.status();
|
||||
async move {
|
||||
while (status.recv().await).is_some() {
|
||||
if let Some(this) = this.upgrade(&cx) {
|
||||
this.update(&mut cx, |_, cx| cx.notify());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let mut this = Self {
|
||||
rpc,
|
||||
channel_list,
|
||||
active_channel: Default::default(),
|
||||
message_list,
|
||||
input_editor,
|
||||
channel_select,
|
||||
local_timezone: cx.platform().local_timezone(),
|
||||
_observe_status,
|
||||
};
|
||||
|
||||
this.init_active_channel(cx);
|
||||
cx.observe(&this.channel_list, |this, _, cx| {
|
||||
this.init_active_channel(cx);
|
||||
})
|
||||
.detach();
|
||||
cx.observe(&this.channel_select, |this, channel_select, cx| {
|
||||
let selected_ix = channel_select.read(cx).selected_index();
|
||||
let selected_channel = this.channel_list.update(cx, |channel_list, cx| {
|
||||
let available_channels = channel_list.available_channels()?;
|
||||
let channel_id = available_channels.get(selected_ix)?.id;
|
||||
channel_list.get_channel(channel_id, cx)
|
||||
});
|
||||
if let Some(selected_channel) = selected_channel {
|
||||
this.set_active_channel(selected_channel, cx);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
fn init_active_channel(&mut self, cx: &mut ViewContext<Self>) {
|
||||
let (active_channel, channel_count) = self.channel_list.update(cx, |list, cx| {
|
||||
let channel_count;
|
||||
let mut active_channel = None;
|
||||
|
||||
if let Some(available_channels) = list.available_channels() {
|
||||
channel_count = available_channels.len();
|
||||
if self.active_channel.is_none() {
|
||||
if let Some(channel_id) = available_channels.first().map(|channel| channel.id) {
|
||||
active_channel = list.get_channel(channel_id, cx);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel_count = 0;
|
||||
}
|
||||
|
||||
(active_channel, channel_count)
|
||||
});
|
||||
|
||||
if let Some(active_channel) = active_channel {
|
||||
self.set_active_channel(active_channel, cx);
|
||||
} else {
|
||||
self.message_list.reset(0);
|
||||
self.active_channel = None;
|
||||
}
|
||||
|
||||
self.channel_select.update(cx, |select, cx| {
|
||||
select.set_item_count(channel_count, cx);
|
||||
});
|
||||
}
|
||||
|
||||
fn set_active_channel(&mut self, channel: ModelHandle<Channel>, cx: &mut ViewContext<Self>) {
|
||||
if self.active_channel.as_ref().map(|e| &e.0) != Some(&channel) {
|
||||
{
|
||||
let channel = channel.read(cx);
|
||||
self.message_list.reset(channel.message_count());
|
||||
let placeholder = format!("Message #{}", channel.name());
|
||||
self.input_editor.update(cx, move |editor, cx| {
|
||||
editor.set_placeholder_text(placeholder, cx);
|
||||
});
|
||||
}
|
||||
let subscription = cx.subscribe(&channel, Self::channel_did_change);
|
||||
self.active_channel = Some((channel, subscription));
|
||||
}
|
||||
}
|
||||
|
||||
fn channel_did_change(
|
||||
&mut self,
|
||||
_: ModelHandle<Channel>,
|
||||
event: &ChannelEvent,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
match event {
|
||||
ChannelEvent::MessagesUpdated {
|
||||
old_range,
|
||||
new_count,
|
||||
} => {
|
||||
self.message_list.splice(old_range.clone(), *new_count);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn render_channel(&self, cx: &mut RenderContext<Self>) -> ElementBox {
|
||||
let theme = &cx.global::<Settings>().theme;
|
||||
Flex::column()
|
||||
.with_child(
|
||||
Container::new(ChildView::new(&self.channel_select).boxed())
|
||||
.with_style(theme.chat_panel.channel_select.container)
|
||||
.boxed(),
|
||||
)
|
||||
.with_child(self.render_active_channel_messages())
|
||||
.with_child(self.render_input_box(cx))
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn render_active_channel_messages(&self) -> ElementBox {
|
||||
let messages = if self.active_channel.is_some() {
|
||||
List::new(self.message_list.clone()).boxed()
|
||||
} else {
|
||||
Empty::new().boxed()
|
||||
};
|
||||
|
||||
FlexItem::new(messages).flex(1., true).boxed()
|
||||
}
|
||||
|
||||
fn render_message(&self, message: &ChannelMessage, cx: &AppContext) -> ElementBox {
|
||||
let now = OffsetDateTime::now_utc();
|
||||
let settings = cx.global::<Settings>();
|
||||
let theme = if message.is_pending() {
|
||||
&settings.theme.chat_panel.pending_message
|
||||
} else {
|
||||
&settings.theme.chat_panel.message
|
||||
};
|
||||
|
||||
Container::new(
|
||||
Flex::column()
|
||||
.with_child(
|
||||
Flex::row()
|
||||
.with_child(
|
||||
Container::new(
|
||||
Label::new(
|
||||
message.sender.github_login.clone(),
|
||||
theme.sender.text.clone(),
|
||||
)
|
||||
.boxed(),
|
||||
)
|
||||
.with_style(theme.sender.container)
|
||||
.boxed(),
|
||||
)
|
||||
.with_child(
|
||||
Container::new(
|
||||
Label::new(
|
||||
format_timestamp(message.timestamp, now, self.local_timezone),
|
||||
theme.timestamp.text.clone(),
|
||||
)
|
||||
.boxed(),
|
||||
)
|
||||
.with_style(theme.timestamp.container)
|
||||
.boxed(),
|
||||
)
|
||||
.boxed(),
|
||||
)
|
||||
.with_child(Text::new(message.body.clone(), theme.body.clone()).boxed())
|
||||
.boxed(),
|
||||
)
|
||||
.with_style(theme.container)
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn render_input_box(&self, cx: &AppContext) -> ElementBox {
|
||||
let theme = &cx.global::<Settings>().theme;
|
||||
Container::new(ChildView::new(&self.input_editor).boxed())
|
||||
.with_style(theme.chat_panel.input_editor.container)
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn render_channel_name(
|
||||
channel_list: &ModelHandle<ChannelList>,
|
||||
ix: usize,
|
||||
item_type: ItemType,
|
||||
is_hovered: bool,
|
||||
theme: &theme::ChannelSelect,
|
||||
cx: &AppContext,
|
||||
) -> ElementBox {
|
||||
let channel = &channel_list.read(cx).available_channels().unwrap()[ix];
|
||||
let theme = match (item_type, is_hovered) {
|
||||
(ItemType::Header, _) => &theme.header,
|
||||
(ItemType::Selected, false) => &theme.active_item,
|
||||
(ItemType::Selected, true) => &theme.hovered_active_item,
|
||||
(ItemType::Unselected, false) => &theme.item,
|
||||
(ItemType::Unselected, true) => &theme.hovered_item,
|
||||
};
|
||||
Container::new(
|
||||
Flex::row()
|
||||
.with_child(
|
||||
Container::new(Label::new("#".to_string(), theme.hash.text.clone()).boxed())
|
||||
.with_style(theme.hash.container)
|
||||
.boxed(),
|
||||
)
|
||||
.with_child(Label::new(channel.name.clone(), theme.name.clone()).boxed())
|
||||
.boxed(),
|
||||
)
|
||||
.with_style(theme.container)
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn render_sign_in_prompt(&self, cx: &mut RenderContext<Self>) -> ElementBox {
|
||||
let theme = cx.global::<Settings>().theme.clone();
|
||||
let rpc = self.rpc.clone();
|
||||
let this = cx.handle();
|
||||
|
||||
enum SignInPromptLabel {}
|
||||
|
||||
Align::new(
|
||||
MouseEventHandler::<SignInPromptLabel>::new(0, cx, |mouse_state, _| {
|
||||
Label::new(
|
||||
"Sign in to use chat".to_string(),
|
||||
if mouse_state.hovered {
|
||||
theme.chat_panel.hovered_sign_in_prompt.clone()
|
||||
} else {
|
||||
theme.chat_panel.sign_in_prompt.clone()
|
||||
},
|
||||
)
|
||||
.boxed()
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(MouseButton::Left, move |_, cx| {
|
||||
let rpc = rpc.clone();
|
||||
let this = this.clone();
|
||||
cx.spawn(|mut cx| async move {
|
||||
if rpc
|
||||
.authenticate_and_connect(true, &cx)
|
||||
.log_err()
|
||||
.await
|
||||
.is_some()
|
||||
{
|
||||
cx.update(|cx| {
|
||||
if let Some(this) = this.upgrade(cx) {
|
||||
if this.is_focused(cx) {
|
||||
this.update(cx, |this, cx| cx.focus(&this.input_editor));
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
})
|
||||
.boxed(),
|
||||
)
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn send(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
|
||||
if let Some((channel, _)) = self.active_channel.as_ref() {
|
||||
let body = self.input_editor.update(cx, |editor, cx| {
|
||||
let body = editor.text(cx);
|
||||
editor.clear(cx);
|
||||
body
|
||||
});
|
||||
|
||||
if let Some(task) = channel
|
||||
.update(cx, |channel, cx| channel.send_message(body, cx))
|
||||
.log_err()
|
||||
{
|
||||
task.detach();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn load_more_messages(&mut self, _: &LoadMoreMessages, cx: &mut ViewContext<Self>) {
|
||||
if let Some((channel, _)) = self.active_channel.as_ref() {
|
||||
channel.update(cx, |channel, cx| {
|
||||
channel.load_more_messages(cx);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Entity for ChatPanel {
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
impl View for ChatPanel {
|
||||
fn ui_name() -> &'static str {
|
||||
"ChatPanel"
|
||||
}
|
||||
|
||||
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
|
||||
let element = if self.rpc.user_id().is_some() {
|
||||
self.render_channel(cx)
|
||||
} else {
|
||||
self.render_sign_in_prompt(cx)
|
||||
};
|
||||
let theme = &cx.global::<Settings>().theme;
|
||||
ConstrainedBox::new(
|
||||
Container::new(element)
|
||||
.with_style(theme.chat_panel.container)
|
||||
.boxed(),
|
||||
)
|
||||
.with_min_width(150.)
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
if matches!(
|
||||
*self.rpc.status().borrow(),
|
||||
client::Status::Connected { .. }
|
||||
) {
|
||||
cx.focus(&self.input_editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn format_timestamp(
|
||||
mut timestamp: OffsetDateTime,
|
||||
mut now: OffsetDateTime,
|
||||
local_timezone: UtcOffset,
|
||||
) -> String {
|
||||
timestamp = timestamp.to_offset(local_timezone);
|
||||
now = now.to_offset(local_timezone);
|
||||
|
||||
let today = now.date();
|
||||
let date = timestamp.date();
|
||||
let mut hour = timestamp.hour();
|
||||
let mut part = "am";
|
||||
if hour > 12 {
|
||||
hour -= 12;
|
||||
part = "pm";
|
||||
}
|
||||
if date == today {
|
||||
format!("{:02}:{:02}{}", hour, timestamp.minute(), part)
|
||||
} else if date.next_day() == Some(today) {
|
||||
format!("yesterday at {:02}:{:02}{}", hour, timestamp.minute(), part)
|
||||
} else {
|
||||
format!("{:02}/{}/{}", date.month() as u32, date.day(), date.year())
|
||||
}
|
||||
}
|
|
@ -1,77 +1,71 @@
|
|||
use alacritty_terminal::{ansi::Color as AnsiColor, term::color::Rgb as AlacRgb};
|
||||
use gpui::color::Color;
|
||||
use theme::TerminalColors;
|
||||
use theme::TerminalStyle;
|
||||
|
||||
///Converts a 2, 8, or 24 bit color ANSI color to the GPUI equivalent
|
||||
pub fn convert_color(alac_color: &AnsiColor, colors: &TerminalColors, modal: bool) -> Color {
|
||||
let background = if modal {
|
||||
colors.modal_background
|
||||
} else {
|
||||
colors.background
|
||||
};
|
||||
|
||||
pub fn convert_color(alac_color: &AnsiColor, style: &TerminalStyle) -> Color {
|
||||
match alac_color {
|
||||
//Named and theme defined colors
|
||||
alacritty_terminal::ansi::Color::Named(n) => match n {
|
||||
alacritty_terminal::ansi::NamedColor::Black => colors.black,
|
||||
alacritty_terminal::ansi::NamedColor::Red => colors.red,
|
||||
alacritty_terminal::ansi::NamedColor::Green => colors.green,
|
||||
alacritty_terminal::ansi::NamedColor::Yellow => colors.yellow,
|
||||
alacritty_terminal::ansi::NamedColor::Blue => colors.blue,
|
||||
alacritty_terminal::ansi::NamedColor::Magenta => colors.magenta,
|
||||
alacritty_terminal::ansi::NamedColor::Cyan => colors.cyan,
|
||||
alacritty_terminal::ansi::NamedColor::White => colors.white,
|
||||
alacritty_terminal::ansi::NamedColor::BrightBlack => colors.bright_black,
|
||||
alacritty_terminal::ansi::NamedColor::BrightRed => colors.bright_red,
|
||||
alacritty_terminal::ansi::NamedColor::BrightGreen => colors.bright_green,
|
||||
alacritty_terminal::ansi::NamedColor::BrightYellow => colors.bright_yellow,
|
||||
alacritty_terminal::ansi::NamedColor::BrightBlue => colors.bright_blue,
|
||||
alacritty_terminal::ansi::NamedColor::BrightMagenta => colors.bright_magenta,
|
||||
alacritty_terminal::ansi::NamedColor::BrightCyan => colors.bright_cyan,
|
||||
alacritty_terminal::ansi::NamedColor::BrightWhite => colors.bright_white,
|
||||
alacritty_terminal::ansi::NamedColor::Foreground => colors.foreground,
|
||||
alacritty_terminal::ansi::NamedColor::Background => background,
|
||||
alacritty_terminal::ansi::NamedColor::Cursor => colors.cursor,
|
||||
alacritty_terminal::ansi::NamedColor::DimBlack => colors.dim_black,
|
||||
alacritty_terminal::ansi::NamedColor::DimRed => colors.dim_red,
|
||||
alacritty_terminal::ansi::NamedColor::DimGreen => colors.dim_green,
|
||||
alacritty_terminal::ansi::NamedColor::DimYellow => colors.dim_yellow,
|
||||
alacritty_terminal::ansi::NamedColor::DimBlue => colors.dim_blue,
|
||||
alacritty_terminal::ansi::NamedColor::DimMagenta => colors.dim_magenta,
|
||||
alacritty_terminal::ansi::NamedColor::DimCyan => colors.dim_cyan,
|
||||
alacritty_terminal::ansi::NamedColor::DimWhite => colors.dim_white,
|
||||
alacritty_terminal::ansi::NamedColor::BrightForeground => colors.bright_foreground,
|
||||
alacritty_terminal::ansi::NamedColor::DimForeground => colors.dim_foreground,
|
||||
alacritty_terminal::ansi::NamedColor::Black => style.black,
|
||||
alacritty_terminal::ansi::NamedColor::Red => style.red,
|
||||
alacritty_terminal::ansi::NamedColor::Green => style.green,
|
||||
alacritty_terminal::ansi::NamedColor::Yellow => style.yellow,
|
||||
alacritty_terminal::ansi::NamedColor::Blue => style.blue,
|
||||
alacritty_terminal::ansi::NamedColor::Magenta => style.magenta,
|
||||
alacritty_terminal::ansi::NamedColor::Cyan => style.cyan,
|
||||
alacritty_terminal::ansi::NamedColor::White => style.white,
|
||||
alacritty_terminal::ansi::NamedColor::BrightBlack => style.bright_black,
|
||||
alacritty_terminal::ansi::NamedColor::BrightRed => style.bright_red,
|
||||
alacritty_terminal::ansi::NamedColor::BrightGreen => style.bright_green,
|
||||
alacritty_terminal::ansi::NamedColor::BrightYellow => style.bright_yellow,
|
||||
alacritty_terminal::ansi::NamedColor::BrightBlue => style.bright_blue,
|
||||
alacritty_terminal::ansi::NamedColor::BrightMagenta => style.bright_magenta,
|
||||
alacritty_terminal::ansi::NamedColor::BrightCyan => style.bright_cyan,
|
||||
alacritty_terminal::ansi::NamedColor::BrightWhite => style.bright_white,
|
||||
alacritty_terminal::ansi::NamedColor::Foreground => style.foreground,
|
||||
alacritty_terminal::ansi::NamedColor::Background => style.background,
|
||||
alacritty_terminal::ansi::NamedColor::Cursor => style.cursor,
|
||||
alacritty_terminal::ansi::NamedColor::DimBlack => style.dim_black,
|
||||
alacritty_terminal::ansi::NamedColor::DimRed => style.dim_red,
|
||||
alacritty_terminal::ansi::NamedColor::DimGreen => style.dim_green,
|
||||
alacritty_terminal::ansi::NamedColor::DimYellow => style.dim_yellow,
|
||||
alacritty_terminal::ansi::NamedColor::DimBlue => style.dim_blue,
|
||||
alacritty_terminal::ansi::NamedColor::DimMagenta => style.dim_magenta,
|
||||
alacritty_terminal::ansi::NamedColor::DimCyan => style.dim_cyan,
|
||||
alacritty_terminal::ansi::NamedColor::DimWhite => style.dim_white,
|
||||
alacritty_terminal::ansi::NamedColor::BrightForeground => style.bright_foreground,
|
||||
alacritty_terminal::ansi::NamedColor::DimForeground => style.dim_foreground,
|
||||
},
|
||||
//'True' colors
|
||||
alacritty_terminal::ansi::Color::Spec(rgb) => Color::new(rgb.r, rgb.g, rgb.b, u8::MAX),
|
||||
//8 bit, indexed colors
|
||||
alacritty_terminal::ansi::Color::Indexed(i) => get_color_at_index(&(*i as usize), colors),
|
||||
alacritty_terminal::ansi::Color::Indexed(i) => get_color_at_index(&(*i as usize), style),
|
||||
}
|
||||
}
|
||||
|
||||
///Converts an 8 bit ANSI color to it's GPUI equivalent.
|
||||
///Accepts usize for compatability with the alacritty::Colors interface,
|
||||
///Other than that use case, should only be called with values in the [0,255] range
|
||||
pub fn get_color_at_index(index: &usize, colors: &TerminalColors) -> Color {
|
||||
pub fn get_color_at_index(index: &usize, style: &TerminalStyle) -> Color {
|
||||
match index {
|
||||
//0-15 are the same as the named colors above
|
||||
0 => colors.black,
|
||||
1 => colors.red,
|
||||
2 => colors.green,
|
||||
3 => colors.yellow,
|
||||
4 => colors.blue,
|
||||
5 => colors.magenta,
|
||||
6 => colors.cyan,
|
||||
7 => colors.white,
|
||||
8 => colors.bright_black,
|
||||
9 => colors.bright_red,
|
||||
10 => colors.bright_green,
|
||||
11 => colors.bright_yellow,
|
||||
12 => colors.bright_blue,
|
||||
13 => colors.bright_magenta,
|
||||
14 => colors.bright_cyan,
|
||||
15 => colors.bright_white,
|
||||
0 => style.black,
|
||||
1 => style.red,
|
||||
2 => style.green,
|
||||
3 => style.yellow,
|
||||
4 => style.blue,
|
||||
5 => style.magenta,
|
||||
6 => style.cyan,
|
||||
7 => style.white,
|
||||
8 => style.bright_black,
|
||||
9 => style.bright_red,
|
||||
10 => style.bright_green,
|
||||
11 => style.bright_yellow,
|
||||
12 => style.bright_blue,
|
||||
13 => style.bright_magenta,
|
||||
14 => style.bright_cyan,
|
||||
15 => style.bright_white,
|
||||
//16-231 are mapped to their RGB colors on a 0-5 range per channel
|
||||
16..=231 => {
|
||||
let (r, g, b) = rgb_for_index(&(*index as u8)); //Split the index into it's ANSI-RGB components
|
||||
|
@ -85,19 +79,19 @@ pub fn get_color_at_index(index: &usize, colors: &TerminalColors) -> Color {
|
|||
Color::new(i * step, i * step, i * step, u8::MAX) //Map the ANSI-grayscale components to the RGB-grayscale
|
||||
}
|
||||
//For compatability with the alacritty::Colors interface
|
||||
256 => colors.foreground,
|
||||
257 => colors.background,
|
||||
258 => colors.cursor,
|
||||
259 => colors.dim_black,
|
||||
260 => colors.dim_red,
|
||||
261 => colors.dim_green,
|
||||
262 => colors.dim_yellow,
|
||||
263 => colors.dim_blue,
|
||||
264 => colors.dim_magenta,
|
||||
265 => colors.dim_cyan,
|
||||
266 => colors.dim_white,
|
||||
267 => colors.bright_foreground,
|
||||
268 => colors.black, //'Dim Background', non-standard color
|
||||
256 => style.foreground,
|
||||
257 => style.background,
|
||||
258 => style.cursor,
|
||||
259 => style.dim_black,
|
||||
260 => style.dim_red,
|
||||
261 => style.dim_green,
|
||||
262 => style.dim_yellow,
|
||||
263 => style.dim_blue,
|
||||
264 => style.dim_magenta,
|
||||
265 => style.dim_cyan,
|
||||
266 => style.dim_white,
|
||||
267 => style.bright_foreground,
|
||||
268 => style.black, //'Dim Background', non-standard color
|
||||
_ => Color::new(0, 0, 0, 255),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -569,7 +569,7 @@ impl Terminal {
|
|||
InternalEvent::ColorRequest(index, format) => {
|
||||
let color = term.colors()[*index].unwrap_or_else(|| {
|
||||
let term_style = &cx.global::<Settings>().theme.terminal;
|
||||
to_alac_rgb(get_color_at_index(index, &term_style.colors))
|
||||
to_alac_rgb(get_color_at_index(index, &term_style))
|
||||
});
|
||||
self.write_to_pty(format(color))
|
||||
}
|
||||
|
|
|
@ -165,18 +165,12 @@ impl View for TerminalContainer {
|
|||
"Terminal"
|
||||
}
|
||||
|
||||
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox {
|
||||
let child_view = match &self.content {
|
||||
fn render(&mut self, _cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox {
|
||||
match &self.content {
|
||||
TerminalContainerContent::Connected(connected) => ChildView::new(connected),
|
||||
TerminalContainerContent::Error(error) => ChildView::new(error),
|
||||
};
|
||||
if self.modal {
|
||||
let settings = cx.global::<Settings>();
|
||||
let container_style = settings.theme.terminal.modal_container;
|
||||
child_view.contained().with_style(container_style).boxed()
|
||||
} else {
|
||||
child_view.boxed()
|
||||
}
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
|
|
|
@ -149,7 +149,6 @@ impl LayoutRect {
|
|||
pub struct TerminalElement {
|
||||
terminal: WeakModelHandle<Terminal>,
|
||||
view: WeakViewHandle<TerminalView>,
|
||||
modal: bool,
|
||||
focused: bool,
|
||||
cursor_visible: bool,
|
||||
}
|
||||
|
@ -158,14 +157,12 @@ impl TerminalElement {
|
|||
pub fn new(
|
||||
view: WeakViewHandle<TerminalView>,
|
||||
terminal: WeakModelHandle<Terminal>,
|
||||
modal: bool,
|
||||
focused: bool,
|
||||
cursor_visible: bool,
|
||||
) -> TerminalElement {
|
||||
TerminalElement {
|
||||
view,
|
||||
terminal,
|
||||
modal,
|
||||
focused,
|
||||
cursor_visible,
|
||||
}
|
||||
|
@ -179,7 +176,6 @@ impl TerminalElement {
|
|||
terminal_theme: &TerminalStyle,
|
||||
text_layout_cache: &TextLayoutCache,
|
||||
font_cache: &FontCache,
|
||||
modal: bool,
|
||||
) -> (Vec<LayoutCell>, Vec<LayoutRect>) {
|
||||
let mut cells = vec![];
|
||||
let mut rects = vec![];
|
||||
|
@ -218,7 +214,7 @@ impl TerminalElement {
|
|||
cur_rect = Some(LayoutRect::new(
|
||||
Point::new(line_index as i32, cell.point.column.0 as i32),
|
||||
1,
|
||||
convert_color(&bg, &terminal_theme.colors, modal),
|
||||
convert_color(&bg, &terminal_theme),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -227,7 +223,7 @@ impl TerminalElement {
|
|||
cur_rect = Some(LayoutRect::new(
|
||||
Point::new(line_index as i32, cell.point.column.0 as i32),
|
||||
1,
|
||||
convert_color(&bg, &terminal_theme.colors, modal),
|
||||
convert_color(&bg, &terminal_theme),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -244,7 +240,6 @@ impl TerminalElement {
|
|||
terminal_theme,
|
||||
text_style,
|
||||
font_cache,
|
||||
modal,
|
||||
);
|
||||
|
||||
let layout_cell = text_layout_cache.layout_str(
|
||||
|
@ -303,10 +298,9 @@ impl TerminalElement {
|
|||
style: &TerminalStyle,
|
||||
text_style: &TextStyle,
|
||||
font_cache: &FontCache,
|
||||
modal: bool,
|
||||
) -> RunStyle {
|
||||
let flags = indexed.cell.flags;
|
||||
let fg = convert_color(&fg, &style.colors, modal);
|
||||
let fg = convert_color(&fg, &style);
|
||||
|
||||
let underline = flags
|
||||
.intersects(Flags::ALL_UNDERLINES)
|
||||
|
@ -562,11 +556,7 @@ impl Element for TerminalElement {
|
|||
Default::default()
|
||||
};
|
||||
|
||||
let background_color = if self.modal {
|
||||
terminal_theme.colors.modal_background
|
||||
} else {
|
||||
terminal_theme.colors.background
|
||||
};
|
||||
let background_color = terminal_theme.background;
|
||||
let terminal_handle = self.terminal.upgrade(cx).unwrap();
|
||||
|
||||
terminal_handle.update(cx.app, |terminal, cx| {
|
||||
|
@ -601,7 +591,6 @@ impl Element for TerminalElement {
|
|||
&terminal_theme,
|
||||
cx.text_layout_cache,
|
||||
cx.font_cache(),
|
||||
self.modal,
|
||||
);
|
||||
|
||||
//Layout cursor. Rectangle is used for IME, so we should lay it out even
|
||||
|
@ -614,9 +603,9 @@ impl Element for TerminalElement {
|
|||
let str_trxt = cursor_char.to_string();
|
||||
|
||||
let color = if self.focused {
|
||||
terminal_theme.colors.background
|
||||
terminal_theme.background
|
||||
} else {
|
||||
terminal_theme.colors.foreground
|
||||
terminal_theme.foreground
|
||||
};
|
||||
|
||||
cx.text_layout_cache.layout_str(
|
||||
|
@ -649,7 +638,7 @@ impl Element for TerminalElement {
|
|||
cursor_position,
|
||||
block_width,
|
||||
dimensions.line_height,
|
||||
terminal_theme.colors.cursor,
|
||||
terminal_theme.cursor,
|
||||
shape,
|
||||
Some(cursor_text),
|
||||
)
|
||||
|
|
|
@ -343,7 +343,6 @@ impl View for TerminalView {
|
|||
TerminalElement::new(
|
||||
cx.handle(),
|
||||
terminal_handle,
|
||||
self.modal,
|
||||
focused,
|
||||
self.should_show_cursor(focused, cx),
|
||||
)
|
||||
|
|
|
@ -18,7 +18,6 @@ pub struct Theme {
|
|||
pub meta: ThemeMeta,
|
||||
pub workspace: Workspace,
|
||||
pub context_menu: ContextMenu,
|
||||
pub chat_panel: ChatPanel,
|
||||
pub contacts_popover: ContactsPopover,
|
||||
pub contacts_panel: ContactsPanel,
|
||||
pub contact_finder: ContactFinder,
|
||||
|
@ -256,18 +255,6 @@ pub struct SidebarItem {
|
|||
pub icon_size: f32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default)]
|
||||
pub struct ChatPanel {
|
||||
#[serde(flatten)]
|
||||
pub container: ContainerStyle,
|
||||
pub message: ChatMessage,
|
||||
pub pending_message: ChatMessage,
|
||||
pub channel_select: ChannelSelect,
|
||||
pub input_editor: FieldEditor,
|
||||
pub sign_in_prompt: TextStyle,
|
||||
pub hovered_sign_in_prompt: TextStyle,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default)]
|
||||
pub struct ProjectPanel {
|
||||
#[serde(flatten)]
|
||||
|
@ -710,12 +697,6 @@ pub struct HoverPopover {
|
|||
|
||||
#[derive(Clone, Deserialize, Default)]
|
||||
pub struct TerminalStyle {
|
||||
pub colors: TerminalColors,
|
||||
pub modal_container: ContainerStyle,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Default)]
|
||||
pub struct TerminalColors {
|
||||
pub black: Color,
|
||||
pub red: Color,
|
||||
pub green: Color,
|
||||
|
|
|
@ -19,7 +19,6 @@ activity_indicator = { path = "../activity_indicator" }
|
|||
assets = { path = "../assets" }
|
||||
auto_update = { path = "../auto_update" }
|
||||
breadcrumbs = { path = "../breadcrumbs" }
|
||||
chat_panel = { path = "../chat_panel" }
|
||||
cli = { path = "../cli" }
|
||||
collections = { path = "../collections" }
|
||||
command_palette = { path = "../command_palette" }
|
||||
|
|
|
@ -111,7 +111,6 @@ fn main() {
|
|||
editor::init(cx);
|
||||
go_to_line::init(cx);
|
||||
file_finder::init(cx);
|
||||
chat_panel::init(cx);
|
||||
contacts_panel::init(cx);
|
||||
outline::init(cx);
|
||||
project_symbols::init(cx);
|
||||
|
|
|
@ -2,9 +2,9 @@ import * as fs from "fs";
|
|||
import * as path from "path";
|
||||
import { tmpdir } from "os";
|
||||
import app from "./styleTree/app";
|
||||
import themes, { internalThemes, experimentalThemes } from "./themes";
|
||||
import colorSchemes, { internalColorSchemes, experimentalColorSchemes } from "./colorSchemes";
|
||||
import snakeCase from "./utils/snakeCase";
|
||||
import Theme from "./themes/common/theme";
|
||||
import { ColorScheme } from "./themes/common/colorScheme";
|
||||
|
||||
const themeDirectory = `${__dirname}/../../assets/themes`;
|
||||
const internalDirectory = `${themeDirectory}/internal`;
|
||||
|
@ -16,7 +16,7 @@ function clearThemes(themeDirectory: string) {
|
|||
for (const file of fs.readdirSync(themeDirectory)) {
|
||||
if (file.endsWith(".json")) {
|
||||
const name = file.replace(/\.json$/, "");
|
||||
if (!themes.find((theme) => theme.name === name)) {
|
||||
if (!colorSchemes.find((colorScheme) => colorScheme.name === name)) {
|
||||
fs.unlinkSync(path.join(themeDirectory, file));
|
||||
}
|
||||
}
|
||||
|
@ -27,12 +27,12 @@ clearThemes(themeDirectory);
|
|||
clearThemes(internalDirectory);
|
||||
clearThemes(experimentsDirectory);
|
||||
|
||||
function writeThemes(themes: Theme[], outputDirectory: string) {
|
||||
for (let theme of themes) {
|
||||
let styleTree = snakeCase(app(theme));
|
||||
function writeThemes(colorSchemes: ColorScheme[], outputDirectory: string) {
|
||||
for (let colorScheme of colorSchemes) {
|
||||
let styleTree = snakeCase(app(colorScheme));
|
||||
let styleTreeJSON = JSON.stringify(styleTree, null, 2);
|
||||
let tempPath = path.join(tempDirectory, `${theme.name}.json`);
|
||||
let outPath = path.join(outputDirectory, `${theme.name}.json`);
|
||||
let tempPath = path.join(tempDirectory, `${colorScheme.name}.json`);
|
||||
let outPath = path.join(outputDirectory, `${colorScheme.name}.json`);
|
||||
fs.writeFileSync(tempPath, styleTreeJSON);
|
||||
fs.renameSync(tempPath, outPath);
|
||||
console.log(`- ${outPath} created`);
|
||||
|
@ -40,6 +40,6 @@ function writeThemes(themes: Theme[], outputDirectory: string) {
|
|||
}
|
||||
|
||||
// Write new themes to theme directory
|
||||
writeThemes(themes, themeDirectory);
|
||||
writeThemes(internalThemes, internalDirectory);
|
||||
writeThemes(experimentalThemes, experimentsDirectory);
|
||||
writeThemes(colorSchemes, themeDirectory);
|
||||
writeThemes(internalColorSchemes, internalDirectory);
|
||||
writeThemes(experimentalColorSchemes, experimentsDirectory);
|
||||
|
|
31
styles/src/colorSchemes.ts
Normal file
31
styles/src/colorSchemes.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { ColorScheme } from "./themes/common/colorScheme";
|
||||
|
||||
const colorSchemes: ColorScheme[] = [];
|
||||
export default colorSchemes;
|
||||
|
||||
const internalColorSchemes: ColorScheme[] = [];
|
||||
export { internalColorSchemes }
|
||||
|
||||
const experimentalColorSchemes: ColorScheme[] = [];
|
||||
export { experimentalColorSchemes }
|
||||
|
||||
|
||||
function fillColorSchemes(themesPath: string, colorSchemes: ColorScheme[]) {
|
||||
for (const fileName of fs.readdirSync(themesPath)) {
|
||||
if (fileName == "template.ts") continue;
|
||||
const filePath = path.join(themesPath, fileName);
|
||||
|
||||
if (fs.statSync(filePath).isFile()) {
|
||||
const colorScheme = require(filePath);
|
||||
if (colorScheme.dark) colorSchemes.push(colorScheme.dark);
|
||||
if (colorScheme.light) colorSchemes.push(colorScheme.light);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fillColorSchemes(path.resolve(`${__dirname}/themes`), colorSchemes)
|
||||
fillColorSchemes(path.resolve(`${__dirname}/themes/internal`), internalColorSchemes)
|
||||
fillColorSchemes(path.resolve(`${__dirname}/themes/experiments`), experimentalColorSchemes)
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import chatPanel from "./chatPanel";
|
||||
import { text } from "./components";
|
||||
import contactFinder from "./contactFinder";
|
||||
import contactsPanel from "./contactsPanel";
|
||||
|
@ -16,38 +14,38 @@ import contactNotification from "./contactNotification";
|
|||
import updateNotification from "./updateNotification";
|
||||
import tooltip from "./tooltip";
|
||||
import terminal from "./terminal";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
|
||||
export const panel = {
|
||||
padding: { top: 12, bottom: 12 },
|
||||
};
|
||||
|
||||
export default function app(theme: Theme): Object {
|
||||
export default function app(colorScheme: ColorScheme): Object {
|
||||
return {
|
||||
meta: {
|
||||
name: theme.name,
|
||||
isLight: theme.isLight
|
||||
name: colorScheme.name,
|
||||
isLight: colorScheme.isLight
|
||||
},
|
||||
picker: picker(theme),
|
||||
workspace: workspace(theme),
|
||||
contextMenu: contextMenu(theme),
|
||||
editor: editor(theme),
|
||||
projectDiagnostics: projectDiagnostics(theme),
|
||||
commandPalette: commandPalette(theme),
|
||||
projectPanel: projectPanel(theme),
|
||||
chatPanel: chatPanel(theme),
|
||||
contactsPopover: contactsPopover(theme),
|
||||
contactsPanel: contactsPanel(theme),
|
||||
contactFinder: contactFinder(theme),
|
||||
search: search(theme),
|
||||
picker: picker(colorScheme),
|
||||
workspace: workspace(colorScheme),
|
||||
contextMenu: contextMenu(colorScheme),
|
||||
editor: editor(colorScheme),
|
||||
projectDiagnostics: projectDiagnostics(colorScheme),
|
||||
commandPalette: commandPalette(colorScheme),
|
||||
projectPanel: projectPanel(colorScheme),
|
||||
contactsPopover: contactsPopover(colorScheme),
|
||||
contactsPanel: contactsPanel(colorScheme),
|
||||
contactFinder: contactFinder(colorScheme),
|
||||
search: search(colorScheme),
|
||||
breadcrumbs: {
|
||||
...text(theme, "sans", "secondary"),
|
||||
...text(colorScheme.lowest.top, "sans", "base", "variant"),
|
||||
padding: {
|
||||
left: 6,
|
||||
},
|
||||
},
|
||||
contactNotification: contactNotification(theme),
|
||||
updateNotification: updateNotification(theme),
|
||||
tooltip: tooltip(theme),
|
||||
terminal: terminal(theme),
|
||||
contactNotification: contactNotification(colorScheme),
|
||||
updateNotification: updateNotification(colorScheme),
|
||||
tooltip: tooltip(colorScheme),
|
||||
terminal: terminal(colorScheme.lowest),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { panel } from "./app";
|
||||
import {
|
||||
backgroundColor,
|
||||
border,
|
||||
player,
|
||||
text,
|
||||
TextColor,
|
||||
popoverShadow,
|
||||
} from "./components";
|
||||
|
||||
export default function chatPanel(theme: Theme) {
|
||||
function channelSelectItem(
|
||||
theme: Theme,
|
||||
textColor: TextColor,
|
||||
hovered: boolean
|
||||
) {
|
||||
return {
|
||||
name: text(theme, "sans", textColor),
|
||||
padding: 4,
|
||||
hash: {
|
||||
...text(theme, "sans", "muted"),
|
||||
margin: {
|
||||
right: 8,
|
||||
},
|
||||
},
|
||||
background: hovered ? backgroundColor(theme, 300, "hovered") : undefined,
|
||||
cornerRadius: hovered ? 6 : 0,
|
||||
};
|
||||
}
|
||||
|
||||
const message = {
|
||||
body: text(theme, "sans", "secondary"),
|
||||
timestamp: text(theme, "sans", "muted", { size: "sm" }),
|
||||
padding: {
|
||||
bottom: 6,
|
||||
},
|
||||
sender: {
|
||||
...text(theme, "sans", "primary", { weight: "bold" }),
|
||||
margin: {
|
||||
right: 8,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
...panel,
|
||||
channelName: text(theme, "sans", "primary", { weight: "bold" }),
|
||||
channelNameHash: {
|
||||
...text(theme, "sans", "muted"),
|
||||
padding: {
|
||||
right: 8,
|
||||
},
|
||||
},
|
||||
channelSelect: {
|
||||
header: {
|
||||
...channelSelectItem(theme, "primary", false),
|
||||
padding: {
|
||||
bottom: 4,
|
||||
left: 0,
|
||||
},
|
||||
},
|
||||
item: channelSelectItem(theme, "secondary", false),
|
||||
hoveredItem: channelSelectItem(theme, "secondary", true),
|
||||
activeItem: channelSelectItem(theme, "primary", false),
|
||||
hoveredActiveItem: channelSelectItem(theme, "primary", true),
|
||||
menu: {
|
||||
background: backgroundColor(theme, 500),
|
||||
cornerRadius: 6,
|
||||
padding: 4,
|
||||
border: border(theme, "primary"),
|
||||
shadow: popoverShadow(theme),
|
||||
},
|
||||
},
|
||||
signInPrompt: text(theme, "sans", "secondary", { underline: true }),
|
||||
hoveredSignInPrompt: text(theme, "sans", "primary", { underline: true }),
|
||||
message,
|
||||
pendingMessage: {
|
||||
...message,
|
||||
body: {
|
||||
...message.body,
|
||||
color: theme.textColor.muted,
|
||||
},
|
||||
sender: {
|
||||
...message.sender,
|
||||
color: theme.textColor.muted,
|
||||
},
|
||||
timestamp: {
|
||||
...message.timestamp,
|
||||
color: theme.textColor.muted,
|
||||
},
|
||||
},
|
||||
inputEditor: {
|
||||
background: backgroundColor(theme, 500),
|
||||
cornerRadius: 6,
|
||||
text: text(theme, "mono", "primary"),
|
||||
placeholderText: text(theme, "mono", "placeholder", { size: "sm" }),
|
||||
selection: player(theme, 1).selection,
|
||||
border: border(theme, "secondary"),
|
||||
padding: {
|
||||
bottom: 7,
|
||||
left: 8,
|
||||
right: 8,
|
||||
top: 7,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,14 +1,15 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { text, backgroundColor, border } from "./components";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import { text, border, background } from "./components";
|
||||
|
||||
export default function commandPalette(theme: Theme) {
|
||||
export default function commandPalette(colorScheme: ColorScheme) {
|
||||
let layer = colorScheme.highest.bottom;
|
||||
return {
|
||||
keystrokeSpacing: 8,
|
||||
key: {
|
||||
text: text(theme, "mono", "secondary", { size: "xs" }),
|
||||
text: text(layer, "mono", { size: "xs" }),
|
||||
cornerRadius: 4,
|
||||
background: backgroundColor(theme, "on300"),
|
||||
border: border(theme, "secondary"),
|
||||
background: background(layer, "on"),
|
||||
border: border(layer),
|
||||
padding: {
|
||||
top: 2,
|
||||
bottom: 2,
|
||||
|
@ -19,7 +20,7 @@ export default function commandPalette(theme: Theme) {
|
|||
left: 2,
|
||||
},
|
||||
active: {
|
||||
text: text(theme, "mono", "active", { size: "xs" }),
|
||||
text: text(layer, "mono", "on", "active", { size: "xs" }),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,30 +1,89 @@
|
|||
import Theme, { BackgroundColorSet } from "../themes/common/theme";
|
||||
import { fontFamilies, fontSizes, FontWeight } from "../common";
|
||||
import { Layer, Styles, StyleSets } from "../themes/common/colorScheme";
|
||||
|
||||
export function background(layer: Layer, styleSet?: StyleSets, style?: Styles): string {
|
||||
return layer[styleSet ?? "base"][style ?? "default"].background;
|
||||
}
|
||||
export function borderColor(layer: Layer, styleSet?: StyleSets, style?: Styles): string {
|
||||
return layer[styleSet ?? "base"][style ?? "default"].border;
|
||||
}
|
||||
export function foreground(layer: Layer, styleSet?: StyleSets, style?: Styles): string {
|
||||
return layer[styleSet ?? "base"][style ?? "default"].foreground;
|
||||
}
|
||||
|
||||
|
||||
interface Text {
|
||||
family: keyof typeof fontFamilies,
|
||||
color: string,
|
||||
size: number,
|
||||
weight?: FontWeight,
|
||||
underline?: boolean,
|
||||
}
|
||||
|
||||
interface TextProperties {
|
||||
size?: keyof typeof fontSizes;
|
||||
weight?: FontWeight;
|
||||
underline?: boolean;
|
||||
}
|
||||
|
||||
export type TextColor = keyof Theme["textColor"];
|
||||
export function text(
|
||||
theme: Theme,
|
||||
layer: Layer,
|
||||
fontFamily: keyof typeof fontFamilies,
|
||||
color: TextColor,
|
||||
properties?: {
|
||||
size?: keyof typeof fontSizes;
|
||||
weight?: FontWeight;
|
||||
underline?: boolean;
|
||||
}
|
||||
styleSet: StyleSets,
|
||||
style: Styles,
|
||||
properties?: TextProperties
|
||||
): Text;
|
||||
export function text(
|
||||
layer: Layer,
|
||||
fontFamily: keyof typeof fontFamilies,
|
||||
styleSet: StyleSets,
|
||||
properties?: TextProperties): Text;
|
||||
export function text(
|
||||
layer: Layer,
|
||||
fontFamily: keyof typeof fontFamilies,
|
||||
properties?: TextProperties): Text;
|
||||
export function text(
|
||||
layer: Layer,
|
||||
fontFamily: keyof typeof fontFamilies,
|
||||
styleSetOrProperties?: StyleSets | TextProperties,
|
||||
styleOrProperties?: Styles | TextProperties,
|
||||
properties?: TextProperties
|
||||
) {
|
||||
let styleSet: StyleSets = "base";
|
||||
let style: Styles = "default";
|
||||
|
||||
if (typeof styleSetOrProperties === "string") {
|
||||
styleSet = styleSetOrProperties
|
||||
} else if (styleSetOrProperties !== undefined) {
|
||||
properties = styleSetOrProperties;
|
||||
}
|
||||
|
||||
if (typeof styleOrProperties === "string") {
|
||||
style = styleOrProperties;
|
||||
} else if (styleOrProperties !== undefined) {
|
||||
properties = styleOrProperties;
|
||||
}
|
||||
|
||||
let size = fontSizes[properties?.size || "sm"];
|
||||
return {
|
||||
family: fontFamilies[fontFamily],
|
||||
color: theme.textColor[color],
|
||||
color: layer[styleSet][style].foreground,
|
||||
...properties,
|
||||
size,
|
||||
};
|
||||
}
|
||||
export function textColor(theme: Theme, color: TextColor) {
|
||||
return theme.textColor[color];
|
||||
|
||||
|
||||
export interface Border {
|
||||
color: string,
|
||||
width: number,
|
||||
top?: boolean;
|
||||
bottom?: boolean;
|
||||
left?: boolean;
|
||||
right?: boolean;
|
||||
overlay?: boolean;
|
||||
}
|
||||
|
||||
export type BorderColor = keyof Theme["borderColor"];
|
||||
export interface BorderOptions {
|
||||
width?: number;
|
||||
top?: boolean;
|
||||
|
@ -33,72 +92,46 @@ export interface BorderOptions {
|
|||
right?: boolean;
|
||||
overlay?: boolean;
|
||||
}
|
||||
|
||||
export function border(
|
||||
theme: Theme,
|
||||
color: BorderColor,
|
||||
layer: Layer,
|
||||
styleSet: StyleSets,
|
||||
style: Styles,
|
||||
options?: BorderOptions
|
||||
) {
|
||||
): Border;
|
||||
export function border(
|
||||
layer: Layer,
|
||||
styleSet: StyleSets,
|
||||
options?: BorderOptions
|
||||
): Border;
|
||||
export function border(
|
||||
layer: Layer,
|
||||
options?: BorderOptions
|
||||
): Border;
|
||||
export function border(
|
||||
layer: Layer,
|
||||
styleSetOrOptions?: StyleSets | BorderOptions,
|
||||
styleOrOptions?: Styles | BorderOptions,
|
||||
options?: BorderOptions
|
||||
): Border {
|
||||
let styleSet: StyleSets = "base";
|
||||
let style: Styles = "default";
|
||||
|
||||
if (typeof styleSetOrOptions === "string") {
|
||||
styleSet = styleSetOrOptions
|
||||
} else if (styleSetOrOptions !== undefined) {
|
||||
options = styleSetOrOptions;
|
||||
}
|
||||
|
||||
if (typeof styleOrOptions === "string") {
|
||||
style = styleOrOptions;
|
||||
} else if (styleOrOptions !== undefined) {
|
||||
options = styleOrOptions;
|
||||
}
|
||||
|
||||
return {
|
||||
color: borderColor(theme, color),
|
||||
color: layer[styleSet][style].border,
|
||||
width: 1,
|
||||
...options,
|
||||
};
|
||||
}
|
||||
export function borderColor(theme: Theme, color: BorderColor) {
|
||||
return theme.borderColor[color];
|
||||
}
|
||||
|
||||
export type IconColor = keyof Theme["iconColor"];
|
||||
export function iconColor(theme: Theme, color: IconColor) {
|
||||
return theme.iconColor[color];
|
||||
}
|
||||
|
||||
export type PlayerIndex = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
||||
export interface Player {
|
||||
selection: {
|
||||
cursor: string;
|
||||
selection: string;
|
||||
};
|
||||
}
|
||||
export function player(theme: Theme, playerNumber: PlayerIndex): Player {
|
||||
return {
|
||||
selection: {
|
||||
cursor: theme.player[playerNumber].cursorColor,
|
||||
selection: theme.player[playerNumber].selectionColor,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export type BackgroundColor = keyof Theme["backgroundColor"];
|
||||
export type BackgroundState = keyof BackgroundColorSet;
|
||||
export function backgroundColor(
|
||||
theme: Theme,
|
||||
name: BackgroundColor,
|
||||
state?: BackgroundState
|
||||
): string {
|
||||
return theme.backgroundColor[name][state || "base"];
|
||||
}
|
||||
|
||||
export function modalShadow(theme: Theme) {
|
||||
return {
|
||||
blur: 16,
|
||||
color: theme.shadow,
|
||||
offset: [0, 2],
|
||||
};
|
||||
}
|
||||
|
||||
export function popoverShadow(theme: Theme) {
|
||||
return {
|
||||
blur: 4,
|
||||
color: theme.shadow,
|
||||
offset: [1, 2],
|
||||
};
|
||||
}
|
||||
|
||||
export function draggedShadow(theme: Theme) {
|
||||
return {
|
||||
blur: 6,
|
||||
color: theme.shadow,
|
||||
offset: [1, 2],
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,18 +1,19 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import picker from "./picker";
|
||||
import { backgroundColor, iconColor } from "./components";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import { background, foreground } from "./components";
|
||||
|
||||
export default function contactFinder(theme: Theme) {
|
||||
export default function contactFinder(colorScheme: ColorScheme) {
|
||||
let layer = colorScheme.middle.bottom;
|
||||
const contactButton = {
|
||||
background: backgroundColor(theme, 100),
|
||||
color: iconColor(theme, "primary"),
|
||||
background: background(layer),
|
||||
color: foreground(layer),
|
||||
iconWidth: 8,
|
||||
buttonWidth: 16,
|
||||
cornerRadius: 8,
|
||||
};
|
||||
|
||||
return {
|
||||
...picker(theme),
|
||||
...picker(colorScheme),
|
||||
rowHeight: 28,
|
||||
contactAvatar: {
|
||||
cornerRadius: 10,
|
||||
|
@ -26,13 +27,13 @@ export default function contactFinder(theme: Theme) {
|
|||
contactButton: {
|
||||
...contactButton,
|
||||
hover: {
|
||||
background: backgroundColor(theme, 100, "hovered"),
|
||||
background: background(layer, "base", "hovered"),
|
||||
},
|
||||
},
|
||||
disabledContactButton: {
|
||||
...contactButton,
|
||||
background: backgroundColor(theme, 100),
|
||||
color: iconColor(theme, "muted"),
|
||||
background: background(layer, "base", "disabled"),
|
||||
color: foreground(layer, "base", "disabled"),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { backgroundColor, iconColor, text } from "./components";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import { background, foreground, text } from "./components";
|
||||
|
||||
const avatarSize = 12;
|
||||
const headerPadding = 8;
|
||||
|
||||
export default function contactNotification(theme: Theme): Object {
|
||||
export default function contactNotification(colorScheme: ColorScheme): Object {
|
||||
let layer = colorScheme.middle.bottom;
|
||||
return {
|
||||
headerAvatar: {
|
||||
height: avatarSize,
|
||||
|
@ -12,32 +13,32 @@ export default function contactNotification(theme: Theme): Object {
|
|||
cornerRadius: 6,
|
||||
},
|
||||
headerMessage: {
|
||||
...text(theme, "sans", "primary", { size: "xs" }),
|
||||
...text(layer, "sans", { size: "xs" }),
|
||||
margin: { left: headerPadding, right: headerPadding },
|
||||
},
|
||||
headerHeight: 18,
|
||||
bodyMessage: {
|
||||
...text(theme, "sans", "secondary", { size: "xs" }),
|
||||
...text(layer, "sans", { size: "xs" }),
|
||||
margin: { left: avatarSize + headerPadding, top: 6, bottom: 6 },
|
||||
},
|
||||
button: {
|
||||
...text(theme, "sans", "primary", { size: "xs" }),
|
||||
background: backgroundColor(theme, "on300"),
|
||||
...text(layer, "sans", "on", { size: "xs" }),
|
||||
background: background(layer, "on"),
|
||||
padding: 4,
|
||||
cornerRadius: 6,
|
||||
margin: { left: 6 },
|
||||
hover: {
|
||||
background: backgroundColor(theme, "on300", "hovered"),
|
||||
background: background(layer, "on", "hovered"),
|
||||
},
|
||||
},
|
||||
dismissButton: {
|
||||
color: iconColor(theme, "secondary"),
|
||||
color: foreground(layer, "on"),
|
||||
iconWidth: 8,
|
||||
iconHeight: 8,
|
||||
buttonWidth: 8,
|
||||
buttonHeight: 8,
|
||||
hover: {
|
||||
color: iconColor(theme, "primary"),
|
||||
color: foreground(layer, "on", "hovered"),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import { panel } from "./app";
|
||||
import {
|
||||
backgroundColor,
|
||||
background,
|
||||
border,
|
||||
borderColor,
|
||||
iconColor,
|
||||
player,
|
||||
foreground,
|
||||
text,
|
||||
} from "./components";
|
||||
|
||||
export default function contactsPanel(theme: Theme) {
|
||||
export default function contactsPanel(colorScheme: ColorScheme) {
|
||||
const nameMargin = 8;
|
||||
const sidePadding = 12;
|
||||
|
||||
let layer = colorScheme.lowest.middle;
|
||||
|
||||
const projectRow = {
|
||||
guestAvatarSpacing: 4,
|
||||
height: 24,
|
||||
|
@ -21,7 +22,7 @@ export default function contactsPanel(theme: Theme) {
|
|||
width: 14,
|
||||
},
|
||||
name: {
|
||||
...text(theme, "mono", "placeholder", { size: "sm" }),
|
||||
...text(layer, "mono", { size: "sm" }),
|
||||
margin: {
|
||||
left: nameMargin,
|
||||
right: 6,
|
||||
|
@ -40,8 +41,8 @@ export default function contactsPanel(theme: Theme) {
|
|||
};
|
||||
|
||||
const contactButton = {
|
||||
background: backgroundColor(theme, 100),
|
||||
color: iconColor(theme, "primary"),
|
||||
background: background(layer, "on"),
|
||||
color: foreground(layer, "on"),
|
||||
iconWidth: 8,
|
||||
buttonWidth: 16,
|
||||
cornerRadius: 8,
|
||||
|
@ -51,12 +52,12 @@ export default function contactsPanel(theme: Theme) {
|
|||
...panel,
|
||||
padding: { top: panel.padding.top, bottom: 0 },
|
||||
userQueryEditor: {
|
||||
background: backgroundColor(theme, 500),
|
||||
background: background(layer, "on"),
|
||||
cornerRadius: 6,
|
||||
text: text(theme, "mono", "primary"),
|
||||
placeholderText: text(theme, "mono", "placeholder", { size: "sm" }),
|
||||
selection: player(theme, 1).selection,
|
||||
border: border(theme, "secondary"),
|
||||
text: text(layer, "mono", "on"),
|
||||
placeholderText: text(layer, "mono", "on", "disabled", { size: "sm" }),
|
||||
selection: colorScheme.players[0],
|
||||
border: border(layer, "on"),
|
||||
padding: {
|
||||
bottom: 4,
|
||||
left: 8,
|
||||
|
@ -71,28 +72,28 @@ export default function contactsPanel(theme: Theme) {
|
|||
userQueryEditorHeight: 32,
|
||||
addContactButton: {
|
||||
margin: { left: 6, right: 12 },
|
||||
color: iconColor(theme, "primary"),
|
||||
color: foreground(layer, "on"),
|
||||
buttonWidth: 16,
|
||||
iconWidth: 16,
|
||||
},
|
||||
privateButton: {
|
||||
iconWidth: 12,
|
||||
color: iconColor(theme, "primary"),
|
||||
color: foreground(layer, "on"),
|
||||
cornerRadius: 5,
|
||||
buttonWidth: 12,
|
||||
},
|
||||
rowHeight: 28,
|
||||
sectionIconSize: 8,
|
||||
headerRow: {
|
||||
...text(theme, "mono", "secondary", { size: "sm" }),
|
||||
...text(layer, "mono", { size: "sm" }),
|
||||
margin: { top: 14 },
|
||||
padding: {
|
||||
left: sidePadding,
|
||||
right: sidePadding,
|
||||
},
|
||||
active: {
|
||||
...text(theme, "mono", "primary", { size: "sm" }),
|
||||
background: backgroundColor(theme, 100, "active"),
|
||||
...text(layer, "mono", "base", "active", { size: "sm" }),
|
||||
background: background(layer, "base", "active"),
|
||||
},
|
||||
},
|
||||
contactRow: {
|
||||
|
@ -101,17 +102,17 @@ export default function contactsPanel(theme: Theme) {
|
|||
right: sidePadding,
|
||||
},
|
||||
active: {
|
||||
background: backgroundColor(theme, 100, "active"),
|
||||
background: background(layer, "base", "active"),
|
||||
},
|
||||
},
|
||||
treeBranch: {
|
||||
color: borderColor(theme, "active"),
|
||||
color: borderColor(layer),
|
||||
width: 1,
|
||||
hover: {
|
||||
color: borderColor(theme, "active"),
|
||||
color: borderColor(layer, "base", "hovered"),
|
||||
},
|
||||
active: {
|
||||
color: borderColor(theme, "active"),
|
||||
color: borderColor(layer, "base", "active"),
|
||||
},
|
||||
},
|
||||
contactAvatar: {
|
||||
|
@ -119,7 +120,7 @@ export default function contactsPanel(theme: Theme) {
|
|||
width: 18,
|
||||
},
|
||||
contactUsername: {
|
||||
...text(theme, "mono", "primary", { size: "sm" }),
|
||||
...text(layer, "mono", { size: "sm" }),
|
||||
margin: {
|
||||
left: nameMargin,
|
||||
},
|
||||
|
@ -128,26 +129,26 @@ export default function contactsPanel(theme: Theme) {
|
|||
contactButton: {
|
||||
...contactButton,
|
||||
hover: {
|
||||
background: backgroundColor(theme, "on300", "hovered"),
|
||||
background: background(layer, "base", "hovered"),
|
||||
},
|
||||
},
|
||||
disabledButton: {
|
||||
...contactButton,
|
||||
background: backgroundColor(theme, 100),
|
||||
color: iconColor(theme, "muted"),
|
||||
background: background(layer, "on"),
|
||||
color: foreground(layer, "on"),
|
||||
},
|
||||
projectRow: {
|
||||
...projectRow,
|
||||
background: backgroundColor(theme, 300),
|
||||
background: background(layer, "on"),
|
||||
name: {
|
||||
...projectRow.name,
|
||||
...text(theme, "mono", "secondary", { size: "sm" }),
|
||||
...text(layer, "mono", { size: "sm" }),
|
||||
},
|
||||
hover: {
|
||||
background: backgroundColor(theme, 300, "hovered"),
|
||||
background: background(layer, "base", "hovered"),
|
||||
},
|
||||
active: {
|
||||
background: backgroundColor(theme, 300, "active"),
|
||||
background: background(layer, "base", "active"),
|
||||
},
|
||||
},
|
||||
inviteRow: {
|
||||
|
@ -155,10 +156,10 @@ export default function contactsPanel(theme: Theme) {
|
|||
left: sidePadding,
|
||||
right: sidePadding,
|
||||
},
|
||||
border: { top: true, width: 1, color: borderColor(theme, "primary") },
|
||||
text: text(theme, "sans", "secondary", { size: "sm" }),
|
||||
border: border(layer, { top: true }),
|
||||
text: text(layer, "sans", { size: "sm" }),
|
||||
hover: {
|
||||
text: text(theme, "sans", "active", { size: "sm" }),
|
||||
text: text(layer, "sans", "base", "hovered", { size: "sm" }),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,45 +1,46 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import {
|
||||
backgroundColor,
|
||||
background,
|
||||
border,
|
||||
borderColor,
|
||||
popoverShadow,
|
||||
text,
|
||||
} from "./components";
|
||||
|
||||
export default function contextMenu(theme: Theme) {
|
||||
export default function contextMenu(colorScheme: ColorScheme) {
|
||||
let elevation = colorScheme.middle;
|
||||
let layer = elevation.bottom;
|
||||
return {
|
||||
background: backgroundColor(theme, 300, "base"),
|
||||
background: background(layer),
|
||||
cornerRadius: 6,
|
||||
padding: 6,
|
||||
shadow: popoverShadow(theme),
|
||||
border: border(theme, "primary"),
|
||||
shadow: elevation.shadow,
|
||||
border: border(layer),
|
||||
keystrokeMargin: 30,
|
||||
item: {
|
||||
iconSpacing: 8,
|
||||
iconWidth: 14,
|
||||
padding: { left: 4, right: 4, top: 2, bottom: 2 },
|
||||
cornerRadius: 6,
|
||||
label: text(theme, "sans", "primary", { size: "sm" }),
|
||||
label: text(layer, "sans", { size: "sm" }),
|
||||
keystroke: {
|
||||
...text(theme, "sans", "muted", { size: "sm", weight: "bold" }),
|
||||
...text(layer, "sans", "base", "variant", { size: "sm", weight: "bold" }),
|
||||
padding: { left: 3, right: 3 },
|
||||
},
|
||||
hover: {
|
||||
background: backgroundColor(theme, 300, "hovered"),
|
||||
text: text(theme, "sans", "primary", { size: "sm" }),
|
||||
background: background(layer, "base", "hovered"),
|
||||
text: text(layer, "sans", "base", "hovered", { size: "sm" }),
|
||||
},
|
||||
active: {
|
||||
background: backgroundColor(theme, 300, "active"),
|
||||
text: text(theme, "sans", "active", { size: "sm" }),
|
||||
background: background(layer, "base", "active"),
|
||||
text: text(layer, "sans", "base", "active", { size: "sm" }),
|
||||
},
|
||||
activeHover: {
|
||||
background: backgroundColor(theme, 300, "hovered"),
|
||||
text: text(theme, "sans", "active", { size: "sm" }),
|
||||
background: background(layer, "base", "active"),
|
||||
text: text(layer, "sans", "base", "active", { size: "sm" }),
|
||||
},
|
||||
},
|
||||
separator: {
|
||||
background: borderColor(theme, "primary"),
|
||||
background: borderColor(layer),
|
||||
margin: { top: 2, bottom: 2 },
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { fontWeights } from "../common";
|
||||
import { ColorScheme, Elevation, Layer, StyleSets } from "../themes/common/colorScheme";
|
||||
import {
|
||||
backgroundColor,
|
||||
background,
|
||||
border,
|
||||
borderColor,
|
||||
iconColor,
|
||||
player,
|
||||
popoverShadow,
|
||||
foreground,
|
||||
text,
|
||||
TextColor,
|
||||
} from "./components";
|
||||
import hoverPopover from "./hoverPopover";
|
||||
|
||||
export default function editor(theme: Theme) {
|
||||
export default function editor(colorScheme: ColorScheme) {
|
||||
let elevation = colorScheme.lowest;
|
||||
let layer = elevation.top;
|
||||
|
||||
const autocompleteItem = {
|
||||
cornerRadius: 6,
|
||||
padding: {
|
||||
|
@ -22,17 +23,17 @@ export default function editor(theme: Theme) {
|
|||
},
|
||||
};
|
||||
|
||||
function diagnostic(theme: Theme, color: TextColor) {
|
||||
function diagnostic(layer: Layer, styleSet: StyleSets) {
|
||||
return {
|
||||
textScaleFactor: 0.857,
|
||||
header: {
|
||||
border: border(theme, "primary", {
|
||||
border: border(layer, {
|
||||
top: true,
|
||||
}),
|
||||
},
|
||||
message: {
|
||||
text: text(theme, "sans", color, { size: "sm" }),
|
||||
highlightText: text(theme, "sans", color, {
|
||||
text: text(layer, "sans", styleSet, { size: "sm" }),
|
||||
highlightText: text(layer, "sans", styleSet, {
|
||||
size: "sm",
|
||||
weight: "bold",
|
||||
}),
|
||||
|
@ -40,115 +41,193 @@ export default function editor(theme: Theme) {
|
|||
};
|
||||
}
|
||||
|
||||
const syntax: any = {};
|
||||
for (const syntaxKey in theme.syntax) {
|
||||
const style = theme.syntax[syntaxKey];
|
||||
syntax[syntaxKey] = {
|
||||
color: style.color,
|
||||
weight: style.weight,
|
||||
underline: style.underline,
|
||||
italic: style.italic,
|
||||
};
|
||||
const syntax = {
|
||||
primary: {
|
||||
color: elevation.ramps.neutral(1).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
comment: {
|
||||
color: elevation.ramps.neutral(0.71).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
punctuation: {
|
||||
color: elevation.ramps.neutral(0.86).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
constant: {
|
||||
color: elevation.ramps.neutral(0.57).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
keyword: {
|
||||
color: elevation.ramps.blue(0.5).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
function: {
|
||||
color: elevation.ramps.yellow(0.5).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
type: {
|
||||
color: elevation.ramps.cyan(0.5).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
constructor: {
|
||||
color: elevation.ramps.blue(0.5).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
variant: {
|
||||
color: elevation.ramps.blue(0.5).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
property: {
|
||||
color: elevation.ramps.blue(0.5).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
enum: {
|
||||
color: elevation.ramps.orange(0.5).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
operator: {
|
||||
color: elevation.ramps.orange(0.5).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
string: {
|
||||
color: elevation.ramps.orange(0.5).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
number: {
|
||||
color: elevation.ramps.green(0.5).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
boolean: {
|
||||
color: elevation.ramps.green(0.5).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
predictive: {
|
||||
color: elevation.ramps.neutral(0.57).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
title: {
|
||||
color: elevation.ramps.yellow(0.5).hex(),
|
||||
weight: fontWeights.bold,
|
||||
},
|
||||
emphasis: {
|
||||
color: elevation.ramps.blue(0.5).hex(),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
"emphasis.strong": {
|
||||
color: elevation.ramps.blue(0.5).hex(),
|
||||
weight: fontWeights.bold,
|
||||
},
|
||||
linkUri: {
|
||||
color: elevation.ramps.green(0.5).hex(),
|
||||
weight: fontWeights.normal,
|
||||
underline: true,
|
||||
},
|
||||
linkText: {
|
||||
color: elevation.ramps.orange(0.5).hex(),
|
||||
weight: fontWeights.normal,
|
||||
italic: true,
|
||||
},
|
||||
}
|
||||
|
||||
return {
|
||||
textColor: theme.syntax.primary.color,
|
||||
background: backgroundColor(theme, 500),
|
||||
activeLineBackground: theme.editor.line.active,
|
||||
textColor: syntax.primary.color,
|
||||
background: background(layer),
|
||||
activeLineBackground: elevation.ramps.neutral(0.29).hex(),
|
||||
highlightedLineBackground: elevation.ramps.neutral(0.18).hex(),
|
||||
codeActions: {
|
||||
indicator: iconColor(theme, "secondary"),
|
||||
indicator: foreground(layer, "base", "variant"),
|
||||
verticalScale: 0.618
|
||||
},
|
||||
diffBackgroundDeleted: backgroundColor(theme, "error"),
|
||||
diffBackgroundInserted: backgroundColor(theme, "ok"),
|
||||
documentHighlightReadBackground: theme.editor.highlight.occurrence,
|
||||
documentHighlightWriteBackground: theme.editor.highlight.activeOccurrence,
|
||||
errorColor: theme.textColor.error,
|
||||
gutterBackground: backgroundColor(theme, 500),
|
||||
diffBackgroundDeleted: background(layer, "negative"),
|
||||
diffBackgroundInserted: background(layer, "positive"),
|
||||
documentHighlightReadBackground: elevation.ramps.neutral(0.5).alpha(0.2).hex(), // TODO: This was blend
|
||||
documentHighlightWriteBackground: elevation.ramps.neutral(0.5).alpha(0.4).hex(), // TODO: This was blend * 2
|
||||
errorColor: foreground(layer, "negative"),
|
||||
gutterBackground: background(layer),
|
||||
gutterPaddingFactor: 3.5,
|
||||
highlightedLineBackground: theme.editor.line.highlighted,
|
||||
lineNumber: theme.editor.gutter.primary,
|
||||
lineNumberActive: theme.editor.gutter.active,
|
||||
lineNumber: foreground(layer),
|
||||
lineNumberActive: foreground(layer, "base", "active"),
|
||||
renameFade: 0.6,
|
||||
unnecessaryCodeFade: 0.5,
|
||||
selection: player(theme, 1).selection,
|
||||
selection: colorScheme.players[0],
|
||||
guestSelections: [
|
||||
player(theme, 2).selection,
|
||||
player(theme, 3).selection,
|
||||
player(theme, 4).selection,
|
||||
player(theme, 5).selection,
|
||||
player(theme, 6).selection,
|
||||
player(theme, 7).selection,
|
||||
player(theme, 8).selection,
|
||||
colorScheme.players[1],
|
||||
colorScheme.players[2],
|
||||
colorScheme.players[3],
|
||||
colorScheme.players[4],
|
||||
colorScheme.players[5],
|
||||
colorScheme.players[6],
|
||||
colorScheme.players[7],
|
||||
],
|
||||
autocomplete: {
|
||||
background: backgroundColor(theme, 500),
|
||||
background: background(elevation.above.top),
|
||||
cornerRadius: 8,
|
||||
padding: 4,
|
||||
border: border(theme, "secondary"),
|
||||
shadow: popoverShadow(theme),
|
||||
border: border(elevation.above.top),
|
||||
shadow: elevation.above.shadow,
|
||||
item: autocompleteItem,
|
||||
hoveredItem: {
|
||||
...autocompleteItem,
|
||||
background: backgroundColor(theme, 500, "hovered"),
|
||||
background: background(elevation.above.top, "base", "hovered"),
|
||||
},
|
||||
margin: {
|
||||
left: -14,
|
||||
},
|
||||
matchHighlight: text(theme, "mono", "feature"),
|
||||
matchHighlight: elevation.above.ramps.blue(0.5).hex(),
|
||||
selectedItem: {
|
||||
...autocompleteItem,
|
||||
background: backgroundColor(theme, 500, "active"),
|
||||
background: background(elevation.above.top, "base", "active"),
|
||||
},
|
||||
},
|
||||
diagnosticHeader: {
|
||||
background: backgroundColor(theme, 300),
|
||||
background: background(elevation.middle),
|
||||
iconWidthFactor: 1.5,
|
||||
textScaleFactor: 0.857, // NateQ: Will we need dynamic sizing for text? If so let's create tokens for these.
|
||||
border: border(theme, "secondary", {
|
||||
border: border(elevation.middle, {
|
||||
bottom: true,
|
||||
top: true,
|
||||
}),
|
||||
code: {
|
||||
...text(theme, "mono", "secondary", { size: "sm" }),
|
||||
...text(elevation.middle, "mono", { size: "sm" }),
|
||||
margin: {
|
||||
left: 10,
|
||||
},
|
||||
},
|
||||
message: {
|
||||
highlightText: text(theme, "sans", "primary", {
|
||||
highlightText: text(elevation.middle, "sans", {
|
||||
size: "sm",
|
||||
weight: "bold",
|
||||
}),
|
||||
text: text(theme, "sans", "secondary", { size: "sm" }),
|
||||
text: text(elevation.middle, "sans", { size: "sm" }),
|
||||
},
|
||||
},
|
||||
diagnosticPathHeader: {
|
||||
background: theme.editor.line.active,
|
||||
background: background(elevation.middle),
|
||||
textScaleFactor: 0.857,
|
||||
filename: text(theme, "mono", "primary", { size: "sm" }),
|
||||
filename: text(elevation.middle, "mono", { size: "sm" }),
|
||||
path: {
|
||||
...text(theme, "mono", "muted", { size: "sm" }),
|
||||
...text(elevation.middle, "mono", { size: "sm" }),
|
||||
margin: {
|
||||
left: 12,
|
||||
},
|
||||
},
|
||||
},
|
||||
errorDiagnostic: diagnostic(theme, "error"),
|
||||
warningDiagnostic: diagnostic(theme, "warning"),
|
||||
informationDiagnostic: diagnostic(theme, "info"),
|
||||
hintDiagnostic: diagnostic(theme, "info"),
|
||||
invalidErrorDiagnostic: diagnostic(theme, "secondary"),
|
||||
invalidHintDiagnostic: diagnostic(theme, "secondary"),
|
||||
invalidInformationDiagnostic: diagnostic(theme, "secondary"),
|
||||
invalidWarningDiagnostic: diagnostic(theme, "secondary"),
|
||||
hoverPopover: hoverPopover(theme),
|
||||
errorDiagnostic: diagnostic(elevation.middle, "negative"),
|
||||
warningDiagnostic: diagnostic(elevation.middle, "warning"),
|
||||
informationDiagnostic: diagnostic(elevation.middle, "info"),
|
||||
hintDiagnostic: diagnostic(elevation.middle, "positive"),
|
||||
invalidErrorDiagnostic: diagnostic(elevation.middle, "base"),
|
||||
invalidHintDiagnostic: diagnostic(elevation.middle, "base"),
|
||||
invalidInformationDiagnostic: diagnostic(elevation.middle, "base"),
|
||||
invalidWarningDiagnostic: diagnostic(elevation.middle, "base"),
|
||||
hoverPopover: hoverPopover(elevation.above),
|
||||
linkDefinition: {
|
||||
color: theme.syntax.linkUri.color,
|
||||
underline: theme.syntax.linkUri.underline,
|
||||
color: syntax.linkUri.color,
|
||||
underline: syntax.linkUri.underline,
|
||||
},
|
||||
jumpIcon: {
|
||||
color: iconColor(theme, "secondary"),
|
||||
color: foreground(layer, "on"),
|
||||
iconWidth: 20,
|
||||
buttonWidth: 20,
|
||||
cornerRadius: 6,
|
||||
|
@ -159,14 +238,14 @@ export default function editor(theme: Theme) {
|
|||
right: 6,
|
||||
},
|
||||
hover: {
|
||||
color: iconColor(theme, "active"),
|
||||
background: backgroundColor(theme, "on500"),
|
||||
color: foreground(layer, "on", "hovered"),
|
||||
background: background(layer, "on", "hovered"),
|
||||
},
|
||||
},
|
||||
compositionMark: {
|
||||
underline: {
|
||||
thickness: 1.0,
|
||||
color: borderColor(theme, "active")
|
||||
color: borderColor(layer),
|
||||
},
|
||||
},
|
||||
syntax,
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { backgroundColor, border, popoverShadow, text } from "./components";
|
||||
import { Elevation } from "../themes/common/colorScheme";
|
||||
import { background, border, text } from "./components";
|
||||
|
||||
export default function HoverPopover(theme: Theme) {
|
||||
export default function HoverPopover(elevation: Elevation) {
|
||||
let layer = elevation.middle;
|
||||
let baseContainer = {
|
||||
background: backgroundColor(theme, "on500"),
|
||||
background: background(layer),
|
||||
cornerRadius: 8,
|
||||
padding: {
|
||||
left: 8,
|
||||
|
@ -11,8 +12,8 @@ export default function HoverPopover(theme: Theme) {
|
|||
top: 4,
|
||||
bottom: 4
|
||||
},
|
||||
shadow: popoverShadow(theme),
|
||||
border: border(theme, "secondary"),
|
||||
shadow: elevation.shadow,
|
||||
border: border(layer),
|
||||
margin: {
|
||||
left: -8,
|
||||
},
|
||||
|
@ -22,32 +23,23 @@ export default function HoverPopover(theme: Theme) {
|
|||
container: baseContainer,
|
||||
infoContainer: {
|
||||
...baseContainer,
|
||||
background: backgroundColor(theme, "on500Info"),
|
||||
border: {
|
||||
color: theme.ramps.blue(0).hex(),
|
||||
width: 1,
|
||||
},
|
||||
background: background(layer, "info"),
|
||||
border: border(layer, "info"),
|
||||
},
|
||||
warningContainer: {
|
||||
...baseContainer,
|
||||
background: backgroundColor(theme, "on500Warning"),
|
||||
border: {
|
||||
color: theme.ramps.yellow(0).hex(),
|
||||
width: 1,
|
||||
},
|
||||
background: background(layer, "warning"),
|
||||
border: border(layer, "warning"),
|
||||
},
|
||||
errorContainer: {
|
||||
...baseContainer,
|
||||
background: backgroundColor(theme, "on500Error"),
|
||||
border: {
|
||||
color: theme.ramps.red(0).hex(),
|
||||
width: 1,
|
||||
}
|
||||
background: background(layer, "negative"),
|
||||
border: border(layer, "negative"),
|
||||
},
|
||||
block_style: {
|
||||
padding: { top: 4 },
|
||||
},
|
||||
prose: text(theme, "sans", "primary", { size: "sm" }),
|
||||
highlight: theme.editor.highlight.occurrence,
|
||||
prose: text(layer, "sans", { size: "sm" }),
|
||||
highlight: elevation.ramps.neutral(0.5).alpha(0.2).hex(), // TODO: blend was used here. Replace with something better
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import {
|
||||
backgroundColor,
|
||||
background,
|
||||
border,
|
||||
player,
|
||||
modalShadow,
|
||||
text,
|
||||
} from "./components";
|
||||
|
||||
export default function picker(theme: Theme) {
|
||||
export default function picker(colorScheme: ColorScheme) {
|
||||
let elevation = colorScheme.highest;
|
||||
let layer = elevation.middle;
|
||||
return {
|
||||
background: backgroundColor(theme, 300),
|
||||
background: background(layer),
|
||||
cornerRadius: 8,
|
||||
padding: 8,
|
||||
item: {
|
||||
|
@ -20,19 +20,19 @@ export default function picker(theme: Theme) {
|
|||
top: 4,
|
||||
},
|
||||
cornerRadius: 8,
|
||||
text: text(theme, "sans", "secondary"),
|
||||
highlightText: text(theme, "sans", "feature", { weight: "bold" }),
|
||||
text: text(layer, "sans"),
|
||||
highlightText: text(layer, "sans", { weight: "bold" }),
|
||||
active: {
|
||||
background: backgroundColor(theme, 300, "active"),
|
||||
text: text(theme, "sans", "active"),
|
||||
background: background(layer, "base", "active"),
|
||||
text: text(layer, "sans", "base", "active"),
|
||||
},
|
||||
hover: {
|
||||
background: backgroundColor(theme, 300, "hovered"),
|
||||
background: background(layer, "base", "hovered"),
|
||||
},
|
||||
},
|
||||
border: border(theme, "primary"),
|
||||
border: border(layer),
|
||||
empty: {
|
||||
text: text(theme, "sans", "muted"),
|
||||
text: text(layer, "sans"),
|
||||
padding: {
|
||||
bottom: 4,
|
||||
left: 12,
|
||||
|
@ -41,12 +41,12 @@ export default function picker(theme: Theme) {
|
|||
},
|
||||
},
|
||||
inputEditor: {
|
||||
background: backgroundColor(theme, 500),
|
||||
background: background(layer, "on"),
|
||||
cornerRadius: 8,
|
||||
placeholderText: text(theme, "sans", "placeholder"),
|
||||
selection: player(theme, 1).selection,
|
||||
text: text(theme, "mono", "primary"),
|
||||
border: border(theme, "secondary"),
|
||||
placeholderText: text(layer, "sans", "on", "disabled"),
|
||||
selection: colorScheme.players[0],
|
||||
text: text(layer, "mono", "on"),
|
||||
border: border(layer, "on"),
|
||||
padding: {
|
||||
bottom: 7,
|
||||
left: 16,
|
||||
|
@ -54,6 +54,6 @@ export default function picker(theme: Theme) {
|
|||
top: 7,
|
||||
},
|
||||
},
|
||||
shadow: modalShadow(theme),
|
||||
shadow: elevation.shadow,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { backgroundColor, text } from "./components";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import { background, text } from "./components";
|
||||
|
||||
export default function projectDiagnostics(theme: Theme) {
|
||||
export default function projectDiagnostics(colorScheme: ColorScheme) {
|
||||
let layer = colorScheme.lowest.top;
|
||||
return {
|
||||
background: backgroundColor(theme, 500),
|
||||
background: background(layer),
|
||||
tabIconSpacing: 4,
|
||||
tabIconWidth: 13,
|
||||
tabSummarySpacing: 10,
|
||||
emptyMessage: text(theme, "sans", "secondary", { size: "md" }),
|
||||
emptyMessage: text(layer, "sans", "base", "variant", { size: "md" }),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,36 +1,37 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import { panel } from "./app";
|
||||
import { backgroundColor, iconColor, player, text } from "./components";
|
||||
import { background, foreground, text } from "./components";
|
||||
|
||||
export default function projectPanel(theme: Theme) {
|
||||
export default function projectPanel(colorScheme: ColorScheme) {
|
||||
let layer = colorScheme.lowest.middle;
|
||||
return {
|
||||
...panel,
|
||||
padding: { left: 12, right: 12, top: 6, bottom: 6 },
|
||||
indentWidth: 8,
|
||||
entry: {
|
||||
height: 24,
|
||||
iconColor: iconColor(theme, "muted"),
|
||||
iconColor: foreground(layer, "on"),
|
||||
iconSize: 8,
|
||||
iconSpacing: 8,
|
||||
text: text(theme, "mono", "secondary", { size: "sm" }),
|
||||
text: text(layer, "mono", "on", { size: "sm" }),
|
||||
hover: {
|
||||
background: backgroundColor(theme, 300, "hovered"),
|
||||
background: background(layer, "on", "hovered"),
|
||||
},
|
||||
active: {
|
||||
background: backgroundColor(theme, 300, "active"),
|
||||
text: text(theme, "mono", "active", { size: "sm" }),
|
||||
background: background(layer, "base", "active"),
|
||||
text: text(layer, "mono", "base", "active", { size: "sm" }),
|
||||
},
|
||||
activeHover: {
|
||||
background: backgroundColor(theme, 300, "active"),
|
||||
text: text(theme, "mono", "active", { size: "sm" }),
|
||||
background: background(layer, "base", "hovered"),
|
||||
text: text(layer, "mono", "base", "active", { size: "sm" }),
|
||||
},
|
||||
},
|
||||
cutEntryFade: 0.4,
|
||||
ignoredEntryFade: 0.6,
|
||||
filenameEditor: {
|
||||
background: backgroundColor(theme, "on300"),
|
||||
text: text(theme, "mono", "active", { size: "sm" }),
|
||||
selection: player(theme, 1).selection,
|
||||
background: background(layer, "on"),
|
||||
text: text(layer, "mono", "on", "active", { size: "sm" }),
|
||||
selection: colorScheme.players[0],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { backgroundColor, border, player, text } from "./components";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import { background, border, text } from "./components";
|
||||
|
||||
export default function search(colorScheme: ColorScheme) {
|
||||
let layer = colorScheme.lowest.top;
|
||||
|
||||
export default function search(theme: Theme) {
|
||||
// Search input
|
||||
const editor = {
|
||||
background: backgroundColor(theme, 500),
|
||||
background: background(layer),
|
||||
cornerRadius: 8,
|
||||
minWidth: 200,
|
||||
maxWidth: 500,
|
||||
placeholderText: text(theme, "mono", "placeholder"),
|
||||
selection: player(theme, 1).selection,
|
||||
text: text(theme, "mono", "active"),
|
||||
border: border(theme, "secondary"),
|
||||
placeholderText: text(layer, "mono", "base", "disabled"),
|
||||
selection: colorScheme.players[0],
|
||||
text: text(layer, "mono", "base", "active"),
|
||||
border: border(layer),
|
||||
margin: {
|
||||
right: 12,
|
||||
},
|
||||
|
@ -24,14 +26,14 @@ export default function search(theme: Theme) {
|
|||
};
|
||||
|
||||
return {
|
||||
matchBackground: theme.editor.highlight.match,
|
||||
matchBackground: background(layer), // theme.editor.highlight.match,
|
||||
tabIconSpacing: 8,
|
||||
tabIconWidth: 14,
|
||||
optionButton: {
|
||||
...text(theme, "mono", "secondary"),
|
||||
background: backgroundColor(theme, "on500"),
|
||||
...text(layer, "mono", "on"),
|
||||
background: background(layer, "on"),
|
||||
cornerRadius: 6,
|
||||
border: border(theme, "secondary"),
|
||||
border: border(layer, "on"),
|
||||
margin: {
|
||||
right: 4,
|
||||
},
|
||||
|
@ -42,28 +44,28 @@ export default function search(theme: Theme) {
|
|||
top: 2,
|
||||
},
|
||||
active: {
|
||||
...text(theme, "mono", "active"),
|
||||
background: backgroundColor(theme, "on500", "active"),
|
||||
border: border(theme, "muted"),
|
||||
...text(layer, "mono", "on", "active"),
|
||||
background: background(layer, "on", "active"),
|
||||
border: border(layer, "on", "active"),
|
||||
},
|
||||
clicked: {
|
||||
...text(theme, "mono", "active"),
|
||||
background: backgroundColor(theme, "on300", "active"),
|
||||
border: border(theme, "secondary"),
|
||||
...text(layer, "mono", "on", "pressed"),
|
||||
background: background(layer, "on", "pressed"),
|
||||
border: border(layer, "on", "pressed"),
|
||||
},
|
||||
hover: {
|
||||
...text(theme, "mono", "active"),
|
||||
background: backgroundColor(theme, "on500", "hovered"),
|
||||
border: border(theme, "muted"),
|
||||
...text(layer, "mono", "on", "hovered"),
|
||||
background: background(layer, "on", "hovered"),
|
||||
border: border(layer, "on", "hovered"),
|
||||
},
|
||||
},
|
||||
editor,
|
||||
invalidEditor: {
|
||||
...editor,
|
||||
border: border(theme, "error"),
|
||||
border: border(layer, "negative"),
|
||||
},
|
||||
matchIndex: {
|
||||
...text(theme, "mono", "muted"),
|
||||
...text(layer, "mono", "on", "variant"),
|
||||
padding: 6,
|
||||
},
|
||||
optionButtonGroup: {
|
||||
|
@ -73,7 +75,7 @@ export default function search(theme: Theme) {
|
|||
},
|
||||
},
|
||||
resultsStatus: {
|
||||
...text(theme, "mono", "primary"),
|
||||
...text(layer, "mono", "on"),
|
||||
size: 18,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { backgroundColor, border, iconColor, text } from "./components";
|
||||
import { workspaceBackground } from "./workspace";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import { background, border, foreground, text } from "./components";
|
||||
|
||||
export default function statusBar(colorScheme: ColorScheme) {
|
||||
let layer = colorScheme.lowest.bottom;
|
||||
|
||||
export default function statusBar(theme: Theme) {
|
||||
const statusContainer = {
|
||||
cornerRadius: 6,
|
||||
padding: { top: 3, bottom: 3, left: 6, right: 6 },
|
||||
|
@ -22,70 +23,70 @@ export default function statusBar(theme: Theme) {
|
|||
left: 6,
|
||||
right: 6,
|
||||
},
|
||||
border: border(theme, "primary", { top: true, overlay: true }),
|
||||
cursorPosition: text(theme, "sans", "secondary"),
|
||||
autoUpdateProgressMessage: text(theme, "sans", "secondary"),
|
||||
autoUpdateDoneMessage: text(theme, "sans", "secondary"),
|
||||
border: border(layer, { top: true, overlay: true }),
|
||||
cursorPosition: text(layer, "sans"),
|
||||
autoUpdateProgressMessage: text(layer, "sans"),
|
||||
autoUpdateDoneMessage: text(layer, "sans"),
|
||||
lspStatus: {
|
||||
...diagnosticStatusContainer,
|
||||
iconSpacing: 4,
|
||||
iconWidth: 14,
|
||||
height: 18,
|
||||
message: text(theme, "sans", "secondary"),
|
||||
iconColor: iconColor(theme, "muted"),
|
||||
message: text(layer, "sans"),
|
||||
iconColor: foreground(layer),
|
||||
hover: {
|
||||
message: text(theme, "sans", "primary"),
|
||||
iconColor: iconColor(theme, "primary"),
|
||||
background: backgroundColor(theme, 300, "hovered"),
|
||||
message: text(layer, "sans"),
|
||||
iconColor: foreground(layer),
|
||||
background: background(layer),
|
||||
},
|
||||
},
|
||||
diagnosticMessage: {
|
||||
...text(theme, "sans", "secondary"),
|
||||
hover: text(theme, "sans", "active"),
|
||||
...text(layer, "sans"),
|
||||
hover: text(layer, "sans", "base", "hovered"),
|
||||
},
|
||||
feedback: {
|
||||
...text(theme, "sans", "secondary"),
|
||||
hover: text(theme, "sans", "active"),
|
||||
...text(layer, "sans"),
|
||||
hover: text(layer, "sans"),
|
||||
},
|
||||
diagnosticSummary: {
|
||||
height: 16,
|
||||
iconWidth: 16,
|
||||
iconSpacing: 2,
|
||||
summarySpacing: 6,
|
||||
text: text(theme, "sans", "primary", { size: "sm" }),
|
||||
iconColorOk: iconColor(theme, "muted"),
|
||||
iconColorWarning: iconColor(theme, "warning"),
|
||||
iconColorError: iconColor(theme, "error"),
|
||||
text: text(layer, "sans", { size: "sm" }),
|
||||
iconColorOk: foreground(layer, "positive"),
|
||||
iconColorWarning: foreground(layer, "warning"),
|
||||
iconColorError: foreground(layer, "negative"),
|
||||
containerOk: {
|
||||
cornerRadius: 6,
|
||||
padding: { top: 3, bottom: 3, left: 7, right: 7 },
|
||||
},
|
||||
containerWarning: {
|
||||
...diagnosticStatusContainer,
|
||||
background: backgroundColor(theme, "warning"),
|
||||
border: border(theme, "warning"),
|
||||
background: background(layer, "warning"),
|
||||
border: border(layer, "warning"),
|
||||
},
|
||||
containerError: {
|
||||
...diagnosticStatusContainer,
|
||||
background: backgroundColor(theme, "error"),
|
||||
border: border(theme, "error"),
|
||||
background: background(layer, "negative"),
|
||||
border: border(layer, "negative"),
|
||||
},
|
||||
hover: {
|
||||
iconColorOk: iconColor(theme, "active"),
|
||||
iconColorOk: foreground(layer, "on"),
|
||||
containerOk: {
|
||||
cornerRadius: 6,
|
||||
padding: { top: 3, bottom: 3, left: 7, right: 7 },
|
||||
background: backgroundColor(theme, 300, "hovered"),
|
||||
background: background(layer, "on", "hovered"),
|
||||
},
|
||||
containerWarning: {
|
||||
...diagnosticStatusContainer,
|
||||
background: backgroundColor(theme, "warning", "hovered"),
|
||||
border: border(theme, "warning"),
|
||||
background: background(layer, "warning", "hovered"),
|
||||
border: border(layer, "warning", "hovered"),
|
||||
},
|
||||
containerError: {
|
||||
...diagnosticStatusContainer,
|
||||
background: backgroundColor(theme, "error", "hovered"),
|
||||
border: border(theme, "error"),
|
||||
background: background(layer, "negative", "hovered"),
|
||||
border: border(layer, "negative", "hovered"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -95,22 +96,22 @@ export default function statusBar(theme: Theme) {
|
|||
item: {
|
||||
...statusContainer,
|
||||
iconSize: 16,
|
||||
iconColor: iconColor(theme, "muted"),
|
||||
iconColor: foreground(layer),
|
||||
hover: {
|
||||
iconColor: iconColor(theme, "active"),
|
||||
background: backgroundColor(theme, 300, "hovered"),
|
||||
iconColor: foreground(layer, "base", "hovered"),
|
||||
background: background(layer, "base", "hovered"),
|
||||
},
|
||||
active: {
|
||||
iconColor: iconColor(theme, "active"),
|
||||
background: backgroundColor(theme, 300, "active"),
|
||||
iconColor: foreground(layer, "base", "active"),
|
||||
background: background(layer, "base", "active"),
|
||||
},
|
||||
},
|
||||
badge: {
|
||||
cornerRadius: 3,
|
||||
padding: 2,
|
||||
margin: { bottom: -1, right: -1 },
|
||||
border: { width: 1, color: workspaceBackground(theme) },
|
||||
background: iconColor(theme, "feature"),
|
||||
border: border(layer),
|
||||
background: background(layer),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,39 +1,42 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import { withOpacity } from "../utils/color";
|
||||
import { iconColor, text, border, backgroundColor, draggedShadow } from "./components";
|
||||
import { text, border, background, foreground } from "./components";
|
||||
|
||||
export default function tabBar(theme: Theme) {
|
||||
export default function tabBar(colorScheme: ColorScheme) {
|
||||
const height = 32;
|
||||
|
||||
let elevation = colorScheme.lowest;
|
||||
let layer = elevation.middle;
|
||||
|
||||
const tab = {
|
||||
height,
|
||||
background: backgroundColor(theme, 300),
|
||||
border: border(theme, "primary", {
|
||||
background: background(layer),
|
||||
border: border(layer, {
|
||||
left: true,
|
||||
bottom: true,
|
||||
overlay: true,
|
||||
}),
|
||||
iconClose: iconColor(theme, "muted"),
|
||||
iconCloseActive: iconColor(theme, "active"),
|
||||
iconConflict: iconColor(theme, "warning"),
|
||||
iconDirty: iconColor(theme, "info"),
|
||||
iconClose: foreground(layer),
|
||||
iconCloseActive: foreground(layer, "base", "active"),
|
||||
iconConflict: foreground(layer, "warning"),
|
||||
iconDirty: foreground(layer, "info"),
|
||||
iconWidth: 8,
|
||||
spacing: 8,
|
||||
text: text(theme, "sans", "secondary", { size: "sm" }),
|
||||
text: text(layer, "sans", { size: "sm" }),
|
||||
padding: {
|
||||
left: 8,
|
||||
right: 8,
|
||||
},
|
||||
description: {
|
||||
margin: { left: 6, top: 1 },
|
||||
...text(theme, "sans", "muted", { size: "2xs" })
|
||||
...text(layer, "sans", "base", "variant", { size: "2xs" })
|
||||
}
|
||||
};
|
||||
|
||||
const activePaneActiveTab = {
|
||||
...tab,
|
||||
background: backgroundColor(theme, 500),
|
||||
text: text(theme, "sans", "active", { size: "sm" }),
|
||||
background: background(elevation.top),
|
||||
text: text(elevation.top, "sans", "base", "active", { size: "sm" }),
|
||||
border: {
|
||||
...tab.border,
|
||||
bottom: false
|
||||
|
@ -42,14 +45,14 @@ export default function tabBar(theme: Theme) {
|
|||
|
||||
const inactivePaneInactiveTab = {
|
||||
...tab,
|
||||
background: backgroundColor(theme, 300),
|
||||
text: text(theme, "sans", "muted", { size: "sm" }),
|
||||
background: background(layer),
|
||||
text: text(layer, "sans", { size: "sm" }),
|
||||
};
|
||||
|
||||
const inactivePaneActiveTab = {
|
||||
...tab,
|
||||
background: backgroundColor(theme, 500),
|
||||
text: text(theme, "sans", "secondary", { size: "sm" }),
|
||||
background: background(layer),
|
||||
text: text(layer, "sans", "base", "active", { size: "sm" }),
|
||||
border: {
|
||||
...tab.border,
|
||||
bottom: false
|
||||
|
@ -59,15 +62,16 @@ export default function tabBar(theme: Theme) {
|
|||
const draggedTab = {
|
||||
...activePaneActiveTab,
|
||||
background: withOpacity(tab.background, 0.8),
|
||||
border: undefined as any, // Remove border
|
||||
shadow: draggedShadow(theme),
|
||||
border: undefined as any,
|
||||
shadow: elevation.above.shadow,
|
||||
}
|
||||
|
||||
return {
|
||||
height,
|
||||
background: backgroundColor(theme, 300),
|
||||
dropTargetOverlayColor: withOpacity(theme.textColor.muted, 0.6),
|
||||
border: border(theme, "primary", {
|
||||
background: background(layer),
|
||||
dropTargetOverlayColor: withOpacity(foreground(layer), 0.6),
|
||||
border: border(layer, {
|
||||
left: true,
|
||||
bottom: true,
|
||||
overlay: true,
|
||||
}),
|
||||
|
@ -81,11 +85,11 @@ export default function tabBar(theme: Theme) {
|
|||
},
|
||||
draggedTab,
|
||||
paneButton: {
|
||||
color: iconColor(theme, "secondary"),
|
||||
color: foreground(layer),
|
||||
iconWidth: 12,
|
||||
buttonWidth: activePaneActiveTab.height,
|
||||
hover: {
|
||||
color: iconColor(theme, "active"),
|
||||
color: foreground(layer, "base", "hovered"),
|
||||
},
|
||||
},
|
||||
paneButtonContainer: {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { border, modalShadow, player } from "./components";
|
||||
import { Elevation } from "../themes/common/colorScheme";
|
||||
|
||||
export default function terminal(theme: Theme) {
|
||||
export default function terminal(elevation: Elevation) {
|
||||
/**
|
||||
* Colors are controlled per-cell in the terminal grid.
|
||||
* Cells can be set to any of these more 'theme-capable' colors
|
||||
|
@ -9,57 +8,45 @@ export default function terminal(theme: Theme) {
|
|||
* Here are the common interpretations of these names:
|
||||
* https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
|
||||
*/
|
||||
let colors = {
|
||||
black: theme.ramps.neutral(0).hex(),
|
||||
red: theme.ramps.red(0.5).hex(),
|
||||
green: theme.ramps.green(0.5).hex(),
|
||||
yellow: theme.ramps.yellow(0.5).hex(),
|
||||
blue: theme.ramps.blue(0.5).hex(),
|
||||
magenta: theme.ramps.magenta(0.5).hex(),
|
||||
cyan: theme.ramps.cyan(0.5).hex(),
|
||||
white: theme.ramps.neutral(7).hex(),
|
||||
brightBlack: theme.ramps.neutral(4).hex(),
|
||||
brightRed: theme.ramps.red(0.25).hex(),
|
||||
brightGreen: theme.ramps.green(0.25).hex(),
|
||||
brightYellow: theme.ramps.yellow(0.25).hex(),
|
||||
brightBlue: theme.ramps.blue(0.25).hex(),
|
||||
brightMagenta: theme.ramps.magenta(0.25).hex(),
|
||||
brightCyan: theme.ramps.cyan(0.25).hex(),
|
||||
brightWhite: theme.ramps.neutral(7).hex(),
|
||||
return {
|
||||
black: elevation.ramps.neutral(0).hex(),
|
||||
red: elevation.ramps.red(0.5).hex(),
|
||||
green: elevation.ramps.green(0.5).hex(),
|
||||
yellow: elevation.ramps.yellow(0.5).hex(),
|
||||
blue: elevation.ramps.blue(0.5).hex(),
|
||||
magenta: elevation.ramps.magenta(0.5).hex(),
|
||||
cyan: elevation.ramps.cyan(0.5).hex(),
|
||||
white: elevation.ramps.neutral(1).hex(),
|
||||
brightBlack: elevation.ramps.neutral(0.4).hex(),
|
||||
brightRed: elevation.ramps.red(0.25).hex(),
|
||||
brightGreen: elevation.ramps.green(0.25).hex(),
|
||||
brightYellow: elevation.ramps.yellow(0.25).hex(),
|
||||
brightBlue: elevation.ramps.blue(0.25).hex(),
|
||||
brightMagenta: elevation.ramps.magenta(0.25).hex(),
|
||||
brightCyan: elevation.ramps.cyan(0.25).hex(),
|
||||
brightWhite: elevation.ramps.neutral(1).hex(),
|
||||
/**
|
||||
* Default color for characters
|
||||
*/
|
||||
foreground: theme.ramps.neutral(7).hex(),
|
||||
foreground: elevation.ramps.neutral(1).hex(),
|
||||
/**
|
||||
* Default color for the rectangle background of a cell
|
||||
*/
|
||||
background: theme.ramps.neutral(0).hex(),
|
||||
modalBackground: theme.ramps.neutral(1).hex(),
|
||||
background: elevation.ramps.neutral(0).hex(),
|
||||
modalBackground: elevation.ramps.neutral(0.1).hex(),
|
||||
/**
|
||||
* Default color for the cursor
|
||||
*/
|
||||
cursor: player(theme, 1).selection.cursor,
|
||||
dimBlack: theme.ramps.neutral(7).hex(),
|
||||
dimRed: theme.ramps.red(0.75).hex(),
|
||||
dimGreen: theme.ramps.green(0.75).hex(),
|
||||
dimYellow: theme.ramps.yellow(0.75).hex(),
|
||||
dimBlue: theme.ramps.blue(0.75).hex(),
|
||||
dimMagenta: theme.ramps.magenta(0.75).hex(),
|
||||
dimCyan: theme.ramps.cyan(0.75).hex(),
|
||||
dimWhite: theme.ramps.neutral(5).hex(),
|
||||
brightForeground: theme.ramps.neutral(7).hex(),
|
||||
dimForeground: theme.ramps.neutral(0).hex(),
|
||||
};
|
||||
|
||||
return {
|
||||
colors,
|
||||
modalContainer: {
|
||||
background: colors.modalBackground,
|
||||
cornerRadius: 8,
|
||||
padding: 8,
|
||||
margin: 25,
|
||||
border: border(theme, "primary"),
|
||||
shadow: modalShadow(theme),
|
||||
},
|
||||
cursor: elevation.ramps.blue(0).hex(),
|
||||
dimBlack: elevation.ramps.neutral(1).hex(),
|
||||
dimRed: elevation.ramps.red(0.75).hex(),
|
||||
dimGreen: elevation.ramps.green(0.75).hex(),
|
||||
dimYellow: elevation.ramps.yellow(0.75).hex(),
|
||||
dimBlue: elevation.ramps.blue(0.75).hex(),
|
||||
dimMagenta: elevation.ramps.magenta(0.75).hex(),
|
||||
dimCyan: elevation.ramps.cyan(0.75).hex(),
|
||||
dimWhite: elevation.ramps.neutral(0.6).hex(),
|
||||
brightForeground: elevation.ramps.neutral(1).hex(),
|
||||
dimForeground: elevation.ramps.neutral(0).hex(),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { backgroundColor, border, popoverShadow, text } from "./components";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import { background, border, text } from "./components";
|
||||
|
||||
export default function tooltip(theme: Theme) {
|
||||
export default function tooltip(colorScheme: ColorScheme) {
|
||||
let elevation = colorScheme.middle;
|
||||
let layer = colorScheme.middle.middle;
|
||||
return {
|
||||
background: backgroundColor(theme, 500),
|
||||
border: border(theme, "secondary"),
|
||||
background: background(layer),
|
||||
border: border(layer),
|
||||
padding: { top: 4, bottom: 4, left: 8, right: 8 },
|
||||
margin: { top: 6, left: 6 },
|
||||
shadow: popoverShadow(theme),
|
||||
shadow: elevation.shadow,
|
||||
cornerRadius: 6,
|
||||
text: text(theme, "sans", "primary", { size: "xs" }),
|
||||
text: text(layer, "sans", { size: "xs" }),
|
||||
keystroke: {
|
||||
background: backgroundColor(theme, "on500"),
|
||||
background: background(layer, "on"),
|
||||
cornerRadius: 4,
|
||||
margin: { left: 6 },
|
||||
padding: { left: 4, right: 4 },
|
||||
...text(theme, "mono", "secondary", { size: "xs", weight: "bold" }),
|
||||
...text(layer, "mono", "on", { size: "xs", weight: "bold" }),
|
||||
},
|
||||
maxTextWidth: 200,
|
||||
};
|
||||
|
|
|
@ -1,29 +1,30 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { iconColor, text } from "./components";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import { foreground, text } from "./components";
|
||||
|
||||
const headerPadding = 8;
|
||||
|
||||
export default function updateNotification(theme: Theme): Object {
|
||||
export default function updateNotification(colorScheme: ColorScheme): Object {
|
||||
let layer = colorScheme.middle.middle;
|
||||
return {
|
||||
message: {
|
||||
...text(theme, "sans", "primary", { size: "xs" }),
|
||||
...text(layer, "sans", { size: "xs" }),
|
||||
margin: { left: headerPadding, right: headerPadding },
|
||||
},
|
||||
actionMessage: {
|
||||
...text(theme, "sans", "secondary", { size: "xs" }),
|
||||
...text(layer, "sans", { size: "xs" }),
|
||||
margin: { left: headerPadding, top: 6, bottom: 6 },
|
||||
hover: {
|
||||
color: theme.textColor["active"],
|
||||
color: foreground(layer, "base", "hovered"),
|
||||
},
|
||||
},
|
||||
dismissButton: {
|
||||
color: iconColor(theme, "secondary"),
|
||||
color: foreground(layer),
|
||||
iconWidth: 8,
|
||||
iconHeight: 8,
|
||||
buttonWidth: 8,
|
||||
buttonHeight: 8,
|
||||
hover: {
|
||||
color: iconColor(theme, "primary"),
|
||||
color: foreground(layer, "base", "hovered"),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,35 +1,33 @@
|
|||
import Theme from "../themes/common/theme";
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import { withOpacity } from "../utils/color";
|
||||
import {
|
||||
backgroundColor,
|
||||
background,
|
||||
border,
|
||||
iconColor,
|
||||
modalShadow,
|
||||
text,
|
||||
borderColor,
|
||||
foreground,
|
||||
text
|
||||
} from "./components";
|
||||
import statusBar from "./statusBar";
|
||||
import tabBar from "./tabBar";
|
||||
|
||||
export function workspaceBackground(theme: Theme) {
|
||||
return backgroundColor(theme, 300);
|
||||
}
|
||||
|
||||
export default function workspace(theme: Theme) {
|
||||
export default function workspace(colorScheme: ColorScheme) {
|
||||
const elevation = colorScheme.lowest;
|
||||
const layer = elevation.middle;
|
||||
const titlebarPadding = 6;
|
||||
|
||||
return {
|
||||
background: backgroundColor(theme, 300),
|
||||
background: background(layer),
|
||||
joiningProjectAvatar: {
|
||||
cornerRadius: 40,
|
||||
width: 80,
|
||||
},
|
||||
joiningProjectMessage: {
|
||||
padding: 12,
|
||||
...text(theme, "sans", "primary", { size: "lg" }),
|
||||
...text(layer, "sans", { size: "lg" }),
|
||||
},
|
||||
leaderBorderOpacity: 0.7,
|
||||
leaderBorderWidth: 2.0,
|
||||
tabBar: tabBar(theme),
|
||||
tabBar: tabBar(colorScheme),
|
||||
modal: {
|
||||
margin: {
|
||||
bottom: 52,
|
||||
|
@ -39,28 +37,26 @@ export default function workspace(theme: Theme) {
|
|||
},
|
||||
sidebar: {
|
||||
initialSize: 240,
|
||||
border: {
|
||||
color: border(theme, "primary").color,
|
||||
width: 1,
|
||||
left: true,
|
||||
right: true,
|
||||
}
|
||||
border: border(
|
||||
layer,
|
||||
{ left: true, right: true }
|
||||
),
|
||||
},
|
||||
paneDivider: {
|
||||
color: border(theme, "secondary").color,
|
||||
color: borderColor(layer),
|
||||
width: 1,
|
||||
},
|
||||
statusBar: statusBar(theme),
|
||||
statusBar: statusBar(colorScheme),
|
||||
titlebar: {
|
||||
avatarWidth: 18,
|
||||
avatarMargin: 8,
|
||||
height: 33,
|
||||
background: backgroundColor(theme, 100),
|
||||
background: background(layer),
|
||||
padding: {
|
||||
left: 80,
|
||||
right: titlebarPadding,
|
||||
},
|
||||
title: text(theme, "sans", "primary"),
|
||||
title: text(layer, "sans"),
|
||||
avatar: {
|
||||
cornerRadius: 10,
|
||||
border: {
|
||||
|
@ -74,10 +70,10 @@ export default function workspace(theme: Theme) {
|
|||
// TODO: The background for this ideally should be
|
||||
// set with a token, not hardcoded in rust
|
||||
},
|
||||
border: border(theme, "primary", { bottom: true, overlay: true }),
|
||||
border: border(layer, { bottom: true, overlay: true }),
|
||||
signInPrompt: {
|
||||
background: backgroundColor(theme, 100),
|
||||
border: border(theme, "secondary"),
|
||||
background: background(layer),
|
||||
border: border(layer),
|
||||
cornerRadius: 6,
|
||||
margin: {
|
||||
top: 1,
|
||||
|
@ -88,15 +84,15 @@ export default function workspace(theme: Theme) {
|
|||
left: 7,
|
||||
right: 7,
|
||||
},
|
||||
...text(theme, "sans", "secondary", { size: "xs" }),
|
||||
...text(layer, "sans", { size: "xs" }),
|
||||
hover: {
|
||||
...text(theme, "sans", "active", { size: "xs" }),
|
||||
background: backgroundColor(theme, "on300", "hovered"),
|
||||
border: border(theme, "primary"),
|
||||
...text(layer, "sans", "on", "hovered", { size: "xs" }),
|
||||
background: background(layer, "on", "hovered"),
|
||||
border: border(layer, "on", "hovered"),
|
||||
},
|
||||
},
|
||||
offlineIcon: {
|
||||
color: iconColor(theme, "secondary"),
|
||||
color: foreground(layer, "on"),
|
||||
width: 16,
|
||||
margin: {
|
||||
left: titlebarPadding,
|
||||
|
@ -106,9 +102,9 @@ export default function workspace(theme: Theme) {
|
|||
},
|
||||
},
|
||||
outdatedWarning: {
|
||||
...text(theme, "sans", "warning", { size: "xs" }),
|
||||
background: backgroundColor(theme, "warning"),
|
||||
border: border(theme, "warning"),
|
||||
...text(layer, "sans", "warning", { size: "xs" }),
|
||||
background: background(layer, "warning"),
|
||||
border: border(layer, "warning"),
|
||||
margin: {
|
||||
left: titlebarPadding,
|
||||
},
|
||||
|
@ -121,39 +117,39 @@ export default function workspace(theme: Theme) {
|
|||
},
|
||||
toolbar: {
|
||||
height: 34,
|
||||
background: backgroundColor(theme, 500),
|
||||
border: border(theme, "secondary", { bottom: true }),
|
||||
background: background(layer),
|
||||
border: border(layer, "base", "variant", { bottom: true }),
|
||||
itemSpacing: 8,
|
||||
navButton: {
|
||||
color: iconColor(theme, "primary"),
|
||||
color: foreground(layer, "on"),
|
||||
iconWidth: 12,
|
||||
buttonWidth: 24,
|
||||
cornerRadius: 6,
|
||||
hover: {
|
||||
color: iconColor(theme, "active"),
|
||||
background: backgroundColor(theme, "on500", "hovered"),
|
||||
color: foreground(layer, "on", "hovered"),
|
||||
background: background(layer, "on", "hovered"),
|
||||
},
|
||||
disabled: {
|
||||
color: withOpacity(iconColor(theme, "muted"), 0.6),
|
||||
color: foreground(layer, "on", "disabled"),
|
||||
},
|
||||
},
|
||||
padding: { left: 8, right: 8, top: 4, bottom: 4 },
|
||||
},
|
||||
breadcrumbs: {
|
||||
...text(theme, "mono", "secondary"),
|
||||
...text(layer, "mono", "on", "variant"),
|
||||
padding: { left: 6 },
|
||||
},
|
||||
disconnectedOverlay: {
|
||||
...text(theme, "sans", "active"),
|
||||
background: withOpacity(theme.backgroundColor[500].base, 0.8),
|
||||
...text(layer, "sans"),
|
||||
background: withOpacity(background(layer), 0.8),
|
||||
},
|
||||
notification: {
|
||||
margin: { top: 10 },
|
||||
background: backgroundColor(theme, 300),
|
||||
background: background(elevation.above.middle),
|
||||
cornerRadius: 6,
|
||||
padding: 12,
|
||||
border: border(theme, "primary"),
|
||||
shadow: modalShadow(theme),
|
||||
border: border(elevation.above.middle),
|
||||
shadow: elevation.above.shadow,
|
||||
},
|
||||
notifications: {
|
||||
width: 400,
|
||||
|
@ -162,17 +158,14 @@ export default function workspace(theme: Theme) {
|
|||
dock: {
|
||||
initialSizeRight: 640,
|
||||
initialSizeBottom: 480,
|
||||
wash_color: withOpacity(theme.backgroundColor[500].base, 0.5),
|
||||
wash_color: withOpacity(background(elevation.top), 0.5),
|
||||
panel: {
|
||||
border: {
|
||||
...border(theme, "secondary"),
|
||||
width: 1
|
||||
},
|
||||
border: border(elevation.top),
|
||||
},
|
||||
maximized: {
|
||||
margin: 24,
|
||||
border: border(theme, "secondary", { "overlay": true }),
|
||||
shadow: modalShadow(theme),
|
||||
margin: 32,
|
||||
border: border(elevation.above.top, { "overlay": true }),
|
||||
shadow: elevation.above.shadow,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
import Theme from "./themes/common/theme";
|
||||
|
||||
const themes: Theme[] = [];
|
||||
export default themes;
|
||||
|
||||
const internalThemes: Theme[] = [];
|
||||
export { internalThemes }
|
||||
|
||||
const experimentalThemes: Theme[] = [];
|
||||
export { experimentalThemes }
|
||||
|
||||
|
||||
function fillThemes(themesPath: string, themes: Theme[]) {
|
||||
for (const fileName of fs.readdirSync(themesPath)) {
|
||||
if (fileName == "template.ts") continue;
|
||||
const filePath = path.join(themesPath, fileName);
|
||||
|
||||
if (fs.statSync(filePath).isFile()) {
|
||||
const theme = require(filePath);
|
||||
if (theme.dark) themes.push(theme.dark);
|
||||
if (theme.light) themes.push(theme.light);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fillThemes(path.resolve(`${__dirname}/themes`), themes)
|
||||
fillThemes(path.resolve(`${__dirname}/themes/internal`), internalThemes)
|
||||
fillThemes(path.resolve(`${__dirname}/themes/experiments`), experimentalThemes)
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
const name = "abruzzo";
|
||||
|
||||
|
@ -24,5 +24,5 @@ const ramps = {
|
|||
magenta: colorRamp(chroma("#c1a3ef")),
|
||||
};
|
||||
|
||||
export const dark = createTheme(`${name}`, false, ramps);
|
||||
export const dark = createColorScheme(`${name}`, false, ramps);
|
||||
// export const light = createTheme(`${name}-light`, true, ramps);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
const name = "andromeda";
|
||||
|
||||
|
@ -24,4 +24,4 @@ const ramps = {
|
|||
magenta: colorRamp(chroma("#C74DED")),
|
||||
};
|
||||
|
||||
export const dark = createTheme(`${name}`, false, ramps);
|
||||
export const dark = createColorScheme(`${name}`, false, ramps);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
const name = "brush-tree";
|
||||
|
||||
|
@ -24,5 +24,5 @@ const ramps = {
|
|||
magenta: colorRamp(chroma("#b39f9f")),
|
||||
};
|
||||
|
||||
export const dark = createTheme(`${name}-dark`, false, ramps);
|
||||
export const light = createTheme(`${name}-light`, true, ramps);
|
||||
export const dark = createColorScheme(`${name}-dark`, false, ramps);
|
||||
export const light = createColorScheme(`${name}-light`, true, ramps);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
const name = "cave";
|
||||
|
||||
|
@ -24,5 +24,5 @@ const ramps = {
|
|||
magenta: colorRamp(chroma("#bf40bf")),
|
||||
};
|
||||
|
||||
export const dark = createTheme(`${name}-dark`, false, ramps);
|
||||
export const light = createTheme(`${name}-light`, true, ramps);
|
||||
export const dark = createColorScheme(`${name}-dark`, false, ramps);
|
||||
export const light = createColorScheme(`${name}-light`, true, ramps);
|
||||
|
|
|
@ -1,288 +0,0 @@
|
|||
import chroma, { Color, Scale } from "chroma-js";
|
||||
import { fontWeights } from "../../common";
|
||||
import { withOpacity } from "../../utils/color";
|
||||
import Theme, { buildPlayer, Syntax } from "./theme";
|
||||
|
||||
export function colorRamp(color: Color): Scale {
|
||||
let hue = color.hsl()[0];
|
||||
let endColor = chroma.hsl(hue, 0.88, 0.96);
|
||||
let startColor = chroma.hsl(hue, 0.68, 0.12);
|
||||
return chroma.scale([startColor, color, endColor]).mode("hsl");
|
||||
}
|
||||
|
||||
export function createTheme(
|
||||
name: string,
|
||||
isLight: boolean,
|
||||
color_ramps: { [rampName: string]: Scale }
|
||||
): Theme {
|
||||
let ramps: typeof color_ramps = {};
|
||||
// Chromajs mutates the underlying ramp when you call domain. This causes problems because
|
||||
// we now store the ramps object in the theme so that we can pull colors out of them.
|
||||
// So instead of calling domain and storing the result, we have to construct new ramps for each
|
||||
// theme so that we don't modify the passed in ramps.
|
||||
// This combined with an error in the type definitions for chroma js means we have to cast the colors
|
||||
// function to any in order to get the colors back out from the original ramps.
|
||||
if (isLight) {
|
||||
for (var rampName in color_ramps) {
|
||||
ramps[rampName] = chroma
|
||||
.scale((color_ramps[rampName].colors as any)())
|
||||
.domain([1, 0]);
|
||||
}
|
||||
ramps.neutral = chroma
|
||||
.scale((color_ramps.neutral.colors as any)())
|
||||
.domain([7, 0]);
|
||||
} else {
|
||||
for (var rampName in color_ramps) {
|
||||
ramps[rampName] = chroma
|
||||
.scale((color_ramps[rampName].colors as any)())
|
||||
.domain([0, 1]);
|
||||
}
|
||||
ramps.neutral = chroma
|
||||
.scale((color_ramps.neutral.colors as any)())
|
||||
.domain([0, 7]);
|
||||
}
|
||||
|
||||
let blend = isLight ? 0.12 : 0.24;
|
||||
|
||||
function sample(ramp: Scale, index: number): string {
|
||||
return ramp(index).hex();
|
||||
}
|
||||
const darkest = ramps.neutral(isLight ? 7 : 0).hex();
|
||||
|
||||
const backgroundColor = {
|
||||
// Title bar
|
||||
100: {
|
||||
base: sample(ramps.neutral, 1.25),
|
||||
hovered: sample(ramps.neutral, 1.5),
|
||||
active: sample(ramps.neutral, 1.75),
|
||||
},
|
||||
// Midground (panels, etc)
|
||||
300: {
|
||||
base: sample(ramps.neutral, 1),
|
||||
hovered: sample(ramps.neutral, 1.25),
|
||||
active: sample(ramps.neutral, 1.5),
|
||||
},
|
||||
// Editor
|
||||
500: {
|
||||
base: sample(ramps.neutral, 0),
|
||||
hovered: sample(ramps.neutral, 0.25),
|
||||
active: sample(ramps.neutral, 0.5),
|
||||
},
|
||||
on300: {
|
||||
base: sample(ramps.neutral, 0),
|
||||
hovered: sample(ramps.neutral, 0.5),
|
||||
active: sample(ramps.neutral, 1),
|
||||
},
|
||||
on500: {
|
||||
base: sample(ramps.neutral, 1),
|
||||
hovered: sample(ramps.neutral, 1.5),
|
||||
active: sample(ramps.neutral, 2),
|
||||
},
|
||||
ok: {
|
||||
base: withOpacity(sample(ramps.green, 0.5), 0.15),
|
||||
hovered: withOpacity(sample(ramps.green, 0.5), 0.2),
|
||||
active: withOpacity(sample(ramps.green, 0.5), 0.25),
|
||||
},
|
||||
error: {
|
||||
base: withOpacity(sample(ramps.red, 0.5), 0.15),
|
||||
hovered: withOpacity(sample(ramps.red, 0.5), 0.2),
|
||||
active: withOpacity(sample(ramps.red, 0.5), 0.25),
|
||||
},
|
||||
on500Error: {
|
||||
base: sample(ramps.red, 0.05),
|
||||
hovered: sample(ramps.red, 0.1),
|
||||
active: sample(ramps.red, 0.15),
|
||||
},
|
||||
warning: {
|
||||
base: withOpacity(sample(ramps.yellow, 0.5), 0.15),
|
||||
hovered: withOpacity(sample(ramps.yellow, 0.5), 0.2),
|
||||
active: withOpacity(sample(ramps.yellow, 0.5), 0.25),
|
||||
},
|
||||
on500Warning: {
|
||||
base: sample(ramps.yellow, 0.05),
|
||||
hovered: sample(ramps.yellow, 0.1),
|
||||
active: sample(ramps.yellow, 0.15),
|
||||
},
|
||||
info: {
|
||||
base: withOpacity(sample(ramps.blue, 0.5), 0.15),
|
||||
hovered: withOpacity(sample(ramps.blue, 0.5), 0.2),
|
||||
active: withOpacity(sample(ramps.blue, 0.5), 0.25),
|
||||
},
|
||||
on500Info: {
|
||||
base: sample(ramps.blue, 0.05),
|
||||
hovered: sample(ramps.blue, 0.1),
|
||||
active: sample(ramps.blue, 0.15),
|
||||
},
|
||||
};
|
||||
|
||||
const borderColor = {
|
||||
primary: sample(ramps.neutral, isLight ? 1.5 : 0),
|
||||
secondary: sample(ramps.neutral, isLight ? 1.25 : 1),
|
||||
muted: sample(ramps.neutral, isLight ? 1 : 3),
|
||||
active: sample(ramps.neutral, isLight ? 4 : 3),
|
||||
onMedia: withOpacity(darkest, 0.1),
|
||||
ok: sample(ramps.green, 0.3),
|
||||
error: sample(ramps.red, 0.3),
|
||||
warning: sample(ramps.yellow, 0.3),
|
||||
info: sample(ramps.blue, 0.3),
|
||||
};
|
||||
|
||||
const textColor = {
|
||||
primary: sample(ramps.neutral, 6),
|
||||
secondary: sample(ramps.neutral, 5),
|
||||
muted: sample(ramps.neutral, 4),
|
||||
placeholder: sample(ramps.neutral, 3),
|
||||
active: sample(ramps.neutral, 7),
|
||||
feature: sample(ramps.blue, 0.5),
|
||||
ok: sample(ramps.green, 0.5),
|
||||
error: sample(ramps.red, 0.5),
|
||||
warning: sample(ramps.yellow, 0.5),
|
||||
info: sample(ramps.blue, 0.5),
|
||||
onMedia: darkest,
|
||||
};
|
||||
|
||||
const player = {
|
||||
1: buildPlayer(sample(ramps.blue, 0.5)),
|
||||
2: buildPlayer(sample(ramps.green, 0.5)),
|
||||
3: buildPlayer(sample(ramps.magenta, 0.5)),
|
||||
4: buildPlayer(sample(ramps.orange, 0.5)),
|
||||
5: buildPlayer(sample(ramps.violet, 0.5)),
|
||||
6: buildPlayer(sample(ramps.cyan, 0.5)),
|
||||
7: buildPlayer(sample(ramps.red, 0.5)),
|
||||
8: buildPlayer(sample(ramps.yellow, 0.5)),
|
||||
};
|
||||
|
||||
const editor = {
|
||||
background: backgroundColor[500].base,
|
||||
indent_guide: borderColor.muted,
|
||||
indent_guide_active: borderColor.secondary,
|
||||
line: {
|
||||
active: sample(ramps.neutral, 1),
|
||||
highlighted: sample(ramps.neutral, 1.25), // TODO: Where is this used?
|
||||
},
|
||||
highlight: {
|
||||
selection: player[1].selectionColor,
|
||||
occurrence: withOpacity(sample(ramps.neutral, 3.5), blend),
|
||||
activeOccurrence: withOpacity(sample(ramps.neutral, 3.5), blend * 2), // TODO: Not hooked up - https://github.com/zed-industries/zed/issues/751
|
||||
matchingBracket: backgroundColor[500].active, // TODO: Not hooked up
|
||||
match: sample(ramps.violet, 0.15),
|
||||
activeMatch: withOpacity(sample(ramps.violet, 0.4), blend * 2), // TODO: Not hooked up - https://github.com/zed-industries/zed/issues/751
|
||||
related: backgroundColor[500].hovered,
|
||||
},
|
||||
gutter: {
|
||||
primary: textColor.placeholder,
|
||||
active: textColor.active,
|
||||
},
|
||||
};
|
||||
|
||||
const syntax: Syntax = {
|
||||
primary: {
|
||||
color: sample(ramps.neutral, 7),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
comment: {
|
||||
color: sample(ramps.neutral, 5),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
punctuation: {
|
||||
color: sample(ramps.neutral, 6),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
constant: {
|
||||
color: sample(ramps.neutral, 4),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
keyword: {
|
||||
color: sample(ramps.blue, 0.5),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
function: {
|
||||
color: sample(ramps.yellow, 0.5),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
type: {
|
||||
color: sample(ramps.cyan, 0.5),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
constructor: {
|
||||
color: sample(ramps.blue, 0.5),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
variant: {
|
||||
color: sample(ramps.blue, 0.5),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
property: {
|
||||
color: sample(ramps.blue, 0.5),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
enum: {
|
||||
color: sample(ramps.orange, 0.5),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
operator: {
|
||||
color: sample(ramps.orange, 0.5),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
string: {
|
||||
color: sample(ramps.orange, 0.5),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
number: {
|
||||
color: sample(ramps.green, 0.5),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
boolean: {
|
||||
color: sample(ramps.green, 0.5),
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
predictive: {
|
||||
color: textColor.muted,
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
title: {
|
||||
color: sample(ramps.yellow, 0.5),
|
||||
weight: fontWeights.bold,
|
||||
},
|
||||
emphasis: {
|
||||
color: textColor.feature,
|
||||
weight: fontWeights.normal,
|
||||
},
|
||||
"emphasis.strong": {
|
||||
color: textColor.feature,
|
||||
weight: fontWeights.bold,
|
||||
},
|
||||
linkUri: {
|
||||
color: sample(ramps.green, 0.5),
|
||||
weight: fontWeights.normal,
|
||||
underline: true,
|
||||
},
|
||||
linkText: {
|
||||
color: sample(ramps.orange, 0.5),
|
||||
weight: fontWeights.normal,
|
||||
italic: true,
|
||||
},
|
||||
};
|
||||
|
||||
const shadow = withOpacity(
|
||||
ramps
|
||||
.neutral(isLight ? 7 : 0)
|
||||
.darken()
|
||||
.hex(),
|
||||
blend
|
||||
);
|
||||
|
||||
return {
|
||||
name,
|
||||
isLight,
|
||||
backgroundColor,
|
||||
borderColor,
|
||||
textColor,
|
||||
iconColor: textColor,
|
||||
editor,
|
||||
syntax,
|
||||
player,
|
||||
shadow,
|
||||
ramps,
|
||||
};
|
||||
}
|
83
styles/src/themes/common/colorScheme.ts
Normal file
83
styles/src/themes/common/colorScheme.ts
Normal file
|
@ -0,0 +1,83 @@
|
|||
import { Scale } from "chroma-js";
|
||||
|
||||
export interface ColorScheme {
|
||||
name: string,
|
||||
isLight: boolean,
|
||||
|
||||
lowest: Elevation,
|
||||
middle: Elevation,
|
||||
highest: Elevation,
|
||||
|
||||
players: Players,
|
||||
}
|
||||
|
||||
export interface Player {
|
||||
cursor: string,
|
||||
selection: string,
|
||||
}
|
||||
|
||||
export interface Players {
|
||||
"0": Player,
|
||||
"1": Player,
|
||||
"2": Player,
|
||||
"3": Player,
|
||||
"4": Player,
|
||||
"5": Player,
|
||||
"6": Player,
|
||||
"7": Player,
|
||||
}
|
||||
|
||||
export interface Elevation {
|
||||
ramps: RampSet,
|
||||
|
||||
bottom: Layer,
|
||||
middle: Layer,
|
||||
top: Layer,
|
||||
|
||||
above?: Elevation,
|
||||
shadow?: Shadow
|
||||
}
|
||||
|
||||
export interface Shadow {
|
||||
blur: number,
|
||||
color: string,
|
||||
offset: number[],
|
||||
}
|
||||
|
||||
export type StyleSets = keyof Layer;
|
||||
export interface Layer {
|
||||
base: StyleSet,
|
||||
on: StyleSet,
|
||||
info: StyleSet,
|
||||
positive: StyleSet,
|
||||
warning: StyleSet,
|
||||
negative: StyleSet,
|
||||
}
|
||||
|
||||
export interface RampSet {
|
||||
neutral: Scale,
|
||||
red: Scale,
|
||||
orange: Scale,
|
||||
yellow: Scale,
|
||||
green: Scale,
|
||||
cyan: Scale,
|
||||
blue: Scale,
|
||||
violet: Scale,
|
||||
magenta: Scale,
|
||||
}
|
||||
|
||||
export type Styles = keyof StyleSet;
|
||||
export interface StyleSet {
|
||||
default: Style,
|
||||
variant: Style,
|
||||
active: Style,
|
||||
disabled: Style,
|
||||
hovered: Style,
|
||||
pressed: Style,
|
||||
}
|
||||
|
||||
export interface Style {
|
||||
background: string,
|
||||
border: string,
|
||||
foreground: string,
|
||||
}
|
176
styles/src/themes/common/ramps.ts
Normal file
176
styles/src/themes/common/ramps.ts
Normal file
|
@ -0,0 +1,176 @@
|
|||
import chroma, { Color, Scale } from "chroma-js";
|
||||
import { ColorScheme, Elevation, Layer, Player, RampSet, Shadow, Style, StyleSet } from "./colorScheme";
|
||||
|
||||
export function colorRamp(color: Color): Scale {
|
||||
let hue = color.hsl()[0];
|
||||
let endColor = chroma.hsl(hue, 0.88, 0.96);
|
||||
let startColor = chroma.hsl(hue, 0.68, 0.12);
|
||||
return chroma.scale([startColor, color, endColor]).mode("hsl");
|
||||
}
|
||||
|
||||
export function createColorScheme(name: string, isLight: boolean, colorRamps: { [rampName: string]: Scale }): ColorScheme {
|
||||
// Chromajs scales from 0 to 1 flipped if isLight is true
|
||||
let baseRamps: typeof colorRamps = {};
|
||||
|
||||
// Chromajs mutates the underlying ramp when you call domain. This causes problems because
|
||||
// we now store the ramps object in the theme so that we can pull colors out of them.
|
||||
// So instead of calling domain and storing the result, we have to construct new ramps for each
|
||||
// theme so that we don't modify the passed in ramps.
|
||||
// This combined with an error in the type definitions for chroma js means we have to cast the colors
|
||||
// function to any in order to get the colors back out from the original ramps.
|
||||
if (isLight) {
|
||||
for (var rampName in colorRamps) {
|
||||
baseRamps[rampName] = chroma
|
||||
.scale((colorRamps[rampName].colors as any)())
|
||||
.domain([1, 0]);
|
||||
}
|
||||
baseRamps.neutral = chroma
|
||||
.scale((colorRamps.neutral.colors as any)())
|
||||
.domain([1, 0]);
|
||||
} else {
|
||||
for (var rampName in colorRamps) {
|
||||
baseRamps[rampName] = chroma
|
||||
.scale((colorRamps[rampName].colors as any)())
|
||||
.domain([0, 1]);
|
||||
}
|
||||
baseRamps.neutral = chroma
|
||||
.scale((colorRamps.neutral.colors as any)())
|
||||
.domain([0, 1]);
|
||||
}
|
||||
|
||||
let baseSet = {
|
||||
neutral: baseRamps.neutral,
|
||||
red: baseRamps.red,
|
||||
orange: baseRamps.orange,
|
||||
yellow: baseRamps.yellow,
|
||||
green: baseRamps.green,
|
||||
cyan: baseRamps.cyan,
|
||||
blue: baseRamps.blue,
|
||||
violet: baseRamps.violet,
|
||||
magenta: baseRamps.magenta,
|
||||
};
|
||||
|
||||
let lowest = elevation(
|
||||
resampleSet(
|
||||
baseSet,
|
||||
evenSamples(0, 1)
|
||||
),
|
||||
isLight,
|
||||
);
|
||||
|
||||
let middle = elevation(
|
||||
resampleSet(
|
||||
baseSet,
|
||||
evenSamples(0.125, 1)
|
||||
),
|
||||
isLight,
|
||||
{
|
||||
blur: 4,
|
||||
color: baseSet.neutral(isLight ? 7 : 0).darken().alpha(0.2).hex(), // TODO used blend previously. Replace with something else
|
||||
offset: [1, 2],
|
||||
}
|
||||
);
|
||||
lowest.above = middle;
|
||||
|
||||
let highest = elevation(
|
||||
resampleSet(
|
||||
baseSet,
|
||||
evenSamples(0.25, 1)
|
||||
),
|
||||
isLight,
|
||||
{
|
||||
blur: 16,
|
||||
color: baseSet.neutral(isLight ? 7 : 0).darken().alpha(0.2).hex(), // TODO used blend previously. Replace with something else
|
||||
offset: [0, 2],
|
||||
}
|
||||
);
|
||||
middle.above = highest;
|
||||
|
||||
let players = {
|
||||
"0": player(baseSet.blue),
|
||||
"1": player(baseSet.green),
|
||||
"2": player(baseSet.magenta),
|
||||
"3": player(baseSet.orange),
|
||||
"4": player(baseSet.violet),
|
||||
"5": player(baseSet.cyan),
|
||||
"6": player(baseSet.red),
|
||||
"7": player(baseSet.yellow),
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
isLight,
|
||||
|
||||
lowest,
|
||||
middle,
|
||||
highest,
|
||||
|
||||
players,
|
||||
};
|
||||
}
|
||||
|
||||
function player(ramp: Scale): Player {
|
||||
return {
|
||||
selection: ramp(0.5).alpha(0.24).hex(),
|
||||
cursor: ramp(0.5).hex(),
|
||||
}
|
||||
}
|
||||
|
||||
function evenSamples(min: number, max: number): number[] {
|
||||
return Array.from(Array(101).keys()).map((i) => (i / 100) * (max - min) + min);
|
||||
}
|
||||
|
||||
function resampleSet(ramps: RampSet, samples: number[]): RampSet {
|
||||
return {
|
||||
neutral: resample(ramps.neutral, samples),
|
||||
red: resample(ramps.neutral, samples),
|
||||
orange: resample(ramps.neutral, samples),
|
||||
yellow: resample(ramps.neutral, samples),
|
||||
green: resample(ramps.neutral, samples),
|
||||
cyan: resample(ramps.neutral, samples),
|
||||
blue: resample(ramps.neutral, samples),
|
||||
violet: resample(ramps.neutral, samples),
|
||||
magenta: resample(ramps.neutral, samples),
|
||||
}
|
||||
}
|
||||
|
||||
function resample(scale: Scale, samples: number[]): Scale {
|
||||
let newColors = samples.map((sample) => scale(sample));
|
||||
return chroma.scale(newColors);
|
||||
}
|
||||
|
||||
function elevation(ramps: RampSet, isLight: boolean, shadow?: Shadow): Elevation {
|
||||
let style: Style = {
|
||||
background: ramps.neutral(0.25).hex(),
|
||||
border: ramps.neutral(0.9).hex(),
|
||||
foreground: ramps.neutral(1).hex(),
|
||||
};
|
||||
|
||||
let styleSet: StyleSet = {
|
||||
default: style,
|
||||
variant: style,
|
||||
active: style,
|
||||
disabled: style,
|
||||
hovered: style,
|
||||
pressed: style,
|
||||
};
|
||||
|
||||
let layer: Layer = {
|
||||
base: styleSet,
|
||||
on: styleSet,
|
||||
info: styleSet,
|
||||
positive: styleSet,
|
||||
warning: styleSet,
|
||||
negative: styleSet
|
||||
};
|
||||
|
||||
return {
|
||||
ramps,
|
||||
|
||||
bottom: layer,
|
||||
middle: layer,
|
||||
top: layer,
|
||||
|
||||
shadow,
|
||||
};
|
||||
}
|
|
@ -1,164 +0,0 @@
|
|||
import { Scale } from "chroma-js";
|
||||
import { FontWeight } from "../../common";
|
||||
import { withOpacity } from "../../utils/color";
|
||||
|
||||
export interface SyntaxHighlightStyle {
|
||||
color: string;
|
||||
weight?: FontWeight;
|
||||
underline?: boolean;
|
||||
italic?: boolean;
|
||||
}
|
||||
|
||||
export interface Player {
|
||||
baseColor: string;
|
||||
cursorColor: string;
|
||||
selectionColor: string;
|
||||
borderColor: string;
|
||||
}
|
||||
export function buildPlayer(
|
||||
color: string,
|
||||
cursorOpacity?: number,
|
||||
selectionOpacity?: number,
|
||||
borderOpacity?: number
|
||||
) {
|
||||
return {
|
||||
baseColor: color,
|
||||
cursorColor: withOpacity(color, cursorOpacity || 1.0),
|
||||
selectionColor: withOpacity(color, selectionOpacity || 0.24),
|
||||
borderColor: withOpacity(color, borderOpacity || 0.8),
|
||||
};
|
||||
}
|
||||
|
||||
export interface BackgroundColorSet {
|
||||
base: string;
|
||||
hovered: string;
|
||||
active: string;
|
||||
}
|
||||
|
||||
export interface Syntax {
|
||||
primary: SyntaxHighlightStyle;
|
||||
comment: SyntaxHighlightStyle;
|
||||
punctuation: SyntaxHighlightStyle;
|
||||
constant: SyntaxHighlightStyle;
|
||||
keyword: SyntaxHighlightStyle;
|
||||
function: SyntaxHighlightStyle;
|
||||
type: SyntaxHighlightStyle;
|
||||
variant: SyntaxHighlightStyle;
|
||||
property: SyntaxHighlightStyle;
|
||||
enum: SyntaxHighlightStyle;
|
||||
operator: SyntaxHighlightStyle;
|
||||
string: SyntaxHighlightStyle;
|
||||
number: SyntaxHighlightStyle;
|
||||
boolean: SyntaxHighlightStyle;
|
||||
predictive: SyntaxHighlightStyle;
|
||||
title: SyntaxHighlightStyle;
|
||||
emphasis: SyntaxHighlightStyle;
|
||||
linkUri: SyntaxHighlightStyle;
|
||||
linkText: SyntaxHighlightStyle;
|
||||
|
||||
[key: string]: SyntaxHighlightStyle;
|
||||
}
|
||||
|
||||
export default interface Theme {
|
||||
name: string;
|
||||
isLight: boolean;
|
||||
backgroundColor: {
|
||||
// Basically just Title Bar
|
||||
// Lowest background level
|
||||
100: BackgroundColorSet;
|
||||
// Tab bars, panels, popovers
|
||||
// Mid-ground
|
||||
300: BackgroundColorSet;
|
||||
// The editor
|
||||
// Foreground
|
||||
500: BackgroundColorSet;
|
||||
// Hacks for elements on top of the midground
|
||||
// Buttons in a panel, tab bar, or panel
|
||||
on300: BackgroundColorSet;
|
||||
// Hacks for elements on top of the editor
|
||||
on500: BackgroundColorSet;
|
||||
ok: BackgroundColorSet;
|
||||
error: BackgroundColorSet;
|
||||
on500Error: BackgroundColorSet;
|
||||
warning: BackgroundColorSet;
|
||||
on500Warning: BackgroundColorSet;
|
||||
info: BackgroundColorSet;
|
||||
on500Info: BackgroundColorSet;
|
||||
};
|
||||
borderColor: {
|
||||
primary: string;
|
||||
secondary: string;
|
||||
muted: string;
|
||||
active: string;
|
||||
/**
|
||||
* Used for rendering borders on top of media like avatars, images, video, etc.
|
||||
*/
|
||||
onMedia: string;
|
||||
ok: string;
|
||||
error: string;
|
||||
warning: string;
|
||||
info: string;
|
||||
};
|
||||
textColor: {
|
||||
primary: string;
|
||||
secondary: string;
|
||||
muted: string;
|
||||
placeholder: string;
|
||||
active: string;
|
||||
feature: string;
|
||||
ok: string;
|
||||
error: string;
|
||||
warning: string;
|
||||
info: string;
|
||||
onMedia: string;
|
||||
};
|
||||
iconColor: {
|
||||
primary: string;
|
||||
secondary: string;
|
||||
muted: string;
|
||||
placeholder: string;
|
||||
active: string;
|
||||
feature: string;
|
||||
ok: string;
|
||||
error: string;
|
||||
warning: string;
|
||||
info: string;
|
||||
};
|
||||
editor: {
|
||||
background: string;
|
||||
indent_guide: string;
|
||||
indent_guide_active: string;
|
||||
line: {
|
||||
active: string;
|
||||
highlighted: string;
|
||||
};
|
||||
highlight: {
|
||||
selection: string;
|
||||
occurrence: string;
|
||||
activeOccurrence: string;
|
||||
matchingBracket: string;
|
||||
match: string;
|
||||
activeMatch: string;
|
||||
related: string;
|
||||
};
|
||||
gutter: {
|
||||
primary: string;
|
||||
active: string;
|
||||
};
|
||||
};
|
||||
|
||||
syntax: Syntax;
|
||||
|
||||
player: {
|
||||
1: Player;
|
||||
2: Player;
|
||||
3: Player;
|
||||
4: Player;
|
||||
5: Player;
|
||||
6: Player;
|
||||
7: Player;
|
||||
8: Player;
|
||||
};
|
||||
shadow: string;
|
||||
ramps: { [rampName: string]: Scale };
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
const name = "one";
|
||||
const author = "Chris Kempson (http://chriskempson.com)";
|
||||
|
@ -44,4 +44,4 @@ const ramps = {
|
|||
magenta: colorRamp(chroma(base0F)),
|
||||
};
|
||||
|
||||
export const dark = createTheme(`${name}-dark`, false, ramps);
|
||||
export const dark = createColorScheme(`${name}-dark`, false, ramps);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
const name = "one";
|
||||
const author = "Daniel Pfeifer (http://github.com/purpleKarrot)";
|
||||
|
@ -44,4 +44,4 @@ const ramps = {
|
|||
magenta: colorRamp(chroma(base0F)),
|
||||
};
|
||||
|
||||
export const light = createTheme(`${name}-light`, true, ramps);
|
||||
export const light = createColorScheme(`${name}-light`, true, ramps);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
const name = "rosé-pine-dawn";
|
||||
|
||||
|
@ -24,4 +24,4 @@ const ramps = {
|
|||
magenta: colorRamp(chroma("#79549F")),
|
||||
};
|
||||
|
||||
export const light = createTheme(`${name}`, true, ramps);
|
||||
export const light = createColorScheme(`${name}`, true, ramps);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
const name = "rosé-pine-moon";
|
||||
|
||||
|
@ -24,4 +24,4 @@ const ramps = {
|
|||
magenta: colorRamp(chroma("#AB6FE9")),
|
||||
};
|
||||
|
||||
export const dark = createTheme(`${name}`, false, ramps);
|
||||
export const dark = createColorScheme(`${name}`, false, ramps);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
const name = "rosé-pine";
|
||||
|
||||
|
@ -24,4 +24,4 @@ const ramps = {
|
|||
magenta: colorRamp(chroma("#AB6FE9")),
|
||||
};
|
||||
|
||||
export const dark = createTheme(`${name}`, false, ramps);
|
||||
export const dark = createColorScheme(`${name}`, false, ramps);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
const name = "sandcastle";
|
||||
|
||||
|
@ -24,4 +24,4 @@ const ramps = {
|
|||
magenta: colorRamp(chroma("#a87322")),
|
||||
};
|
||||
|
||||
export const dark = createTheme(`${name}`, false, ramps);
|
||||
export const dark = createColorScheme(`${name}`, false, ramps);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
const name = "solarized";
|
||||
|
||||
|
@ -24,5 +24,5 @@ const ramps = {
|
|||
magenta: colorRamp(chroma("#d33682")),
|
||||
};
|
||||
|
||||
export const dark = createTheme(`${name}-dark`, false, ramps);
|
||||
export const light = createTheme(`${name}-light`, true, ramps);
|
||||
export const dark = createColorScheme(`${name}-dark`, false, ramps);
|
||||
export const light = createColorScheme(`${name}-light`, true, ramps);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
const name = "sulphurpool";
|
||||
|
||||
|
@ -24,5 +24,5 @@ const ramps = {
|
|||
magenta: colorRamp(chroma("#9c637a")),
|
||||
};
|
||||
|
||||
export const dark = createTheme(`${name}-dark`, false, ramps);
|
||||
export const light = createTheme(`${name}-light`, true, ramps);
|
||||
export const dark = createColorScheme(`${name}-dark`, false, ramps);
|
||||
export const light = createColorScheme(`${name}-light`, true, ramps);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
const name = "summercamp";
|
||||
|
||||
|
@ -24,4 +24,4 @@ const ramps = {
|
|||
magenta: colorRamp(chroma("#F69BE7")),
|
||||
};
|
||||
|
||||
export const dark = createTheme(`${name}`, false, ramps);
|
||||
export const dark = createColorScheme(`${name}`, false, ramps);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
const name = "summerfruit";
|
||||
|
||||
|
@ -24,5 +24,5 @@ const ramps = {
|
|||
magenta: colorRamp(chroma("#CC6633")),
|
||||
};
|
||||
|
||||
export const dark = createTheme(`${name}-dark`, false, ramps);
|
||||
export const light = createTheme(`${name}-light`, true, ramps);
|
||||
export const dark = createColorScheme(`${name}-dark`, false, ramps);
|
||||
export const light = createColorScheme(`${name}-light`, true, ramps);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
**/
|
||||
|
||||
import chroma from "chroma-js";
|
||||
import { colorRamp, createTheme } from "./common/base16";
|
||||
import { colorRamp, createColorScheme } from "./common/ramps";
|
||||
|
||||
/**
|
||||
* Theme Name
|
||||
|
@ -56,14 +56,14 @@ const ramps = {
|
|||
};
|
||||
|
||||
/**
|
||||
* Theme Variants
|
||||
* Color Scheme Variants
|
||||
*
|
||||
* Currently we only support (and require) dark and light themes
|
||||
* Eventually you will be able to have only a light or dark theme,
|
||||
* and define other variants here.
|
||||
*
|
||||
* createTheme([name], [isLight], [arrayOfRamps])
|
||||
* createColorScheme([name], [isLight], [arrayOfRamps])
|
||||
**/
|
||||
|
||||
export const dark = createTheme(`${name}-dark`, false, ramps);
|
||||
export const light = createTheme(`${name}-light`, true, ramps);
|
||||
export const dark = createColorScheme(`${name}-dark`, false, ramps);
|
||||
export const light = createColorScheme(`${name}-light`, true, ramps);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue