dropdown_button: Add more button option methods to DropdownButton. (#1633)
- Fix to not handle `dropdown_menu` when Button is disabled. - Split a single DropdownButtonStory.
This commit is contained in:
parent
446831af33
commit
f8a7dd71bf
8 changed files with 369 additions and 59 deletions
230
crates/story/src/dropdown_button_story.rs
Normal file
230
crates/story/src/dropdown_button_story.rs
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
use gpui::{
|
||||
Action, App, AppContext as _, Context, Corner, Entity, Focusable, IntoElement,
|
||||
ParentElement as _, Render, Styled as _, Window, prelude::FluentBuilder as _,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::section;
|
||||
use gpui_component::{
|
||||
ActiveTheme, Disableable, Selectable as _, Sizable as _, Theme,
|
||||
button::{Button, ButtonVariants as _, DropdownButton},
|
||||
checkbox::Checkbox,
|
||||
h_flex, v_flex,
|
||||
};
|
||||
|
||||
#[derive(Clone, Action, PartialEq, Eq, Deserialize)]
|
||||
#[action(namespace = dropdown_button_story, no_json)]
|
||||
enum ButtonAction {
|
||||
Disabled,
|
||||
Loading,
|
||||
Selected,
|
||||
Compact,
|
||||
}
|
||||
|
||||
pub struct DropdownButtonStory {
|
||||
focus_handle: gpui::FocusHandle,
|
||||
disabled: bool,
|
||||
loading: bool,
|
||||
selected: bool,
|
||||
compact: bool,
|
||||
}
|
||||
|
||||
impl DropdownButtonStory {
|
||||
pub fn view(_: &mut Window, cx: &mut App) -> Entity<Self> {
|
||||
cx.new(|cx| Self {
|
||||
focus_handle: cx.focus_handle(),
|
||||
disabled: false,
|
||||
loading: false,
|
||||
selected: false,
|
||||
compact: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl super::Story for DropdownButtonStory {
|
||||
fn title() -> &'static str {
|
||||
"DropdownButton"
|
||||
}
|
||||
|
||||
fn description() -> &'static str {
|
||||
"A button with an attached dropdown menu for additional options."
|
||||
}
|
||||
|
||||
fn closable() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
|
||||
Self::view(window, cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Focusable for DropdownButtonStory {
|
||||
fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for DropdownButtonStory {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let disabled = self.disabled;
|
||||
let loading = self.loading;
|
||||
let selected = self.selected;
|
||||
let compact = self.compact;
|
||||
|
||||
v_flex()
|
||||
.gap_6()
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_3()
|
||||
.child(
|
||||
Checkbox::new("disabled-button")
|
||||
.label("Disabled")
|
||||
.checked(self.disabled)
|
||||
.on_click(cx.listener(|view, _, _, cx| {
|
||||
view.disabled = !view.disabled;
|
||||
cx.notify();
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Checkbox::new("loading-button")
|
||||
.label("Loading")
|
||||
.checked(self.loading)
|
||||
.on_click(cx.listener(|view, _, _, cx| {
|
||||
view.loading = !view.loading;
|
||||
cx.notify();
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Checkbox::new("selected-button")
|
||||
.label("Selected")
|
||||
.checked(self.selected)
|
||||
.on_click(cx.listener(|view, _, _, cx| {
|
||||
view.selected = !view.selected;
|
||||
cx.notify();
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Checkbox::new("compact-button")
|
||||
.label("Compact")
|
||||
.checked(self.compact)
|
||||
.on_click(cx.listener(|view, _, _, cx| {
|
||||
view.compact = !view.compact;
|
||||
cx.notify();
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Checkbox::new("shadow-button")
|
||||
.label("Shadow")
|
||||
.checked(cx.theme().shadow)
|
||||
.on_click(cx.listener(|_, _, window, cx| {
|
||||
let mut theme = cx.theme().clone();
|
||||
theme.shadow = !theme.shadow;
|
||||
cx.set_global::<Theme>(theme);
|
||||
window.refresh();
|
||||
})),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
section("Dropdown Button").child(
|
||||
DropdownButton::new("btn0")
|
||||
.primary()
|
||||
.button(Button::new("btn").label("Primary Dropdown"))
|
||||
.when(self.compact, |this| this.compact())
|
||||
.loading(self.loading)
|
||||
.disabled(self.disabled)
|
||||
.selected(selected)
|
||||
.dropdown_menu_with_anchor(Corner::BottomRight, move |this, _, _| {
|
||||
this.menu_with_check(
|
||||
"Disabled",
|
||||
disabled,
|
||||
Box::new(ButtonAction::Disabled),
|
||||
)
|
||||
.menu_with_check("Loading", loading, Box::new(ButtonAction::Loading))
|
||||
.menu_with_check("Selected", selected, Box::new(ButtonAction::Selected))
|
||||
.menu_with_check(
|
||||
"Compact",
|
||||
compact,
|
||||
Box::new(ButtonAction::Compact),
|
||||
)
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
section("Small Size").child(
|
||||
DropdownButton::new("btn-sm")
|
||||
.small()
|
||||
.button(Button::new("btn").label("Small Dropdown"))
|
||||
.when(self.compact, |this| this.compact())
|
||||
.loading(self.loading)
|
||||
.disabled(self.disabled)
|
||||
.selected(selected)
|
||||
.dropdown_menu(move |this, _, _| {
|
||||
this.menu_with_check(
|
||||
"Disabled",
|
||||
disabled,
|
||||
Box::new(ButtonAction::Disabled),
|
||||
)
|
||||
.menu_with_check("Loading", loading, Box::new(ButtonAction::Loading))
|
||||
.menu_with_check("Selected", selected, Box::new(ButtonAction::Selected))
|
||||
.menu_with_check(
|
||||
"Compact",
|
||||
compact,
|
||||
Box::new(ButtonAction::Compact),
|
||||
)
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
section("Outline").child(
|
||||
DropdownButton::new("btn-outline")
|
||||
.outline()
|
||||
.danger()
|
||||
.button(Button::new("btn").label("Outline Dropdown"))
|
||||
.when(self.compact, |this| this.compact())
|
||||
.loading(self.loading)
|
||||
.disabled(self.disabled)
|
||||
.selected(selected)
|
||||
.dropdown_menu(move |this, _, _| {
|
||||
this.menu_with_check(
|
||||
"Disabled",
|
||||
disabled,
|
||||
Box::new(ButtonAction::Disabled),
|
||||
)
|
||||
.menu_with_check("Loading", loading, Box::new(ButtonAction::Loading))
|
||||
.menu_with_check("Selected", selected, Box::new(ButtonAction::Selected))
|
||||
.menu_with_check(
|
||||
"Compact",
|
||||
compact,
|
||||
Box::new(ButtonAction::Compact),
|
||||
)
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
section("Ghost").child(
|
||||
DropdownButton::new("btn-ghost")
|
||||
.ghost()
|
||||
.button(Button::new("btn").label("Ghost Dropdown"))
|
||||
.when(self.compact, |this| this.compact())
|
||||
.loading(self.loading)
|
||||
.disabled(self.disabled)
|
||||
.selected(selected)
|
||||
.dropdown_menu(move |this, _, _| {
|
||||
this.menu_with_check(
|
||||
"Disabled",
|
||||
disabled,
|
||||
Box::new(ButtonAction::Disabled),
|
||||
)
|
||||
.menu_with_check("Loading", loading, Box::new(ButtonAction::Loading))
|
||||
.menu_with_check("Selected", selected, Box::new(ButtonAction::Selected))
|
||||
.menu_with_check(
|
||||
"Compact",
|
||||
compact,
|
||||
Box::new(ButtonAction::Compact),
|
||||
)
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ mod color_picker_story;
|
|||
mod date_picker_story;
|
||||
mod description_list_story;
|
||||
mod dialog_story;
|
||||
mod dropdown_button_story;
|
||||
mod form_story;
|
||||
mod group_box_story;
|
||||
mod icon_story;
|
||||
|
|
@ -72,6 +73,7 @@ pub use color_picker_story::ColorPickerStory;
|
|||
pub use date_picker_story::DatePickerStory;
|
||||
pub use description_list_story::DescriptionListStory;
|
||||
pub use dialog_story::DialogStory;
|
||||
pub use dropdown_button_story::DropdownButtonStory;
|
||||
pub use form_story::FormStory;
|
||||
pub use group_box_story::GroupBoxStory;
|
||||
pub use icon_story::IconStory;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ impl Gallery {
|
|||
StoryContainer::panel::<DatePickerStory>(window, cx),
|
||||
StoryContainer::panel::<DescriptionListStory>(window, cx),
|
||||
StoryContainer::panel::<DialogStory>(window, cx),
|
||||
StoryContainer::panel::<DropdownButtonStory>(window, cx),
|
||||
StoryContainer::panel::<FormStory>(window, cx),
|
||||
StoryContainer::panel::<GroupBoxStory>(window, cx),
|
||||
StoryContainer::panel::<IconStory>(window, cx),
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ use crate::{
|
|||
};
|
||||
use gpui::{
|
||||
div, prelude::FluentBuilder as _, px, relative, Action, AnyElement, App, ClickEvent, Corners,
|
||||
Div, Edges, ElementId, Hsla, InteractiveElement, Interactivity, IntoElement, ParentElement,
|
||||
Pixels, RenderOnce, SharedString, Stateful, StatefulInteractiveElement as _, StyleRefinement,
|
||||
Styled, Window,
|
||||
Div, Edges, ElementId, Hsla, InteractiveElement, Interactivity, IntoElement, MouseButton,
|
||||
ParentElement, Pixels, RenderOnce, SharedString, Stateful, StatefulInteractiveElement as _,
|
||||
StyleRefinement, Styled, Window,
|
||||
};
|
||||
|
||||
#[derive(Default, Clone, Copy)]
|
||||
|
|
@ -417,6 +417,7 @@ impl RenderOnce for Button {
|
|||
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let style: ButtonVariant = self.variant;
|
||||
let clickable = self.clickable();
|
||||
let is_disabled = self.disabled;
|
||||
let hoverable = self.hoverable();
|
||||
let normal_style = style.normal(self.outline, cx);
|
||||
let icon_size = match self.size {
|
||||
|
|
@ -475,10 +476,18 @@ impl RenderOnce for Button {
|
|||
}
|
||||
}
|
||||
})
|
||||
.when(self.border_corners.top_left, |this| this.rounded_tl(rounding))
|
||||
.when(self.border_corners.top_right, |this| this.rounded_tr(rounding))
|
||||
.when(self.border_corners.bottom_left, |this| this.rounded_bl(rounding))
|
||||
.when(self.border_corners.bottom_right, |this| this.rounded_br(rounding))
|
||||
.when(self.border_corners.top_left, |this| {
|
||||
this.rounded_tl(rounding)
|
||||
})
|
||||
.when(self.border_corners.top_right, |this| {
|
||||
this.rounded_tr(rounding)
|
||||
})
|
||||
.when(self.border_corners.bottom_left, |this| {
|
||||
this.rounded_bl(rounding)
|
||||
})
|
||||
.when(self.border_corners.bottom_right, |this| {
|
||||
this.rounded_br(rounding)
|
||||
})
|
||||
.when(self.border_edges.left, |this| this.border_l_1())
|
||||
.when(self.border_edges.right, |this| this.border_r_1())
|
||||
.when(self.border_edges.top, |this| this.border_t_1())
|
||||
|
|
@ -515,12 +524,26 @@ impl RenderOnce for Button {
|
|||
.shadow_none()
|
||||
})
|
||||
.refine_style(&self.style)
|
||||
.on_mouse_down(gpui::MouseButton::Left, |_, window, _| {
|
||||
.on_mouse_down(MouseButton::Left, move |_, window, cx| {
|
||||
// Stop handle any click event when disabled.
|
||||
// To avoid handle dropdown menu open when button is disabled.
|
||||
if is_disabled {
|
||||
cx.stop_propagation();
|
||||
return;
|
||||
}
|
||||
|
||||
// Avoid focus on mouse down.
|
||||
window.prevent_default();
|
||||
})
|
||||
.when_some(self.on_click.filter(|_| clickable), |this, on_click| {
|
||||
.when_some(self.on_click, |this, on_click| {
|
||||
this.on_click(move |event, window, cx| {
|
||||
// Stop handle any click event when disabled.
|
||||
// To avoid handle dropdown menu open when button is disabled.
|
||||
if !clickable {
|
||||
cx.stop_propagation();
|
||||
return;
|
||||
}
|
||||
|
||||
(on_click)(event, window, cx);
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use gpui::{
|
|||
|
||||
use crate::{
|
||||
menu::{DropdownMenu, PopupMenu},
|
||||
IconName, Selectable, Sizable, Size, StyledExt as _,
|
||||
Disableable, IconName, Selectable, Sizable, Size, StyledExt as _,
|
||||
};
|
||||
|
||||
use super::{Button, ButtonRounded, ButtonVariant, ButtonVariants};
|
||||
|
|
@ -19,11 +19,13 @@ pub struct DropdownButton {
|
|||
menu:
|
||||
Option<Box<dyn Fn(PopupMenu, &mut Window, &mut Context<PopupMenu>) -> PopupMenu + 'static>>,
|
||||
selected: bool,
|
||||
disabled: bool,
|
||||
// The button props
|
||||
compact: Option<bool>,
|
||||
outline: Option<bool>,
|
||||
variant: Option<ButtonVariant>,
|
||||
size: Option<Size>,
|
||||
compact: bool,
|
||||
outline: bool,
|
||||
loading: bool,
|
||||
variant: ButtonVariant,
|
||||
size: Size,
|
||||
rounded: ButtonRounded,
|
||||
anchor: Corner,
|
||||
}
|
||||
|
|
@ -37,10 +39,12 @@ impl DropdownButton {
|
|||
button: None,
|
||||
menu: None,
|
||||
selected: false,
|
||||
compact: None,
|
||||
outline: None,
|
||||
variant: None,
|
||||
size: None,
|
||||
disabled: false,
|
||||
compact: false,
|
||||
outline: false,
|
||||
loading: false,
|
||||
variant: ButtonVariant::default(),
|
||||
size: Size::default(),
|
||||
rounded: ButtonRounded::default(),
|
||||
anchor: Corner::TopRight,
|
||||
}
|
||||
|
|
@ -82,7 +86,7 @@ impl DropdownButton {
|
|||
///
|
||||
/// See also: [`Button::compact`]
|
||||
pub fn compact(mut self) -> Self {
|
||||
self.compact = Some(true);
|
||||
self.compact = true;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +94,20 @@ impl DropdownButton {
|
|||
///
|
||||
/// See also: [`Button::outline`]
|
||||
pub fn outline(mut self) -> Self {
|
||||
self.outline = Some(true);
|
||||
self.outline = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the button to loading state.
|
||||
pub fn loading(mut self, loading: bool) -> Self {
|
||||
self.loading = loading;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Disableable for DropdownButton {
|
||||
fn disabled(mut self, disabled: bool) -> Self {
|
||||
self.disabled = disabled;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
@ -103,14 +120,14 @@ impl Styled for DropdownButton {
|
|||
|
||||
impl Sizable for DropdownButton {
|
||||
fn with_size(mut self, size: impl Into<Size>) -> Self {
|
||||
self.size = Some(size.into());
|
||||
self.size = size.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl ButtonVariants for DropdownButton {
|
||||
fn with_variant(mut self, variant: ButtonVariant) -> Self {
|
||||
self.variant = Some(variant);
|
||||
self.variant = variant;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
@ -128,10 +145,7 @@ impl Selectable for DropdownButton {
|
|||
|
||||
impl RenderOnce for DropdownButton {
|
||||
fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
|
||||
let rounded = self
|
||||
.variant
|
||||
.map(|variant| variant.is_ghost() && !self.selected)
|
||||
.unwrap_or(false);
|
||||
let rounded = self.variant.is_ghost() && !self.selected;
|
||||
|
||||
div()
|
||||
.id(self.id)
|
||||
|
|
@ -153,11 +167,13 @@ impl RenderOnce for DropdownButton {
|
|||
right: true,
|
||||
bottom: true,
|
||||
})
|
||||
.loading(self.loading)
|
||||
.selected(self.selected)
|
||||
.when_some(self.compact, |this, _| this.compact())
|
||||
.when_some(self.outline, |this, _| this.outline())
|
||||
.when_some(self.size, |this, size| this.with_size(size))
|
||||
.when_some(self.variant, |this, variant| this.with_variant(variant)),
|
||||
.disabled(self.disabled || self.loading)
|
||||
.when(self.compact, |this| this.compact())
|
||||
.when(self.outline, |this| this.outline())
|
||||
.with_size(self.size)
|
||||
.with_variant(self.variant),
|
||||
)
|
||||
.when_some(self.menu, |this, menu| {
|
||||
this.child(
|
||||
|
|
@ -177,10 +193,11 @@ impl RenderOnce for DropdownButton {
|
|||
bottom_right: true,
|
||||
})
|
||||
.selected(self.selected)
|
||||
.when_some(self.compact, |this, _| this.compact())
|
||||
.when_some(self.outline, |this, _| this.outline())
|
||||
.when_some(self.size, |this, size| this.with_size(size))
|
||||
.when_some(self.variant, |this, variant| this.with_variant(variant))
|
||||
.disabled(self.disabled || self.loading)
|
||||
.when(self.compact, |this| this.compact())
|
||||
.when(self.outline, |this| this.outline())
|
||||
.with_size(self.size)
|
||||
.with_variant(self.variant)
|
||||
.dropdown_menu_with_anchor(self.anchor, menu),
|
||||
)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ The [Button] element with multiple variants, sizes, and states. Supports icons,
|
|||
## Import
|
||||
|
||||
```rust
|
||||
use gpui_component::button::{Button, ButtonGroup, DropdownButton};
|
||||
use gpui_component::button::{Button, ButtonGroup};
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
|
@ -150,28 +150,6 @@ ButtonGroup::new("toggle-group")
|
|||
})
|
||||
```
|
||||
|
||||
## Dropdown Button
|
||||
|
||||
```rust
|
||||
use gpui::Corner;
|
||||
|
||||
DropdownButton::new("dropdown")
|
||||
.button(Button::new("btn").label("Click Me"))
|
||||
.dropdown_menu(|menu, _, _| {
|
||||
menu.menu("Option 1", Box::new(MyAction))
|
||||
.menu("Option 2", Box::new(MyAction))
|
||||
.separator()
|
||||
.menu("Option 3", Box::new(MyAction))
|
||||
})
|
||||
|
||||
// With custom anchor
|
||||
DropdownButton::new("dropdown")
|
||||
.button(Button::new("btn").label("Click Me"))
|
||||
.dropdown_menu_with_anchor(Corner::BottomRight, |menu, _, _| {
|
||||
menu.menu("Option 1", Box::new(MyAction))
|
||||
})
|
||||
```
|
||||
|
||||
## Custom Variant
|
||||
|
||||
```rust
|
||||
|
|
@ -193,7 +171,6 @@ Button::new("custom-btn")
|
|||
|
||||
- [Button]
|
||||
- [ButtonGroup]
|
||||
- [DropdownButton]
|
||||
- [ButtonCustomVariant]
|
||||
|
||||
## Examples
|
||||
|
|
@ -222,6 +199,5 @@ Button::new("btn")
|
|||
|
||||
[Button]: https://docs.rs/gpui-component/latest/gpui_component/button/struct.Button.html
|
||||
[ButtonGroup]: https://docs.rs/gpui-component/latest/gpui_component/button/struct.ButtonGroup.html
|
||||
[DropdownButton]: https://docs.rs/gpui-component/latest/gpui_component/button/struct.DropdownButton.html
|
||||
[ButtonCustomVariant]: https://docs.rs/gpui-component/latest/gpui_component/button/struct.ButtonCustomVariant.html
|
||||
[Sizable]: https://docs.rs/gpui-component/latest/gpui_component/trait.Sizable.html
|
||||
|
|
|
|||
60
docs/docs/components/dropdown_button.md
Normal file
60
docs/docs/components/dropdown_button.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
title: DropdownButton
|
||||
description: A DropdownButton is a combination of a button and a trigger button. It allows us to display a dropdown menu when the trigger is clicked, but the left Button can still respond to independent events.
|
||||
---
|
||||
|
||||
# DropdownButton
|
||||
|
||||
A [DropdownButton] is a combination of a button and a trigger button. It allows us to display a dropdown menu when the trigger is clicked, but the left Button can still respond to independent events.
|
||||
|
||||
And more option methods of [Button] are also available for the DropdownButton, such as setting different variants using [ButtonCustomVariant], sizes using [Sizable], adding icons, loading states.
|
||||
|
||||
## Import
|
||||
|
||||
```rust
|
||||
use gpui_component::button::{Button, DropdownButton};
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```rust
|
||||
use gpui::Corner;
|
||||
|
||||
DropdownButton::new("dropdown")
|
||||
.button(Button::new("btn").label("Click Me"))
|
||||
.dropdown_menu(|menu, _, _| {
|
||||
menu.menu("Option 1", Box::new(MyAction))
|
||||
.menu("Option 2", Box::new(MyAction))
|
||||
.separator()
|
||||
.menu("Option 3", Box::new(MyAction))
|
||||
})
|
||||
```
|
||||
|
||||
### Variants
|
||||
|
||||
Same as [Button], DropdownButton supports different variants.
|
||||
|
||||
````rust
|
||||
DropdownButton::new("dropdown")
|
||||
.primary()
|
||||
.button(Button::new("btn").label("Primary"))
|
||||
.dropdown_menu(|menu, _, _| {
|
||||
menu.menu("Option 1", Box::new(MyAction))
|
||||
})
|
||||
```
|
||||
|
||||
### With custom anchor
|
||||
|
||||
```rust
|
||||
// With custom anchor
|
||||
DropdownButton::new("dropdown")
|
||||
.button(Button::new("btn").label("Click Me"))
|
||||
.dropdown_menu_with_anchor(Corner::BottomRight, |menu, _, _| {
|
||||
menu.menu("Option 1", Box::new(MyAction))
|
||||
})
|
||||
````
|
||||
|
||||
[Button]: https://docs.rs/gpui-component/latest/gpui_component/button/struct.Button.html
|
||||
[DropdownButton]: https://docs.rs/gpui-component/latest/gpui_component/button/struct.DropdownButton.html
|
||||
[ButtonCustomVariant]: https://docs.rs/gpui-component/latest/gpui_component/button/struct.ButtonCustomVariant.html
|
||||
[Sizable]: https://docs.rs/gpui-component/latest/gpui_component/trait.Sizable.html
|
||||
|
|
@ -15,6 +15,7 @@ collapsed: false
|
|||
- [Button](button) - Interactive buttons with multiple variants
|
||||
- [Checkbox](checkbox) - Binary selection control
|
||||
- [Collapsible](collapsible) - Expandable/collapsible content
|
||||
- [DropdownButton](dropdown_button) - Button with dropdown menu
|
||||
- [Icon](icon) - Icon display component
|
||||
- [Image](image) - Image display with fallbacks
|
||||
- [Kbd](kbd) - Keyboard shortcut display
|
||||
|
|
|
|||
Loading…
Reference in a new issue