Card and elevation (#16)

Co-authored-by: rbeard0330 <@dul2k3BKW6m>
Co-authored-by: Cecile Tonglet <cecile.tonglet@cecton.com>
This commit is contained in:
rbeard0330 2020-10-01 01:32:24 -04:00 committed by GitHub
parent 43b629f1ff
commit 1dff5a6f7e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 311 additions and 6 deletions

View file

@ -1,5 +1,6 @@
use crate::buttons::*;
use crate::callout::*;
use crate::card::*;
use crate::collapse::*;
use crate::icon::*;
use crate::progressbar::*;
@ -109,6 +110,11 @@ impl Component for App {
onclick=self.link
.callback(|_| Msg::GoToMenu(DocMenu::Callout))
/>
<MenuItem
text={html!("Card")}
onclick=self.link
.callback(|_| Msg::GoToMenu(DocMenu::Card))
/>
<MenuItem
text={html!("Collapse")}
onclick=self.link
@ -122,6 +128,11 @@ impl Component for App {
text={html!("Menu")}
onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::Menu))
/>
<MenuItem
text={html!("ProgressBar")}
onclick=self.link
.callback(|_| Msg::GoToMenu(DocMenu::ProgressBar))
/>
<MenuItem
text={html!("Switch")}
onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::Switch))
@ -130,10 +141,6 @@ impl Component for App {
text={html!("Tree")}
onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::Tree))
/>
<MenuItem
text={html!("ProgressBar")}
onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::ProgressBar))
/>
</Menu>
<div class="docs-nav-sponsors">
<a href="https://www.netlify.com">
@ -153,6 +160,7 @@ impl Component for App {
DocMenu::Button | DocMenu::Home => html! (<ButtonDoc />),
DocMenu::Switch => html! (),
DocMenu::Callout => html!(<CalloutDoc />),
DocMenu::Card => html!(<CardDoc />),
DocMenu::Collapse => html!(<CollapseDoc />),
DocMenu::Tree => html!(<TreeDoc />),
DocMenu::Icon => html!(<IconDoc />),
@ -175,18 +183,20 @@ pub enum DocMenu {
Button,
#[to = "/#callout"]
Callout,
#[to = "/#card"]
Card,
#[to = "/#collapse"]
Collapse,
#[to = "/#icon"]
Icon,
#[to = "/#menu"]
Menu,
#[to = "/#progress-bar"]
ProgressBar,
#[to = "/#switch"]
Switch,
#[to = "/#tree"]
Tree,
#[to = "/#progress-bar"]
ProgressBar,
#[to = "/"]
Home,
}

View file

@ -0,0 +1,47 @@
use yew::prelude::*;
use yewprint::{Card, Elevation};
pub struct Example {
props: ExampleProps,
}
#[derive(Clone, PartialEq, Properties)]
pub struct ExampleProps {
pub elevation: Elevation,
pub interactive: bool,
}
impl Component for Example {
type Message = ();
type Properties = ExampleProps;
fn create(props: Self::Properties, _link: ComponentLink<Self>) -> Self {
Example { 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 {
html! {
<Card elevation=self.props.elevation interactive=self.props.interactive>
<p>
{
"This is a card component. The elevation of the card can be adjusted. \
An interactive card reacts to being moused over."
}
</p>
</Card>
}
}
}

View file

@ -0,0 +1,119 @@
mod example;
use crate::ExampleContainer;
use example::*;
use yew::prelude::*;
use yewprint::{Elevation, Menu, MenuItem, Switch, H1, H5};
pub struct CardDoc {
callback: Callback<ExampleProps>,
state: ExampleProps,
}
impl Component for CardDoc {
type Message = ExampleProps;
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
CardDoc {
callback: link.callback(|x| x),
state: ExampleProps {
elevation: Elevation::Level0,
interactive: false,
},
}
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
self.state = msg;
true
}
fn change(&mut self, _props: Self::Properties) -> ShouldRender {
true
}
fn view(&self) -> Html {
let example_props = self.state.clone();
let source = crate::include_raw_html!(
concat!(env!("OUT_DIR"), "/", file!(), ".html"),
"bp3-code-block"
);
html! {
<div>
<H1 class="docs-title">{"Card"}</H1>
<ExampleContainer
source=source
props=Some(html! {
<CardProps
callback={self.callback.clone()}
props=example_props.clone()
/>
})
>
<Example with example_props />
</ExampleContainer>
</div>
}
}
}
crate::build_example_prop_component! {
CardProps for ExampleProps =>
fn view(&self) -> Html {
html! {
<div>
<H5>{"Props"}</H5>
<div>
<Switch
onclick=self.update_props(|props| ExampleProps {
interactive: !props.interactive,
..props
})
checked=self.props.interactive
label="Toggle interaction"
/>
<p>{"Elevation:"}</p>
<Menu>
<MenuItem
onclick=self.update_props(|props| ExampleProps {
elevation: Elevation::Level0,
..props
})
text=html!{"Level 0"}
/>
<MenuItem
onclick=self.update_props(|props| ExampleProps {
elevation: Elevation::Level1,
..props
})
text=html!{"Level 1"}
/>
<MenuItem
onclick=self.update_props(|props| ExampleProps {
elevation: Elevation::Level2,
..props
})
text=html!{"Level 2"}
/>
<MenuItem
onclick=self.update_props(|props| ExampleProps {
elevation: Elevation::Level3,
..props
})
text=html!{"Level 3"}
/>
<MenuItem
onclick=self.update_props(|props| ExampleProps {
elevation: Elevation::Level4,
..props
})
text=html!{"Level 4"}
/>
</Menu>
</div>
</div>
}
}
}

View file

@ -1,6 +1,7 @@
mod app;
mod buttons;
mod callout;
mod card;
mod collapse;
mod example;
mod icon;

56
yewprint/src/card/mod.rs Normal file
View file

@ -0,0 +1,56 @@
use crate::Elevation;
use yew::prelude::*;
#[derive(Clone, PartialEq, Properties)]
pub struct CardProps {
#[prop_or_default]
pub class: Option<String>,
#[prop_or_default]
pub elevation: Elevation,
#[prop_or_default]
pub onclick: Callback<MouseEvent>,
#[prop_or(false)]
pub interactive: bool,
pub children: html::Children,
}
pub struct Card {
props: CardProps,
}
impl Component for Card {
type Message = ();
type Properties = CardProps;
fn create(props: Self::Properties, _link: ComponentLink<Self>) -> Self {
Self { props }
}
fn update(&mut self, _msg: Self::Message) -> bool {
true
}
fn change(&mut self, props: Self::Properties) -> bool {
if self.props != props {
self.props = props;
true
} else {
false
}
}
fn view(&self) -> Html {
let mut classes = Classes::from("bp3-card")
.extend(&self.props.class)
.extend(self.props.elevation);
if self.props.interactive {
classes.push("bp3-interactive");
}
html! {
<div class=classes onclick={self.props.onclick.clone()}>
{self.props.children.clone()}
</div>
}
}
}

View file

@ -1,5 +1,6 @@
mod buttons;
mod callout;
mod card;
mod collapse;
mod html_elements;
mod icon;
@ -10,6 +11,7 @@ mod tree;
pub use buttons::*;
pub use callout::*;
pub use card::*;
pub use collapse::*;
pub use html_elements::*;
pub use icon::*;
@ -102,3 +104,73 @@ impl AsRef<str> for Intent {
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Elevation {
Level0,
Level1,
Level2,
Level3,
Level4,
}
impl Elevation {
/// Return the next highest `Elevation`.
/// ```
/// # use yewprint::Elevation;
/// assert_eq!(Elevation::Level1.above(), Elevation::Level2);
/// assert_eq!(Elevation::Level4.above(), Elevation::Level4);
/// ```
pub fn above(&self) -> Self {
use Elevation::*;
match self {
Level0 => Level1,
Level1 => Level2,
Level2 => Level3,
Level3 => Level4,
Level4 => Level4,
}
}
/// Return the next lowest `Elevation`.
/// ```
/// # use yewprint::Elevation;
/// assert_eq!(Elevation::Level3.below(), Elevation::Level2);
/// assert_eq!(Elevation::Level0.below(), Elevation::Level0);
/// ```
pub fn below(&self) -> Self {
use Elevation::*;
match self {
Level0 => Level0,
Level1 => Level0,
Level2 => Level1,
Level3 => Level2,
Level4 => Level3,
}
}
}
impl Default for Elevation {
fn default() -> Self {
Elevation::Level0
}
}
impl AsRef<str> for Elevation {
fn as_ref(&self) -> &str {
use Elevation::*;
match self {
Level0 => "bp3-elevation-0",
Level1 => "bp3-elevation-1",
Level2 => "bp3-elevation-2",
Level3 => "bp3-elevation-3",
Level4 => "bp3-elevation-4",
}
}
}
impl From<Elevation> for Classes {
fn from(elevation: Elevation) -> Self {
Classes::from(elevation.as_ref())
}
}