Added CTA buttons to welcome experience

Mikayla Maki and Nathan created

Co-authored-by: Nathan <nathan@zed.dev>

Change summary

Cargo.lock                      |   1 
crates/theme/src/theme.rs       |   1 
crates/welcome/Cargo.toml       |   1 
crates/welcome/src/welcome.rs   |  36 ++++++++++
styles/src/styleTree/welcome.ts | 111 ++++++++++++++++++++--------------
5 files changed, 102 insertions(+), 48 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -8024,6 +8024,7 @@ dependencies = [
  "project",
  "settings",
  "theme",
+ "theme_selector",
  "util",
  "workspace",
 ]

crates/theme/src/theme.rs 🔗

@@ -854,6 +854,7 @@ pub struct FeedbackStyle {
 #[derive(Clone, Deserialize, Default)]
 pub struct WelcomeStyle {
     pub checkbox: CheckboxStyle,
+    pub button: Interactive<ContainedText>,
 }
 
 #[derive(Clone, Deserialize, Default)]

crates/welcome/Cargo.toml 🔗

@@ -18,5 +18,6 @@ gpui = { path = "../gpui" }
 project = { path = "../project" }
 settings = { path = "../settings" }
 theme = { path = "../theme" }
+theme_selector = { path = "../theme_selector" }
 util = { path = "../util" }
 workspace = { path = "../workspace" }

crates/welcome/src/welcome.rs 🔗

@@ -1,12 +1,14 @@
+use std::borrow::Cow;
+
 use gpui::{
     color::Color,
     elements::{Canvas, Empty, Flex, Label, MouseEventHandler, ParentElement, Stack, Svg},
     geometry::rect::RectF,
-    Element, ElementBox, Entity, MouseRegion, MutableAppContext, RenderContext, Subscription, View,
-    ViewContext,
+    Action, Element, ElementBox, Entity, MouseButton, MouseRegion, MutableAppContext,
+    RenderContext, Subscription, View, ViewContext,
 };
 use settings::{settings_file::SettingsFile, Settings, SettingsFileContent};
-use theme::CheckboxStyle;
+use theme::{CheckboxStyle, ContainedText, Interactive};
 use workspace::{item::Item, Welcome, Workspace};
 
 pub fn init(cx: &mut MutableAppContext) {
@@ -86,6 +88,8 @@ impl View for WelcomePage {
                             theme.editor.hover_popover.prose.clone(),
                         )
                         .boxed(),
+                        self.render_cta_button(2, "Choose a theme", theme_selector::Toggle, cx),
+                        self.render_cta_button(3, "Choose a keymap", theme_selector::Toggle, cx),
                         Flex::row()
                             .with_children([
                                 self.render_settings_checkbox::<Metrics>(
@@ -141,6 +145,32 @@ impl WelcomePage {
         }
     }
 
+    fn render_cta_button<L, A>(
+        &self,
+        region_id: usize,
+        label: L,
+        action: A,
+        cx: &mut RenderContext<Self>,
+    ) -> ElementBox
+    where
+        L: Into<Cow<'static, str>>,
+        A: 'static + Action + Clone,
+    {
+        let theme = cx.global::<Settings>().theme.clone();
+        MouseEventHandler::<A>::new(region_id, cx, |state, _| {
+            let style = theme.welcome.button.style_for(state, false);
+            Label::new(label, style.text.clone())
+                .contained()
+                .with_style(style.container)
+                .boxed()
+        })
+        .on_click(MouseButton::Left, move |_, cx| {
+            cx.dispatch_action(action.clone())
+        })
+        .aligned()
+        .boxed()
+    }
+
     fn render_settings_checkbox<T: 'static>(
         &self,
         style: &CheckboxStyle,

styles/src/styleTree/welcome.ts 🔗

@@ -1,55 +1,76 @@
 
 import { ColorScheme } from "../themes/common/colorScheme";
-import { border } from "./components";
+import { border, background, text } from "./components";
+
 
 export default function welcome(colorScheme: ColorScheme) {
-    let layer = colorScheme.highest;
+  let layer = colorScheme.highest;
 
-    // TODO
-    let checkboxBase = {
-        cornerRadius: 4,
-        padding: {
-            left: 8,
-            right: 8,
-            top: 4,
-            bottom: 4,
-        },
-        shadow: colorScheme.popoverShadow,
-        border: border(layer),
-        margin: {
-            left: -8,
-        },
-    };
+  // TODO
+  let checkboxBase = {
+    cornerRadius: 4,
+    padding: {
+      left: 8,
+      right: 8,
+      top: 4,
+      bottom: 4,
+    },
+    shadow: colorScheme.popoverShadow,
+    border: border(layer),
+    margin: {
+      left: -8,
+    },
+  };
 
-    return {
-        checkbox: {
-            width: 9,
-            height: 9,
-            default: {
-                ...checkboxBase,
-                background: colorScheme.ramps.blue(0.5).hex(),
-            },
-            checked: {
-                ...checkboxBase,
-                background: colorScheme.ramps.red(0.5).hex(),
-            },
-            hovered: {
-                ...checkboxBase,
-                background: colorScheme.ramps.blue(0.5).hex(),
+  return {
+    button: {
+      background: background(layer),
+      border: border(layer),
+      cornerRadius: 6,
+      margin: {
+        top: 1,
+      },
+      padding: {
+        top: 1,
+        bottom: 1,
+        left: 7,
+        right: 7,
+      },
+      ...text(layer, "sans", "variant", { size: "xs" }),
+      hover: {
+        ...text(layer, "sans", "hovered", { size: "xs" }),
+        background: background(layer, "hovered"),
+        border: border(layer, "hovered"),
+      },
+    },
+    checkbox: {
+      width: 9,
+      height: 9,
+      default: {
+        ...checkboxBase,
+        background: colorScheme.ramps.blue(0.5).hex(),
+      },
+      checked: {
+        ...checkboxBase,
+        background: colorScheme.ramps.red(0.5).hex(),
+      },
+      hovered: {
+        ...checkboxBase,
+        background: colorScheme.ramps.blue(0.5).hex(),
 
-                border: {
-                    color: colorScheme.ramps.green(0.5).hex(),
-                    width: 1,
-                }
-            },
-            hoveredAndChecked: {
-                ...checkboxBase,
-                background: colorScheme.ramps.red(0.5).hex(),
-                border: {
-                    color: colorScheme.ramps.green(0.5).hex(),
-                    width: 1,
-                }
-            }
+        border: {
+          color: colorScheme.ramps.green(0.5).hex(),
+          width: 1,
+        }
+      },
+      hoveredAndChecked: {
+        ...checkboxBase,
+        background: colorScheme.ramps.red(0.5).hex(),
+        border: {
+          color: colorScheme.ramps.green(0.5).hex(),
+          width: 1,
         }
+      }
     }
+  }
 }