parent
106d4cfce9
commit
070f7dbe1a
12 changed files with 155 additions and 72 deletions
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 6.4 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 5.3 KiB |
1
assets/images/pro_user_stamp.svg
Normal file
1
assets/images/pro_user_stamp.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 5.5 KiB |
|
@ -1103,6 +1103,13 @@
|
|||
"ctrl-enter": "menu::Confirm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "OnboardingAiConfigurationModal",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"escape": "menu::Cancel"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Diagnostics",
|
||||
"use_key_equivalents": true,
|
||||
|
@ -1179,7 +1186,8 @@
|
|||
"ctrl-1": "onboarding::ActivateBasicsPage",
|
||||
"ctrl-2": "onboarding::ActivateEditingPage",
|
||||
"ctrl-3": "onboarding::ActivateAISetupPage",
|
||||
"ctrl-escape": "onboarding::Finish"
|
||||
"ctrl-escape": "onboarding::Finish",
|
||||
"alt-tab": "onboarding::SignIn"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1205,6 +1205,13 @@
|
|||
"cmd-enter": "menu::Confirm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "OnboardingAiConfigurationModal",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"escape": "menu::Cancel"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Diagnostics",
|
||||
"use_key_equivalents": true,
|
||||
|
@ -1281,7 +1288,8 @@
|
|||
"cmd-1": "onboarding::ActivateBasicsPage",
|
||||
"cmd-2": "onboarding::ActivateEditingPage",
|
||||
"cmd-3": "onboarding::ActivateAISetupPage",
|
||||
"cmd-escape": "onboarding::Finish"
|
||||
"cmd-escape": "onboarding::Finish",
|
||||
"alt-tab": "onboarding::SignIn"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -137,7 +137,7 @@ impl RenderOnce for AiUpsellCard {
|
|||
.size(rems_from_px(72.))
|
||||
.child(
|
||||
Vector::new(
|
||||
VectorName::CertifiedUserStamp,
|
||||
VectorName::ProUserStamp,
|
||||
rems_from_px(72.),
|
||||
rems_from_px(72.),
|
||||
)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use ai_onboarding::{AiUpsellCard, SignInStatus};
|
||||
use client::UserStore;
|
||||
use ai_onboarding::AiUpsellCard;
|
||||
use client::{Client, UserStore};
|
||||
use fs::Fs;
|
||||
use gpui::{
|
||||
Action, AnyView, App, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, WeakEntity,
|
||||
|
@ -12,8 +12,8 @@ use language_model::{LanguageModelProvider, LanguageModelProviderId, LanguageMod
|
|||
use project::DisableAiSettings;
|
||||
use settings::{Settings, update_settings_file};
|
||||
use ui::{
|
||||
Badge, ButtonLike, Divider, Modal, ModalFooter, ModalHeader, Section, SwitchField, ToggleState,
|
||||
prelude::*, tooltip_container,
|
||||
Badge, ButtonLike, Divider, KeyBinding, Modal, ModalFooter, ModalHeader, Section, SwitchField,
|
||||
ToggleState, prelude::*, tooltip_container,
|
||||
};
|
||||
use util::ResultExt;
|
||||
use workspace::{ModalView, Workspace};
|
||||
|
@ -88,7 +88,7 @@ fn render_privacy_card(tab_index: &mut isize, disabled: bool, cx: &mut App) -> i
|
|||
h_flex()
|
||||
.gap_2()
|
||||
.justify_between()
|
||||
.child(Label::new("We don't train models using your data"))
|
||||
.child(Label::new("Privacy is the default for Zed"))
|
||||
.child(
|
||||
h_flex().gap_1().child(privacy_badge()).child(
|
||||
Button::new("learn_more", "Learn More")
|
||||
|
@ -109,7 +109,7 @@ fn render_privacy_card(tab_index: &mut isize, disabled: bool, cx: &mut App) -> i
|
|||
)
|
||||
.child(
|
||||
Label::new(
|
||||
"Feel confident in the security and privacy of your projects using Zed.",
|
||||
"Any use or storage of your data is with your explicit, single-use, opt-in consent.",
|
||||
)
|
||||
.size(LabelSize::Small)
|
||||
.color(Color::Muted),
|
||||
|
@ -240,6 +240,7 @@ fn render_llm_provider_card(
|
|||
pub(crate) fn render_ai_setup_page(
|
||||
workspace: WeakEntity<Workspace>,
|
||||
user_store: Entity<UserStore>,
|
||||
client: Arc<Client>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> impl IntoElement {
|
||||
|
@ -283,15 +284,16 @@ pub(crate) fn render_ai_setup_page(
|
|||
v_flex()
|
||||
.mt_2()
|
||||
.gap_6()
|
||||
.child(AiUpsellCard {
|
||||
sign_in_status: SignInStatus::SignedIn,
|
||||
sign_in: Arc::new(|_, _| {}),
|
||||
account_too_young: user_store.read(cx).account_too_young(),
|
||||
user_plan: user_store.read(cx).plan(),
|
||||
tab_index: Some({
|
||||
.child({
|
||||
let mut ai_upsell_card =
|
||||
AiUpsellCard::new(client, &user_store, user_store.read(cx).plan(), cx);
|
||||
|
||||
ai_upsell_card.tab_index = Some({
|
||||
tab_index += 1;
|
||||
tab_index - 1
|
||||
}),
|
||||
});
|
||||
|
||||
ai_upsell_card
|
||||
})
|
||||
.child(render_llm_provider_section(
|
||||
&mut tab_index,
|
||||
|
@ -336,6 +338,10 @@ impl AiConfigurationModal {
|
|||
selected_provider,
|
||||
}
|
||||
}
|
||||
|
||||
fn cancel(&mut self, _: &menu::Cancel, cx: &mut Context<Self>) {
|
||||
cx.emit(DismissEvent);
|
||||
}
|
||||
}
|
||||
|
||||
impl ModalView for AiConfigurationModal {}
|
||||
|
@ -349,11 +355,15 @@ impl Focusable for AiConfigurationModal {
|
|||
}
|
||||
|
||||
impl Render for AiConfigurationModal {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.key_context("OnboardingAiConfigurationModal")
|
||||
.w(rems(34.))
|
||||
.elevation_3(cx)
|
||||
.track_focus(&self.focus_handle)
|
||||
.on_action(
|
||||
cx.listener(|this, _: &menu::Cancel, _window, cx| this.cancel(&menu::Cancel, cx)),
|
||||
)
|
||||
.child(
|
||||
Modal::new("onboarding-ai-setup-modal", None)
|
||||
.header(
|
||||
|
@ -368,18 +378,19 @@ impl Render for AiConfigurationModal {
|
|||
.section(Section::new().child(self.configuration_view.clone()))
|
||||
.footer(
|
||||
ModalFooter::new().end_slot(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
Button::new("onboarding-closing-cancel", "Cancel")
|
||||
.on_click(cx.listener(|_, _, _, cx| cx.emit(DismissEvent))),
|
||||
Button::new("ai-onb-modal-Done", "Done")
|
||||
.key_binding(
|
||||
KeyBinding::for_action_in(
|
||||
&menu::Cancel,
|
||||
&self.focus_handle.clone(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.map(|kb| kb.size(rems_from_px(12.))),
|
||||
)
|
||||
.child(Button::new("save-btn", "Done").on_click(cx.listener(
|
||||
|_, _, window, cx| {
|
||||
window.dispatch_action(menu::Confirm.boxed_clone(), cx);
|
||||
cx.emit(DismissEvent);
|
||||
},
|
||||
))),
|
||||
.on_click(cx.listener(|this, _event, _window, cx| {
|
||||
this.cancel(&menu::Cancel, cx)
|
||||
})),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
@ -396,7 +407,7 @@ impl AiPrivacyTooltip {
|
|||
|
||||
impl Render for AiPrivacyTooltip {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
const DESCRIPTION: &'static str = "One of Zed's most important principles is transparency. This is why we are and value open-source so much. And it wouldn't be any different with AI.";
|
||||
const DESCRIPTION: &'static str = "We believe in opt-in data sharing as the default for building AI products, rather than opt-out. We'll only use or store your data if you affirmatively send it to us. ";
|
||||
|
||||
tooltip_container(window, cx, move |this, _, _| {
|
||||
this.child(
|
||||
|
@ -407,7 +418,7 @@ impl Render for AiPrivacyTooltip {
|
|||
.size(IconSize::Small)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
.child(Label::new("Privacy Principle")),
|
||||
.child(Label::new("Privacy First")),
|
||||
)
|
||||
.child(
|
||||
div().max_w_64().child(
|
||||
|
|
|
@ -201,12 +201,15 @@ fn render_telemetry_section(tab_index: &mut isize, cx: &App) -> impl IntoElement
|
|||
let fs = <dyn Fs>::global(cx);
|
||||
|
||||
v_flex()
|
||||
.pt_6()
|
||||
.gap_4()
|
||||
.border_t_1()
|
||||
.border_color(cx.theme().colors().border_variant.opacity(0.5))
|
||||
.child(Label::new("Telemetry").size(LabelSize::Large))
|
||||
.child(SwitchField::new(
|
||||
"onboarding-telemetry-metrics",
|
||||
"Help Improve Zed",
|
||||
Some("Sending anonymous usage data helps us build the right features and create the best experience.".into()),
|
||||
Some("Anonymous usage data helps us build the right features and improve your experience.".into()),
|
||||
if TelemetrySettings::get_global(cx).metrics {
|
||||
ui::ToggleState::Selected
|
||||
} else {
|
||||
|
@ -294,7 +297,7 @@ fn render_base_keymap_section(tab_index: &mut isize, cx: &mut App) -> impl IntoE
|
|||
ToggleButtonWithIcon::new("Emacs", IconName::EditorEmacs, |_, _, cx| {
|
||||
write_keymap_base(BaseKeymap::Emacs, cx);
|
||||
}),
|
||||
ToggleButtonWithIcon::new("Cursor (Beta)", IconName::EditorCursor, |_, _, cx| {
|
||||
ToggleButtonWithIcon::new("Cursor", IconName::EditorCursor, |_, _, cx| {
|
||||
write_keymap_base(BaseKeymap::Cursor, cx);
|
||||
}),
|
||||
],
|
||||
|
@ -326,10 +329,7 @@ fn render_vim_mode_switch(tab_index: &mut isize, cx: &mut App) -> impl IntoEleme
|
|||
SwitchField::new(
|
||||
"onboarding-vim-mode",
|
||||
"Vim Mode",
|
||||
Some(
|
||||
"Coming from Neovim? Zed's first-class implementation of Vim Mode has got your back."
|
||||
.into(),
|
||||
),
|
||||
Some("Coming from Neovim? Use our first-class implementation of Vim Mode.".into()),
|
||||
toggle_state,
|
||||
{
|
||||
let fs = <dyn Fs>::global(cx);
|
||||
|
|
|
@ -584,11 +584,15 @@ fn render_popular_settings_section(
|
|||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> impl IntoElement {
|
||||
const LIGATURE_TOOLTIP: &'static str = "Ligatures are when a font creates a special character out of combining two characters into one. For example, with ligatures turned on, =/= would become ≠.";
|
||||
const LIGATURE_TOOLTIP: &'static str =
|
||||
"Font ligatures combine two characters into one. For example, turning =/= into ≠.";
|
||||
|
||||
v_flex()
|
||||
.gap_5()
|
||||
.child(Label::new("Popular Settings").size(LabelSize::Large).mt_8())
|
||||
.pt_6()
|
||||
.gap_4()
|
||||
.border_t_1()
|
||||
.border_color(cx.theme().colors().border_variant.opacity(0.5))
|
||||
.child(Label::new("Popular Settings").size(LabelSize::Large))
|
||||
.child(render_font_customization_section(tab_index, window, cx))
|
||||
.child(
|
||||
SwitchField::new(
|
||||
|
@ -683,7 +687,10 @@ fn render_popular_settings_section(
|
|||
[
|
||||
ToggleButtonSimple::new("Auto", |_, _, cx| {
|
||||
write_show_mini_map(ShowMinimap::Auto, cx);
|
||||
}),
|
||||
})
|
||||
.tooltip(Tooltip::text(
|
||||
"Show the minimap if the editor's scrollbar is visible.",
|
||||
)),
|
||||
ToggleButtonSimple::new("Always", |_, _, cx| {
|
||||
write_show_mini_map(ShowMinimap::Always, cx);
|
||||
}),
|
||||
|
@ -707,7 +714,7 @@ fn render_popular_settings_section(
|
|||
pub(crate) fn render_editing_page(window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let mut tab_index = 0;
|
||||
v_flex()
|
||||
.gap_4()
|
||||
.gap_6()
|
||||
.child(render_import_settings_section(&mut tab_index, cx))
|
||||
.child(render_popular_settings_section(&mut tab_index, window, cx))
|
||||
}
|
||||
|
|
|
@ -77,6 +77,8 @@ actions!(
|
|||
ActivateAISetupPage,
|
||||
/// Finish the onboarding process.
|
||||
Finish,
|
||||
/// Sign in while in the onboarding flow.
|
||||
SignIn
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -376,6 +378,7 @@ impl Onboarding {
|
|||
cx,
|
||||
)
|
||||
.map(|kb| kb.size(rems_from_px(12.)));
|
||||
|
||||
if ai_setup_page {
|
||||
this.child(
|
||||
ButtonLike::new("start_building")
|
||||
|
@ -387,14 +390,7 @@ impl Onboarding {
|
|||
.w_full()
|
||||
.justify_between()
|
||||
.child(Label::new("Start Building"))
|
||||
.child(keybinding.map_or_else(
|
||||
|| {
|
||||
Icon::new(IconName::Check)
|
||||
.size(IconSize::Small)
|
||||
.into_any_element()
|
||||
},
|
||||
IntoElement::into_any_element,
|
||||
)),
|
||||
.children(keybinding),
|
||||
)
|
||||
.on_click(|_, window, cx| {
|
||||
window.dispatch_action(Finish.boxed_clone(), cx);
|
||||
|
@ -409,11 +405,10 @@ impl Onboarding {
|
|||
.ml_1()
|
||||
.w_full()
|
||||
.justify_between()
|
||||
.child(Label::new("Skip All"))
|
||||
.child(keybinding.map_or_else(
|
||||
|| gpui::Empty.into_any_element(),
|
||||
IntoElement::into_any_element,
|
||||
)),
|
||||
.child(
|
||||
Label::new("Skip All").color(Color::Muted),
|
||||
)
|
||||
.children(keybinding),
|
||||
)
|
||||
.on_click(|_, window, cx| {
|
||||
window.dispatch_action(Finish.boxed_clone(), cx);
|
||||
|
@ -435,23 +430,39 @@ impl Onboarding {
|
|||
Button::new("sign_in", "Sign In")
|
||||
.full_width()
|
||||
.style(ButtonStyle::Outlined)
|
||||
.size(ButtonSize::Medium)
|
||||
.key_binding(
|
||||
KeyBinding::for_action_in(&SignIn, &self.focus_handle, window, cx)
|
||||
.map(|kb| kb.size(rems_from_px(12.))),
|
||||
)
|
||||
.on_click(|_, window, cx| {
|
||||
let client = Client::global(cx);
|
||||
window
|
||||
.spawn(cx, async move |cx| {
|
||||
client
|
||||
.sign_in_with_optional_connect(true, &cx)
|
||||
.await
|
||||
.notify_async_err(cx);
|
||||
})
|
||||
.detach();
|
||||
window.dispatch_action(SignIn.boxed_clone(), cx);
|
||||
})
|
||||
.into_any_element()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn on_finish(_: &Finish, _: &mut Window, cx: &mut App) {
|
||||
go_to_welcome_page(cx);
|
||||
}
|
||||
|
||||
fn handle_sign_in(_: &SignIn, window: &mut Window, cx: &mut App) {
|
||||
let client = Client::global(cx);
|
||||
|
||||
window
|
||||
.spawn(cx, async move |cx| {
|
||||
client
|
||||
.sign_in_with_optional_connect(true, &cx)
|
||||
.await
|
||||
.notify_async_err(cx);
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn render_page(&mut self, window: &mut Window, cx: &mut Context<Self>) -> AnyElement {
|
||||
let client = Client::global(cx);
|
||||
|
||||
match self.selected_page {
|
||||
SelectedPage::Basics => crate::basics_page::render_basics_page(cx).into_any_element(),
|
||||
SelectedPage::Editing => {
|
||||
|
@ -460,16 +471,13 @@ impl Onboarding {
|
|||
SelectedPage::AiSetup => crate::ai_setup_page::render_ai_setup_page(
|
||||
self.workspace.clone(),
|
||||
self.user_store.clone(),
|
||||
client,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.into_any_element(),
|
||||
}
|
||||
}
|
||||
|
||||
fn on_finish(_: &Finish, _: &mut Window, cx: &mut App) {
|
||||
go_to_welcome_page(cx);
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for Onboarding {
|
||||
|
@ -486,6 +494,7 @@ impl Render for Onboarding {
|
|||
.size_full()
|
||||
.bg(cx.theme().colors().editor_background)
|
||||
.on_action(Self::on_finish)
|
||||
.on_action(Self::handle_sign_in)
|
||||
.on_action(cx.listener(|this, _: &ActivateBasicsPage, _, cx| {
|
||||
this.set_page(SelectedPage::Basics, cx);
|
||||
}))
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use gpui::{AnyView, ClickEvent};
|
||||
|
||||
use crate::{ButtonLike, ButtonLikeRounding, ElevationIndex, TintColor, prelude::*};
|
||||
use crate::{ButtonLike, ButtonLikeRounding, ElevationIndex, TintColor, Tooltip, prelude::*};
|
||||
|
||||
/// The position of a [`ToggleButton`] within a group of buttons.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
|
@ -301,6 +303,7 @@ pub struct ButtonConfiguration {
|
|||
icon: Option<IconName>,
|
||||
on_click: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
|
||||
selected: bool,
|
||||
tooltip: Option<Rc<dyn Fn(&mut Window, &mut App) -> AnyView>>,
|
||||
}
|
||||
|
||||
mod private {
|
||||
|
@ -315,6 +318,7 @@ pub struct ToggleButtonSimple {
|
|||
label: SharedString,
|
||||
on_click: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
|
||||
selected: bool,
|
||||
tooltip: Option<Rc<dyn Fn(&mut Window, &mut App) -> AnyView>>,
|
||||
}
|
||||
|
||||
impl ToggleButtonSimple {
|
||||
|
@ -326,6 +330,7 @@ impl ToggleButtonSimple {
|
|||
label: label.into(),
|
||||
on_click: Box::new(on_click),
|
||||
selected: false,
|
||||
tooltip: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -333,6 +338,11 @@ impl ToggleButtonSimple {
|
|||
self.selected = selected;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
|
||||
self.tooltip = Some(Rc::new(tooltip));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl private::ToggleButtonStyle for ToggleButtonSimple {}
|
||||
|
@ -344,6 +354,7 @@ impl ButtonBuilder for ToggleButtonSimple {
|
|||
icon: None,
|
||||
on_click: self.on_click,
|
||||
selected: self.selected,
|
||||
tooltip: self.tooltip,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -353,6 +364,7 @@ pub struct ToggleButtonWithIcon {
|
|||
icon: IconName,
|
||||
on_click: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
|
||||
selected: bool,
|
||||
tooltip: Option<Rc<dyn Fn(&mut Window, &mut App) -> AnyView>>,
|
||||
}
|
||||
|
||||
impl ToggleButtonWithIcon {
|
||||
|
@ -366,6 +378,7 @@ impl ToggleButtonWithIcon {
|
|||
icon,
|
||||
on_click: Box::new(on_click),
|
||||
selected: false,
|
||||
tooltip: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,6 +386,11 @@ impl ToggleButtonWithIcon {
|
|||
self.selected = selected;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
|
||||
self.tooltip = Some(Rc::new(tooltip));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl private::ToggleButtonStyle for ToggleButtonWithIcon {}
|
||||
|
@ -384,6 +402,7 @@ impl ButtonBuilder for ToggleButtonWithIcon {
|
|||
icon: Some(self.icon),
|
||||
on_click: self.on_click,
|
||||
selected: self.selected,
|
||||
tooltip: self.tooltip,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -486,11 +505,13 @@ impl<T: ButtonBuilder, const COLS: usize, const ROWS: usize> RenderOnce
|
|||
icon,
|
||||
on_click,
|
||||
selected,
|
||||
tooltip,
|
||||
} = button.into_configuration();
|
||||
|
||||
let entry_index = row_index * COLS + col_index;
|
||||
|
||||
ButtonLike::new((self.group_name, entry_index))
|
||||
.rounding(None)
|
||||
.when_some(self.tab_index, |this, tab_index| {
|
||||
this.tab_index(tab_index + entry_index as isize)
|
||||
})
|
||||
|
@ -498,7 +519,6 @@ impl<T: ButtonBuilder, const COLS: usize, const ROWS: usize> RenderOnce
|
|||
this.toggle_state(true)
|
||||
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
|
||||
})
|
||||
.rounding(None)
|
||||
.when(self.style == ToggleButtonGroupStyle::Filled, |button| {
|
||||
button.style(ButtonStyle::Filled)
|
||||
})
|
||||
|
@ -527,6 +547,9 @@ impl<T: ButtonBuilder, const COLS: usize, const ROWS: usize> RenderOnce
|
|||
|this| this.color(Color::Accent),
|
||||
)),
|
||||
)
|
||||
.when_some(tooltip, |this, tooltip| {
|
||||
this.tooltip(move |window, cx| tooltip(window, cx))
|
||||
})
|
||||
.on_click(on_click)
|
||||
.into_any_element()
|
||||
})
|
||||
|
@ -920,6 +943,23 @@ impl<T: ButtonBuilder, const COLS: usize, const ROWS: usize> Component
|
|||
),
|
||||
],
|
||||
)])
|
||||
.children(vec![single_example(
|
||||
"With Tooltips",
|
||||
ToggleButtonGroup::single_row(
|
||||
"with_tooltips",
|
||||
[
|
||||
ToggleButtonSimple::new("First", |_, _, _| {})
|
||||
.tooltip(Tooltip::text("This is a tooltip. Hello!")),
|
||||
ToggleButtonSimple::new("Second", |_, _, _| {})
|
||||
.tooltip(Tooltip::text("This is a tooltip. Hey?")),
|
||||
ToggleButtonSimple::new("Third", |_, _, _| {})
|
||||
.tooltip(Tooltip::text("This is a tooltip. Get out of here now!")),
|
||||
],
|
||||
)
|
||||
.selected_index(1)
|
||||
.button_width(rems_from_px(100.))
|
||||
.into_any_element(),
|
||||
)])
|
||||
.into_any_element(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@ use crate::prelude::*;
|
|||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum VectorName {
|
||||
AiGrid,
|
||||
CertifiedUserStamp,
|
||||
DebuggerGrid,
|
||||
Grid,
|
||||
ProTrialStamp,
|
||||
ProUserStamp,
|
||||
ZedLogo,
|
||||
ZedXCopilot,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue