feat: adds Flex component (#256)

This commit is contained in:
luoxiaozero 2024-09-09 21:44:16 +08:00 committed by GitHub
parent 40761706c2
commit 5f235339ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 252 additions and 0 deletions

View file

@ -78,6 +78,7 @@ fn TheRouter() -> impl IntoView {
<Route path=path!("/divider") view=DividerMdPage/> <Route path=path!("/divider") view=DividerMdPage/>
<Route path=path!("/drawer") view=DrawerMdPage/> <Route path=path!("/drawer") view=DrawerMdPage/>
<Route path=path!("/field") view=FieldMdPage/> <Route path=path!("/field") view=FieldMdPage/>
<Route path=path!("/flex") view=FlexMdPage/>
<Route path=path!("/menu") view=MenuMdPage/> <Route path=path!("/menu") view=MenuMdPage/>
<Route path=path!("/grid") view=GridMdPage/> <Route path=path!("/grid") view=GridMdPage/>
<Route path=path!("/icon") view=IconMdPage/> <Route path=path!("/icon") view=IconMdPage/>

View file

@ -272,6 +272,11 @@ pub(crate) fn gen_nav_data() -> Vec<NavGroupOption> {
value: "/components/field", value: "/components/field",
label: "Field", label: "Field",
}, },
NavItemOption {
group: None,
value: "/components/flex",
label: "Flex",
},
NavItemOption { NavItemOption {
group: None, group: None,
value: "/components/grid", value: "/components/grid",

View file

@ -42,6 +42,7 @@ pub fn include_md(_token_stream: proc_macro::TokenStream) -> proc_macro::TokenSt
"DividerMdPage" => "../../thaw/src/divider/docs/mod.md", "DividerMdPage" => "../../thaw/src/divider/docs/mod.md",
"DrawerMdPage" => "../../thaw/src/drawer/docs/mod.md", "DrawerMdPage" => "../../thaw/src/drawer/docs/mod.md",
"FieldMdPage" => "../../thaw/src/field/docs/mod.md", "FieldMdPage" => "../../thaw/src/field/docs/mod.md",
"FlexMdPage" => "../../thaw/src/flex/docs/mod.md",
"GridMdPage" => "../../thaw/src/grid/docs/mod.md", "GridMdPage" => "../../thaw/src/grid/docs/mod.md",
"IconMdPage" => "../../thaw/src/icon/docs/mod.md", "IconMdPage" => "../../thaw/src/icon/docs/mod.md",
"ImageMdPage" => "../../thaw/src/image/docs/mod.md", "ImageMdPage" => "../../thaw/src/image/docs/mod.md",

110
thaw/src/flex/docs/mod.md Normal file
View file

@ -0,0 +1,110 @@
# Flex
```rust demo
view! {
<Flex>
<Button>"1"</Button>
<Button>"2"</Button>
<Button>"3"</Button>
</Flex>
<Flex>
<For
each=move || 0..4
key=move |i| i.clone()
let:i
>
<Button>{i}</Button>
</For>
</Flex>
}
```
### Vertical
```rust demo
view! {
<Flex vertical=true>
<Button>"1"</Button>
<Button>"2"</Button>
<Button>"3"</Button>
</Flex>
}
```
### Gap
```rust demo
view! {
<Flex gap=FlexGap::Large>
<Button>"1"</Button>
<Button>"2"</Button>
<Button>"3"</Button>
</Flex>
<Flex gap=FlexGap::WH(36, 36)>
<Button>"1"</Button>
<Button>"2"</Button>
<Button>"3"</Button>
</Flex>
}
```
### Align
```rust demo
view! {
<Flex vertical=true>
<Flex align=FlexAlign::Start>
<Button attr:style="height: 60px">"Start"</Button>
<Button attr:style="height: 40px">"Start"</Button>
<Button>"Start"</Button>
</Flex>
<Flex align=FlexAlign::Center>
<Button attr:style="height: 60px">"Center"</Button>
<Button attr:style="height: 40px">"Center"</Button>
<Button>"Center"</Button>
</Flex>
<Flex align=FlexAlign::End>
<Button attr:style="height: 60px">"End"</Button>
<Button attr:style="height: 40px">"End"</Button>
<Button>"End"</Button>
</Flex>
</Flex>
}
```
### Justify
```rust demo
view! {
<Flex vertical=true>
<Flex justify=FlexJustify::SpaceAround>
<Button>"SpaceAround"</Button>
<Button>"SpaceAround"</Button>
<Button>"SpaceAround"</Button>
</Flex>
<Flex justify=FlexJustify::Center>
<Button>"Center"</Button>
<Button>"Center"</Button>
<Button>"Center"</Button>
</Flex>
<Flex justify=FlexJustify::End>
<Button>"End"</Button>
<Button>"End"</Button>
<Button>"End"</Button>
</Flex>
</Flex>
}
```
### Flex Props
| Name | Type | Default | Description |
| -------- | ------------------------ | -------------------- | -------------------------------------- |
| class | `MaybeProp<String>` | `Default::default()` | |
| style | `MaybeProp<String>` | `Default::default()` | |
| inline | `MaybeSignal<bool>` | `false` | Whether it's display is `inline-flex`. |
| vertical | `bool` | `false` | Whether to lay out vertically. |
| gap | `FlexGap` | `FlexGap::Medium` | Flex's gap. |
| align | `MaybeProp<FlexAlign>` | `None` | Vertical arrangement. |
| justify | `MaybeProp<FlexJustify>` | `None` | Horizontal arrangement. |
| children | `Children` | | |

130
thaw/src/flex/flex.rs Normal file
View file

@ -0,0 +1,130 @@
use leptos::prelude::*;
use thaw_utils::class_list;
#[component]
pub fn Flex(
#[prop(optional, into)] class: MaybeProp<String>,
#[prop(optional, into)] style: MaybeProp<String>,
/// Flex's gap.
#[prop(optional)]
gap: FlexGap,
/// Whether to lay out vertically.
#[prop(optional)]
vertical: bool,
/// Whether it's display is `inline-flex`.
#[prop(optional, into)]
inline: MaybeSignal<bool>,
/// Vertical arrangement.
#[prop(optional, into)]
align: MaybeProp<FlexAlign>,
/// Horizontal arrangement.
#[prop(optional, into)]
justify: MaybeProp<FlexJustify>,
children: Children,
) -> impl IntoView {
let style = Memo::new(move |_| {
let mut s = String::new();
let display = if inline.get() {
"display: inline-flex;"
} else {
"display: flex;"
};
s.push_str(display);
let direction = if vertical {
"flex-direction: column;"
} else {
"flex-direction: row;"
};
let gap = match gap {
FlexGap::Small => "gap: 4px 8px;",
FlexGap::Medium => "gap: 8px 12px;",
FlexGap::Large => "gap: 12px 16px;",
FlexGap::Size(size) => &format!("gap: {size}px {size}px;"),
FlexGap::WH(width, height) => &format!("gap: {width}px {height}px;"),
};
s.push_str(direction);
s.push_str(gap);
if let Some(align) = align.get() {
s.push_str(&format!("align-items: {};", align.as_str()));
}
if let Some(justify) = justify.get() {
s.push_str(&format!("justify-content: {};", justify.as_str()));
}
style.with(|style| {
if let Some(style) = style.as_ref() {
s.push_str(style);
}
});
s
});
view! {
<div class=class_list!["thaw-flex", class] style=move || style.get()>
{children()}
</div>
}
}
#[derive(Default)]
pub enum FlexGap {
Small,
#[default]
Medium,
Large,
Size(u16),
/// width and height
WH(u16, u16),
}
#[derive(Clone)]
pub enum FlexAlign {
FlexStart,
FlexEnd,
Start,
End,
Center,
Baseline,
Stretch,
}
impl FlexAlign {
fn as_str(&self) -> &'static str {
match self {
Self::FlexStart => "flex-start",
Self::FlexEnd => "flex-end",
Self::Start => "start",
Self::End => "end",
Self::Center => "center",
Self::Baseline => "baseline",
Self::Stretch => "stretch",
}
}
}
#[derive(Clone)]
pub enum FlexJustify {
FlexStart,
FlexEnd,
Start,
End,
Center,
SpaceAround,
SpaceBetween,
SpaceEvenly,
}
impl FlexJustify {
fn as_str(&self) -> &'static str {
match self {
Self::FlexStart => "flex-start",
Self::FlexEnd => "flex-end",
Self::Start => "start",
Self::End => "end",
Self::Center => "center",
Self::SpaceAround => "space-around",
Self::SpaceBetween => "space-between",
Self::SpaceEvenly => "space-evenly",
}
}
}

3
thaw/src/flex/mod.rs Normal file
View file

@ -0,0 +1,3 @@
mod flex;
pub use flex::*;

View file

@ -19,6 +19,7 @@ mod dialog;
mod divider; mod divider;
mod drawer; mod drawer;
mod field; mod field;
mod flex;
mod grid; mod grid;
mod icon; mod icon;
mod image; mod image;
@ -73,6 +74,7 @@ pub use dialog::*;
pub use divider::*; pub use divider::*;
pub use drawer::*; pub use drawer::*;
pub use field::*; pub use field::*;
pub use flex::*;
pub use grid::*; pub use grid::*;
pub use icon::*; pub use icon::*;
pub use image::*; pub use image::*;