Finish device code flow for copilot

Mikayla Maki created

Change summary

crates/copilot/src/sign_in.rs   | 528 ++++++++++++++--------------------
crates/theme/src/theme.rs       |  49 ++-
crates/theme/src/ui.rs          |  24 +
styles/src/styleTree/copilot.ts | 260 +++++++++-------
4 files changed, 412 insertions(+), 449 deletions(-)

Detailed changes

crates/copilot/src/sign_in.rs 🔗

@@ -4,6 +4,7 @@ use gpui::{
     ViewContext, ViewHandle, WindowKind, WindowOptions,
 };
 use settings::Settings;
+use theme::ui::modal;
 
 #[derive(PartialEq, Eq, Debug, Clone)]
 struct CopyUserCode;
@@ -11,7 +12,7 @@ struct CopyUserCode;
 #[derive(PartialEq, Eq, Debug, Clone)]
 struct OpenGithub;
 
-const _COPILOT_SIGN_UP_URL: &'static str = "https://github.com/features/copilot";
+const COPILOT_SIGN_UP_URL: &'static str = "https://github.com/features/copilot";
 
 pub fn init(cx: &mut MutableAppContext) {
     let copilot = Copilot::global(cx).unwrap();
@@ -66,53 +67,60 @@ pub fn init(cx: &mut MutableAppContext) {
     .detach();
 
     // Modal theming test:
-    // use gpui::geometry::vector::vec2f;
-    // let window_size = cx.global::<Settings>().theme.copilot.modal.dimensions();
-    // let window_options = WindowOptions {
-    //     bounds: gpui::WindowBounds::Fixed(RectF::new(Default::default(), window_size)),
-    //     titlebar: None,
-    //     center: false,
-    //     focus: false,
-    //     kind: WindowKind::PopUp,
-    //     is_movable: true,
-    //     screen: None,
-    // };
-    // let (_, _view) = cx.add_window(window_options, |_cx| {
-    //     CopilotCodeVerification::new(Status::SigningIn {
-    //         prompt: Some(PromptUserDeviceFlow {
-    //             user_code: "ABCD-1234".to_string(),
-    //             verification_uri: "https://github.com/login/device".to_string(),
-    //         }),
-    //     })
-    // });
+    use gpui::geometry::vector::vec2f;
 
-    // let window_size = cx.global::<Settings>().theme.copilot.modal.dimensions();
-    // let window_options = WindowOptions {
-    //     bounds: gpui::WindowBounds::Fixed(RectF::new(vec2f(window_size.x(), 0.), window_size)),
-    //     titlebar: None,
-    //     center: false,
-    //     focus: false,
-    //     kind: WindowKind::PopUp,
-    //     is_movable: true,
-    //     screen: None,
-    // };
-    // let (_, _view) = cx.add_window(window_options, |_cx| {
-    //     CopilotCodeVerification::new(Status::Authorized)
-    // });
+    let window_size = cx.global::<Settings>().theme.copilot.modal.dimensions();
+    let window_options = WindowOptions {
+        bounds: gpui::WindowBounds::Fixed(RectF::new(vec2f(0., 0.), window_size)),
+        titlebar: None,
+        center: false,
+        focus: false,
+        kind: WindowKind::PopUp,
+        is_movable: true,
+        screen: None,
+    };
+    let (_, _view) = cx.add_window(window_options, |_cx| {
+        CopilotCodeVerification::new(Status::Authorized)
+    });
 
-    // let window_size = cx.global::<Settings>().theme.copilot.modal.dimensions();
-    // let window_options = WindowOptions {
-    //     bounds: gpui::WindowBounds::Fixed(RectF::new(vec2f(0., window_size.y()), window_size)),
-    //     titlebar: None,
-    //     center: false,
-    //     focus: false,
-    //     kind: WindowKind::PopUp,
-    //     is_movable: true,
-    //     screen: None,
-    // };
-    // let (_, _view) = cx.add_window(window_options, |_cx| {
-    //     CopilotCodeVerification::new(Status::Unauthorized)
-    // });
+    let window_size = cx.global::<Settings>().theme.copilot.modal.dimensions();
+    let window_options = WindowOptions {
+        bounds: gpui::WindowBounds::Fixed(RectF::new(
+            vec2f(window_size.x() + 10., 0.),
+            window_size,
+        )),
+        titlebar: None,
+        center: false,
+        focus: false,
+        kind: WindowKind::PopUp,
+        is_movable: true,
+        screen: None,
+    };
+    let (_, _view) = cx.add_window(window_options, |_cx| {
+        CopilotCodeVerification::new(Status::SigningIn {
+            prompt: Some(PromptUserDeviceFlow {
+                user_code: "ABCD-1234".to_string(),
+                verification_uri: "https://github.com/login/device".to_string(),
+            }),
+        })
+    });
+
+    let window_size = cx.global::<Settings>().theme.copilot.modal.dimensions();
+    let window_options = WindowOptions {
+        bounds: gpui::WindowBounds::Fixed(RectF::new(
+            vec2f((window_size.x() + 10.) * 2., 0.),
+            window_size,
+        )),
+        titlebar: None,
+        center: false,
+        focus: false,
+        kind: WindowKind::PopUp,
+        is_movable: true,
+        screen: None,
+    };
+    let (_, _view) = cx.add_window(window_options, |_cx| {
+        CopilotCodeVerification::new(Status::Unauthorized)
+    });
 }
 
 pub struct CopilotCodeVerification {
@@ -139,323 +147,216 @@ impl CopilotCodeVerification {
             .map(|item| item.text() == &data.user_code)
             .unwrap_or(false);
 
-        Flex::column()
-            .with_children([
-                MouseEventHandler::<Self>::new(0, cx, |state, _cx| {
-                    Flex::row()
-                        .with_children([
-                            Label::new(data.user_code.clone(), style.auth.device_code.clone())
-                                .aligned()
-                                .contained()
-                                .with_style(style.auth.device_code_left_container)
-                                .constrained()
-                                .with_width(style.auth.device_code_left)
-                                .boxed(),
-                            Empty::new()
-                                .constrained()
-                                .with_width(1.)
-                                .with_height(style.auth.device_code_seperator_height)
-                                .contained()
-                                .with_background_color(
-                                    style
-                                        .auth
-                                        .cta_button
-                                        .style_for(state, false)
-                                        .container
-                                        .border
-                                        .color,
-                                )
-                                .boxed(),
-                            Label::new(
-                                if copied { "Copied!" } else { "Copy" },
-                                style.auth.cta_button.style_for(state, false).text.clone(),
-                            )
-                            .aligned()
-                            .contained()
-                            .with_style(style.auth.device_code_right_container)
-                            .constrained()
-                            .with_width(style.auth.device_code_right)
-                            .boxed(),
-                        ])
+        let device_code_style = &style.auth.prompting.device_code;
+
+        MouseEventHandler::<Self>::new(0, cx, |state, _cx| {
+            Flex::row()
+                .with_children([
+                    Label::new(data.user_code.clone(), device_code_style.text.clone())
+                        .aligned()
                         .contained()
-                        .with_style(style.auth.device_code_cta.style_for(state, false).container)
+                        .with_style(device_code_style.left_container)
                         .constrained()
-                        .with_width(style.auth.content_width)
-                        .boxed()
-                })
-                .on_click(gpui::MouseButton::Left, {
-                    let user_code = data.user_code.clone();
-                    move |_, cx| {
-                        cx.platform()
-                            .write_to_clipboard(ClipboardItem::new(user_code.clone()));
-                        cx.notify();
-                    }
-                })
-                .with_cursor_style(gpui::CursorStyle::PointingHand)
-                .boxed(),
-                Flex::column()
-                    .with_children([
-                        Label::new(
-                            "Paste this code into GitHub after",
-                            style.auth.hint.text.clone(),
-                        )
+                        .with_width(device_code_style.left)
                         .boxed(),
-                        Label::new("clicking the button below.", style.auth.hint.text.clone())
-                            .boxed(),
-                    ])
-                    .align_children_center()
+                    Label::new(
+                        if copied { "Copied!" } else { "Copy" },
+                        device_code_style.cta.style_for(state, false).text.clone(),
+                    )
+                    .aligned()
                     .contained()
-                    .with_style(style.auth.hint.container.clone())
+                    .with_style(*device_code_style.right_container.style_for(state, false))
+                    .constrained()
+                    .with_width(device_code_style.right)
                     .boxed(),
-            ])
-            .align_children_center()
-            .contained()
-            .with_style(style.auth.device_code_group)
-            .aligned()
-            .boxed()
+                ])
+                .contained()
+                .with_style(device_code_style.cta.style_for(state, false).container)
+                .boxed()
+        })
+        .on_click(gpui::MouseButton::Left, {
+            let user_code = data.user_code.clone();
+            move |_, cx| {
+                cx.platform()
+                    .write_to_clipboard(ClipboardItem::new(user_code.clone()));
+                cx.notify();
+            }
+        })
+        .with_cursor_style(gpui::CursorStyle::PointingHand)
+        .boxed()
     }
 
-    fn render_not_authorized_warning(style: &theme::Copilot) -> ElementBox {
+    fn render_prompting_modal(
+        data: &PromptUserDeviceFlow,
+        style: &theme::Copilot,
+        cx: &mut gpui::RenderContext<Self>,
+    ) -> ElementBox {
         Flex::column()
             .with_children([
                 Flex::column()
                     .with_children([
                         Label::new(
-                            "You must have an active copilot",
-                            style.auth.warning.text.to_owned(),
+                            "Enable Copilot by connecting",
+                            style.auth.prompting.subheading.text.clone(),
                         )
                         .aligned()
                         .boxed(),
                         Label::new(
-                            "license to use it in Zed.",
-                            style.auth.warning.text.to_owned(),
+                            "your existing license.",
+                            style.auth.prompting.subheading.text.clone(),
                         )
                         .aligned()
                         .boxed(),
                     ])
                     .align_children_center()
                     .contained()
-                    .with_style(style.auth.warning.container)
+                    .with_style(style.auth.prompting.subheading.container)
                     .boxed(),
+                Self::render_device_code(data, &style, cx),
                 Flex::column()
                     .with_children([
                         Label::new(
-                            "Try connecting again once you",
-                            style.auth.hint.text.to_owned(),
+                            "Paste this code into GitHub after",
+                            style.auth.prompting.hint.text.clone(),
                         )
                         .aligned()
                         .boxed(),
                         Label::new(
-                            "have activated a Copilot license.",
-                            style.auth.hint.text.to_owned(),
+                            "clicking the button below.",
+                            style.auth.prompting.hint.text.clone(),
                         )
                         .aligned()
                         .boxed(),
                     ])
                     .align_children_center()
                     .contained()
-                    .with_style(style.auth.not_authorized_hint)
+                    .with_style(style.auth.prompting.hint.container.clone())
                     .boxed(),
-            ])
-            .align_children_center()
-            .boxed()
-    }
-
-    fn render_copilot_enabled(style: &theme::Copilot) -> ElementBox {
-        Flex::column()
-            .with_children([
-                Label::new(
-                    "You can update your settings or",
-                    style.auth.hint.text.clone(),
-                )
-                .aligned()
-                .boxed(),
-                Label::new(
-                    "sign out from the Copilot menu in",
-                    style.auth.hint.text.clone(),
+                theme::ui::cta_button_with_click(
+                    "Connect to GitHub",
+                    style.auth.content_width,
+                    &style.auth.cta_button,
+                    cx,
+                    {
+                        let verification_uri = data.verification_uri.clone();
+                        move |_, cx| cx.platform().open_url(&verification_uri)
+                    },
                 )
-                .aligned()
                 .boxed(),
-                Label::new("the status bar.", style.auth.hint.text.clone())
-                    .aligned()
-                    .boxed(),
             ])
             .align_children_center()
-            .contained()
-            .with_style(style.auth.enabled_hint)
             .boxed()
     }
-
-    fn render_prompting_modal(
-        data: &PromptUserDeviceFlow,
+    fn render_enabled_modal(
         style: &theme::Copilot,
         cx: &mut gpui::RenderContext<Self>,
     ) -> ElementBox {
-        theme::ui::modal("Connect Copilot to Zed", &style.modal, cx, |cx| {
-            Flex::column()
-                .with_children([
-                    Flex::column()
-                        .with_children([
-                            Flex::row()
-                                .with_children([
-                                    theme::ui::svg(&style.auth.copilot_plus_zed_icon).boxed()
-                                ])
-                                .boxed(),
-                            Flex::column()
-                                .with_children([
-                                    Label::new(
-                                        "Enable Copilot by connecting",
-                                        style.auth.enable_text.clone(),
-                                    )
-                                    .boxed(),
-                                    Label::new(
-                                        "your existing license.",
-                                        style.auth.enable_text.clone(),
-                                    )
-                                    .boxed(),
-                                ])
-                                .align_children_center()
-                                .contained()
-                                .with_style(style.auth.enable_group.clone())
-                                .boxed(),
-                        ])
-                        .align_children_center()
-                        .contained()
-                        .with_style(style.auth.header_group)
+        let enabled_style = &style.auth.authorized;
+        Flex::column()
+            .with_children([
+                Label::new("Copilot Enabled!", enabled_style.subheading.text.clone())
+                    .contained()
+                    .with_style(enabled_style.subheading.container)
+                    .aligned()
+                    .boxed(),
+                Flex::column()
+                    .with_children([
+                        Label::new(
+                            "You can update your settings or",
+                            enabled_style.hint.text.clone(),
+                        )
                         .aligned()
                         .boxed(),
-                    Self::render_device_code(data, &style, cx),
-                    Flex::column()
-                        .with_child(theme::ui::cta_button_with_click(
-                            "Connect to GitHub",
-                            style.auth.content_width,
-                            &style.auth.cta_button,
-                            cx,
-                            {
-                                let verification_uri = data.verification_uri.clone();
-                                move |_, cx| cx.platform().open_url(&verification_uri)
-                            },
-                        ))
-                        .align_children_center()
-                        .contained()
-                        .with_style(style.auth.github_group)
+                        Label::new(
+                            "sign out from the Copilot menu in",
+                            enabled_style.hint.text.clone(),
+                        )
                         .aligned()
                         .boxed(),
-                ])
-                .align_children_center()
-                .constrained()
-                .with_width(style.auth.content_width)
-                .aligned()
-                .boxed()
-        })
+                        Label::new("the status bar.", enabled_style.hint.text.clone())
+                            .aligned()
+                            .boxed(),
+                    ])
+                    .align_children_center()
+                    .contained()
+                    .with_style(enabled_style.hint.container)
+                    .boxed(),
+                theme::ui::cta_button_with_click(
+                    "Done",
+                    style.auth.content_width,
+                    &style.auth.cta_button,
+                    cx,
+                    |_, cx| {
+                        let window_id = cx.window_id();
+                        cx.remove_window(window_id)
+                    },
+                )
+                .boxed(),
+            ])
+            .align_children_center()
+            .boxed()
     }
-    fn render_enabled_modal(
+    fn render_unauthorized_modal(
         style: &theme::Copilot,
         cx: &mut gpui::RenderContext<Self>,
     ) -> ElementBox {
-        theme::ui::modal("Connect Copilot to Zed", &style.modal, cx, |cx| {
-            Flex::column()
-                .with_children([
-                    Flex::column()
-                        .with_children([
-                            Flex::row()
-                                .with_children([
-                                    theme::ui::svg(&style.auth.copilot_plus_zed_icon).boxed()
-                                ])
-                                .boxed(),
-                            Label::new("Copilot Enabled!", style.auth.enable_text.clone()).boxed(),
-                        ])
-                        .align_children_center()
-                        .contained()
-                        .with_style(style.auth.header_group)
+        let unauthorized_style = &style.auth.not_authorized;
+
+        Flex::column()
+            .with_children([
+                Flex::column()
+                    .with_children([
+                        Label::new(
+                            "Enable Copilot by connecting",
+                            unauthorized_style.subheading.text.clone(),
+                        )
                         .aligned()
                         .boxed(),
-                    Self::render_copilot_enabled(&style),
-                    Flex::column()
-                        .with_child(theme::ui::cta_button_with_click(
-                            "Close",
-                            style.auth.content_width,
-                            &style.auth.cta_button,
-                            cx,
-                            |_, cx| {
-                                let window_id = cx.window_id();
-                                cx.remove_window(window_id)
-                            },
-                        ))
-                        .align_children_center()
-                        .contained()
-                        .with_style(style.auth.github_group)
+                        Label::new(
+                            "your existing license.",
+                            unauthorized_style.subheading.text.clone(),
+                        )
                         .aligned()
                         .boxed(),
-                ])
-                .align_children_center()
-                .constrained()
-                .with_width(style.auth.content_width)
-                .aligned()
-                .boxed()
-        })
-    }
-    fn render_unauthorized_modal(
-        style: &theme::Copilot,
-        cx: &mut gpui::RenderContext<Self>,
-    ) -> ElementBox {
-        theme::ui::modal("Connect Copilot to Zed", &style.modal, cx, |cx| {
-            Flex::column()
-                .with_children([
-                    Flex::column()
-                        .with_children([
-                            Flex::row()
-                                .with_children([
-                                    theme::ui::svg(&style.auth.copilot_plus_zed_icon).boxed()
-                                ])
-                                .boxed(),
-                            Flex::column()
-                                .with_children([
-                                    Label::new(
-                                        "Enable Copilot by connecting",
-                                        style.auth.enable_text.clone(),
-                                    )
-                                    .boxed(),
-                                    Label::new(
-                                        "your existing license.",
-                                        style.auth.enable_text.clone(),
-                                    )
-                                    .boxed(),
-                                ])
-                                .align_children_center()
-                                .contained()
-                                .with_style(style.auth.enable_group.clone())
-                                .boxed(),
-                        ])
-                        .align_children_center()
-                        .contained()
-                        .with_style(style.auth.header_group)
+                    ])
+                    .align_children_center()
+                    .contained()
+                    .with_style(unauthorized_style.subheading.container)
+                    .boxed(),
+                Flex::column()
+                    .with_children([
+                        Label::new(
+                            "You must have an active copilot",
+                            unauthorized_style.warning.text.clone(),
+                        )
                         .aligned()
                         .boxed(),
-                    Self::render_not_authorized_warning(&style),
-                    Flex::column()
-                        .with_child(theme::ui::cta_button_with_click(
-                            "Close",
-                            style.auth.content_width,
-                            &style.auth.cta_button,
-                            cx,
-                            |_, cx| {
-                                let window_id = cx.window_id();
-                                cx.remove_window(window_id)
-                            },
-                        ))
-                        .align_children_center()
-                        .contained()
-                        .with_style(style.auth.github_group)
+                        Label::new(
+                            "license to use it in Zed.",
+                            unauthorized_style.warning.text.clone(),
+                        )
                         .aligned()
                         .boxed(),
-                ])
-                .align_children_center()
-                .constrained()
-                .with_width(style.auth.content_width)
-                .aligned()
-                .boxed()
-        })
+                    ])
+                    .align_children_center()
+                    .contained()
+                    .with_style(unauthorized_style.warning.container)
+                    .boxed(),
+                theme::ui::cta_button_with_click(
+                    "Subscribe on GitHub",
+                    style.auth.content_width,
+                    &style.auth.cta_button,
+                    cx,
+                    |_, cx| {
+                        let window_id = cx.window_id();
+                        cx.remove_window(window_id);
+                        cx.platform().open_url(COPILOT_SIGN_UP_URL)
+                    },
+                )
+                .boxed(),
+            ])
+            .align_children_center()
+            .boxed()
     }
 }
 
@@ -478,13 +379,22 @@ impl View for CopilotCodeVerification {
 
     fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> gpui::ElementBox {
         let style = cx.global::<Settings>().theme.clone();
-        match &self.status {
-            Status::SigningIn {
-                prompt: Some(prompt),
-            } => Self::render_prompting_modal(&prompt, &style.copilot, cx),
-            Status::Unauthorized => Self::render_unauthorized_modal(&style.copilot, cx),
-            Status::Authorized => Self::render_enabled_modal(&style.copilot, cx),
-            _ => Empty::new().boxed(),
-        }
+
+        modal("Connect Copilot to Zed", &style.copilot.modal, cx, |cx| {
+            Flex::column()
+                .with_children([
+                    theme::ui::icon(&style.copilot.auth.header).boxed(),
+                    match &self.status {
+                        Status::SigningIn {
+                            prompt: Some(prompt),
+                        } => Self::render_prompting_modal(&prompt, &style.copilot, cx),
+                        Status::Unauthorized => Self::render_unauthorized_modal(&style.copilot, cx),
+                        Status::Authorized => Self::render_enabled_modal(&style.copilot, cx),
+                        _ => Empty::new().boxed(),
+                    },
+                ])
+                .align_children_center()
+                .boxed()
+        })
     }
 }

crates/theme/src/theme.rs 🔗

@@ -126,28 +126,43 @@ pub struct Copilot {
 
 #[derive(Deserialize, Default, Clone)]
 pub struct CopilotAuth {
-    pub enable_group: ContainerStyle,
-    pub enable_text: TextStyle,
-    pub instruction_text: TextStyle,
-    pub cta_button: ButtonStyle,
     pub content_width: f32,
-    pub copilot_plus_zed_icon: SvgStyle,
-    pub device_code_group: ContainerStyle,
-    pub github_group: ContainerStyle,
-    pub header_group: ContainerStyle,
-    pub device_code: TextStyle,
-    pub device_code_cta: ButtonStyle,
-    pub device_code_left: f32,
-    pub device_code_left_container: ContainerStyle,
-    pub device_code_right: f32,
-    pub device_code_right_container: ContainerStyle,
-    pub device_code_seperator_height: f32,
+    pub prompting: CopilotAuthPrompting,
+    pub not_authorized: CopilotAuthNotAuthorized,
+    pub authorized: CopilotAuthAuthorized,
+    pub cta_button: ButtonStyle,
+    pub header: IconStyle,
+}
+
+#[derive(Deserialize, Default, Clone)]
+pub struct CopilotAuthPrompting {
+    pub subheading: ContainedText,
     pub hint: ContainedText,
-    pub enabled_hint: ContainerStyle,
-    pub not_authorized_hint: ContainerStyle,
+    pub device_code: DeviceCode,
+}
+
+#[derive(Deserialize, Default, Clone)]
+pub struct DeviceCode {
+    pub text: TextStyle,
+    pub cta: ButtonStyle,
+    pub left: f32,
+    pub left_container: ContainerStyle,
+    pub right: f32,
+    pub right_container: Interactive<ContainerStyle>,
+}
+
+#[derive(Deserialize, Default, Clone)]
+pub struct CopilotAuthNotAuthorized {
+    pub subheading: ContainedText,
     pub warning: ContainedText,
 }
 
+#[derive(Deserialize, Default, Clone)]
+pub struct CopilotAuthAuthorized {
+    pub subheading: ContainedText,
+    pub hint: ContainedText,
+}
+
 #[derive(Deserialize, Default)]
 pub struct ContactsPopover {
     #[serde(flatten)]

crates/theme/src/ui.rs 🔗

@@ -186,6 +186,7 @@ where
     cta_button_with_click(label, max_width, style, cx, move |_, cx| {
         cx.dispatch_action(action.clone())
     })
+    .boxed()
 }
 
 pub fn cta_button_with_click<L, V, F>(
@@ -194,7 +195,7 @@ pub fn cta_button_with_click<L, V, F>(
     style: &ButtonStyle,
     cx: &mut RenderContext<V>,
     f: F,
-) -> ElementBox
+) -> MouseEventHandler<F>
 where
     L: Into<Cow<'static, str>>,
     V: View,
@@ -212,7 +213,6 @@ where
     })
     .on_click(MouseButton::Left, f)
     .with_cursor_style(gpui::CursorStyle::PointingHand)
-    .boxed()
 }
 
 #[derive(Clone, Deserialize, Default)]
@@ -241,7 +241,8 @@ where
     I: Into<Cow<'static, str>>,
     F: FnOnce(&mut gpui::RenderContext<V>) -> ElementBox,
 {
-    let active = cx.window_is_active(cx.window_id());
+    const TITLEBAR_HEIGHT: f32 = 28.;
+    // let active = cx.window_is_active(cx.window_id());
 
     Flex::column()
         .with_child(
@@ -251,13 +252,13 @@ where
                         title,
                         style
                             .title_text
-                            .style_for(&mut MouseState::default(), active)
+                            .style_for(&mut MouseState::default(), false)
                             .clone(),
                     )
                     .boxed(),
                     // FIXME: Get a better tag type
                     MouseEventHandler::<V>::new(999999, cx, |state, _cx| {
-                        let style = style.close_icon.style_for(state, active);
+                        let style = style.close_icon.style_for(state, false);
                         icon(style).boxed()
                     })
                     .on_click(gpui::MouseButton::Left, move |_, cx| {
@@ -271,11 +272,18 @@ where
                 ])
                 .contained()
                 .with_style(style.titlebar)
+                .constrained()
+                .with_height(TITLEBAR_HEIGHT)
+                .boxed(),
+        )
+        .with_child(
+            Container::new(build_modal(cx))
+                .with_style(style.container)
+                .constrained()
+                .with_width(style.dimensions().x())
+                .with_height(style.dimensions().y() - TITLEBAR_HEIGHT)
                 .boxed(),
         )
-        .with_child(build_modal(cx))
-        .contained()
-        .with_style(style.container)
         .constrained()
         .with_height(style.dimensions().y())
         .boxed()

styles/src/styleTree/copilot.ts 🔗

@@ -3,17 +3,19 @@ import { background, border, foreground, svg, text } from "./components";
 
 
 export default function copilot(colorScheme: ColorScheme) {
-    let layer = colorScheme.highest;
+    let layer = colorScheme.middle;
 
-    let content_width = 304;
+    let content_width = 264;
 
     let ctaButton = { // Copied from welcome screen. FIXME: Move this into a ZDS component
         background: background(layer),
-        border: border(layer, "active"),
+        border: border(layer, "default"),
         cornerRadius: 4,
         margin: {
             top: 4,
             bottom: 4,
+            left: 8,
+            right: 8
         },
         padding: {
             top: 3,
@@ -42,155 +44,183 @@ export default function copilot(colorScheme: ColorScheme) {
         },
         modal: {
             titleText: {
-                ...text(layer, "sans", { size: "md", color: background(layer, "default") }),
-                active: {
-                    ...text(layer, "sans", { size: "md" }),
-                }
+                ...text(layer, "sans", { size: "xs", "weight": "bold" })
             },
             titlebar: {
+                background: background(colorScheme.lowest),
                 border: border(layer, "active"),
                 padding: {
-                    top: 8,
-                    bottom: 8,
+                    top: 4,
+                    bottom: 4,
                     left: 8,
                     right: 8,
-                },
-                margin: {
+                }
+            },
+            container: {
+                background: background(colorScheme.lowest),
+                padding: {
                     top: 0,
                     left: 0,
                     right: 0,
-                    bottom: 16
+                    bottom: 8,
                 }
             },
-            container: {
-                background: background(colorScheme.highest),
-
-            },
             closeIcon: {
-                icon: svg(background(layer, "on"), "icons/x_mark_16.svg", 16, 16),
+                icon: svg(foreground(layer, "variant"), "icons/x_mark_8.svg", 8, 8),
                 container: {
                     cornerRadius: 2,
                     padding: {
-                        top: 3,
-                        bottom: 3,
-                        left: 7,
-                        right: 0,
+                        top: 4,
+                        bottom: 4,
+                        left: 4,
+                        right: 4,
+                    },
+                    margin: {
+                        right: 0
                     }
                 },
-                active: {
-                    icon: svg(foreground(colorScheme.lowest, "warning"), "icons/x_mark_16.svg", 16, 16),
+                hover: {
+                    icon: svg(foreground(layer, "on"), "icons/x_mark_8.svg", 8, 8),
                 },
-                hoverAndActive: {
-                    icon: svg(foreground(layer, "on", "hovered"), "icons/x_mark_16.svg", 16, 16),
-                },
-                clickedAndactive: {
-                    icon: svg(foreground(layer, "on", "pressed"), "icons/x_mark_16.svg", 16, 16),
+                clicked: {
+                    icon: svg(foreground(layer, "base"), "icons/x_mark_8.svg", 8, 8),
                 }
             },
             dimensions: {
-                width: 400,
-                height: 500,
+                width: 280,
+                height: 280,
             },
         },
+
         auth: {
             content_width,
 
-            headerGroup: {
-                margin: {
-                    top: 5,
-                    bottom: 5,
-                    left: 0,
-                    right: 0
-                }
-            },
-            copilotPlusZedIcon: svg(foreground(layer, "default"), "icons/zed_plus_copilot_32.svg", 32, 92),
-            enableText: text(layer, "sans", { size: "md" }),
-            enableGroup: {
-                margin: {
-                    top: 5,
-                    bottom: 5,
-                    left: 0,
-                    right: 0
-                }
+            ctaButton,
+
+            header: {
+                icon: svg(foreground(layer, "default"), "icons/zed_plus_copilot_32.svg", 92, 32),
+                container: {
+                    margin: {
+                        top: 35,
+                        bottom: 5,
+                        left: 0,
+                        right: 0
+                    }
+                },
             },
 
-            instructionText: text(layer, "sans"),
+            prompting: {
+                subheading: {
+                    ...text(layer, "sans", { size: "xs" }),
+                    margin: {
+                        top: 6,
+                        bottom: 12,
+                        left: 0,
+                        right: 0
+                    }
+                },
 
-            deviceCodeGroup: {
-                margin: {
-                    top: 20,
-                    bottom: 20,
-                    left: 0,
-                    right: 0
-                }
-            },
-            deviceCode:
-                text(layer, "mono", { size: "md" }),
-            deviceCodeCta: {
-                ...ctaButton,
-                padding: {
-                    top: 0,
-                    bottom: 0,
-                    left: 0,
-                    right: 0,
+                hint: {
+                    ...text(layer, "sans", { size: "xs", color: "#838994" }),
+                    margin: {
+                        top: 6,
+                        bottom: 2
+                    }
                 },
-            },
-            deviceCodeLeft: content_width * 2 / 3,
-            deviceCodeLeftContainer: {
-                padding: {
-                    top: 3,
-                    bottom: 3,
-                    left: 0,
-                    right: 0,
+
+                deviceCode: {
+                    text:
+                        text(layer, "mono", { size: "sm" }),
+                    cta: {
+                        ...ctaButton,
+                        background: background(colorScheme.lowest),
+                        border: border(colorScheme.lowest, "inverted"),
+                        padding: {
+                            top: 0,
+                            bottom: 0,
+                            left: 16,
+                            right: 16,
+                        },
+                        margin: {
+                            left: 16,
+                            right: 16,
+                        }
+                    },
+                    left: content_width / 2,
+                    leftContainer: {
+                        padding: {
+                            top: 3,
+                            bottom: 3,
+                            left: 0,
+                            right: 6,
+                        },
+                    },
+                    right: content_width * 1 / 3,
+                    rightContainer: {
+                        border: border(colorScheme.lowest, "inverted", { bottom: false, right: false, top: false, left: true }),
+                        padding: {
+                            top: 3,
+                            bottom: 5,
+                            left: 8,
+                            right: 0,
+                        },
+                        hover: {
+                            border: border(layer, "active", { bottom: false, right: false, top: false, left: true }),
+                        },
+                    }
                 },
             },
-            deviceCodeRight: content_width * 1 / 3,
-            deviceCodeRightContainer: {
-                border: border(layer, "active", { bottom: false, right: false, top: false, left: true }),
-                padding: {
-                    top: 3,
-                    bottom: 5,
-                    left: 0,
-                    right: 0,
+
+            notAuthorized: {
+                subheading: {
+                    ...text(layer, "sans", { size: "xs" }),
+
+                    margin: {
+                        top: 16,
+                        bottom: 16,
+                        left: 0,
+                        right: 0
+                    }
                 },
-            },
-            deviceCodeSeperatorHeight: 0,
-            hint: {
-                ...text(layer, "sans", { size: "xs" }),
-                margin: {
-                    top: -5,
-                }
-            },
-            enabledHint: {
-                margin: {
-                    top: 10,
-                    bottom: 10
-                }
-            },
-            notAuthorizedHint: {
-                margin: {
-                    top: 10,
-                    bottom: 10
-                }
-            },
 
-            warning: {
-                ...text(layer, "sans", { size: "md", color: foreground(layer, "warning") }),
-                border: border(layer, "warning"),
-                background_color: background(layer, "warning"),
-                cornerRadius: 2,
+                warning: {
+                    ...text(layer, "sans", { size: "xs", color: foreground(layer, "warning") }),
+                    border: border(layer, "warning"),
+                    background: background(layer, "warning"),
+                    cornerRadius: 2,
+                    padding: {
+                        top: 4,
+                        left: 4,
+                        bottom: 4,
+                        right: 4,
+                    },
+                    margin: {
+                        bottom: 16,
+                        left: 8,
+                        right: 8
+                    }
+                },
             },
 
-            githubGroup: {
-                margin: {
-                    top: 3,
-                    bottom: 3,
-                    left: 0,
-                    right: 0
-                }
-            },
+            authorized: {
+                subheading: {
+                    ...text(layer, "sans", { size: "xs" }),
+
+                    margin: {
+                        top: 16,
+                        bottom: 16
+                    }
+                },
 
-            ctaButton
+                hint: {
+                    ...text(layer, "sans", { size: "xs", color: "#838994" }),
+                    margin: {
+                        top: 24,
+                        bottom: 4
+                    }
+                },
+
+            },
         }
     }
 }