feat: adds Field component

This commit is contained in:
luoxiao 2024-08-18 23:15:55 +08:00 committed by luoxiaozero
parent 5a77c874cd
commit a45354c852
9 changed files with 130 additions and 3 deletions

View file

@ -78,6 +78,7 @@ fn TheRouter() -> impl IntoView {
<Route path=path!("/dialog") view=DialogMdPage/>
<Route path=path!("/divider") view=DividerMdPage/>
<Route path=path!("/drawer") view=DrawerMdPage/>
<Route path=path!("/field") view=FieldMdPage/>
<Route path=path!("/menu") view=MenuMdPage/>
<Route path=path!("/grid") view=GridMdPage/>
<Route path=path!("/icon") view=IconMdPage/>
@ -89,9 +90,9 @@ fn TheRouter() -> impl IntoView {
<Route path=path!("/nav") view=NavMdPage/>
<Route path=path!("/pagination") view=PaginationMdPage/>
<Route path=path!("/popover") view=PopoverMdPage/>
<Route path=path!("/progress-bar") view=ProgressBarMdPage/>
</ParentRoute>
<ParentRoute path=path!("/components") view=ComponentsPage>
<Route path=path!("/progress-bar") view=ProgressBarMdPage/>
<Route path=path!("/radio") view=RadioMdPage/>
<Route path=path!("/scrollbar") view=ScrollbarMdPage/>
<Route path=path!("/skeleton") view=SkeletonMdPage/>
@ -107,9 +108,9 @@ fn TheRouter() -> impl IntoView {
<Route path=path!("/textarea") view=TextareaMdPage/>
<Route path=path!("/time-picker") view=TimePickerMdPage/>
<Route path=path!("/toast") view=ToastMdPage />
<Route path=path!("/tooltip") view=TooltipMdPage />
</ParentRoute>
<ParentRoute path=path!("/components") view=ComponentsPage>
<Route path=path!("/tooltip") view=TooltipMdPage />
<Route path=path!("/upload") view=UploadMdPage/>
</ParentRoute>
</Routes>

View file

@ -196,6 +196,10 @@ pub(crate) fn gen_nav_data() -> Vec<NavGroupOption> {
value: "/components/drawer",
label: "Drawer",
},
NavItemOption {
value: "/components/field",
label: "Field",
},
NavItemOption {
value: "/components/grid",
label: "Grid",

View file

@ -24,7 +24,6 @@ pub fn include_md(_token_stream: proc_macro::TokenStream) -> proc_macro::TokenSt
"InstallationMdPage" => "../docs/_guide/installation.md",
"ServerSiderRenderingMdPage" => "../docs/_guide/server_sider_rendering.md",
"AccordionMdPage" => "../../thaw/src/accordion/docs/mod.md",
// "AlertMdPage" => "../docs/alert/mod.md",
"AnchorMdPage" => "../../thaw/src/anchor/docs/mod.md",
"AutoCompleteMdPage" => "../../thaw/src/auto_complete/docs/mod.md",
"AvatarMdPage" => "../../thaw/src/avatar/docs/mod.md",
@ -42,6 +41,7 @@ pub fn include_md(_token_stream: proc_macro::TokenStream) -> proc_macro::TokenSt
"DialogMdPage" => "../../thaw/src/dialog/docs/mod.md",
"DividerMdPage" => "../../thaw/src/divider/docs/mod.md",
"DrawerMdPage" => "../../thaw/src/drawer/docs/mod.md",
"FieldMdPage" => "../../thaw/src/field/docs/mod.md",
"GridMdPage" => "../../thaw/src/grid/docs/mod.md",
"IconMdPage" => "../../thaw/src/icon/docs/mod.md",
"ImageMdPage" => "../../thaw/src/image/docs/mod.md",

View file

@ -0,0 +1,22 @@
# Field
```rust demo
view! {
<Field label="Example field">
<Input />
</Field>
}
```
### Horizontal Orientation
```rust demo
view! {
<Field
label="Horizontal"
orientation=FieldOrientation::Horizontal
>
<Input />
</Field>
}
```

28
thaw/src/field/field.css Normal file
View file

@ -0,0 +1,28 @@
.thaw-field {
display: grid;
}
.thaw-field__label {
margin-bottom: var(--spacingVerticalXXS);
padding-bottom: var(--spacingVerticalXXS);
padding-top: var(--spacingVerticalXXS);
line-height: var(--lineHeightBase300);
font-size: var(--fontSizeBase300);
font-family: var(--fontFamilyBase);
color: var(--colorNeutralForeground1);
}
.thaw-field--horizontal {
grid-template-columns: 33% 1fr;
grid-template-rows: auto auto auto 1fr;
}
.thaw-field--horizontal > .thaw-field__label {
grid-row-end: -1;
grid-row-start: 1;
margin-bottom: 0;
margin-right: var(--spacingHorizontalM);
padding-bottom: var(--spacingVerticalSNudge);
padding-top: var(--spacingVerticalSNudge);
}

65
thaw/src/field/field.rs Normal file
View file

@ -0,0 +1,65 @@
use leptos::{context::Provider, prelude::*};
use thaw_components::OptionComp;
use thaw_utils::{class_list, mount_style};
use uuid::Uuid;
#[component]
pub fn Field(
#[prop(optional, into)] class: MaybeProp<String>,
#[prop(optional, into)] label: MaybeProp<String>,
#[prop(optional, into)] name: MaybeProp<String>,
#[prop(optional, into)] orientation: MaybeSignal<FieldOrientation>,
children: Children,
) -> impl IntoView {
mount_style("field", include_str!("./field.css"));
let id = StoredValue::new(Uuid::new_v4().to_string());
view! {
<div class=class_list![
"thaw-field",
move || {
format!("thaw-field--{}", orientation.get().as_str())
},
class
]>
{move || {
view! {
<OptionComp value=label.get() let:label>
<label class="thaw-field__label" for=id.get_value()>
{label}
</label>
</OptionComp>
}
}}
<Provider value=FieldInjection { id, name }>{children()}</Provider>
</div>
}
}
#[derive(Clone)]
pub(crate) struct FieldInjection {
id: StoredValue<String>,
name: MaybeProp<String>,
}
impl FieldInjection {
pub fn expect_context() -> Self {
expect_context()
}
}
#[derive(Debug, Default, Clone)]
pub enum FieldOrientation {
Horizontal,
#[default]
Vertical,
}
impl FieldOrientation {
pub fn as_str(&self) -> &'static str {
match self {
Self::Horizontal => "horizontal",
Self::Vertical => "vertical",
}
}
}

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

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

View file

@ -18,6 +18,7 @@ mod date_picker;
mod dialog;
mod divider;
mod drawer;
mod field;
mod grid;
mod icon;
mod image;
@ -68,6 +69,7 @@ pub use date_picker::*;
pub use dialog::*;
pub use divider::*;
pub use drawer::*;
pub use field::*;
pub use grid::*;
pub use icon::*;
pub use image::*;

View file

@ -47,6 +47,7 @@ pub struct CommonTheme {
pub spacing_horizontal_l: String,
pub spacing_horizontal_x_x_l: String,
pub spacing_vertical_none: String,
pub spacing_vertical_x_x_s: String,
pub spacing_vertical_x_s: String,
pub spacing_vertical_s_nudge: String,
pub spacing_vertical_s: String,
@ -113,6 +114,7 @@ impl CommonTheme {
spacing_horizontal_l: "16px".into(),
spacing_horizontal_x_x_l: "24px".into(),
spacing_vertical_none: "0".into(),
spacing_vertical_x_x_s: "2px".into(),
spacing_vertical_x_s: "4px".into(),
spacing_vertical_s_nudge: "6px".into(),
spacing_vertical_s: "8px".into(),