Finish basic welcome experience

This commit is contained in:
Mikayla Maki 2023-03-06 16:28:23 -08:00
parent 020a0965b0
commit ba652fc033
5 changed files with 143 additions and 139 deletions

View file

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

View file

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

View file

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

View file

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

View file

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