Finish basic welcome experience

Mikayla Maki created

Change summary

crates/theme/src/theme.rs            |   8 +
crates/welcome/src/welcome.rs        | 135 ++++++++++++++---------------
styles/src/styleTree/components.ts   |   2 
styles/src/styleTree/hoverPopover.ts |  78 ++++++++--------
styles/src/styleTree/welcome.ts      |  59 +++++++------
5 files changed, 143 insertions(+), 139 deletions(-)

Detailed changes

crates/theme/src/theme.rs 🔗

@@ -853,14 +853,18 @@ pub struct FeedbackStyle {
 
 #[derive(Clone, Deserialize, Default)]
 pub struct WelcomeStyle {
+    pub page_width: f32,
+    pub logo_subheading: ContainedText,
     pub checkbox: CheckboxStyle,
     pub button: Interactive<ContainedText>,
 }
 
 #[derive(Clone, Deserialize, Default)]
 pub struct CheckboxStyle {
-    pub icon: String,
-    pub icon_color: Color,
+    pub check_icon: String,
+    pub check_icon_color: Color,
+    pub label: ContainedText,
+    pub container: ContainerStyle,
     pub width: f32,
     pub height: f32,
     pub default: ContainerStyle,

crates/welcome/src/welcome.rs 🔗

@@ -34,6 +34,8 @@ impl View for WelcomePage {
         let settings = cx.global::<Settings>();
         let theme = settings.theme.clone();
 
+        let width = theme.welcome.page_width;
+
         let (diagnostics, metrics) = {
             let telemetry = settings.telemetry();
             (telemetry.diagnostics(), telemetry.metrics())
@@ -46,63 +48,42 @@ impl View for WelcomePage {
             self_handle.id(),
             Flex::column()
                 .with_children([
-                    Flex::row()
-                        .with_children([
-                            Image::new("images/zed-logo-90x90.png")
-                                .constrained()
-                                .with_width(90.)
-                                .with_height(90.)
-                                .aligned()
-                                .contained()
-                                .boxed(),
-                            // Label::new("Zed", theme.editor.hover_popover.prose.clone()).boxed(),
-                        ])
+                    Image::new("images/zed-logo-90x90.png")
+                        .constrained()
+                        .with_width(90.)
+                        .with_height(90.)
+                        .aligned()
+                        .contained()
+                        .aligned()
                         .boxed(),
                     Label::new(
                         "Code at the speed of thought",
-                        theme.editor.hover_popover.prose.clone(),
+                        theme.welcome.logo_subheading.text.clone(),
                     )
+                    .aligned()
+                    .contained()
+                    .with_style(theme.welcome.logo_subheading.container)
                     .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>(
-                                &theme.welcome.checkbox,
-                                metrics,
-                                cx,
-                                |content, checked| {
-                                    content.telemetry.set_metrics(checked);
-                                },
-                            ),
-                            Label::new(
-                                "Do you want to send telemetry?",
-                                theme.editor.hover_popover.prose.clone(),
-                            )
-                            .boxed(),
-                        ])
-                        .align_children_center()
-                        .boxed(),
-                    Flex::row()
-                        .with_children([
-                            self.render_settings_checkbox::<Diagnostics>(
-                                &theme.welcome.checkbox,
-                                diagnostics,
-                                cx,
-                                |content, checked| content.telemetry.set_diagnostics(checked),
-                            ),
-                            Label::new(
-                                "Send crash reports",
-                                theme.editor.hover_popover.prose.clone(),
-                            )
-                            .boxed(),
-                        ])
-                        .align_children_center()
-                        .boxed(),
+                    self.render_cta_button(2, "Choose a theme", theme_selector::Toggle, width, cx),
+                    self.render_cta_button(3, "Choose a keymap", theme_selector::Toggle, width, cx),
+                    self.render_settings_checkbox::<Metrics>(
+                        "Do you want to send telemetry?",
+                        &theme.welcome.checkbox,
+                        metrics,
+                        cx,
+                        |content, checked| content.telemetry.set_metrics(checked),
+                    ),
+                    self.render_settings_checkbox::<Diagnostics>(
+                        "Send crash reports",
+                        &theme.welcome.checkbox,
+                        diagnostics,
+                        cx,
+                        |content, checked| content.telemetry.set_diagnostics(checked),
+                    ),
                 ])
-                .aligned()
                 .constrained()
-                .with_max_width(300.)
+                .with_max_width(width)
+                .aligned()
                 .boxed(),
         )
         .boxed()
@@ -129,6 +110,7 @@ impl WelcomePage {
         region_id: usize,
         label: L,
         action: A,
+        width: f32,
         cx: &mut RenderContext<Self>,
     ) -> ElementBox
     where
@@ -139,19 +121,23 @@ impl WelcomePage {
         MouseEventHandler::<A>::new(region_id, cx, |state, _| {
             let style = theme.welcome.button.style_for(state, false);
             Label::new(label, style.text.clone())
+                .aligned()
                 .contained()
                 .with_style(style.container)
+                .constrained()
+                .with_width(width)
                 .boxed()
         })
         .on_click(MouseButton::Left, move |_, cx| {
             cx.dispatch_action(action.clone())
         })
-        .aligned()
+        .with_cursor_style(gpui::CursorStyle::PointingHand)
         .boxed()
     }
 
     fn render_settings_checkbox<T: 'static>(
         &self,
+        label: &'static str,
         style: &CheckboxStyle,
         checked: bool,
         cx: &mut RenderContext<Self>,
@@ -159,35 +145,44 @@ impl WelcomePage {
     ) -> ElementBox {
         MouseEventHandler::<T>::new(0, cx, |state, _| {
             let indicator = if checked {
-                Svg::new(style.icon.clone())
-                    .with_color(style.icon_color)
+                Svg::new(style.check_icon.clone())
+                    .with_color(style.check_icon_color)
                     .constrained()
             } else {
                 Empty::new().constrained()
             };
 
-            indicator
-                .with_width(style.width)
-                .with_height(style.height)
-                .contained()
-                .with_style(if checked {
-                    if state.hovered() {
-                        style.hovered_and_checked
-                    } else {
-                        style.checked
-                    }
-                } else {
-                    if state.hovered() {
-                        style.hovered
-                    } else {
-                        style.default
-                    }
-                })
+            Flex::row()
+                .with_children([
+                    indicator
+                        .with_width(style.width)
+                        .with_height(style.height)
+                        .contained()
+                        .with_style(if checked {
+                            if state.hovered() {
+                                style.hovered_and_checked
+                            } else {
+                                style.checked
+                            }
+                        } else {
+                            if state.hovered() {
+                                style.hovered
+                            } else {
+                                style.default
+                            }
+                        })
+                        .boxed(),
+                    Label::new(label, style.label.text.clone()).contained().with_style(style.label.container).boxed(),
+                ])
+                .align_children_center()
                 .boxed()
         })
         .on_click(gpui::MouseButton::Left, move |_, cx| {
             SettingsFile::update(cx, move |content| set_value(content, !checked))
         })
+        .with_cursor_style(gpui::CursorStyle::PointingHand)
+        .contained()
+        .with_style(style.container)
         .boxed()
     }
 }

styles/src/styleTree/components.ts 🔗

@@ -93,7 +93,7 @@ interface Text {
     underline?: boolean
 }
 
-interface TextProperties {
+export interface TextProperties {
     size?: keyof typeof fontSizes
     weight?: FontWeight
     underline?: boolean

styles/src/styleTree/hoverPopover.ts 🔗

@@ -2,44 +2,44 @@ import { ColorScheme } from "../themes/common/colorScheme"
 import { background, border, text } from "./components"
 
 export default function HoverPopover(colorScheme: ColorScheme) {
-    let layer = colorScheme.middle
-    let baseContainer = {
-        background: background(layer),
-        cornerRadius: 8,
-        padding: {
-            left: 8,
-            right: 8,
-            top: 4,
-            bottom: 4,
-        },
-        shadow: colorScheme.popoverShadow,
-        border: border(layer),
-        margin: {
-            left: -8,
-        },
-    }
+  let layer = colorScheme.middle
+  let baseContainer = {
+    background: background(layer),
+    cornerRadius: 8,
+    padding: {
+      left: 8,
+      right: 8,
+      top: 4,
+      bottom: 4,
+    },
+    shadow: colorScheme.popoverShadow,
+    border: border(layer),
+    margin: {
+      left: -8,
+    },
+  }
 
-    return {
-        container: baseContainer,
-        infoContainer: {
-            ...baseContainer,
-            background: background(layer, "accent"),
-            border: border(layer, "accent"),
-        },
-        warningContainer: {
-            ...baseContainer,
-            background: background(layer, "warning"),
-            border: border(layer, "warning"),
-        },
-        errorContainer: {
-            ...baseContainer,
-            background: background(layer, "negative"),
-            border: border(layer, "negative"),
-        },
-        block_style: {
-            padding: { top: 4 },
-        },
-        prose: text(layer, "sans", { size: "sm" }),
-        highlight: colorScheme.ramps.neutral(0.5).alpha(0.2).hex(), // TODO: blend was used here. Replace with something better
-    }
+  return {
+    container: baseContainer,
+    infoContainer: {
+      ...baseContainer,
+      background: background(layer, "accent"),
+      border: border(layer, "accent"),
+    },
+    warningContainer: {
+      ...baseContainer,
+      background: background(layer, "warning"),
+      border: border(layer, "warning"),
+    },
+    errorContainer: {
+      ...baseContainer,
+      background: background(layer, "negative"),
+      border: border(layer, "negative"),
+    },
+    block_style: {
+      padding: { top: 4 },
+    },
+    prose: text(layer, "sans", { size: "sm" }),
+    highlight: colorScheme.ramps.neutral(0.5).alpha(0.2).hex(), // TODO: blend was used here. Replace with something better
+  }
 }

styles/src/styleTree/welcome.ts 🔗

@@ -1,12 +1,11 @@
 
 import { ColorScheme } from "../themes/common/colorScheme";
-import { border, background, foreground, text } from "./components";
+import { border, background, foreground, text, TextProperties } from "./components";
 
 
 export default function welcome(colorScheme: ColorScheme) {
   let layer = colorScheme.highest;
 
-  // TODO
   let checkboxBase = {
     cornerRadius: 4,
     padding: {
@@ -18,20 +17,30 @@ export default function welcome(colorScheme: ColorScheme) {
     shadow: colorScheme.popoverShadow,
     border: border(layer),
     margin: {
-      left: 8,
       right: 8,
       top: 5,
       bottom: 5
     },
   };
+  
+  let interactive_text_size: TextProperties = { size: "md" }
 
   return {
+    pageWidth: 450,
+    logoSubheading: {
+      ...text(layer, "sans", { size: "lg" }),
+      margin: {
+        top: 10,
+        bottom: 7,
+      },
+    },
     button: {
       background: background(layer),
-      border: border(layer),
-      cornerRadius: 6,
+      border: border(layer, "active"),
+      cornerRadius: 4,
       margin: {
-        top: 1,
+        top: 8,
+        bottom: 7
       },
       padding: {
         top: 1,
@@ -39,50 +48,46 @@ export default function welcome(colorScheme: ColorScheme) {
         left: 7,
         right: 7,
       },
-      ...text(layer, "sans", "variant", { size: "xs" }),
+      ...text(layer, "sans", "hovered", interactive_text_size),
       hover: {
-        ...text(layer, "sans", "hovered", { size: "xs" }),
+        ...text(layer, "sans", "hovered", interactive_text_size),
         background: background(layer, "hovered"),
         border: border(layer, "hovered"),
       },
     },
     checkbox: {
+      label: {
+          ...text(layer, "sans", interactive_text_size),
+          // Also supports margin, container, border, etc.
+      },
+      container: {
+        margin: {
+          top: 5,
+        },
+      },
       width: 12,
       height: 12,
-      icon: "icons/check_12.svg",
-      iconColor: foreground(layer, "on"),
+      checkIcon: "icons/check_12.svg",
+      checkIconColor: foreground(layer, "on"),
       default: {
         ...checkboxBase,
         background: background(layer, "default"),
-        border: {
-          color: foreground(layer, "hovered"),
-          width: 1,
-        }
+        border: border(layer, "active")
       },
       checked: {
         ...checkboxBase,
         background: background(layer, "hovered"),
-        border: {
-          color: foreground(layer, "hovered"),
-          width: 1,
-        }
+        border: border(layer, "active")
       },
       hovered: {
         ...checkboxBase,
         background: background(layer, "hovered"),
-
-        border: {
-          color: foreground(layer, "hovered"),
-          width: 1,
-        }
+        border: border(layer, "hovered")
       },
       hoveredAndChecked: {
         ...checkboxBase,
         background: background(layer, "hovered"),
-        border: {
-          color: foreground(layer, "hovered"),
-          width: 1,
-        }
+        border: border(layer, "active")
       }
     }
   }