T06b forms selection: checkbox, radio, cards, switch, select, combobox, multi select, cascader, transfer list, list box, chips, rating, sliders, knob, stepper
This commit is contained in:
36 files changed
+5170
-198
No files matched your search
@@ -0,0 +1,214 @@
|
||||
use ely_gpui_component::{
|
||||
forms::{
|
||||
CheckState, Checkbox, CheckboxCard, CheckboxGroup, Choice, RadioCard, RadioGroup, Switch,
|
||||
},
|
||||
primitives::IconName,
|
||||
};
|
||||
use gpui::{App, Entity, IntoElement, ParentElement, SharedString, Styled, Window, div, px};
|
||||
|
||||
use crate::{
|
||||
probe::probe,
|
||||
ui::{code, section, specimen},
|
||||
};
|
||||
|
||||
pub(super) fn keep<T: 'static>(
|
||||
key: &'static str,
|
||||
init: impl FnOnce() -> T,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Entity<T> {
|
||||
window.use_keyed_state(key, cx, move |_, _| init())
|
||||
}
|
||||
|
||||
pub(super) fn set<T: 'static>(state: &Entity<T>, value: T, cx: &mut App) {
|
||||
state.update(cx, |state, cx| {
|
||||
*state = value;
|
||||
cx.notify();
|
||||
});
|
||||
}
|
||||
|
||||
fn values(list: &[&'static str]) -> Vec<SharedString> {
|
||||
list.iter()
|
||||
.map(|value| SharedString::from(*value))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn checkboxes(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let channels = [
|
||||
Choice::new("email", "Email"),
|
||||
Choice::new("push", "Push"),
|
||||
Choice::new("sms", "Text message").disabled(),
|
||||
];
|
||||
let open: Vec<SharedString> = channels
|
||||
.iter()
|
||||
.filter(|choice| !choice.disabled)
|
||||
.map(|choice| choice.value.clone())
|
||||
.collect();
|
||||
let on = keep("check-channels", || values(&["email"]), window, cx);
|
||||
let now = on.read(cx).clone();
|
||||
let parent = match now.len() {
|
||||
0 => CheckState::Off,
|
||||
n if n == open.len() => CheckState::On,
|
||||
_ => CheckState::Mixed,
|
||||
};
|
||||
let (all, some) = (on.clone(), on.clone());
|
||||
section(
|
||||
"Checkbox / CheckboxGroup",
|
||||
"On, off, or mixed when a parent's children disagree. The check pops in.",
|
||||
cx,
|
||||
)
|
||||
.child(probe(
|
||||
"checks",
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_2()
|
||||
.w(px(280.0))
|
||||
.child(
|
||||
Checkbox::new("check-all", parent)
|
||||
.label("All notifications")
|
||||
.on_change(move |on, _, cx| {
|
||||
set(&all, if on { open.clone() } else { Vec::new() }, cx)
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
div().pl_6().child(
|
||||
CheckboxGroup::new("check-group", channels)
|
||||
.selected(now)
|
||||
.on_change(move |next, _, cx| set(&some, next.to_vec(), cx)),
|
||||
),
|
||||
),
|
||||
))
|
||||
.child(code("Checkbox::new(id, CheckState::Mixed)", cx))
|
||||
}
|
||||
|
||||
pub fn radios(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let plan = keep("radio-plan", || SharedString::from("pro"), window, cx);
|
||||
let density = keep(
|
||||
"radio-density",
|
||||
|| SharedString::from("standard"),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
let (plan_now, density_now) = (plan.read(cx).clone(), density.read(cx).clone());
|
||||
section(
|
||||
"Radio / RadioGroup",
|
||||
"One Tab stop per group; the arrow keys move the choice.",
|
||||
cx,
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_6()
|
||||
.child(specimen(
|
||||
"plan",
|
||||
probe(
|
||||
"radios",
|
||||
RadioGroup::new(
|
||||
"radio-plan",
|
||||
[
|
||||
Choice::new("free", "Free"),
|
||||
Choice::new("pro", "Pro"),
|
||||
Choice::new("team", "Team"),
|
||||
Choice::new("enterprise", "Enterprise").disabled(),
|
||||
],
|
||||
)
|
||||
.selected(plan_now)
|
||||
.on_change(move |value, _, cx| set(&plan, value.clone(), cx)),
|
||||
),
|
||||
cx,
|
||||
))
|
||||
.child(specimen(
|
||||
"density, in a row",
|
||||
RadioGroup::new(
|
||||
"radio-density",
|
||||
[
|
||||
Choice::new("compact", "Compact"),
|
||||
Choice::new("standard", "Standard"),
|
||||
Choice::new("comfortable", "Comfortable"),
|
||||
],
|
||||
)
|
||||
.horizontal()
|
||||
.selected(density_now)
|
||||
.on_change(move |value, _, cx| set(&density, value.clone(), cx)),
|
||||
cx,
|
||||
)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn cards(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let space = keep("card-space", || SharedString::from("personal"), window, cx);
|
||||
let backup = keep("card-backup", || true, window, cx);
|
||||
let (space_now, backup_now) = (space.read(cx).clone(), *backup.read(cx));
|
||||
let (personal, team) = (space.clone(), space);
|
||||
section(
|
||||
"CheckboxCard / RadioCard",
|
||||
"Larger targets that explain a choice. The chosen border turns to ink.",
|
||||
cx,
|
||||
)
|
||||
.child(probe(
|
||||
"cards",
|
||||
div()
|
||||
.flex()
|
||||
.gap_3()
|
||||
.w(px(640.0))
|
||||
.child(
|
||||
div().flex_1().child(
|
||||
RadioCard::new("card-personal", space_now == "personal", "Personal")
|
||||
.description("Just you. Notes stay on this Mac.")
|
||||
.icon(IconName::User)
|
||||
.on_select(move |_, cx| set(&personal, "personal".into(), cx)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div().flex_1().child(
|
||||
RadioCard::new("card-team", space_now == "team", "Team")
|
||||
.description("Shared with everyone you invite.")
|
||||
.icon(IconName::Users)
|
||||
.on_select(move |_, cx| set(&team, "team".into(), cx)),
|
||||
),
|
||||
),
|
||||
))
|
||||
.child(
|
||||
div().w(px(640.0)).child(
|
||||
CheckboxCard::new("card-backup", backup_now, "Back up nightly")
|
||||
.description("Copies change sets to the cloud at 2 AM.")
|
||||
.icon(IconName::Cloud)
|
||||
.on_change(move |on, _, cx| set(&backup, on, cx)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn switches(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let wifi = keep("switch-wifi", || true, window, cx);
|
||||
let sync = keep("switch-sync", || false, window, cx);
|
||||
let (wifi_now, sync_now) = (*wifi.read(cx), *sync.read(cx));
|
||||
section(
|
||||
"Switch / Toggle",
|
||||
"Takes effect at once. The thumb slides with a little overshoot.",
|
||||
cx,
|
||||
)
|
||||
.child(probe(
|
||||
"switches",
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_3()
|
||||
.child(
|
||||
Switch::new("switch-wifi", wifi_now)
|
||||
.label("Wi-Fi")
|
||||
.on_change(move |on, _, cx| set(&wifi, on, cx)),
|
||||
)
|
||||
.child(
|
||||
Switch::new("switch-sync", sync_now)
|
||||
.label("Sync over cellular")
|
||||
.on_change(move |on, _, cx| set(&sync, on, cx)),
|
||||
)
|
||||
.child(
|
||||
Switch::new("switch-locked", true)
|
||||
.label("Managed by your admin")
|
||||
.disabled(true),
|
||||
),
|
||||
))
|
||||
}
|
||||
Reference in new issue
Block a user