toggle: Refactor Toggle, ToggleGroup API. (#1515)
## Break Changes
- Refactor `Toggle` new API to require a `id`, and renamed `on_change`
to `on_click.
- Renamed `on_change` method to `on_click` for `ToggleGroup`.
```diff
- Toggle::label("Hello").id("hello").on_change(..)
+ Toggle::new("hello).label("Hello").on_click(..)
- ToggleGroup::new("group1).on_change(..)
+ ToggleGroup::new("group1).on_click(..)
```
This commit is contained in:
parent
a4e93132f1
commit
0524c51b3e
4 changed files with 225 additions and 273 deletions
|
|
@ -77,6 +77,7 @@ impl Gallery {
|
||||||
StoryContainer::panel::<TabsStory>(window, cx),
|
StoryContainer::panel::<TabsStory>(window, cx),
|
||||||
StoryContainer::panel::<TagStory>(window, cx),
|
StoryContainer::panel::<TagStory>(window, cx),
|
||||||
StoryContainer::panel::<TextareaStory>(window, cx),
|
StoryContainer::panel::<TextareaStory>(window, cx),
|
||||||
|
StoryContainer::panel::<ToggleStory>(window, cx),
|
||||||
StoryContainer::panel::<TooltipStory>(window, cx),
|
StoryContainer::panel::<TooltipStory>(window, cx),
|
||||||
StoryContainer::panel::<TreeStory>(window, cx),
|
StoryContainer::panel::<TreeStory>(window, cx),
|
||||||
StoryContainer::panel::<VirtualListStory>(window, cx),
|
StoryContainer::panel::<VirtualListStory>(window, cx),
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,13 @@ use gpui::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use gpui_component::{
|
use gpui_component::{
|
||||||
|
IconName, Sizable, StyledExt,
|
||||||
button::{Toggle, ToggleGroup, ToggleVariants},
|
button::{Toggle, ToggleGroup, ToggleVariants},
|
||||||
h_flex, v_flex, IconName, Sizable,
|
v_flex,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::section;
|
||||||
|
|
||||||
pub struct ToggleStory {
|
pub struct ToggleStory {
|
||||||
focus_handle: FocusHandle,
|
focus_handle: FocusHandle,
|
||||||
single_toggle: usize,
|
single_toggle: usize,
|
||||||
|
|
@ -51,16 +54,16 @@ impl Focusable for ToggleStory {
|
||||||
impl Render for ToggleStory {
|
impl Render for ToggleStory {
|
||||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
v_flex()
|
v_flex()
|
||||||
|
.size_full()
|
||||||
.gap_6()
|
.gap_6()
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
section("Toggle")
|
||||||
.gap_2()
|
|
||||||
.child(
|
.child(
|
||||||
Toggle::label("Single Toggle Item 1")
|
Toggle::new("item1")
|
||||||
.id("single-toggle-item-1")
|
.label("Single Toggle Item 1")
|
||||||
.large()
|
.large()
|
||||||
.checked(self.single_toggle == 1)
|
.checked(self.single_toggle == 1)
|
||||||
.on_change(cx.listener(|view, checked, _, cx| {
|
.on_click(cx.listener(|view, checked, _, cx| {
|
||||||
if *checked {
|
if *checked {
|
||||||
view.single_toggle = 1;
|
view.single_toggle = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -68,11 +71,11 @@ impl Render for ToggleStory {
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
Toggle::label("Single Toggle Item 2")
|
Toggle::new("item2")
|
||||||
.id("single-toggle-item-2")
|
.label("Single Toggle Item 2")
|
||||||
.large()
|
.large()
|
||||||
.checked(self.single_toggle == 2)
|
.checked(self.single_toggle == 2)
|
||||||
.on_change(cx.listener(|view, checked, _, cx| {
|
.on_click(cx.listener(|view, checked, _, cx| {
|
||||||
if *checked {
|
if *checked {
|
||||||
view.single_toggle = 2;
|
view.single_toggle = 2;
|
||||||
}
|
}
|
||||||
|
|
@ -80,11 +83,11 @@ impl Render for ToggleStory {
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
Toggle::icon(IconName::Eye)
|
Toggle::new("item3")
|
||||||
.id("single-toggle-item-3")
|
.icon(IconName::Eye)
|
||||||
.large()
|
.large()
|
||||||
.checked(self.single_toggle == 3)
|
.checked(self.single_toggle == 3)
|
||||||
.on_change(cx.listener(|view, checked, _, cx| {
|
.on_click(cx.listener(|view, checked, _, cx| {
|
||||||
if *checked {
|
if *checked {
|
||||||
view.single_toggle = 3;
|
view.single_toggle = 3;
|
||||||
}
|
}
|
||||||
|
|
@ -93,32 +96,50 @@ impl Render for ToggleStory {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
section("Toggle Group with Ghost Style")
|
||||||
.gap_5()
|
.v_flex()
|
||||||
|
.gap_4()
|
||||||
.child(
|
.child(
|
||||||
ToggleGroup::new("toggle-button-group1")
|
ToggleGroup::new("toggle-button-group1")
|
||||||
.child(Toggle::icon(IconName::Bell).checked(self.checked[0]))
|
.child(Toggle::new(0).icon(IconName::Bell).checked(self.checked[0]))
|
||||||
.child(Toggle::icon(IconName::Bot).checked(self.checked[1]))
|
.child(Toggle::new(1).icon(IconName::Bot).checked(self.checked[1]))
|
||||||
.child(Toggle::icon(IconName::Inbox).checked(self.checked[2]))
|
.child(
|
||||||
.child(Toggle::icon(IconName::Check).checked(self.checked[3]))
|
Toggle::new(2)
|
||||||
.child(Toggle::label("Other").checked(self.checked[4]))
|
.icon(IconName::Inbox)
|
||||||
.on_change(cx.listener(|view, checkeds: &Vec<bool>, _, cx| {
|
.checked(self.checked[2]),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Toggle::new(3)
|
||||||
|
.icon(IconName::Check)
|
||||||
|
.checked(self.checked[3]),
|
||||||
|
)
|
||||||
|
.child(Toggle::new(4).label("Other").checked(self.checked[4]))
|
||||||
|
.on_click(cx.listener(|view, checkeds: &Vec<bool>, _, cx| {
|
||||||
view.checked[0] = checkeds[0];
|
view.checked[0] = checkeds[0];
|
||||||
view.checked[1] = checkeds[1];
|
view.checked[1] = checkeds[1];
|
||||||
view.checked[2] = checkeds[2];
|
view.checked[2] = checkeds[2];
|
||||||
view.checked[3] = checkeds[3];
|
view.checked[3] = checkeds[3];
|
||||||
|
view.checked[4] = checkeds[4];
|
||||||
cx.notify();
|
cx.notify();
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
ToggleGroup::new("toggle-button-group1-sm")
|
ToggleGroup::new("toggle-button-group1-sm")
|
||||||
.small()
|
.small()
|
||||||
.child(Toggle::icon(IconName::Bell).checked(self.checked[0]))
|
.child(Toggle::new(0).icon(IconName::Bell).checked(self.checked[0]))
|
||||||
.child(Toggle::icon(IconName::Bot).checked(self.checked[1]))
|
.child(Toggle::new(1).icon(IconName::Bot).checked(self.checked[1]))
|
||||||
.child(Toggle::icon(IconName::Inbox).checked(self.checked[2]))
|
.child(
|
||||||
.child(Toggle::icon(IconName::Check).checked(self.checked[3]))
|
Toggle::new(2)
|
||||||
.child(Toggle::label("Other").checked(self.checked[4]))
|
.icon(IconName::Inbox)
|
||||||
.on_change(cx.listener(|view, checkeds: &Vec<bool>, _, cx| {
|
.checked(self.checked[2]),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Toggle::new(3)
|
||||||
|
.icon(IconName::Check)
|
||||||
|
.checked(self.checked[3]),
|
||||||
|
)
|
||||||
|
.child(Toggle::new(4).label("Other").checked(self.checked[4]))
|
||||||
|
.on_click(cx.listener(|view, checkeds: &Vec<bool>, _, cx| {
|
||||||
view.checked[0] = checkeds[0];
|
view.checked[0] = checkeds[0];
|
||||||
view.checked[1] = checkeds[1];
|
view.checked[1] = checkeds[1];
|
||||||
view.checked[2] = checkeds[2];
|
view.checked[2] = checkeds[2];
|
||||||
|
|
@ -130,12 +151,20 @@ impl Render for ToggleStory {
|
||||||
.child(
|
.child(
|
||||||
ToggleGroup::new("toggle-button-group1-xs")
|
ToggleGroup::new("toggle-button-group1-xs")
|
||||||
.xsmall()
|
.xsmall()
|
||||||
.child(Toggle::icon(IconName::Bell).checked(self.checked[0]))
|
.child(Toggle::new(0).icon(IconName::Bell).checked(self.checked[0]))
|
||||||
.child(Toggle::icon(IconName::Bot).checked(self.checked[1]))
|
.child(Toggle::new(1).icon(IconName::Bot).checked(self.checked[1]))
|
||||||
.child(Toggle::icon(IconName::Inbox).checked(self.checked[2]))
|
.child(
|
||||||
.child(Toggle::icon(IconName::Check).checked(self.checked[3]))
|
Toggle::new(2)
|
||||||
.child(Toggle::label("Other").checked(self.checked[4]))
|
.icon(IconName::Inbox)
|
||||||
.on_change(cx.listener(|view, checkeds: &Vec<bool>, _, cx| {
|
.checked(self.checked[2]),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Toggle::new(3)
|
||||||
|
.icon(IconName::Check)
|
||||||
|
.checked(self.checked[3]),
|
||||||
|
)
|
||||||
|
.child(Toggle::new(4).label("Other").checked(self.checked[4]))
|
||||||
|
.on_click(cx.listener(|view, checkeds: &Vec<bool>, _, cx| {
|
||||||
view.checked[0] = checkeds[0];
|
view.checked[0] = checkeds[0];
|
||||||
view.checked[1] = checkeds[1];
|
view.checked[1] = checkeds[1];
|
||||||
view.checked[2] = checkeds[2];
|
view.checked[2] = checkeds[2];
|
||||||
|
|
@ -146,17 +175,26 @@ impl Render for ToggleStory {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
section("Toggle Group with Outline Style")
|
||||||
.gap_5()
|
.v_flex()
|
||||||
|
.gap_4()
|
||||||
.child(
|
.child(
|
||||||
ToggleGroup::new("toggle-button-group2")
|
ToggleGroup::new("toggle-button-group2")
|
||||||
.outline()
|
.outline()
|
||||||
.child(Toggle::icon(IconName::Bell).checked(self.checked[0]))
|
.child(Toggle::new(0).icon(IconName::Bell).checked(self.checked[0]))
|
||||||
.child(Toggle::icon(IconName::Bot).checked(self.checked[1]))
|
.child(Toggle::new(1).icon(IconName::Bot).checked(self.checked[1]))
|
||||||
.child(Toggle::icon(IconName::Inbox).checked(self.checked[2]))
|
.child(
|
||||||
.child(Toggle::icon(IconName::Check).checked(self.checked[3]))
|
Toggle::new(2)
|
||||||
.child(Toggle::label("Other").checked(self.checked[4]))
|
.icon(IconName::Inbox)
|
||||||
.on_change(cx.listener(|view, checkeds: &Vec<bool>, _, cx| {
|
.checked(self.checked[2]),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Toggle::new(3)
|
||||||
|
.icon(IconName::Check)
|
||||||
|
.checked(self.checked[3]),
|
||||||
|
)
|
||||||
|
.child(Toggle::new(4).label("Other").checked(self.checked[4]))
|
||||||
|
.on_click(cx.listener(|view, checkeds: &Vec<bool>, _, cx| {
|
||||||
view.checked[0] = checkeds[0];
|
view.checked[0] = checkeds[0];
|
||||||
view.checked[1] = checkeds[1];
|
view.checked[1] = checkeds[1];
|
||||||
view.checked[2] = checkeds[2];
|
view.checked[2] = checkeds[2];
|
||||||
|
|
@ -169,12 +207,20 @@ impl Render for ToggleStory {
|
||||||
ToggleGroup::new("toggle-button-group2-sm")
|
ToggleGroup::new("toggle-button-group2-sm")
|
||||||
.outline()
|
.outline()
|
||||||
.small()
|
.small()
|
||||||
.child(Toggle::icon(IconName::Bell).checked(self.checked[0]))
|
.child(Toggle::new(0).icon(IconName::Bell).checked(self.checked[0]))
|
||||||
.child(Toggle::icon(IconName::Bot).checked(self.checked[1]))
|
.child(Toggle::new(1).icon(IconName::Bot).checked(self.checked[1]))
|
||||||
.child(Toggle::icon(IconName::Inbox).checked(self.checked[2]))
|
.child(
|
||||||
.child(Toggle::icon(IconName::Check).checked(self.checked[3]))
|
Toggle::new(2)
|
||||||
.child(Toggle::label("Other").checked(self.checked[4]))
|
.icon(IconName::Inbox)
|
||||||
.on_change(cx.listener(|view, checkeds: &Vec<bool>, _, cx| {
|
.checked(self.checked[2]),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Toggle::new(3)
|
||||||
|
.icon(IconName::Check)
|
||||||
|
.checked(self.checked[3]),
|
||||||
|
)
|
||||||
|
.child(Toggle::new(4).label("Other").checked(self.checked[4]))
|
||||||
|
.on_click(cx.listener(|view, checkeds: &Vec<bool>, _, cx| {
|
||||||
view.checked[0] = checkeds[0];
|
view.checked[0] = checkeds[0];
|
||||||
view.checked[1] = checkeds[1];
|
view.checked[1] = checkeds[1];
|
||||||
view.checked[2] = checkeds[2];
|
view.checked[2] = checkeds[2];
|
||||||
|
|
@ -187,12 +233,20 @@ impl Render for ToggleStory {
|
||||||
ToggleGroup::new("toggle-button-group2-xs")
|
ToggleGroup::new("toggle-button-group2-xs")
|
||||||
.outline()
|
.outline()
|
||||||
.xsmall()
|
.xsmall()
|
||||||
.child(Toggle::icon(IconName::Bell).checked(self.checked[0]))
|
.child(Toggle::new(0).icon(IconName::Bell).checked(self.checked[0]))
|
||||||
.child(Toggle::icon(IconName::Bot).checked(self.checked[1]))
|
.child(Toggle::new(1).icon(IconName::Bot).checked(self.checked[1]))
|
||||||
.child(Toggle::icon(IconName::Inbox).checked(self.checked[2]))
|
.child(
|
||||||
.child(Toggle::icon(IconName::Check).checked(self.checked[3]))
|
Toggle::new(2)
|
||||||
.child(Toggle::label("Other").checked(self.checked[4]))
|
.icon(IconName::Inbox)
|
||||||
.on_change(cx.listener(|view, checkeds: &Vec<bool>, _, cx| {
|
.checked(self.checked[2]),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Toggle::new(3)
|
||||||
|
.icon(IconName::Check)
|
||||||
|
.checked(self.checked[3]),
|
||||||
|
)
|
||||||
|
.child(Toggle::new(4).label("Other").checked(self.checked[4]))
|
||||||
|
.on_click(cx.listener(|view, checkeds: &Vec<bool>, _, cx| {
|
||||||
view.checked[0] = checkeds[0];
|
view.checked[0] = checkeds[0];
|
||||||
view.checked[1] = checkeds[1];
|
view.checked[1] = checkeds[1];
|
||||||
view.checked[2] = checkeds[2];
|
view.checked[2] = checkeds[2];
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,13 @@ pub enum ToggleVariant {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ToggleVariants: Sized {
|
pub trait ToggleVariants: Sized {
|
||||||
|
/// Set the variant of the toggle.
|
||||||
fn with_variant(self, variant: ToggleVariant) -> Self;
|
fn with_variant(self, variant: ToggleVariant) -> Self;
|
||||||
|
/// Set the variant to ghost.
|
||||||
fn ghost(self) -> Self {
|
fn ghost(self) -> Self {
|
||||||
self.with_variant(ToggleVariant::Ghost)
|
self.with_variant(ToggleVariant::Ghost)
|
||||||
}
|
}
|
||||||
|
/// Set the variant to outline.
|
||||||
fn outline(self) -> Self {
|
fn outline(self) -> Self {
|
||||||
self.with_variant(ToggleVariant::Outline)
|
self.with_variant(ToggleVariant::Outline)
|
||||||
}
|
}
|
||||||
|
|
@ -28,53 +31,58 @@ pub trait ToggleVariants: Sized {
|
||||||
|
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
pub struct Toggle {
|
pub struct Toggle {
|
||||||
|
id: ElementId,
|
||||||
style: StyleRefinement,
|
style: StyleRefinement,
|
||||||
checked: bool,
|
checked: bool,
|
||||||
size: Size,
|
size: Size,
|
||||||
variant: ToggleVariant,
|
variant: ToggleVariant,
|
||||||
disabled: bool,
|
disabled: bool,
|
||||||
children: SmallVec<[AnyElement; 1]>,
|
children: SmallVec<[AnyElement; 1]>,
|
||||||
}
|
on_click: Option<Box<dyn Fn(&bool, &mut Window, &mut App) + 'static>>,
|
||||||
|
|
||||||
#[derive(IntoElement)]
|
|
||||||
pub struct InteractiveToggle {
|
|
||||||
id: ElementId,
|
|
||||||
toggle: Toggle,
|
|
||||||
on_change: Option<Box<dyn Fn(&bool, &mut Window, &mut App) + 'static>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Toggle {
|
impl Toggle {
|
||||||
fn new() -> Self {
|
/// Create a new Toggle element.
|
||||||
|
pub fn new(id: impl Into<ElementId>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
id: id.into(),
|
||||||
style: StyleRefinement::default(),
|
style: StyleRefinement::default(),
|
||||||
checked: false,
|
checked: false,
|
||||||
size: Size::default(),
|
size: Size::default(),
|
||||||
variant: ToggleVariant::default(),
|
variant: ToggleVariant::default(),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
children: smallvec![],
|
children: smallvec![],
|
||||||
|
on_click: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn label(label: impl Into<SharedString>) -> Self {
|
/// Add a label to the toggle.
|
||||||
Self::new().child(label.into())
|
pub fn label(mut self, label: impl Into<SharedString>) -> Self {
|
||||||
|
let label: SharedString = label.into();
|
||||||
|
self.children.push(label.into_any_element());
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn icon(icon: impl Into<Icon>) -> Self {
|
/// Add icon to the toggle.
|
||||||
Self::new().child(icon.into())
|
pub fn icon(mut self, icon: impl Into<Icon>) -> Self {
|
||||||
}
|
let icon: Icon = icon.into();
|
||||||
|
self.children.push(icon.into());
|
||||||
pub fn id(self, id: impl Into<ElementId>) -> InteractiveToggle {
|
self
|
||||||
InteractiveToggle {
|
|
||||||
id: id.into(),
|
|
||||||
toggle: self,
|
|
||||||
on_change: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the checked state of the toggle, default: false
|
||||||
pub fn checked(mut self, checked: bool) -> Self {
|
pub fn checked(mut self, checked: bool) -> Self {
|
||||||
self.checked = checked;
|
self.checked = checked;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the callback to be called when the toggle is clicked.
|
||||||
|
///
|
||||||
|
/// The `&bool` parameter represents the new checked state of the toggle.
|
||||||
|
pub fn on_click(mut self, handler: impl Fn(&bool, &mut Window, &mut App) + 'static) -> Self {
|
||||||
|
self.on_click = Some(Box::new(handler));
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToggleVariants for Toggle {
|
impl ToggleVariants for Toggle {
|
||||||
|
|
@ -84,6 +92,12 @@ impl ToggleVariants for Toggle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ParentElement for Toggle {
|
||||||
|
fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
|
||||||
|
self.children.extend(elements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Disableable for Toggle {
|
impl Disableable for Toggle {
|
||||||
fn disabled(mut self, disabled: bool) -> Self {
|
fn disabled(mut self, disabled: bool) -> Self {
|
||||||
self.disabled = disabled;
|
self.disabled = disabled;
|
||||||
|
|
@ -104,12 +118,6 @@ impl Styled for Toggle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParentElement for Toggle {
|
|
||||||
fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
|
|
||||||
self.children.extend(elements);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RenderOnce for Toggle {
|
impl RenderOnce for Toggle {
|
||||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||||
let checked = self.checked;
|
let checked = self.checked;
|
||||||
|
|
@ -117,6 +125,7 @@ impl RenderOnce for Toggle {
|
||||||
let hoverable = !disabled && !checked;
|
let hoverable = !disabled && !checked;
|
||||||
|
|
||||||
div()
|
div()
|
||||||
|
.id(self.id)
|
||||||
.flex()
|
.flex()
|
||||||
.flex_row()
|
.flex_row()
|
||||||
.items_center()
|
.items_center()
|
||||||
|
|
@ -146,67 +155,15 @@ impl RenderOnce for Toggle {
|
||||||
})
|
})
|
||||||
.refine_style(&self.style)
|
.refine_style(&self.style)
|
||||||
.children(self.children)
|
.children(self.children)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InteractiveToggle {
|
|
||||||
/// Sets the callback to be invoked when the toggle is clicked.
|
|
||||||
///
|
|
||||||
/// The first argument is a boolean indicating whether the toggle is checked.
|
|
||||||
pub fn on_change(mut self, on_change: impl Fn(&bool, &mut Window, &mut App) + 'static) -> Self {
|
|
||||||
self.on_change = Some(Box::new(on_change));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn checked(mut self, checked: bool) -> Self {
|
|
||||||
self.toggle.checked = checked;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Sizable for InteractiveToggle {
|
|
||||||
fn with_size(mut self, size: impl Into<Size>) -> Self {
|
|
||||||
self.toggle = self.toggle.with_size(size);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToggleVariants for InteractiveToggle {
|
|
||||||
fn with_variant(mut self, variant: ToggleVariant) -> Self {
|
|
||||||
self.toggle.variant = variant;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Disableable for InteractiveToggle {
|
|
||||||
fn disabled(mut self, disabled: bool) -> Self {
|
|
||||||
self.toggle.disabled = disabled;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ParentElement for InteractiveToggle {
|
|
||||||
fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
|
|
||||||
self.toggle.extend(elements);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RenderOnce for InteractiveToggle {
|
|
||||||
fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
|
|
||||||
let checked = self.toggle.checked;
|
|
||||||
let disabled = self.toggle.disabled;
|
|
||||||
|
|
||||||
div()
|
|
||||||
.id(self.id)
|
|
||||||
.child(self.toggle)
|
|
||||||
.when(!disabled, |this| {
|
.when(!disabled, |this| {
|
||||||
this.when_some(self.on_change, |this, on_change| {
|
this.when_some(self.on_click, |this, on_click| {
|
||||||
this.on_click(move |_, window, cx| on_change(&!checked, window, cx))
|
this.on_click(move |_, window, cx| on_click(&!checked, window, cx))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A group of toggles.
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
pub struct ToggleGroup {
|
pub struct ToggleGroup {
|
||||||
id: ElementId,
|
id: ElementId,
|
||||||
|
|
@ -215,10 +172,11 @@ pub struct ToggleGroup {
|
||||||
variant: ToggleVariant,
|
variant: ToggleVariant,
|
||||||
disabled: bool,
|
disabled: bool,
|
||||||
items: Vec<Toggle>,
|
items: Vec<Toggle>,
|
||||||
on_change: Option<Rc<dyn Fn(&Vec<bool>, &mut Window, &mut App) + 'static>>,
|
on_click: Option<Rc<dyn Fn(&Vec<bool>, &mut Window, &mut App) + 'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToggleGroup {
|
impl ToggleGroup {
|
||||||
|
/// Create a new ToggleGroup element.
|
||||||
pub fn new(id: impl Into<ElementId>) -> Self {
|
pub fn new(id: impl Into<ElementId>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
|
|
@ -227,7 +185,7 @@ impl ToggleGroup {
|
||||||
variant: ToggleVariant::default(),
|
variant: ToggleVariant::default(),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
items: Vec::new(),
|
items: Vec::new(),
|
||||||
on_change: None,
|
on_click: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -245,12 +203,12 @@ impl ToggleGroup {
|
||||||
|
|
||||||
/// Set the callback to be called when the toggle group changes.
|
/// Set the callback to be called when the toggle group changes.
|
||||||
///
|
///
|
||||||
/// The `&Vec<bool>` parameter represents the check state of each [`Toggle`] in the group.
|
/// The `&Vec<bool>` parameter represents the new check state of each [`Toggle`] in the group.
|
||||||
pub fn on_change(
|
pub fn on_click(
|
||||||
mut self,
|
mut self,
|
||||||
on_change: impl Fn(&Vec<bool>, &mut Window, &mut App) + 'static,
|
on_click: impl Fn(&Vec<bool>, &mut Window, &mut App) + 'static,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.on_change = Some(Rc::new(on_change));
|
self.on_click = Some(Rc::new(on_click));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -300,21 +258,20 @@ impl RenderOnce for ToggleGroup {
|
||||||
|(ix, item)| {
|
|(ix, item)| {
|
||||||
let state = state.clone();
|
let state = state.clone();
|
||||||
item.disabled(disabled)
|
item.disabled(disabled)
|
||||||
.id(ix)
|
|
||||||
.with_size(self.size)
|
.with_size(self.size)
|
||||||
.with_variant(self.variant)
|
.with_variant(self.variant)
|
||||||
.on_change(move |_, _, _| {
|
.on_click(move |_, _, _| {
|
||||||
state.set(Some(ix));
|
state.set(Some(ix));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.when(!disabled, |this| {
|
.when(!disabled, |this| {
|
||||||
this.when_some(self.on_change, |this, on_change| {
|
this.when_some(self.on_click, |this, on_click| {
|
||||||
this.on_click(move |_, window, cx| {
|
this.on_click(move |_, window, cx| {
|
||||||
if let Some(ix) = state.get() {
|
if let Some(ix) = state.get() {
|
||||||
let mut checks = checks.clone();
|
let mut checks = checks.clone();
|
||||||
checks[ix] = !checks[ix];
|
checks[ix] = !checks[ix];
|
||||||
on_change(&checks, window, cx);
|
on_click(&checks, window, cx);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -18,23 +18,25 @@ use gpui_component::button::{Toggle, ToggleGroup};
|
||||||
### Basic Toggle
|
### Basic Toggle
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
Toggle::label("Toggle me")
|
Toggle::new("toggle1").
|
||||||
.id("basic-toggle")
|
.label("Toggle me")
|
||||||
.checked(false)
|
.checked(false)
|
||||||
.on_change(|checked, _, _| {
|
.on_click(|checked, _, _| {
|
||||||
println!("Toggle is now: {}", checked);
|
println!("Toggle is now: {}", checked);
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Here, we can use `on_click` to handle toggle state changes. The callback receives the **new checked state** as a `bool`.
|
||||||
|
|
||||||
### Icon Toggle
|
### Icon Toggle
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use gpui_component::IconName;
|
use gpui_component::IconName;
|
||||||
|
|
||||||
Toggle::icon(IconName::Eye)
|
Toggle::new("toggle2")
|
||||||
.id("visibility-toggle")
|
.icon(IconName::Eye)
|
||||||
.checked(true)
|
.checked(true)
|
||||||
.on_change(|checked, _, _| {
|
.on_click(|checked, _, _| {
|
||||||
println!("Visibility: {}", if *checked { "shown" } else { "hidden" });
|
println!("Visibility: {}", if *checked { "shown" } else { "hidden" });
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
@ -48,10 +50,10 @@ struct MyView {
|
||||||
|
|
||||||
impl Render for MyView {
|
impl Render for MyView {
|
||||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
Toggle::label("Active")
|
Toggle::new("active")
|
||||||
.id("active-toggle")
|
.label("Active")
|
||||||
.checked(self.is_active)
|
.checked(self.is_active)
|
||||||
.on_change(cx.listener(|view, checked, _, cx| {
|
.on_click(cx.listener(|view, checked, _, cx| {
|
||||||
view.is_active = *checked;
|
view.is_active = *checked;
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}))
|
}))
|
||||||
|
|
@ -63,36 +65,37 @@ impl Render for MyView {
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// Ghost toggle (default)
|
// Ghost toggle (default)
|
||||||
Toggle::label("Ghost")
|
Toggle::new("ghost-toggle")
|
||||||
.id("ghost-toggle")
|
|
||||||
.ghost()
|
.ghost()
|
||||||
|
.label("Ghost")
|
||||||
|
|
||||||
// Outline toggle
|
// Outline toggle
|
||||||
Toggle::label("Outline")
|
Toggle::new("outline-toggle")
|
||||||
.id("outline-toggle")
|
|
||||||
.outline()
|
.outline()
|
||||||
|
.label("Outline")
|
||||||
```
|
```
|
||||||
|
|
||||||
### Different Sizes
|
### Different Sizes
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// Extra small
|
// Extra small
|
||||||
Toggle::icon(IconName::Star)
|
Toggle::new("xs-toggle")
|
||||||
.id("xs-toggle")
|
.icon(IconName::Star)
|
||||||
.xsmall()
|
.xsmall()
|
||||||
|
|
||||||
// Small
|
// Small
|
||||||
Toggle::label("Small")
|
Toggle::new("small-toggle")
|
||||||
.id("small-toggle")
|
.label("Small")
|
||||||
.small()
|
.small()
|
||||||
|
|
||||||
// Medium (default)
|
// Medium (default)
|
||||||
Toggle::label("Medium")
|
Toggle::new("medium-toggle")
|
||||||
.id("medium-toggle")
|
.label("Medium")
|
||||||
|
|
||||||
|
|
||||||
// Large
|
// Large
|
||||||
Toggle::label("Large")
|
Toggle::new("large-toggle")
|
||||||
.id("large-toggle")
|
.label("Large")
|
||||||
.large()
|
.large()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -100,14 +103,14 @@ Toggle::label("Large")
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// Disabled unchecked
|
// Disabled unchecked
|
||||||
Toggle::label("Disabled")
|
Toggle::new("disabled-toggle")
|
||||||
.id("disabled-toggle")
|
.label("Disabled")
|
||||||
.disabled(true)
|
.disabled(true)
|
||||||
.checked(false)
|
.checked(false)
|
||||||
|
|
||||||
// Disabled checked
|
// Disabled checked
|
||||||
Toggle::label("Selected (Disabled)")
|
Toggle::new("disabled-checked-toggle")
|
||||||
.id("disabled-checked-toggle")
|
.label("Selected (Disabled)")
|
||||||
.disabled(true)
|
.disabled(true)
|
||||||
.checked(true)
|
.checked(true)
|
||||||
```
|
```
|
||||||
|
|
@ -144,15 +147,17 @@ Toggle buttons can be grouped together using `ToggleGroup` for related options:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
ToggleGroup::new("filter-group")
|
ToggleGroup::new("filter-group")
|
||||||
.child(Toggle::icon(IconName::Bell))
|
.child(Toggle::new(0).icon(IconName::Bell))
|
||||||
.child(Toggle::icon(IconName::Bot))
|
.child(Toggle::new(1).icon(IconName::Bot))
|
||||||
.child(Toggle::icon(IconName::Inbox))
|
.child(Toggle::new(2).icon(IconName::Inbox))
|
||||||
.child(Toggle::label("Other"))
|
.child(Toggle::new(3).label("Other"))
|
||||||
.on_change(|checkeds, _, _| {
|
.on_click(|checkeds, _, _| {
|
||||||
println!("Selected toggles: {:?}", checkeds);
|
println!("Selected toggles: {:?}", checkeds);
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The `on_click` callback receives a `Vec<bool>` representing the **new checked state** of each toggle in the group.
|
||||||
|
|
||||||
### Toggle Group with Controlled State
|
### Toggle Group with Controlled State
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
|
@ -166,11 +171,11 @@ struct FilterView {
|
||||||
impl Render for FilterView {
|
impl Render for FilterView {
|
||||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
ToggleGroup::new("filters")
|
ToggleGroup::new("filters")
|
||||||
.child(Toggle::icon(IconName::Bell).checked(self.notifications))
|
.child(Toggle::new(0).icon(IconName::Bell).checked(self.notifications))
|
||||||
.child(Toggle::icon(IconName::Bot).checked(self.bots))
|
.child(Toggle::new(1).icon(IconName::Bot).checked(self.bots))
|
||||||
.child(Toggle::icon(IconName::Inbox).checked(self.inbox))
|
.child(Toggle::new(2).icon(IconName::Inbox).checked(self.inbox))
|
||||||
.child(Toggle::label("Other").checked(self.other))
|
.child(Toggle::new(3).label("Other").checked(self.other))
|
||||||
.on_change(cx.listener(|view, checkeds, _, cx| {
|
.on_click(cx.listener(|view, checkeds, _, cx| {
|
||||||
view.notifications = checkeds[0];
|
view.notifications = checkeds[0];
|
||||||
view.bots = checkeds[1];
|
view.bots = checkeds[1];
|
||||||
view.inbox = checkeds[2];
|
view.inbox = checkeds[2];
|
||||||
|
|
@ -188,16 +193,16 @@ impl Render for FilterView {
|
||||||
ToggleGroup::new("compact-filters")
|
ToggleGroup::new("compact-filters")
|
||||||
.outline()
|
.outline()
|
||||||
.small()
|
.small()
|
||||||
.child(Toggle::icon(IconName::Filter))
|
.child(Toggle::new(0).icon(IconName::Filter))
|
||||||
.child(Toggle::icon(IconName::Sort))
|
.child(Toggle::new(1).icon(IconName::Sort))
|
||||||
.child(Toggle::icon(IconName::Search))
|
.child(Toggle::new(2).icon(IconName::Search))
|
||||||
|
|
||||||
// Ghost variant (default), extra small
|
// Ghost variant (default), extra small
|
||||||
ToggleGroup::new("mini-toolbar")
|
ToggleGroup::new("mini-toolbar")
|
||||||
.xsmall()
|
.xsmall()
|
||||||
.child(Toggle::icon(IconName::Bold))
|
.child(Toggle::new(0).icon(IconName::Bold))
|
||||||
.child(Toggle::icon(IconName::Italic))
|
.child(Toggle::new(1).icon(IconName::Italic))
|
||||||
.child(Toggle::icon(IconName::Underline))
|
.child(Toggle::new(2).icon(IconName::Underline))
|
||||||
```
|
```
|
||||||
|
|
||||||
## Event Handling
|
## Event Handling
|
||||||
|
|
@ -205,9 +210,9 @@ ToggleGroup::new("mini-toolbar")
|
||||||
### Individual Toggle Events
|
### Individual Toggle Events
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
Toggle::label("Subscribe")
|
Toggle::new("subscribe-toggle")
|
||||||
.id("subscribe-toggle")
|
.label("Subscribe")
|
||||||
.on_change(|checked, window, cx| {
|
.on_click(|checked, window, cx| {
|
||||||
if *checked {
|
if *checked {
|
||||||
// Handle subscription logic
|
// Handle subscription logic
|
||||||
println!("Subscribed!");
|
println!("Subscribed!");
|
||||||
|
|
@ -218,72 +223,6 @@ Toggle::label("Subscribe")
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
### Toggle Group Events
|
|
||||||
|
|
||||||
The `on_change` callback for `ToggleGroup` receives a `Vec<bool>` representing the state of each toggle:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
ToggleGroup::new("options")
|
|
||||||
.child(Toggle::label("Option 1"))
|
|
||||||
.child(Toggle::label("Option 2"))
|
|
||||||
.child(Toggle::label("Option 3"))
|
|
||||||
.on_change(|states, _, _| {
|
|
||||||
for (i, checked) in states.iter().enumerate() {
|
|
||||||
if *checked {
|
|
||||||
println!("Option {} is selected", i + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Toggle
|
|
||||||
|
|
||||||
| Method | Description |
|
|
||||||
| ---------------- | ----------------------------------------------------------- |
|
|
||||||
| `label(str)` | Create toggle with text label |
|
|
||||||
| `icon(icon)` | Create toggle with icon |
|
|
||||||
| `id(id)` | Set element ID and make interactive |
|
|
||||||
| `checked(bool)` | Set checked/selected state |
|
|
||||||
| `disabled(bool)` | Set disabled state |
|
|
||||||
| `on_change(fn)` | Callback when clicked, receives `&bool` (new checked state) |
|
|
||||||
|
|
||||||
### Toggle Variants
|
|
||||||
|
|
||||||
| Method | Description |
|
|
||||||
| ----------- | ------------------------------------------------ |
|
|
||||||
| `ghost()` | Ghost variant (default) - transparent background |
|
|
||||||
| `outline()` | Outline variant - visible border |
|
|
||||||
|
|
||||||
### Toggle Sizing
|
|
||||||
|
|
||||||
Implements `Sizable` trait:
|
|
||||||
|
|
||||||
- `xsmall()` - Extra small toggle (20x20px)
|
|
||||||
- `small()` - Small toggle (24x24px)
|
|
||||||
- `medium()` - Medium toggle (32x32px, default)
|
|
||||||
- `large()` - Large toggle (36x36px)
|
|
||||||
- `with_size(size)` - Set explicit size
|
|
||||||
|
|
||||||
### ToggleGroup
|
|
||||||
|
|
||||||
| Method | Description |
|
|
||||||
| ---------------- | ------------------------------------------------------- |
|
|
||||||
| `new(id)` | Create a new toggle group with ID |
|
|
||||||
| `child(toggle)` | Add a toggle to the group |
|
|
||||||
| `children(iter)` | Add multiple toggles to the group |
|
|
||||||
| `on_change(fn)` | Callback when any toggle changes, receives `&Vec<bool>` |
|
|
||||||
| `disabled(bool)` | Disable all toggles in the group |
|
|
||||||
|
|
||||||
### ToggleGroup Styling
|
|
||||||
|
|
||||||
Implements `Sizable`, `ToggleVariants`, and `Disableable` traits:
|
|
||||||
|
|
||||||
- Size methods apply to all child toggles
|
|
||||||
- Variant methods apply to all child toggles
|
|
||||||
- `disabled(bool)` affects the entire group
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
### Toolbar with Toggle Buttons
|
### Toolbar with Toggle Buttons
|
||||||
|
|
@ -305,11 +244,11 @@ h_flex()
|
||||||
.child(
|
.child(
|
||||||
ToggleGroup::new("formatting")
|
ToggleGroup::new("formatting")
|
||||||
.small()
|
.small()
|
||||||
.child(Toggle::icon(IconName::Bold).checked(self.bold))
|
.child(Toggle::new(0).icon(IconName::Bold).checked(self.bold))
|
||||||
.child(Toggle::icon(IconName::Italic).checked(self.italic))
|
.child(Toggle::new(1).icon(IconName::Italic).checked(self.italic))
|
||||||
.child(Toggle::icon(IconName::Underline).checked(self.underline))
|
.child(Toggle::new(2).icon(IconName::Underline).checked(self.underline))
|
||||||
.child(Toggle::icon(IconName::Strikethrough).checked(self.strikethrough))
|
.child(Toggle::new(3).icon(IconName::Strikethrough).checked(self.strikethrough))
|
||||||
.on_change(cx.listener(|view, states, _, cx| {
|
.on_click(cx.listener(|view, states, _, cx| {
|
||||||
view.bold = states[0];
|
view.bold = states[0];
|
||||||
view.italic = states[1];
|
view.italic = states[1];
|
||||||
view.underline = states[2];
|
view.underline = states[2];
|
||||||
|
|
@ -336,10 +275,10 @@ v_flex()
|
||||||
.child(
|
.child(
|
||||||
ToggleGroup::new("status-filters")
|
ToggleGroup::new("status-filters")
|
||||||
.outline()
|
.outline()
|
||||||
.child(Toggle::label("Completed").checked(self.show_completed))
|
.child(Toggle::new(0).label("Completed").checked(self.show_completed))
|
||||||
.child(Toggle::label("Pending").checked(self.show_pending))
|
.child(Toggle::new(1).label("Pending").checked(self.show_pending))
|
||||||
.child(Toggle::label("Cancelled").checked(self.show_cancelled))
|
.child(Toggle::new(2).label("Cancelled").checked(self.show_cancelled))
|
||||||
.on_change(cx.listener(|view, states, _, cx| {
|
.on_click(cx.listener(|view, states, _, cx| {
|
||||||
view.show_completed = states[0];
|
view.show_completed = states[0];
|
||||||
view.show_pending = states[1];
|
view.show_pending = states[1];
|
||||||
view.show_cancelled = states[2];
|
view.show_cancelled = states[2];
|
||||||
|
|
@ -347,10 +286,10 @@ v_flex()
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
Toggle::label("Show urgent only")
|
Toggle::new("urgent-filter")
|
||||||
.id("urgent-filter")
|
.label("Show urgent only")
|
||||||
.checked(self.show_urgent)
|
.checked(self.show_urgent)
|
||||||
.on_change(cx.listener(|view, checked, _, cx| {
|
.on_click(cx.listener(|view, checked, _, cx| {
|
||||||
view.show_urgent = *checked;
|
view.show_urgent = *checked;
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}))
|
}))
|
||||||
|
|
@ -382,10 +321,10 @@ v_flex()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
Toggle::icon(IconName::Mail)
|
Toggle::new("email-notifications")
|
||||||
.id("email-notifications")
|
.icon(IconName::Mail)
|
||||||
.checked(self.email_notifications)
|
.checked(self.email_notifications)
|
||||||
.on_change(cx.listener(|view, checked, _, cx| {
|
.on_click(cx.listener(|view, checked, _, cx| {
|
||||||
view.email_notifications = *checked;
|
view.email_notifications = *checked;
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}))
|
}))
|
||||||
|
|
@ -397,10 +336,10 @@ v_flex()
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.child(Label::new("Push notifications"))
|
.child(Label::new("Push notifications"))
|
||||||
.child(
|
.child(
|
||||||
Toggle::icon(IconName::Bell)
|
Toggle::new("push-notifications")
|
||||||
.id("push-notifications")
|
.icon(IconName::Bell)
|
||||||
.checked(self.push_notifications)
|
.checked(self.push_notifications)
|
||||||
.on_change(cx.listener(|view, checked, _, cx| {
|
.on_click(cx.listener(|view, checked, _, cx| {
|
||||||
view.push_notifications = *checked;
|
view.push_notifications = *checked;
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}))
|
}))
|
||||||
|
|
@ -431,11 +370,12 @@ v_flex()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, category)| {
|
.map(|(i, category)| {
|
||||||
Toggle::label(category)
|
Toggle::new(i)
|
||||||
|
.label(category)
|
||||||
.checked(self.selected_categories.get(i).copied().unwrap_or(false))
|
.checked(self.selected_categories.get(i).copied().unwrap_or(false))
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.on_change(cx.listener(|view, states, _, cx| {
|
.on_click(cx.listener(|view, states, _, cx| {
|
||||||
view.selected_categories = states.clone();
|
view.selected_categories = states.clone();
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}))
|
}))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue