mirror of
https://github.com/zed-industries/zed.git
synced 2026-05-31 19:05:00 +07:00
Add Tailwind CSS and Ruff to built-in features list (#41285)
Closes https://github.com/zed-industries/zed/issues/41168 This PR adds both Tailwind CSS and Ruff (linter for Python) as built-in features; a banner mentioning this should show up now for these two when searching for them in the extensions UI. There will also be a corresponding zed.dev site PR adding a "Ruff is built-in" card to the zed.dev/extensions page. Release Notes: - N/A
This commit is contained in:
parent
ebf4a23b18
commit
7f17d4b61d
3 changed files with 184 additions and 145 deletions
|
|
@ -1,5 +1,3 @@
|
|||
mod extension_card;
|
||||
mod feature_upsell;
|
||||
|
||||
pub use extension_card::*;
|
||||
pub use feature_upsell::*;
|
||||
|
|
|
|||
|
|
@ -1,77 +0,0 @@
|
|||
use gpui::{AnyElement, Div, StyleRefinement};
|
||||
use smallvec::SmallVec;
|
||||
use ui::prelude::*;
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct FeatureUpsell {
|
||||
base: Div,
|
||||
text: SharedString,
|
||||
docs_url: Option<SharedString>,
|
||||
children: SmallVec<[AnyElement; 2]>,
|
||||
}
|
||||
|
||||
impl FeatureUpsell {
|
||||
pub fn new(text: impl Into<SharedString>) -> Self {
|
||||
Self {
|
||||
base: h_flex(),
|
||||
text: text.into(),
|
||||
docs_url: None,
|
||||
children: SmallVec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn docs_url(mut self, docs_url: impl Into<SharedString>) -> Self {
|
||||
self.docs_url = Some(docs_url.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl ParentElement for FeatureUpsell {
|
||||
fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
|
||||
self.children.extend(elements)
|
||||
}
|
||||
}
|
||||
|
||||
// Style methods.
|
||||
impl FeatureUpsell {
|
||||
fn style(&mut self) -> &mut StyleRefinement {
|
||||
self.base.style()
|
||||
}
|
||||
|
||||
gpui::border_style_methods!({
|
||||
visibility: pub
|
||||
});
|
||||
}
|
||||
|
||||
impl RenderOnce for FeatureUpsell {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
self.base
|
||||
.py_2()
|
||||
.px_4()
|
||||
.justify_between()
|
||||
.flex_wrap()
|
||||
.border_color(cx.theme().colors().border_variant)
|
||||
.child(Label::new(self.text))
|
||||
.child(h_flex().gap_2().children(self.children).when_some(
|
||||
self.docs_url,
|
||||
|el, docs_url| {
|
||||
el.child(
|
||||
Button::new("open_docs", "View Documentation")
|
||||
.icon(IconName::ArrowUpRight)
|
||||
.icon_size(IconSize::Small)
|
||||
.icon_position(IconPosition::End)
|
||||
.on_click({
|
||||
move |_event, _window, cx| {
|
||||
telemetry::event!(
|
||||
"Documentation Viewed",
|
||||
source = "Feature Upsell",
|
||||
url = docs_url,
|
||||
);
|
||||
cx.open_url(&docs_url)
|
||||
}
|
||||
}),
|
||||
)
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
@ -24,8 +24,8 @@ use settings::{Settings, SettingsContent};
|
|||
use strum::IntoEnumIterator as _;
|
||||
use theme::ThemeSettings;
|
||||
use ui::{
|
||||
CheckboxWithLabel, Chip, ContextMenu, PopoverMenu, ScrollableHandle, ToggleButton, Tooltip,
|
||||
WithScrollbar, prelude::*,
|
||||
Banner, Chip, ContextMenu, Divider, PopoverMenu, ScrollableHandle, Switch, ToggleButton,
|
||||
Tooltip, WithScrollbar, prelude::*,
|
||||
};
|
||||
use vim_mode_setting::VimModeSetting;
|
||||
use workspace::{
|
||||
|
|
@ -34,7 +34,7 @@ use workspace::{
|
|||
};
|
||||
use zed_actions::ExtensionCategoryFilter;
|
||||
|
||||
use crate::components::{ExtensionCard, FeatureUpsell};
|
||||
use crate::components::ExtensionCard;
|
||||
use crate::extension_version_selector::{
|
||||
ExtensionVersionSelector, ExtensionVersionSelectorDelegate,
|
||||
};
|
||||
|
|
@ -225,9 +225,9 @@ impl ExtensionFilter {
|
|||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
|
||||
enum Feature {
|
||||
ExtensionRuff,
|
||||
ExtensionTailwind,
|
||||
Git,
|
||||
OpenIn,
|
||||
Vim,
|
||||
LanguageBash,
|
||||
LanguageC,
|
||||
LanguageCpp,
|
||||
|
|
@ -236,13 +236,28 @@ enum Feature {
|
|||
LanguageReact,
|
||||
LanguageRust,
|
||||
LanguageTypescript,
|
||||
OpenIn,
|
||||
Vim,
|
||||
}
|
||||
|
||||
fn keywords_by_feature() -> &'static BTreeMap<Feature, Vec<&'static str>> {
|
||||
static KEYWORDS_BY_FEATURE: OnceLock<BTreeMap<Feature, Vec<&'static str>>> = OnceLock::new();
|
||||
KEYWORDS_BY_FEATURE.get_or_init(|| {
|
||||
BTreeMap::from_iter([
|
||||
(Feature::ExtensionRuff, vec!["ruff"]),
|
||||
(Feature::ExtensionTailwind, vec!["tail", "tailwind"]),
|
||||
(Feature::Git, vec!["git"]),
|
||||
(Feature::LanguageBash, vec!["sh", "bash"]),
|
||||
(Feature::LanguageC, vec!["c", "clang"]),
|
||||
(Feature::LanguageCpp, vec!["c++", "cpp", "clang"]),
|
||||
(Feature::LanguageGo, vec!["go", "golang"]),
|
||||
(Feature::LanguagePython, vec!["python", "py"]),
|
||||
(Feature::LanguageReact, vec!["react"]),
|
||||
(Feature::LanguageRust, vec!["rust", "rs"]),
|
||||
(
|
||||
Feature::LanguageTypescript,
|
||||
vec!["type", "typescript", "ts"],
|
||||
),
|
||||
(
|
||||
Feature::OpenIn,
|
||||
vec![
|
||||
|
|
@ -257,17 +272,6 @@ fn keywords_by_feature() -> &'static BTreeMap<Feature, Vec<&'static str>> {
|
|||
],
|
||||
),
|
||||
(Feature::Vim, vec!["vim"]),
|
||||
(Feature::LanguageBash, vec!["sh", "bash"]),
|
||||
(Feature::LanguageC, vec!["c", "clang"]),
|
||||
(Feature::LanguageCpp, vec!["c++", "cpp", "clang"]),
|
||||
(Feature::LanguageGo, vec!["go", "golang"]),
|
||||
(Feature::LanguagePython, vec!["python", "py"]),
|
||||
(Feature::LanguageReact, vec!["react"]),
|
||||
(Feature::LanguageRust, vec!["rust", "rs"]),
|
||||
(
|
||||
Feature::LanguageTypescript,
|
||||
vec!["type", "typescript", "ts"],
|
||||
),
|
||||
])
|
||||
})
|
||||
}
|
||||
|
|
@ -1336,58 +1340,172 @@ impl ExtensionsPage {
|
|||
}
|
||||
}
|
||||
|
||||
fn render_feature_upsells(&self, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let upsells_count = self.upsells.len();
|
||||
|
||||
v_flex().children(self.upsells.iter().enumerate().map(|(ix, feature)| {
|
||||
let upsell = match feature {
|
||||
Feature::Git => FeatureUpsell::new(
|
||||
"Zed comes with basic Git support. More Git features are coming in the future.",
|
||||
)
|
||||
.docs_url("https://zed.dev/docs/git"),
|
||||
Feature::OpenIn => FeatureUpsell::new(
|
||||
"Zed supports linking to a source line on GitHub and others.",
|
||||
)
|
||||
.docs_url("https://zed.dev/docs/git#git-integrations"),
|
||||
Feature::Vim => FeatureUpsell::new("Vim support is built-in to Zed!")
|
||||
.docs_url("https://zed.dev/docs/vim")
|
||||
.child(CheckboxWithLabel::new(
|
||||
"enable-vim",
|
||||
Label::new("Enable vim mode"),
|
||||
if VimModeSetting::get_global(cx).0 {
|
||||
ui::ToggleState::Selected
|
||||
} else {
|
||||
ui::ToggleState::Unselected
|
||||
},
|
||||
cx.listener(move |this, selection, _, cx| {
|
||||
telemetry::event!("Vim Mode Toggled", source = "Feature Upsell");
|
||||
this.update_settings(selection, cx, |setting, value| {
|
||||
setting.vim_mode = Some(value)
|
||||
});
|
||||
}),
|
||||
)),
|
||||
Feature::LanguageBash => FeatureUpsell::new("Shell support is built-in to Zed!")
|
||||
.docs_url("https://zed.dev/docs/languages/bash"),
|
||||
Feature::LanguageC => FeatureUpsell::new("C support is built-in to Zed!")
|
||||
.docs_url("https://zed.dev/docs/languages/c"),
|
||||
Feature::LanguageCpp => FeatureUpsell::new("C++ support is built-in to Zed!")
|
||||
.docs_url("https://zed.dev/docs/languages/cpp"),
|
||||
Feature::LanguageGo => FeatureUpsell::new("Go support is built-in to Zed!")
|
||||
.docs_url("https://zed.dev/docs/languages/go"),
|
||||
Feature::LanguagePython => FeatureUpsell::new("Python support is built-in to Zed!")
|
||||
.docs_url("https://zed.dev/docs/languages/python"),
|
||||
Feature::LanguageReact => FeatureUpsell::new("React support is built-in to Zed!")
|
||||
.docs_url("https://zed.dev/docs/languages/typescript"),
|
||||
Feature::LanguageRust => FeatureUpsell::new("Rust support is built-in to Zed!")
|
||||
.docs_url("https://zed.dev/docs/languages/rust"),
|
||||
Feature::LanguageTypescript => {
|
||||
FeatureUpsell::new("Typescript support is built-in to Zed!")
|
||||
.docs_url("https://zed.dev/docs/languages/typescript")
|
||||
fn render_feature_upsell_banner(
|
||||
&self,
|
||||
label: SharedString,
|
||||
docs_url: SharedString,
|
||||
vim: bool,
|
||||
cx: &mut Context<Self>,
|
||||
) -> impl IntoElement {
|
||||
let docs_url_button = Button::new("open_docs", "View Documentation")
|
||||
.icon(IconName::ArrowUpRight)
|
||||
.icon_size(IconSize::Small)
|
||||
.icon_position(IconPosition::End)
|
||||
.on_click({
|
||||
move |_event, _window, cx| {
|
||||
telemetry::event!(
|
||||
"Documentation Viewed",
|
||||
source = "Feature Upsell",
|
||||
url = docs_url,
|
||||
);
|
||||
cx.open_url(&docs_url)
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
upsell.when(ix < upsells_count, |upsell| upsell.border_b_1())
|
||||
}))
|
||||
div()
|
||||
.pt_4()
|
||||
.px_4()
|
||||
.child(
|
||||
Banner::new()
|
||||
.severity(Severity::Success)
|
||||
.child(Label::new(label).mt_0p5())
|
||||
.map(|this| {
|
||||
if vim {
|
||||
this.action_slot(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.child(docs_url_button)
|
||||
.child(Divider::vertical().color(ui::DividerColor::Border))
|
||||
.child(
|
||||
h_flex()
|
||||
.pl_1()
|
||||
.gap_1()
|
||||
.child(Label::new("Enable Vim mode"))
|
||||
.child(
|
||||
Switch::new(
|
||||
"enable-vim",
|
||||
if VimModeSetting::get_global(cx).0 {
|
||||
ui::ToggleState::Selected
|
||||
} else {
|
||||
ui::ToggleState::Unselected
|
||||
},
|
||||
)
|
||||
.on_click(cx.listener(
|
||||
move |this, selection, _, cx| {
|
||||
telemetry::event!(
|
||||
"Vim Mode Toggled",
|
||||
source = "Feature Upsell"
|
||||
);
|
||||
this.update_settings(
|
||||
selection,
|
||||
cx,
|
||||
|setting, value| {
|
||||
setting.vim_mode = Some(value)
|
||||
},
|
||||
);
|
||||
},
|
||||
))
|
||||
.color(ui::SwitchColor::Accent),
|
||||
),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
this.action_slot(docs_url_button)
|
||||
}
|
||||
}),
|
||||
)
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn render_feature_upsells(&self, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let mut container = v_flex();
|
||||
|
||||
for feature in &self.upsells {
|
||||
let banner = match feature {
|
||||
Feature::ExtensionRuff => self.render_feature_upsell_banner(
|
||||
"Ruff (linter for Python) support is built-in to Zed!".into(),
|
||||
"https://zed.dev/docs/languages/python#code-formatting--linting".into(),
|
||||
false,
|
||||
cx,
|
||||
),
|
||||
Feature::ExtensionTailwind => self.render_feature_upsell_banner(
|
||||
"Tailwind CSS support is built-in to Zed!".into(),
|
||||
"https://zed.dev/docs/languages/tailwindcss".into(),
|
||||
false,
|
||||
cx,
|
||||
),
|
||||
Feature::Git => self.render_feature_upsell_banner(
|
||||
"Zed comes with basic Git support—more features are coming in the future."
|
||||
.into(),
|
||||
"https://zed.dev/docs/git".into(),
|
||||
false,
|
||||
cx,
|
||||
),
|
||||
Feature::LanguageBash => self.render_feature_upsell_banner(
|
||||
"Shell support is built-in to Zed!".into(),
|
||||
"https://zed.dev/docs/languages/bash".into(),
|
||||
false,
|
||||
cx,
|
||||
),
|
||||
Feature::LanguageC => self.render_feature_upsell_banner(
|
||||
"C support is built-in to Zed!".into(),
|
||||
"https://zed.dev/docs/languages/c".into(),
|
||||
false,
|
||||
cx,
|
||||
),
|
||||
Feature::LanguageCpp => self.render_feature_upsell_banner(
|
||||
"C++ support is built-in to Zed!".into(),
|
||||
"https://zed.dev/docs/languages/cpp".into(),
|
||||
false,
|
||||
cx,
|
||||
),
|
||||
Feature::LanguageGo => self.render_feature_upsell_banner(
|
||||
"Go support is built-in to Zed!".into(),
|
||||
"https://zed.dev/docs/languages/go".into(),
|
||||
false,
|
||||
cx,
|
||||
),
|
||||
Feature::LanguagePython => self.render_feature_upsell_banner(
|
||||
"Python support is built-in to Zed!".into(),
|
||||
"https://zed.dev/docs/languages/python".into(),
|
||||
false,
|
||||
cx,
|
||||
),
|
||||
Feature::LanguageReact => self.render_feature_upsell_banner(
|
||||
"React support is built-in to Zed!".into(),
|
||||
"https://zed.dev/docs/languages/typescript".into(),
|
||||
false,
|
||||
cx,
|
||||
),
|
||||
Feature::LanguageRust => self.render_feature_upsell_banner(
|
||||
"Rust support is built-in to Zed!".into(),
|
||||
"https://zed.dev/docs/languages/rust".into(),
|
||||
false,
|
||||
cx,
|
||||
),
|
||||
Feature::LanguageTypescript => self.render_feature_upsell_banner(
|
||||
"Typescript support is built-in to Zed!".into(),
|
||||
"https://zed.dev/docs/languages/typescript".into(),
|
||||
false,
|
||||
cx,
|
||||
),
|
||||
Feature::OpenIn => self.render_feature_upsell_banner(
|
||||
"Zed supports linking to a source line on GitHub and others.".into(),
|
||||
"https://zed.dev/docs/git#git-integrations".into(),
|
||||
false,
|
||||
cx,
|
||||
),
|
||||
Feature::Vim => self.render_feature_upsell_banner(
|
||||
"Vim support is built-in to Zed!".into(),
|
||||
"https://zed.dev/docs/vim".into(),
|
||||
true,
|
||||
cx,
|
||||
),
|
||||
};
|
||||
container = container.child(banner);
|
||||
}
|
||||
|
||||
container
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue