Base for doc-like website to demo and help development

This commit is contained in:
Cecile Tonglet 2020-09-20 19:02:25 +02:00
parent 608cae413c
commit e7a1e9df78
3 changed files with 239 additions and 44 deletions

View file

@ -2,6 +2,7 @@ use crate::buttons::Button;
use crate::collapse::Collapse;
use crate::forms::controls::Switch;
use crate::icon::*;
use crate::menu::*;
use crate::tree::*;
use crate::Intent;
use yew::prelude::*;
@ -19,6 +20,7 @@ pub struct App {
tree: TreeData<i32>,
callback_expand_node: Callback<(NodeId, MouseEvent)>,
callback_select_node: Callback<(NodeId, MouseEvent)>,
doc_menu: DocMenu,
}
pub enum Msg {
@ -27,6 +29,7 @@ pub enum Msg {
ToggleCollapse,
ExpandNode(NodeId),
SelectNode(NodeId),
GoToMenu(DocMenu),
}
impl Component for App {
@ -102,6 +105,7 @@ impl Component for App {
tree: tree.into(),
callback_expand_node: link.callback(|(node_id, _)| Msg::ExpandNode(node_id)),
callback_select_node: link.callback(|(node_id, _)| Msg::SelectNode(node_id)),
doc_menu: DocMenu::Tree,
link,
}
}
@ -127,6 +131,9 @@ impl Component for App {
let node = tree.get_mut(&node_id).unwrap();
node.data_mut().is_selected ^= true;
}
Msg::GoToMenu(doc_menu) => {
self.doc_menu = doc_menu;
}
}
true
}
@ -149,10 +156,27 @@ impl Component for App {
html! {
<div class={class} style={style}>
<div>
<Menu>
<MenuItem text={html!("Button")} onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::Button)) />
<MenuItem text={html!("Collapse")} onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::Collapse)) />
<MenuItem text={html!("Icon")} onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::Icon)) />
<MenuItem text={html!("Menu")} onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::Menu)) />
<MenuItem text={html!("Switch")} onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::Switch)) />
<MenuItem text={html!("Tree")} onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::Tree)) />
</Menu>
</div>
{
match self.doc_menu {
DocMenu::Button => html! {
<div>
<p> {"Counter: "} { self.counter }</p>
<div>
<Button onclick=self.link.callback(|_| Msg::AddOne)>{ "Add 1" }</Button>
</div>
</div>
},
DocMenu::Switch => html! {
<div>
<Switch
onclick=self.link.callback(|_| Msg::ToggleLight)
@ -160,6 +184,8 @@ impl Component for App {
label="Dark theme"
/>
</div>
},
DocMenu::Collapse => html! {
<div>
<Button onclick=self.link.callback(|_| Msg::ToggleCollapse)>
{"Toggle collapse"}
@ -187,6 +213,8 @@ impl Component for App {
</pre>
</Collapse>
</div>
},
DocMenu::Tree => html! {
<div>
<Tree<i32>
tree=self.tree.clone()
@ -195,7 +223,26 @@ impl Component for App {
onclick=Some(self.callback_select_node.clone())
/>
</div>
},
DocMenu::Icon => html! {
<div>
<Icon icon=IconName::Print />
</div>
},
DocMenu::Menu => html!(),
}
}
</div>
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum DocMenu {
Button,
Collapse,
Icon,
Menu,
Switch,
Tree,
}

View file

@ -6,6 +6,7 @@ pub mod buttons;
pub mod collapse;
pub mod forms;
pub mod icon;
pub mod menu;
pub mod tree;
use yew::virtual_dom::Classes;

147
src/menu.rs Normal file
View file

@ -0,0 +1,147 @@
use crate::icon::{Icon, IconName};
use crate::Intent;
use yew::prelude::*;
pub struct Menu {
props: MenuProps,
}
#[derive(Clone, PartialEq, Properties)]
pub struct MenuProps {
#[prop_or_default]
pub large: bool,
#[prop_or_default]
pub class: Option<String>,
#[prop_or_default]
pub r#ref: NodeRef,
pub children: html::Children,
}
impl Component for Menu {
type Message = ();
type Properties = MenuProps;
fn create(props: Self::Properties, _link: ComponentLink<Self>) -> Self {
Menu { props }
}
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
true
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
if self.props != props {
self.props = props;
true
} else {
false
}
}
fn view(&self) -> Html {
let mut class = Classes::from("bp3-menu");
if self.props.large {
class.push("bp3-large");
}
class = class.extend(self.props.class.clone());
html! {
<ul class=class ref={self.props.r#ref.clone()}>
{self.props.children.clone()}
</ul>
}
}
}
pub struct MenuItem {
props: MenuItemProps,
}
#[derive(Clone, PartialEq, Properties)]
pub struct MenuItemProps {
#[prop_or_default]
pub text: yew::virtual_dom::VNode,
#[prop_or_default]
pub text_class: Option<String>,
#[prop_or_default]
pub active: bool,
#[prop_or_default]
pub class: Option<String>,
// TODO: pub disabled: bool,
#[prop_or_default]
pub label: Option<yew::virtual_dom::VNode>,
#[prop_or_default]
pub label_class: Option<String>,
// TODO: pub multiline: bool, (requires <Text>)
// TODO: popover_props, should_dismiss_popover
#[prop_or_default]
pub intent: Option<Intent>,
#[prop_or_default]
pub icon: IconName,
#[prop_or_default]
pub onclick: Callback<MouseEvent>,
// TODO: pub children: html::Children,
}
impl Component for MenuItem {
type Message = ();
type Properties = MenuItemProps;
fn create(props: Self::Properties, _link: ComponentLink<Self>) -> Self {
MenuItem { props }
}
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
true
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
if self.props != props {
self.props = props;
true
} else {
false
}
}
fn view(&self) -> Html {
let mut anchor_class = Classes::from("bp3-menu-item");
if self.props.active {
anchor_class.push("bp3-active");
}
if let Some(intent) = self.props.intent.clone() {
anchor_class = anchor_class.extend(intent);
} else if self.props.active {
anchor_class = anchor_class.extend(Intent::Primary);
}
anchor_class = anchor_class.extend(self.props.class.clone());
let mut text_class = Classes::from("bp3-text");
text_class.push("bp3-fill");
text_class = text_class.extend(self.props.text_class.clone());
html! {
<li>
<a
class=anchor_class
onclick={self.props.onclick.clone()}
>
<Icon icon={self.props.icon} />
<div class=text_class>
{self.props.text.clone()}
</div>
{
if let Some(label) = self.props.label.clone() {
let mut label_class = Classes::from("bp3-menu-item-label");
label_class = label_class.extend(self.props.label_class.clone());
html!(<span class=label_class>{label}</span>)
} else {
html!()
}
}
</a>
</li>
}
}
}