diff --git a/demo/src/app.rs b/demo/src/app.rs index 178b5ce..1afd4ac 100644 --- a/demo/src/app.rs +++ b/demo/src/app.rs @@ -78,6 +78,7 @@ fn TheRouter() -> impl IntoView { + diff --git a/demo/src/pages/components.rs b/demo/src/pages/components.rs index 11073eb..54e97c9 100644 --- a/demo/src/pages/components.rs +++ b/demo/src/pages/components.rs @@ -272,6 +272,11 @@ pub(crate) fn gen_nav_data() -> Vec { value: "/components/field", label: "Field", }, + NavItemOption { + group: None, + value: "/components/flex", + label: "Flex", + }, NavItemOption { group: None, value: "/components/grid", diff --git a/demo_markdown/src/lib.rs b/demo_markdown/src/lib.rs index ec48ca4..cce3490 100644 --- a/demo_markdown/src/lib.rs +++ b/demo_markdown/src/lib.rs @@ -42,6 +42,7 @@ pub fn include_md(_token_stream: proc_macro::TokenStream) -> proc_macro::TokenSt "DividerMdPage" => "../../thaw/src/divider/docs/mod.md", "DrawerMdPage" => "../../thaw/src/drawer/docs/mod.md", "FieldMdPage" => "../../thaw/src/field/docs/mod.md", + "FlexMdPage" => "../../thaw/src/flex/docs/mod.md", "GridMdPage" => "../../thaw/src/grid/docs/mod.md", "IconMdPage" => "../../thaw/src/icon/docs/mod.md", "ImageMdPage" => "../../thaw/src/image/docs/mod.md", diff --git a/thaw/src/flex/docs/mod.md b/thaw/src/flex/docs/mod.md new file mode 100644 index 0000000..819ab39 --- /dev/null +++ b/thaw/src/flex/docs/mod.md @@ -0,0 +1,110 @@ +# Flex + +```rust demo +view! { + + + + + + + + + + +} +``` + +### Vertical + +```rust demo +view! { + + + + + +} +``` + +### Gap + +```rust demo +view! { + + + + + + + + + + +} +``` + +### Align + +```rust demo +view! { + + + + + + + + + + + + + + + + + +} +``` + +### Justify + +```rust demo +view! { + + + + + + + + + + + + + + + + + +} +``` + +### Flex Props + +| Name | Type | Default | Description | +| -------- | ------------------------ | -------------------- | -------------------------------------- | +| class | `MaybeProp` | `Default::default()` | | +| style | `MaybeProp` | `Default::default()` | | +| inline | `MaybeSignal` | `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` | `None` | Vertical arrangement. | +| justify | `MaybeProp` | `None` | Horizontal arrangement. | +| children | `Children` | | | diff --git a/thaw/src/flex/flex.rs b/thaw/src/flex/flex.rs new file mode 100644 index 0000000..a4e7172 --- /dev/null +++ b/thaw/src/flex/flex.rs @@ -0,0 +1,130 @@ +use leptos::prelude::*; +use thaw_utils::class_list; + +#[component] +pub fn Flex( + #[prop(optional, into)] class: MaybeProp, + #[prop(optional, into)] style: MaybeProp, + /// 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, + /// Vertical arrangement. + #[prop(optional, into)] + align: MaybeProp, + /// Horizontal arrangement. + #[prop(optional, into)] + justify: MaybeProp, + 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! { +
+ {children()} +
+ } +} + +#[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", + } + } +} diff --git a/thaw/src/flex/mod.rs b/thaw/src/flex/mod.rs new file mode 100644 index 0000000..aaf7e40 --- /dev/null +++ b/thaw/src/flex/mod.rs @@ -0,0 +1,3 @@ +mod flex; + +pub use flex::*; diff --git a/thaw/src/lib.rs b/thaw/src/lib.rs index 89cdf12..856fab1 100644 --- a/thaw/src/lib.rs +++ b/thaw/src/lib.rs @@ -19,6 +19,7 @@ mod dialog; mod divider; mod drawer; mod field; +mod flex; mod grid; mod icon; mod image; @@ -73,6 +74,7 @@ pub use dialog::*; pub use divider::*; pub use drawer::*; pub use field::*; +pub use flex::*; pub use grid::*; pub use icon::*; pub use image::*;