Keyboardable buttons in linux alerts (#13235)

Conrad Irwin created

Release Notes:

- N/A

Change summary

crates/zed/src/zed/linux_prompts.rs | 90 ++++++++++++++++++------------
1 file changed, 54 insertions(+), 36 deletions(-)

Detailed changes

crates/zed/src/zed/linux_prompts.rs 🔗

@@ -3,7 +3,10 @@ use gpui::{
     InteractiveElement, IntoElement, ParentElement, PromptHandle, PromptLevel, PromptResponse,
     Render, RenderablePromptHandle, Styled, ViewContext, VisualContext, WindowContext,
 };
-use ui::{h_flex, v_flex, ButtonCommon, ButtonStyle, Clickable, ElevationIndex, LabelSize};
+use ui::{
+    h_flex, v_flex, ButtonCommon, ButtonStyle, Clickable, ElevationIndex, FluentBuilder, LabelSize,
+    TintColor,
+};
 use workspace::ui::StyledExt;
 
 pub fn init(cx: &mut AppContext) {
@@ -40,44 +43,59 @@ pub struct FallbackPromptRenderer {
     actions: Vec<String>,
     focus: FocusHandle,
 }
+impl FallbackPromptRenderer {
+    fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+        cx.emit(PromptResponse(0));
+    }
 
+    fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
+        if let Some(ix) = self.actions.iter().position(|a| a == "Cancel") {
+            cx.emit(PromptResponse(ix));
+        }
+    }
+}
 impl Render for FallbackPromptRenderer {
     fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
-        let prompt =
-            v_flex()
-                .cursor_default()
-                .track_focus(&self.focus)
-                .elevation_3(cx)
-                .w_72()
-                .overflow_hidden()
-                .p_4()
-                .gap_4()
-                .font_family("Zed Sans")
-                .child(
-                    div()
-                        .w_full()
-                        .font_weight(FontWeight::BOLD)
-                        .child(self.message.clone())
-                        .text_color(ui::Color::Default.color(cx)),
-                )
-                .children(self.detail.clone().map(|detail| {
-                    div()
-                        .w_full()
-                        .text_xs()
-                        .text_color(ui::Color::Muted.color(cx))
-                        .child(detail)
-                }))
-                .child(h_flex().justify_end().gap_2().children(
-                    self.actions.iter().enumerate().map(|(ix, action)| {
-                        ui::Button::new(ix, action.clone())
-                            .label_size(LabelSize::Large)
-                            .style(ButtonStyle::Filled)
-                            .layer(ElevationIndex::ModalSurface)
-                            .on_click(cx.listener(move |_, _, cx| {
-                                cx.emit(PromptResponse(ix));
-                            }))
-                    }),
-                ));
+        let prompt = v_flex()
+            .key_context("Prompt")
+            .cursor_default()
+            .track_focus(&self.focus)
+            .on_action(cx.listener(Self::confirm))
+            .on_action(cx.listener(Self::cancel))
+            .elevation_3(cx)
+            .w_72()
+            .overflow_hidden()
+            .p_4()
+            .gap_4()
+            .font_family("Zed Sans")
+            .child(
+                div()
+                    .w_full()
+                    .font_weight(FontWeight::BOLD)
+                    .child(self.message.clone())
+                    .text_color(ui::Color::Default.color(cx)),
+            )
+            .children(self.detail.clone().map(|detail| {
+                div()
+                    .w_full()
+                    .text_xs()
+                    .text_color(ui::Color::Muted.color(cx))
+                    .child(detail)
+            }))
+            .child(h_flex().justify_end().gap_2().children(
+                self.actions.iter().enumerate().rev().map(|(ix, action)| {
+                    ui::Button::new(ix, action.clone())
+                        .label_size(LabelSize::Large)
+                        .style(ButtonStyle::Filled)
+                        .when(ix == 0, |el| {
+                            el.style(ButtonStyle::Tinted(TintColor::Accent))
+                        })
+                        .layer(ElevationIndex::ModalSurface)
+                        .on_click(cx.listener(move |_, _, cx| {
+                            cx.emit(PromptResponse(ix));
+                        }))
+                }),
+            ));
 
         div()
             .size_full()