Add affordance to copy user's invite link if they have a code

Nathan Sobo and Antonio Scandurra created

Co-Authored-By: Antonio Scandurra <me@as-cii.com>

Change summary

assets/themes/cave-dark.json                |  26 +
assets/themes/cave-light.json               |  26 +
assets/themes/solarized-dark.json           |  26 +
assets/themes/solarized-light.json          |  26 +
assets/themes/sulphurpool-dark.json         |  26 +
assets/themes/sulphurpool-light.json        |  26 +
crates/client/src/user.rs                   |  40 +
crates/collab/.env.template.toml            |   7 
crates/collab/src/main.rs                   |   3 
crates/collab/src/rpc.rs                    |  19 
crates/contacts_panel/src/contacts_panel.rs |  58 ++
crates/rpc/proto/zed.proto                  |  30 
crates/rpc/src/proto.rs                     |   1 
crates/theme/src/theme.rs                   |  19 
styles/dist/cave-dark.json                  | 519 +++++++++++++++++++++++
styles/dist/cave-light.json                 | 519 +++++++++++++++++++++++
styles/dist/solarized-light.json            |  10 
styles/dist/sulphurpool-dark.json           | 519 +++++++++++++++++++++++
styles/dist/sulphurpool-light.json          | 519 +++++++++++++++++++++++
styles/dist/tokens.json                     |  30 
styles/src/styleTree/contactsPanel.ts       |  12 
21 files changed, 2,414 insertions(+), 47 deletions(-)

Detailed changes

assets/themes/cave-dark.json 🔗

@@ -1256,7 +1256,7 @@
   "contacts_panel": {
     "padding": {
       "top": 12,
-      "bottom": 12
+      "bottom": 0
     },
     "user_query_editor": {
       "background": "#19171c",
@@ -1402,6 +1402,30 @@
       "active": {
         "background": "#3f3b45"
       }
+    },
+    "invite_row": {
+      "padding": {
+        "left": 12,
+        "right": 12
+      },
+      "border": {
+        "top": true,
+        "width": 1,
+        "color": "#19171c"
+      },
+      "text": {
+        "family": "Zed Sans",
+        "color": "#e2dfe7",
+        "size": 14
+      },
+      "hover": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#e2dfe7",
+          "size": 14,
+          "underline": true
+        }
+      }
     }
   },
   "contact_finder": {

assets/themes/cave-light.json 🔗

@@ -1256,7 +1256,7 @@
   "contacts_panel": {
     "padding": {
       "top": 12,
-      "bottom": 12
+      "bottom": 0
     },
     "user_query_editor": {
       "background": "#efecf4",
@@ -1402,6 +1402,30 @@
       "active": {
         "background": "#b7b3bd"
       }
+    },
+    "invite_row": {
+      "padding": {
+        "left": 12,
+        "right": 12
+      },
+      "border": {
+        "top": true,
+        "width": 1,
+        "color": "#b7b3bd"
+      },
+      "text": {
+        "family": "Zed Sans",
+        "color": "#26232a",
+        "size": 14
+      },
+      "hover": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#26232a",
+          "size": 14,
+          "underline": true
+        }
+      }
     }
   },
   "contact_finder": {

assets/themes/solarized-dark.json 🔗

@@ -1256,7 +1256,7 @@
   "contacts_panel": {
     "padding": {
       "top": 12,
-      "bottom": 12
+      "bottom": 0
     },
     "user_query_editor": {
       "background": "#002b36",
@@ -1402,6 +1402,30 @@
       "active": {
         "background": "#30525c"
       }
+    },
+    "invite_row": {
+      "padding": {
+        "left": 12,
+        "right": 12
+      },
+      "border": {
+        "top": true,
+        "width": 1,
+        "color": "#002b36"
+      },
+      "text": {
+        "family": "Zed Sans",
+        "color": "#eee8d5",
+        "size": 14
+      },
+      "hover": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#eee8d5",
+          "size": 14,
+          "underline": true
+        }
+      }
     }
   },
   "contact_finder": {

assets/themes/solarized-light.json 🔗

@@ -1256,7 +1256,7 @@
   "contacts_panel": {
     "padding": {
       "top": 12,
-      "bottom": 12
+      "bottom": 0
     },
     "user_query_editor": {
       "background": "#fdf6e3",
@@ -1402,6 +1402,30 @@
       "active": {
         "background": "#c1c5bb"
       }
+    },
+    "invite_row": {
+      "padding": {
+        "left": 12,
+        "right": 12
+      },
+      "border": {
+        "top": true,
+        "width": 1,
+        "color": "#c1c5bb"
+      },
+      "text": {
+        "family": "Zed Sans",
+        "color": "#073642",
+        "size": 14
+      },
+      "hover": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#073642",
+          "size": 14,
+          "underline": true
+        }
+      }
     }
   },
   "contact_finder": {

assets/themes/sulphurpool-dark.json 🔗

@@ -1256,7 +1256,7 @@
   "contacts_panel": {
     "padding": {
       "top": 12,
-      "bottom": 12
+      "bottom": 0
     },
     "user_query_editor": {
       "background": "#202746",
@@ -1402,6 +1402,30 @@
       "active": {
         "background": "#444c6f"
       }
+    },
+    "invite_row": {
+      "padding": {
+        "left": 12,
+        "right": 12
+      },
+      "border": {
+        "top": true,
+        "width": 1,
+        "color": "#202746"
+      },
+      "text": {
+        "family": "Zed Sans",
+        "color": "#dfe2f1",
+        "size": 14
+      },
+      "hover": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#dfe2f1",
+          "size": 14,
+          "underline": true
+        }
+      }
     }
   },
   "contact_finder": {

assets/themes/sulphurpool-light.json 🔗

@@ -1256,7 +1256,7 @@
   "contacts_panel": {
     "padding": {
       "top": 12,
-      "bottom": 12
+      "bottom": 0
     },
     "user_query_editor": {
       "background": "#f5f7ff",
@@ -1402,6 +1402,30 @@
       "active": {
         "background": "#bbc0d3"
       }
+    },
+    "invite_row": {
+      "padding": {
+        "left": 12,
+        "right": 12
+      },
+      "border": {
+        "top": true,
+        "width": 1,
+        "color": "#bbc0d3"
+      },
+      "text": {
+        "family": "Zed Sans",
+        "color": "#293256",
+        "size": 14
+      },
+      "hover": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#293256",
+          "size": 14,
+          "underline": true
+        }
+      }
     }
   },
   "contact_finder": {

crates/client/src/user.rs 🔗

@@ -65,12 +65,19 @@ pub struct UserStore {
     incoming_contact_requests: Vec<Arc<User>>,
     outgoing_contact_requests: Vec<Arc<User>>,
     pending_contact_requests: HashMap<u64, usize>,
+    invite_info: Option<InviteInfo>,
     client: Weak<Client>,
     http: Arc<dyn HttpClient>,
     _maintain_contacts: Task<()>,
     _maintain_current_user: Task<()>,
 }
 
+#[derive(Clone)]
+pub struct InviteInfo {
+    pub count: u32,
+    pub url: Arc<str>,
+}
+
 #[derive(Clone)]
 pub struct ContactEvent {
     pub user: Arc<User>,
@@ -101,19 +108,22 @@ impl UserStore {
     ) -> Self {
         let (mut current_user_tx, current_user_rx) = watch::channel();
         let (update_contacts_tx, mut update_contacts_rx) = mpsc::unbounded();
-        let rpc_subscription =
-            client.add_message_handler(cx.handle(), Self::handle_update_contacts);
+        let rpc_subscriptions = vec![
+            client.add_message_handler(cx.handle(), Self::handle_update_contacts),
+            client.add_message_handler(cx.handle(), Self::handle_update_invite_info),
+        ];
         Self {
             users: Default::default(),
             current_user: current_user_rx,
             contacts: Default::default(),
             incoming_contact_requests: Default::default(),
             outgoing_contact_requests: Default::default(),
+            invite_info: None,
             client: Arc::downgrade(&client),
             update_contacts_tx,
             http,
             _maintain_contacts: cx.spawn_weak(|this, mut cx| async move {
-                let _subscription = rpc_subscription;
+                let _subscriptions = rpc_subscriptions;
                 while let Some(message) = update_contacts_rx.next().await {
                     if let Some(this) = this.upgrade(&cx) {
                         this.update(&mut cx, |this, cx| this.update_contacts(message, cx))
@@ -154,15 +164,35 @@ impl UserStore {
         }
     }
 
+    async fn handle_update_invite_info(
+        this: ModelHandle<Self>,
+        message: TypedEnvelope<proto::UpdateInviteInfo>,
+        _: Arc<Client>,
+        mut cx: AsyncAppContext,
+    ) -> Result<()> {
+        this.update(&mut cx, |this, cx| {
+            this.invite_info = Some(InviteInfo {
+                url: Arc::from(message.payload.url),
+                count: message.payload.count,
+            });
+            cx.notify();
+        });
+        Ok(())
+    }
+
+    pub fn invite_info(&self) -> Option<&InviteInfo> {
+        self.invite_info.as_ref()
+    }
+
     async fn handle_update_contacts(
         this: ModelHandle<Self>,
-        msg: TypedEnvelope<proto::UpdateContacts>,
+        message: TypedEnvelope<proto::UpdateContacts>,
         _: Arc<Client>,
         mut cx: AsyncAppContext,
     ) -> Result<()> {
         this.update(&mut cx, |this, _| {
             this.update_contacts_tx
-                .unbounded_send(UpdateContacts::Update(msg.payload))
+                .unbounded_send(UpdateContacts::Update(message.payload))
                 .unwrap();
         });
         Ok(())

crates/collab/.env.template.toml 🔗

@@ -1,2 +1,9 @@
 DATABASE_URL = "postgres://postgres@localhost/zed"
 HTTP_PORT = 8080
+API_TOKEN = "secret"
+INVITE_LINK_PREFIX = "http://localhost:3000/invites/"
+
+# HONEYCOMB_API_KEY=
+# HONEYCOMB_DATASET=
+# RUST_LOG=info
+# LOG_JSON=true

crates/collab/src/main.rs 🔗

@@ -20,6 +20,7 @@ pub struct Config {
     pub http_port: u16,
     pub database_url: String,
     pub api_token: String,
+    pub invite_link_prefix: String,
     pub honeycomb_api_key: Option<String>,
     pub honeycomb_dataset: Option<String>,
     pub rust_log: Option<String>,
@@ -29,6 +30,7 @@ pub struct Config {
 pub struct AppState {
     db: Arc<dyn Db>,
     api_token: String,
+    invite_link_prefix: String,
 }
 
 impl AppState {
@@ -37,6 +39,7 @@ impl AppState {
         let this = Self {
             db: Arc::new(db),
             api_token: config.api_token.clone(),
+            invite_link_prefix: config.invite_link_prefix.clone(),
         };
         Ok(Arc::new(this))
     }

crates/collab/src/rpc.rs 🔗

@@ -23,7 +23,11 @@ use axum::{
     Extension, Router, TypedHeader,
 };
 use collections::HashMap;
-use futures::{channel::mpsc, future::BoxFuture, FutureExt, SinkExt, StreamExt, TryStreamExt};
+use futures::{
+    channel::mpsc,
+    future::{self, BoxFuture},
+    FutureExt, SinkExt, StreamExt, TryStreamExt,
+};
 use lazy_static::lazy_static;
 use rpc::{
     proto::{self, AnyTypedEnvelope, EntityMessage, EnvelopedMessage, RequestMessage},
@@ -276,12 +280,22 @@ impl Server {
                 let _ = send_connection_id.send(connection_id).await;
             }
 
-            let contacts = this.app_state.db.get_contacts(user_id).await?;
+            let (contacts, invite_code) = future::try_join(
+                this.app_state.db.get_contacts(user_id),
+                this.app_state.db.get_invite_code_for_user(user_id)
+            ).await?;
 
             {
                 let mut store = this.store_mut().await;
                 store.add_connection(connection_id, user_id);
                 this.peer.send(connection_id, store.build_initial_contacts_update(contacts))?;
+                
+                if let Some((code, count)) = invite_code {
+                    this.peer.send(connection_id, proto::UpdateInviteInfo {
+                        url: format!("{}{}", this.app_state.invite_link_prefix, code),
+                        count,
+                    })?;
+                }
             }
             this.update_user_contacts(user_id).await?;
 
@@ -6670,6 +6684,7 @@ mod tests {
             Arc::new(AppState {
                 db: test_db.db().clone(),
                 api_token: Default::default(),
+                invite_link_prefix: Default::default(),
             })
         }
 

crates/contacts_panel/src/contacts_panel.rs 🔗

@@ -8,12 +8,13 @@ use contact_notification::ContactNotification;
 use editor::{Cancel, Editor};
 use fuzzy::{match_strings, StringMatchCandidate};
 use gpui::{
+    color::Color,
     elements::*,
     geometry::{rect::RectF, vector::vec2f},
     impl_actions, impl_internal_actions,
     platform::CursorStyle,
-    AppContext, Element, ElementBox, Entity, LayoutContext, ModelHandle, MutableAppContext,
-    RenderContext, Subscription, View, ViewContext, ViewHandle, WeakViewHandle,
+    AppContext, ClipboardItem, Element, ElementBox, Entity, LayoutContext, ModelHandle,
+    MutableAppContext, RenderContext, Subscription, View, ViewContext, ViewHandle, WeakViewHandle,
 };
 use join_project_notification::JoinProjectNotification;
 use serde::Deserialize;
@@ -863,6 +864,59 @@ impl View for ContactsPanel {
                         .boxed(),
                 )
                 .with_child(List::new(self.list_state.clone()).flex(1., false).boxed())
+                .with_children(
+                    self.user_store
+                        .read(cx)
+                        .invite_info()
+                        .cloned()
+                        .and_then(|info| {
+                            enum InviteLink {}
+
+                            if info.count > 0 {
+                                Some(
+                                    MouseEventHandler::new::<InviteLink, _, _>(
+                                        0,
+                                        cx,
+                                        |state, cx| {
+                                            let style =
+                                                theme.invite_row.style_for(state, false).clone();
+
+                                            let copied =
+                                                cx.read_from_clipboard().map_or(false, |item| {
+                                                    item.text().as_str() == info.url.as_ref()
+                                                });
+
+                                            Label::new(
+                                                format!(
+                                                    "{} invite link ({} left)",
+                                                    if copied { "Copied" } else { "Copy" },
+                                                    info.count
+                                                ),
+                                                style.label.clone(),
+                                            )
+                                            .aligned()
+                                            .left()
+                                            .constrained()
+                                            .with_height(theme.row_height)
+                                            .contained()
+                                            .with_style(style.container)
+                                            .boxed()
+                                        },
+                                    )
+                                    .with_cursor_style(CursorStyle::PointingHand)
+                                    .on_click(move |_, cx| {
+                                        cx.write_to_clipboard(ClipboardItem::new(
+                                            info.url.to_string(),
+                                        ));
+                                        cx.notify();
+                                    })
+                                    .boxed(),
+                                )
+                            } else {
+                                None
+                            }
+                        }),
+                )
                 .boxed(),
         )
         .with_style(theme.container)

crates/rpc/proto/zed.proto 🔗

@@ -87,18 +87,19 @@ message Envelope {
         GetChannelMessagesResponse get_channel_messages_response = 75;
 
         UpdateContacts update_contacts = 76;
-
-        GetUsers get_users = 77;
-        FuzzySearchUsers fuzzy_search_users = 78;
-        UsersResponse users_response = 79;
-        RequestContact request_contact = 80;
-        RespondToContactRequest respond_to_contact_request = 81;
-        RemoveContact remove_contact = 82;
-
-        Follow follow = 83;
-        FollowResponse follow_response = 84;
-        UpdateFollowers update_followers = 85;
-        Unfollow unfollow = 86;
+        UpdateInviteInfo update_invite_info = 77;
+
+        GetUsers get_users = 78;
+        FuzzySearchUsers fuzzy_search_users = 79;
+        UsersResponse users_response = 80;
+        RequestContact request_contact = 81;
+        RespondToContactRequest respond_to_contact_request = 82;
+        RemoveContact remove_contact = 83;
+
+        Follow follow = 84;
+        FollowResponse follow_response = 85;
+        UpdateFollowers update_followers = 86;
+        Unfollow unfollow = 87;
     }
 }
 
@@ -634,6 +635,11 @@ message UpdateContacts {
     repeated uint64 remove_outgoing_requests = 6;
 }
 
+message UpdateInviteInfo {
+    string url = 1;
+    uint32 count = 2;
+}
+
 message IncomingContactRequest {
     uint64 requester_id = 1;
     bool should_notify = 2;

crates/rpc/src/proto.rs 🔗

@@ -155,6 +155,7 @@ messages!(
     (UpdateContacts, Foreground),
     (UpdateDiagnosticSummary, Foreground),
     (UpdateFollowers, Foreground),
+    (UpdateInviteInfo, Foreground),
     (UpdateLanguageServer, Foreground),
     (UpdateWorktree, Foreground),
 );

crates/theme/src/theme.rs 🔗

@@ -262,6 +262,16 @@ pub struct ContactsPanel {
     pub disabled_contact_button: IconButton,
     pub tree_branch: Interactive<TreeBranch>,
     pub section_icon_size: f32,
+    pub invite_row: Interactive<ContainedLabel>,
+}
+
+#[derive(Deserialize, Default)]
+pub struct InviteLink {
+    #[serde(flatten)]
+    pub container: ContainerStyle,
+    #[serde(flatten)]
+    pub label: LabelStyle,
+    pub icon: Icon,
 }
 
 #[derive(Deserialize, Default, Clone, Copy)]
@@ -279,6 +289,15 @@ pub struct ContactFinder {
     pub disabled_contact_button: IconButton,
 }
 
+#[derive(Deserialize, Default)]
+pub struct Icon {
+    #[serde(flatten)]
+    pub container: ContainerStyle,
+    pub color: Color,
+    pub width: f32,
+    pub path: String,
+}
+
 #[derive(Deserialize, Default)]
 pub struct IconButton {
     #[serde(flatten)]

styles/dist/cave-dark.json 🔗

@@ -0,0 +1,519 @@
+{
+  "meta": {
+    "themeName": "cave-dark"
+  },
+  "text": {
+    "primary": {
+      "value": "#e2dfe7",
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#8b8792",
+      "type": "color"
+    },
+    "muted": {
+      "value": "#8b8792",
+      "type": "color"
+    },
+    "placeholder": {
+      "value": "#7e7887",
+      "type": "color"
+    },
+    "active": {
+      "value": "#efecf4",
+      "type": "color"
+    },
+    "feature": {
+      "value": "#576ddb",
+      "type": "color"
+    },
+    "ok": {
+      "value": "#2a9292",
+      "type": "color"
+    },
+    "error": {
+      "value": "#be4678",
+      "type": "color"
+    },
+    "warning": {
+      "value": "#a06e3b",
+      "type": "color"
+    },
+    "info": {
+      "value": "#576ddb",
+      "type": "color"
+    }
+  },
+  "icon": {
+    "primary": {
+      "value": "#e2dfe7",
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#8b8792",
+      "type": "color"
+    },
+    "muted": {
+      "value": "#8b8792",
+      "type": "color"
+    },
+    "placeholder": {
+      "value": "#7e7887",
+      "type": "color"
+    },
+    "active": {
+      "value": "#efecf4",
+      "type": "color"
+    },
+    "feature": {
+      "value": "#576ddb",
+      "type": "color"
+    },
+    "ok": {
+      "value": "#2a9292",
+      "type": "color"
+    },
+    "error": {
+      "value": "#be4678",
+      "type": "color"
+    },
+    "warning": {
+      "value": "#a06e3b",
+      "type": "color"
+    },
+    "info": {
+      "value": "#576ddb",
+      "type": "color"
+    }
+  },
+  "background": {
+    "100": {
+      "base": {
+        "value": "#332f38",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#3f3b45",
+        "type": "color"
+      },
+      "active": {
+        "value": "#4c4653",
+        "type": "color"
+      }
+    },
+    "300": {
+      "base": {
+        "value": "#26232a",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#332f38",
+        "type": "color"
+      },
+      "active": {
+        "value": "#3f3b45",
+        "type": "color"
+      }
+    },
+    "500": {
+      "base": {
+        "value": "#19171c",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#1c1a20",
+        "type": "color"
+      },
+      "active": {
+        "value": "#201d23",
+        "type": "color"
+      }
+    },
+    "on300": {
+      "base": {
+        "value": "#19171c",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#1c1a20",
+        "type": "color"
+      },
+      "active": {
+        "value": "#201d23",
+        "type": "color"
+      }
+    },
+    "on500": {
+      "base": {
+        "value": "#332f38",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#3f3b45",
+        "type": "color"
+      },
+      "active": {
+        "value": "#4c4653",
+        "type": "color"
+      }
+    },
+    "ok": {
+      "base": {
+        "value": "#2a929226",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#2a929233",
+        "type": "color"
+      },
+      "active": {
+        "value": "#2a929240",
+        "type": "color"
+      }
+    },
+    "error": {
+      "base": {
+        "value": "#be467826",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#be467833",
+        "type": "color"
+      },
+      "active": {
+        "value": "#be467840",
+        "type": "color"
+      }
+    },
+    "warning": {
+      "base": {
+        "value": "#a06e3b26",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#a06e3b33",
+        "type": "color"
+      },
+      "active": {
+        "value": "#a06e3b40",
+        "type": "color"
+      }
+    },
+    "info": {
+      "base": {
+        "value": "#576ddb26",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#576ddb33",
+        "type": "color"
+      },
+      "active": {
+        "value": "#576ddb40",
+        "type": "color"
+      }
+    }
+  },
+  "border": {
+    "primary": {
+      "value": "#19171c",
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#26232a",
+      "type": "color"
+    },
+    "muted": {
+      "value": "#655f6d",
+      "type": "color"
+    },
+    "active": {
+      "value": "#655f6d",
+      "type": "color"
+    },
+    "onMedia": {
+      "value": "#19171c1a",
+      "type": "color"
+    },
+    "ok": {
+      "value": "#2a929226",
+      "type": "color"
+    },
+    "error": {
+      "value": "#be467826",
+      "type": "color"
+    },
+    "warning": {
+      "value": "#a06e3b26",
+      "type": "color"
+    },
+    "info": {
+      "value": "#576ddb26",
+      "type": "color"
+    }
+  },
+  "editor": {
+    "background": {
+      "value": "#19171c",
+      "type": "color"
+    },
+    "indent_guide": {
+      "value": "#655f6d",
+      "type": "color"
+    },
+    "indent_guide_active": {
+      "value": "#26232a",
+      "type": "color"
+    },
+    "line": {
+      "active": {
+        "value": "#26232a",
+        "type": "color"
+      },
+      "highlighted": {
+        "value": "#332f38",
+        "type": "color"
+      }
+    },
+    "highlight": {
+      "selection": {
+        "value": "#576ddb3d",
+        "type": "color"
+      },
+      "occurrence": {
+        "value": "#5852603d",
+        "type": "color"
+      },
+      "activeOccurrence": {
+        "value": "#5852607a",
+        "type": "color"
+      },
+      "matchingBracket": {
+        "value": "#201d23",
+        "type": "color"
+      },
+      "match": {
+        "value": "#3d1576",
+        "type": "color"
+      },
+      "activeMatch": {
+        "value": "#782edf7a",
+        "type": "color"
+      },
+      "related": {
+        "value": "#1c1a20",
+        "type": "color"
+      }
+    },
+    "gutter": {
+      "primary": {
+        "value": "#7e7887",
+        "type": "color"
+      },
+      "active": {
+        "value": "#efecf4",
+        "type": "color"
+      }
+    }
+  },
+  "syntax": {
+    "primary": {
+      "value": "#efecf4",
+      "type": "color"
+    },
+    "comment": {
+      "value": "#8b8792",
+      "type": "color"
+    },
+    "keyword": {
+      "value": "#576ddb",
+      "type": "color"
+    },
+    "function": {
+      "value": "#a06e3b",
+      "type": "color"
+    },
+    "type": {
+      "value": "#398bc6",
+      "type": "color"
+    },
+    "variant": {
+      "value": "#576ddb",
+      "type": "color"
+    },
+    "property": {
+      "value": "#576ddb",
+      "type": "color"
+    },
+    "enum": {
+      "value": "#aa573c",
+      "type": "color"
+    },
+    "operator": {
+      "value": "#aa573c",
+      "type": "color"
+    },
+    "string": {
+      "value": "#aa573c",
+      "type": "color"
+    },
+    "number": {
+      "value": "#2a9292",
+      "type": "color"
+    },
+    "boolean": {
+      "value": "#2a9292",
+      "type": "color"
+    }
+  },
+  "player": {
+    "1": {
+      "baseColor": {
+        "value": "#576ddb",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#576ddb",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#576ddb3d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#576ddbcc",
+        "type": "color"
+      }
+    },
+    "2": {
+      "baseColor": {
+        "value": "#2a9292",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#2a9292",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#2a92923d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#2a9292cc",
+        "type": "color"
+      }
+    },
+    "3": {
+      "baseColor": {
+        "value": "#bf40bf",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#bf40bf",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#bf40bf3d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#bf40bfcc",
+        "type": "color"
+      }
+    },
+    "4": {
+      "baseColor": {
+        "value": "#aa573c",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#aa573c",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#aa573c3d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#aa573ccc",
+        "type": "color"
+      }
+    },
+    "5": {
+      "baseColor": {
+        "value": "#955ae7",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#955ae7",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#955ae73d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#955ae7cc",
+        "type": "color"
+      }
+    },
+    "6": {
+      "baseColor": {
+        "value": "#398bc6",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#398bc6",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#398bc63d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#398bc6cc",
+        "type": "color"
+      }
+    },
+    "7": {
+      "baseColor": {
+        "value": "#be4678",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#be4678",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#be46783d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#be4678cc",
+        "type": "color"
+      }
+    },
+    "8": {
+      "baseColor": {
+        "value": "#a06e3b",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#a06e3b",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#a06e3b3d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#a06e3bcc",
+        "type": "color"
+      }
+    }
+  },
+  "shadowAlpha": {
+    "value": 0.24,
+    "type": "number"
+  }
+}

styles/dist/cave-light.json 🔗

@@ -0,0 +1,519 @@
+{
+  "meta": {
+    "themeName": "cave-light"
+  },
+  "text": {
+    "primary": {
+      "value": "#26232a",
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#585260",
+      "type": "color"
+    },
+    "muted": {
+      "value": "#585260",
+      "type": "color"
+    },
+    "placeholder": {
+      "value": "#655f6d",
+      "type": "color"
+    },
+    "active": {
+      "value": "#19171c",
+      "type": "color"
+    },
+    "feature": {
+      "value": "#576ddb",
+      "type": "color"
+    },
+    "ok": {
+      "value": "#2a9292",
+      "type": "color"
+    },
+    "error": {
+      "value": "#be4678",
+      "type": "color"
+    },
+    "warning": {
+      "value": "#a06e3b",
+      "type": "color"
+    },
+    "info": {
+      "value": "#576ddb",
+      "type": "color"
+    }
+  },
+  "icon": {
+    "primary": {
+      "value": "#26232a",
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#585260",
+      "type": "color"
+    },
+    "muted": {
+      "value": "#585260",
+      "type": "color"
+    },
+    "placeholder": {
+      "value": "#655f6d",
+      "type": "color"
+    },
+    "active": {
+      "value": "#19171c",
+      "type": "color"
+    },
+    "feature": {
+      "value": "#576ddb",
+      "type": "color"
+    },
+    "ok": {
+      "value": "#2a9292",
+      "type": "color"
+    },
+    "error": {
+      "value": "#be4678",
+      "type": "color"
+    },
+    "warning": {
+      "value": "#a06e3b",
+      "type": "color"
+    },
+    "info": {
+      "value": "#576ddb",
+      "type": "color"
+    }
+  },
+  "background": {
+    "100": {
+      "base": {
+        "value": "#ccc9d2",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#b7b3bd",
+        "type": "color"
+      },
+      "active": {
+        "value": "#a19da7",
+        "type": "color"
+      }
+    },
+    "300": {
+      "base": {
+        "value": "#e2dfe7",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#ccc9d2",
+        "type": "color"
+      },
+      "active": {
+        "value": "#b7b3bd",
+        "type": "color"
+      }
+    },
+    "500": {
+      "base": {
+        "value": "#efecf4",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#ece9f1",
+        "type": "color"
+      },
+      "active": {
+        "value": "#e9e6ee",
+        "type": "color"
+      }
+    },
+    "on300": {
+      "base": {
+        "value": "#efecf4",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#ece9f1",
+        "type": "color"
+      },
+      "active": {
+        "value": "#e9e6ee",
+        "type": "color"
+      }
+    },
+    "on500": {
+      "base": {
+        "value": "#ccc9d2",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#b7b3bd",
+        "type": "color"
+      },
+      "active": {
+        "value": "#a19da7",
+        "type": "color"
+      }
+    },
+    "ok": {
+      "base": {
+        "value": "#2a929226",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#2a929233",
+        "type": "color"
+      },
+      "active": {
+        "value": "#2a929240",
+        "type": "color"
+      }
+    },
+    "error": {
+      "base": {
+        "value": "#be467826",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#be467833",
+        "type": "color"
+      },
+      "active": {
+        "value": "#be467840",
+        "type": "color"
+      }
+    },
+    "warning": {
+      "base": {
+        "value": "#a06e3b26",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#a06e3b33",
+        "type": "color"
+      },
+      "active": {
+        "value": "#a06e3b40",
+        "type": "color"
+      }
+    },
+    "info": {
+      "base": {
+        "value": "#576ddb26",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#576ddb33",
+        "type": "color"
+      },
+      "active": {
+        "value": "#576ddb40",
+        "type": "color"
+      }
+    }
+  },
+  "border": {
+    "primary": {
+      "value": "#b7b3bd",
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#ccc9d2",
+      "type": "color"
+    },
+    "muted": {
+      "value": "#e2dfe7",
+      "type": "color"
+    },
+    "active": {
+      "value": "#655f6d",
+      "type": "color"
+    },
+    "onMedia": {
+      "value": "#efecf41a",
+      "type": "color"
+    },
+    "ok": {
+      "value": "#2a929226",
+      "type": "color"
+    },
+    "error": {
+      "value": "#be467826",
+      "type": "color"
+    },
+    "warning": {
+      "value": "#a06e3b26",
+      "type": "color"
+    },
+    "info": {
+      "value": "#576ddb26",
+      "type": "color"
+    }
+  },
+  "editor": {
+    "background": {
+      "value": "#efecf4",
+      "type": "color"
+    },
+    "indent_guide": {
+      "value": "#e2dfe7",
+      "type": "color"
+    },
+    "indent_guide_active": {
+      "value": "#ccc9d2",
+      "type": "color"
+    },
+    "line": {
+      "active": {
+        "value": "#e2dfe7",
+        "type": "color"
+      },
+      "highlighted": {
+        "value": "#ccc9d2",
+        "type": "color"
+      }
+    },
+    "highlight": {
+      "selection": {
+        "value": "#576ddb3d",
+        "type": "color"
+      },
+      "occurrence": {
+        "value": "#8b87921f",
+        "type": "color"
+      },
+      "activeOccurrence": {
+        "value": "#8b87923d",
+        "type": "color"
+      },
+      "matchingBracket": {
+        "value": "#e9e6ee",
+        "type": "color"
+      },
+      "match": {
+        "value": "#d5bdfa",
+        "type": "color"
+      },
+      "activeMatch": {
+        "value": "#a775ee3d",
+        "type": "color"
+      },
+      "related": {
+        "value": "#ece9f1",
+        "type": "color"
+      }
+    },
+    "gutter": {
+      "primary": {
+        "value": "#655f6d",
+        "type": "color"
+      },
+      "active": {
+        "value": "#19171c",
+        "type": "color"
+      }
+    }
+  },
+  "syntax": {
+    "primary": {
+      "value": "#19171c",
+      "type": "color"
+    },
+    "comment": {
+      "value": "#585260",
+      "type": "color"
+    },
+    "keyword": {
+      "value": "#576ddb",
+      "type": "color"
+    },
+    "function": {
+      "value": "#a06e3b",
+      "type": "color"
+    },
+    "type": {
+      "value": "#398bc6",
+      "type": "color"
+    },
+    "variant": {
+      "value": "#576ddb",
+      "type": "color"
+    },
+    "property": {
+      "value": "#576ddb",
+      "type": "color"
+    },
+    "enum": {
+      "value": "#aa573c",
+      "type": "color"
+    },
+    "operator": {
+      "value": "#aa573c",
+      "type": "color"
+    },
+    "string": {
+      "value": "#aa573c",
+      "type": "color"
+    },
+    "number": {
+      "value": "#2a9292",
+      "type": "color"
+    },
+    "boolean": {
+      "value": "#2a9292",
+      "type": "color"
+    }
+  },
+  "player": {
+    "1": {
+      "baseColor": {
+        "value": "#576ddb",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#576ddb",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#576ddb3d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#576ddbcc",
+        "type": "color"
+      }
+    },
+    "2": {
+      "baseColor": {
+        "value": "#2a9292",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#2a9292",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#2a92923d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#2a9292cc",
+        "type": "color"
+      }
+    },
+    "3": {
+      "baseColor": {
+        "value": "#bf40bf",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#bf40bf",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#bf40bf3d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#bf40bfcc",
+        "type": "color"
+      }
+    },
+    "4": {
+      "baseColor": {
+        "value": "#aa573c",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#aa573c",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#aa573c3d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#aa573ccc",
+        "type": "color"
+      }
+    },
+    "5": {
+      "baseColor": {
+        "value": "#955ae7",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#955ae7",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#955ae73d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#955ae7cc",
+        "type": "color"
+      }
+    },
+    "6": {
+      "baseColor": {
+        "value": "#398bc6",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#398bc6",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#398bc63d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#398bc6cc",
+        "type": "color"
+      }
+    },
+    "7": {
+      "baseColor": {
+        "value": "#be4678",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#be4678",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#be46783d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#be4678cc",
+        "type": "color"
+      }
+    },
+    "8": {
+      "baseColor": {
+        "value": "#a06e3b",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#a06e3b",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#a06e3b3d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#a06e3bcc",
+        "type": "color"
+      }
+    }
+  },
+  "shadowAlpha": {
+    "value": 0.12,
+    "type": "number"
+  }
+}

styles/dist/solarized-light.json 🔗

@@ -216,15 +216,15 @@
   },
   "border": {
     "primary": {
-      "value": "#93a1a1",
+      "value": "#c1c5bb",
       "type": "color"
     },
     "secondary": {
-      "value": "#93a1a1",
+      "value": "#d7d6c8",
       "type": "color"
     },
     "muted": {
-      "value": "#657b83",
+      "value": "#eee8d5",
       "type": "color"
     },
     "active": {
@@ -258,11 +258,11 @@
       "type": "color"
     },
     "indent_guide": {
-      "value": "#657b83",
+      "value": "#eee8d5",
       "type": "color"
     },
     "indent_guide_active": {
-      "value": "#93a1a1",
+      "value": "#d7d6c8",
       "type": "color"
     },
     "line": {

styles/dist/sulphurpool-dark.json 🔗

@@ -0,0 +1,519 @@
+{
+  "meta": {
+    "themeName": "sulphurpool-dark"
+  },
+  "text": {
+    "primary": {
+      "value": "#dfe2f1",
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#979db4",
+      "type": "color"
+    },
+    "muted": {
+      "value": "#979db4",
+      "type": "color"
+    },
+    "placeholder": {
+      "value": "#898ea4",
+      "type": "color"
+    },
+    "active": {
+      "value": "#f5f7ff",
+      "type": "color"
+    },
+    "feature": {
+      "value": "#3d8fd1",
+      "type": "color"
+    },
+    "ok": {
+      "value": "#ac9739",
+      "type": "color"
+    },
+    "error": {
+      "value": "#c94922",
+      "type": "color"
+    },
+    "warning": {
+      "value": "#c08b30",
+      "type": "color"
+    },
+    "info": {
+      "value": "#3d8fd1",
+      "type": "color"
+    }
+  },
+  "icon": {
+    "primary": {
+      "value": "#dfe2f1",
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#979db4",
+      "type": "color"
+    },
+    "muted": {
+      "value": "#979db4",
+      "type": "color"
+    },
+    "placeholder": {
+      "value": "#898ea4",
+      "type": "color"
+    },
+    "active": {
+      "value": "#f5f7ff",
+      "type": "color"
+    },
+    "feature": {
+      "value": "#3d8fd1",
+      "type": "color"
+    },
+    "ok": {
+      "value": "#ac9739",
+      "type": "color"
+    },
+    "error": {
+      "value": "#c94922",
+      "type": "color"
+    },
+    "warning": {
+      "value": "#c08b30",
+      "type": "color"
+    },
+    "info": {
+      "value": "#3d8fd1",
+      "type": "color"
+    }
+  },
+  "background": {
+    "100": {
+      "base": {
+        "value": "#363f62",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#444c6f",
+        "type": "color"
+      },
+      "active": {
+        "value": "#51597b",
+        "type": "color"
+      }
+    },
+    "300": {
+      "base": {
+        "value": "#293256",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#363f62",
+        "type": "color"
+      },
+      "active": {
+        "value": "#444c6f",
+        "type": "color"
+      }
+    },
+    "500": {
+      "base": {
+        "value": "#202746",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#222a4a",
+        "type": "color"
+      },
+      "active": {
+        "value": "#252d4e",
+        "type": "color"
+      }
+    },
+    "on300": {
+      "base": {
+        "value": "#202746",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#222a4a",
+        "type": "color"
+      },
+      "active": {
+        "value": "#252d4e",
+        "type": "color"
+      }
+    },
+    "on500": {
+      "base": {
+        "value": "#363f62",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#444c6f",
+        "type": "color"
+      },
+      "active": {
+        "value": "#51597b",
+        "type": "color"
+      }
+    },
+    "ok": {
+      "base": {
+        "value": "#ac973926",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#ac973933",
+        "type": "color"
+      },
+      "active": {
+        "value": "#ac973940",
+        "type": "color"
+      }
+    },
+    "error": {
+      "base": {
+        "value": "#c9492226",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#c9492233",
+        "type": "color"
+      },
+      "active": {
+        "value": "#c9492240",
+        "type": "color"
+      }
+    },
+    "warning": {
+      "base": {
+        "value": "#c08b3026",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#c08b3033",
+        "type": "color"
+      },
+      "active": {
+        "value": "#c08b3040",
+        "type": "color"
+      }
+    },
+    "info": {
+      "base": {
+        "value": "#3d8fd126",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#3d8fd133",
+        "type": "color"
+      },
+      "active": {
+        "value": "#3d8fd140",
+        "type": "color"
+      }
+    }
+  },
+  "border": {
+    "primary": {
+      "value": "#202746",
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#293256",
+      "type": "color"
+    },
+    "muted": {
+      "value": "#6b7394",
+      "type": "color"
+    },
+    "active": {
+      "value": "#6b7394",
+      "type": "color"
+    },
+    "onMedia": {
+      "value": "#2027461a",
+      "type": "color"
+    },
+    "ok": {
+      "value": "#ac973926",
+      "type": "color"
+    },
+    "error": {
+      "value": "#c9492226",
+      "type": "color"
+    },
+    "warning": {
+      "value": "#c08b3026",
+      "type": "color"
+    },
+    "info": {
+      "value": "#3d8fd126",
+      "type": "color"
+    }
+  },
+  "editor": {
+    "background": {
+      "value": "#202746",
+      "type": "color"
+    },
+    "indent_guide": {
+      "value": "#6b7394",
+      "type": "color"
+    },
+    "indent_guide_active": {
+      "value": "#293256",
+      "type": "color"
+    },
+    "line": {
+      "active": {
+        "value": "#293256",
+        "type": "color"
+      },
+      "highlighted": {
+        "value": "#363f62",
+        "type": "color"
+      }
+    },
+    "highlight": {
+      "selection": {
+        "value": "#3d8fd13d",
+        "type": "color"
+      },
+      "occurrence": {
+        "value": "#5e66873d",
+        "type": "color"
+      },
+      "activeOccurrence": {
+        "value": "#5e66877a",
+        "type": "color"
+      },
+      "matchingBracket": {
+        "value": "#252d4e",
+        "type": "color"
+      },
+      "match": {
+        "value": "#1a2a6d",
+        "type": "color"
+      },
+      "activeMatch": {
+        "value": "#3d56c47a",
+        "type": "color"
+      },
+      "related": {
+        "value": "#222a4a",
+        "type": "color"
+      }
+    },
+    "gutter": {
+      "primary": {
+        "value": "#898ea4",
+        "type": "color"
+      },
+      "active": {
+        "value": "#f5f7ff",
+        "type": "color"
+      }
+    }
+  },
+  "syntax": {
+    "primary": {
+      "value": "#f5f7ff",
+      "type": "color"
+    },
+    "comment": {
+      "value": "#979db4",
+      "type": "color"
+    },
+    "keyword": {
+      "value": "#3d8fd1",
+      "type": "color"
+    },
+    "function": {
+      "value": "#c08b30",
+      "type": "color"
+    },
+    "type": {
+      "value": "#22a2c9",
+      "type": "color"
+    },
+    "variant": {
+      "value": "#3d8fd1",
+      "type": "color"
+    },
+    "property": {
+      "value": "#3d8fd1",
+      "type": "color"
+    },
+    "enum": {
+      "value": "#c76b29",
+      "type": "color"
+    },
+    "operator": {
+      "value": "#c76b29",
+      "type": "color"
+    },
+    "string": {
+      "value": "#c76b29",
+      "type": "color"
+    },
+    "number": {
+      "value": "#ac9739",
+      "type": "color"
+    },
+    "boolean": {
+      "value": "#ac9739",
+      "type": "color"
+    }
+  },
+  "player": {
+    "1": {
+      "baseColor": {
+        "value": "#3d8fd1",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#3d8fd1",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#3d8fd13d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#3d8fd1cc",
+        "type": "color"
+      }
+    },
+    "2": {
+      "baseColor": {
+        "value": "#ac9739",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#ac9739",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#ac97393d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#ac9739cc",
+        "type": "color"
+      }
+    },
+    "3": {
+      "baseColor": {
+        "value": "#9c637a",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#9c637a",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#9c637a3d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#9c637acc",
+        "type": "color"
+      }
+    },
+    "4": {
+      "baseColor": {
+        "value": "#c76b29",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#c76b29",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#c76b293d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#c76b29cc",
+        "type": "color"
+      }
+    },
+    "5": {
+      "baseColor": {
+        "value": "#6679cc",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#6679cc",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#6679cc3d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#6679cccc",
+        "type": "color"
+      }
+    },
+    "6": {
+      "baseColor": {
+        "value": "#22a2c9",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#22a2c9",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#22a2c93d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#22a2c9cc",
+        "type": "color"
+      }
+    },
+    "7": {
+      "baseColor": {
+        "value": "#c94922",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#c94922",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#c949223d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#c94922cc",
+        "type": "color"
+      }
+    },
+    "8": {
+      "baseColor": {
+        "value": "#c08b30",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#c08b30",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#c08b303d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#c08b30cc",
+        "type": "color"
+      }
+    }
+  },
+  "shadowAlpha": {
+    "value": 0.24,
+    "type": "number"
+  }
+}

styles/dist/sulphurpool-light.json 🔗

@@ -0,0 +1,519 @@
+{
+  "meta": {
+    "themeName": "sulphurpool-light"
+  },
+  "text": {
+    "primary": {
+      "value": "#293256",
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#5e6687",
+      "type": "color"
+    },
+    "muted": {
+      "value": "#5e6687",
+      "type": "color"
+    },
+    "placeholder": {
+      "value": "#6b7394",
+      "type": "color"
+    },
+    "active": {
+      "value": "#202746",
+      "type": "color"
+    },
+    "feature": {
+      "value": "#3d8fd1",
+      "type": "color"
+    },
+    "ok": {
+      "value": "#ac9739",
+      "type": "color"
+    },
+    "error": {
+      "value": "#c94922",
+      "type": "color"
+    },
+    "warning": {
+      "value": "#c08b30",
+      "type": "color"
+    },
+    "info": {
+      "value": "#3d8fd1",
+      "type": "color"
+    }
+  },
+  "icon": {
+    "primary": {
+      "value": "#293256",
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#5e6687",
+      "type": "color"
+    },
+    "muted": {
+      "value": "#5e6687",
+      "type": "color"
+    },
+    "placeholder": {
+      "value": "#6b7394",
+      "type": "color"
+    },
+    "active": {
+      "value": "#202746",
+      "type": "color"
+    },
+    "feature": {
+      "value": "#3d8fd1",
+      "type": "color"
+    },
+    "ok": {
+      "value": "#ac9739",
+      "type": "color"
+    },
+    "error": {
+      "value": "#c94922",
+      "type": "color"
+    },
+    "warning": {
+      "value": "#c08b30",
+      "type": "color"
+    },
+    "info": {
+      "value": "#3d8fd1",
+      "type": "color"
+    }
+  },
+  "background": {
+    "100": {
+      "base": {
+        "value": "#cdd1e2",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#bbc0d3",
+        "type": "color"
+      },
+      "active": {
+        "value": "#a9aec3",
+        "type": "color"
+      }
+    },
+    "300": {
+      "base": {
+        "value": "#dfe2f1",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#cdd1e2",
+        "type": "color"
+      },
+      "active": {
+        "value": "#bbc0d3",
+        "type": "color"
+      }
+    },
+    "500": {
+      "base": {
+        "value": "#f5f7ff",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#f0f2fc",
+        "type": "color"
+      },
+      "active": {
+        "value": "#eaedf8",
+        "type": "color"
+      }
+    },
+    "on300": {
+      "base": {
+        "value": "#f5f7ff",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#f0f2fc",
+        "type": "color"
+      },
+      "active": {
+        "value": "#eaedf8",
+        "type": "color"
+      }
+    },
+    "on500": {
+      "base": {
+        "value": "#cdd1e2",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#bbc0d3",
+        "type": "color"
+      },
+      "active": {
+        "value": "#a9aec3",
+        "type": "color"
+      }
+    },
+    "ok": {
+      "base": {
+        "value": "#ac973926",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#ac973933",
+        "type": "color"
+      },
+      "active": {
+        "value": "#ac973940",
+        "type": "color"
+      }
+    },
+    "error": {
+      "base": {
+        "value": "#c9492226",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#c9492233",
+        "type": "color"
+      },
+      "active": {
+        "value": "#c9492240",
+        "type": "color"
+      }
+    },
+    "warning": {
+      "base": {
+        "value": "#c08b3026",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#c08b3033",
+        "type": "color"
+      },
+      "active": {
+        "value": "#c08b3040",
+        "type": "color"
+      }
+    },
+    "info": {
+      "base": {
+        "value": "#3d8fd126",
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#3d8fd133",
+        "type": "color"
+      },
+      "active": {
+        "value": "#3d8fd140",
+        "type": "color"
+      }
+    }
+  },
+  "border": {
+    "primary": {
+      "value": "#bbc0d3",
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#cdd1e2",
+      "type": "color"
+    },
+    "muted": {
+      "value": "#dfe2f1",
+      "type": "color"
+    },
+    "active": {
+      "value": "#6b7394",
+      "type": "color"
+    },
+    "onMedia": {
+      "value": "#f5f7ff1a",
+      "type": "color"
+    },
+    "ok": {
+      "value": "#ac973926",
+      "type": "color"
+    },
+    "error": {
+      "value": "#c9492226",
+      "type": "color"
+    },
+    "warning": {
+      "value": "#c08b3026",
+      "type": "color"
+    },
+    "info": {
+      "value": "#3d8fd126",
+      "type": "color"
+    }
+  },
+  "editor": {
+    "background": {
+      "value": "#f5f7ff",
+      "type": "color"
+    },
+    "indent_guide": {
+      "value": "#dfe2f1",
+      "type": "color"
+    },
+    "indent_guide_active": {
+      "value": "#cdd1e2",
+      "type": "color"
+    },
+    "line": {
+      "active": {
+        "value": "#dfe2f1",
+        "type": "color"
+      },
+      "highlighted": {
+        "value": "#cdd1e2",
+        "type": "color"
+      }
+    },
+    "highlight": {
+      "selection": {
+        "value": "#3d8fd13d",
+        "type": "color"
+      },
+      "occurrence": {
+        "value": "#979db41f",
+        "type": "color"
+      },
+      "activeOccurrence": {
+        "value": "#979db43d",
+        "type": "color"
+      },
+      "matchingBracket": {
+        "value": "#eaedf8",
+        "type": "color"
+      },
+      "match": {
+        "value": "#bcc6f7",
+        "type": "color"
+      },
+      "activeMatch": {
+        "value": "#7b8ddc3d",
+        "type": "color"
+      },
+      "related": {
+        "value": "#f0f2fc",
+        "type": "color"
+      }
+    },
+    "gutter": {
+      "primary": {
+        "value": "#6b7394",
+        "type": "color"
+      },
+      "active": {
+        "value": "#202746",
+        "type": "color"
+      }
+    }
+  },
+  "syntax": {
+    "primary": {
+      "value": "#202746",
+      "type": "color"
+    },
+    "comment": {
+      "value": "#5e6687",
+      "type": "color"
+    },
+    "keyword": {
+      "value": "#3d8fd1",
+      "type": "color"
+    },
+    "function": {
+      "value": "#c08b30",
+      "type": "color"
+    },
+    "type": {
+      "value": "#22a2c9",
+      "type": "color"
+    },
+    "variant": {
+      "value": "#3d8fd1",
+      "type": "color"
+    },
+    "property": {
+      "value": "#3d8fd1",
+      "type": "color"
+    },
+    "enum": {
+      "value": "#c76b29",
+      "type": "color"
+    },
+    "operator": {
+      "value": "#c76b29",
+      "type": "color"
+    },
+    "string": {
+      "value": "#c76b29",
+      "type": "color"
+    },
+    "number": {
+      "value": "#ac9739",
+      "type": "color"
+    },
+    "boolean": {
+      "value": "#ac9739",
+      "type": "color"
+    }
+  },
+  "player": {
+    "1": {
+      "baseColor": {
+        "value": "#3d8fd1",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#3d8fd1",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#3d8fd13d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#3d8fd1cc",
+        "type": "color"
+      }
+    },
+    "2": {
+      "baseColor": {
+        "value": "#ac9739",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#ac9739",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#ac97393d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#ac9739cc",
+        "type": "color"
+      }
+    },
+    "3": {
+      "baseColor": {
+        "value": "#9c637a",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#9c637a",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#9c637a3d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#9c637acc",
+        "type": "color"
+      }
+    },
+    "4": {
+      "baseColor": {
+        "value": "#c76b29",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#c76b29",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#c76b293d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#c76b29cc",
+        "type": "color"
+      }
+    },
+    "5": {
+      "baseColor": {
+        "value": "#6679cc",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#6679cc",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#6679cc3d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#6679cccc",
+        "type": "color"
+      }
+    },
+    "6": {
+      "baseColor": {
+        "value": "#22a2c9",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#22a2c9",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#22a2c93d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#22a2c9cc",
+        "type": "color"
+      }
+    },
+    "7": {
+      "baseColor": {
+        "value": "#c94922",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#c94922",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#c949223d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#c94922cc",
+        "type": "color"
+      }
+    },
+    "8": {
+      "baseColor": {
+        "value": "#c08b30",
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#c08b30",
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#c08b303d",
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#c08b30cc",
+        "type": "color"
+      }
+    }
+  },
+  "shadowAlpha": {
+    "value": 0.12,
+    "type": "number"
+  }
+}

styles/dist/tokens.json 🔗

@@ -1917,15 +1917,15 @@
     },
     "border": {
       "primary": {
-        "value": "#8b8792",
+        "value": "#b7b3bd",
         "type": "color"
       },
       "secondary": {
-        "value": "#8b8792",
+        "value": "#ccc9d2",
         "type": "color"
       },
       "muted": {
-        "value": "#655f6d",
+        "value": "#e2dfe7",
         "type": "color"
       },
       "active": {
@@ -1959,11 +1959,11 @@
         "type": "color"
       },
       "indent_guide": {
-        "value": "#655f6d",
+        "value": "#e2dfe7",
         "type": "color"
       },
       "indent_guide_active": {
-        "value": "#8b8792",
+        "value": "#ccc9d2",
         "type": "color"
       },
       "line": {
@@ -2955,15 +2955,15 @@
     },
     "border": {
       "primary": {
-        "value": "#93a1a1",
+        "value": "#c1c5bb",
         "type": "color"
       },
       "secondary": {
-        "value": "#93a1a1",
+        "value": "#d7d6c8",
         "type": "color"
       },
       "muted": {
-        "value": "#657b83",
+        "value": "#eee8d5",
         "type": "color"
       },
       "active": {
@@ -2997,11 +2997,11 @@
         "type": "color"
       },
       "indent_guide": {
-        "value": "#657b83",
+        "value": "#eee8d5",
         "type": "color"
       },
       "indent_guide_active": {
-        "value": "#93a1a1",
+        "value": "#d7d6c8",
         "type": "color"
       },
       "line": {
@@ -3993,15 +3993,15 @@
     },
     "border": {
       "primary": {
-        "value": "#979db4",
+        "value": "#bbc0d3",
         "type": "color"
       },
       "secondary": {
-        "value": "#979db4",
+        "value": "#cdd1e2",
         "type": "color"
       },
       "muted": {
-        "value": "#6b7394",
+        "value": "#dfe2f1",
         "type": "color"
       },
       "active": {
@@ -4035,11 +4035,11 @@
         "type": "color"
       },
       "indent_guide": {
-        "value": "#6b7394",
+        "value": "#dfe2f1",
         "type": "color"
       },
       "indent_guide_active": {
-        "value": "#979db4",
+        "value": "#cdd1e2",
         "type": "color"
       },
       "line": {

styles/src/styleTree/contactsPanel.ts 🔗

@@ -42,6 +42,7 @@ export default function contactsPanel(theme: Theme) {
 
   return {
     ...panel,
+    padding: { top: panel.padding.top, bottom: 0 },
     userQueryEditor: {
       background: backgroundColor(theme, 500),
       cornerRadius: 6,
@@ -136,5 +137,16 @@ export default function contactsPanel(theme: Theme) {
         background: backgroundColor(theme, 300, "active"),
       }
     },
+    inviteRow: {
+      padding: {
+        left: sidePadding,
+        right: sidePadding
+      },
+      border: { top: true, width: 1, color: borderColor(theme, "primary") },
+      text: text(theme, "sans", "primary", { size: "sm" }),
+      hover: {
+        text: text(theme, "sans", "primary", { size: "sm", underline: true })
+      }
+    }
   }
 }