demo: adaptive mobile (#68)

* demo: adaptive mobile

* fix: demo callback
This commit is contained in:
luoxiaozero 2024-01-04 23:32:58 +08:00 committed by GitHub
parent 3684f5961b
commit 5cce9afcb9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 210 additions and 64 deletions

View file

@ -10,7 +10,7 @@ edition = "2021"
leptos = { version = "0.5.4" } leptos = { version = "0.5.4" }
leptos_meta = { version = "0.5.4" } leptos_meta = { version = "0.5.4" }
leptos_router = { version = "0.5.4" } leptos_router = { version = "0.5.4" }
leptos_devtools = "0.0.1" leptos_devtools = { version = "0.0.1", optional = true}
thaw = { path = "../thaw", default-features = false } thaw = { path = "../thaw", default-features = false }
icondata = { version = "0.1.0", features = [ icondata = { version = "0.1.0", features = [
"AiCloseOutlined", "AiCloseOutlined",
@ -18,6 +18,7 @@ icondata = { version = "0.1.0", features = [
"AiGithubOutlined", "AiGithubOutlined",
"AiUserOutlined", "AiUserOutlined",
"AiSearchOutlined", "AiSearchOutlined",
"AiUnorderedListOutlined"
] } ] }
demo_markdown = { path = "../demo_markdown" } demo_markdown = { path = "../demo_markdown" }

View file

@ -1,5 +1,6 @@
use leptos::*; use leptos::*;
use leptos_router::use_navigate; use leptos_meta::Style;
use leptos_router::{use_location, use_navigate};
use thaw::*; use thaw::*;
#[component] #[component]
@ -8,23 +9,21 @@ pub fn SiteHeader() -> impl IntoView {
let theme_name = create_memo(move |_| { let theme_name = create_memo(move |_| {
theme.with(|theme| { theme.with(|theme| {
if theme.name == *"light" { if theme.name == *"light" {
"Dark" "Dark".to_string()
} else { } else {
"Light" "Light".to_string()
} }
}) })
}); });
let on_theme = move |_| { let change_theme = Callback::new(move |_| {
if theme_name.get_untracked() == "Light" { if theme_name.get_untracked() == "Light" {
theme.set(Theme::light()) theme.set(Theme::light());
} else { } else {
theme.set(Theme::dark()) theme.set(Theme::dark());
} }
}; });
let style = create_memo(move |_| { let style = create_memo(move |_| {
theme.with(|theme| { theme.with(|theme| format!("border-bottom: 1px solid {}", theme.common.border_color))
format!("height: 64px; display: flex; align-items: center; justify-content: space-between; padding: 0 20px; border-bottom: 1px solid {}", theme.common.border_color)
})
}); });
let search_value = create_rw_signal(String::new()); let search_value = create_rw_signal(String::new());
let search_all_options = store_value(gen_search_all_options()); let search_all_options = store_value(gen_search_all_options());
@ -77,18 +76,58 @@ pub fn SiteHeader() -> impl IntoView {
} }
}); });
on_cleanup(move || handle.remove()); on_cleanup(move || handle.remove());
let menu_value = use_menu_value(change_theme);
view! { view! {
<LayoutHeader style> <Style id="demo-header">
<Space> "
<img src="/thaw/logo.svg" style="width: 36px"/> .demo-header {
<div height: 64px;
style="cursor: pointer; display: flex; align-items: center; height: 100%; font-weight: 600; font-size: 20px" display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
}
.demo-name {
cursor: pointer;
display: flex;
align-items: center;
height: 100%;
font-weight: 600;
font-size: 20px;
}
.demo-header__menu-mobile {
display: none;
}
.demo-header__menu-popover-mobile {
padding: 0;
}
@media screen and (max-width: 600px) {
.demo-header {
padding: 0 8px;
}
.demo-name {
display: none;
}
}
@media screen and (max-width: 1200px) {
.demo-header__right-btn {
display: none;
}
.demo-header__menu-mobile {
display: block;
}
}
"
</Style>
<LayoutHeader class="demo-header" style>
<Space
on:click=move |_| { on:click=move |_| {
let navigate = use_navigate(); let navigate = use_navigate();
navigate("/", Default::default()); navigate("/", Default::default());
} }>
> <img src="/thaw/logo.svg" style="width: 36px"/>
<div class="demo-name">
"Thaw UI" "Thaw UI"
</div> </div>
</Space> </Space>
@ -105,6 +144,29 @@ pub fn SiteHeader() -> impl IntoView {
<Icon icon=icondata::Icon::from(icondata::AiIcon::AiSearchOutlined) style="font-size: 18px; color: var(--thaw-placeholder-color);"/> <Icon icon=icondata::Icon::from(icondata::AiIcon::AiSearchOutlined) style="font-size: 18px; color: var(--thaw-placeholder-color);"/>
</AutoCompletePrefix> </AutoCompletePrefix>
</AutoComplete> </AutoComplete>
<Popover placement=PopoverPlacement::BottomEnd class="demo-header__menu-popover-mobile">
<PopoverTrigger slot class="demo-header__menu-mobile">
<Button
variant=ButtonVariant::Text
icon=icondata::AiIcon::AiUnorderedListOutlined
style="font-size: 22px; padding: 0px 6px;"
/>
</PopoverTrigger>
<div style="height: 70vh; overflow: auto;">
<Menu value=menu_value>
<MenuItem key=theme_name label=theme_name />
<MenuItem key="github" label="Github" />
{
use crate::pages::{gen_guide_menu_data, gen_menu_data};
vec![
gen_guide_menu_data().into_view(),
gen_menu_data().into_view(),
]
}
</Menu>
</div>
</Popover>
<Space class="demo-header__right-btn">
<Button <Button
variant=ButtonVariant::Text variant=ButtonVariant::Text
on_click=move |_| { on_click=move |_| {
@ -125,7 +187,7 @@ pub fn SiteHeader() -> impl IntoView {
"Components" "Components"
</Button> </Button>
<Button variant=ButtonVariant::Text on_click=on_theme> <Button variant=ButtonVariant::Text on_click=Callback::new(move |_| change_theme.call(()))>
{move || theme_name.get()} {move || theme_name.get()}
</Button> </Button>
<Button <Button
@ -137,7 +199,7 @@ pub fn SiteHeader() -> impl IntoView {
_ = window().open_with_url("http://github.com/thaw-ui/thaw"); _ = window().open_with_url("http://github.com/thaw-ui/thaw");
} }
/> />
</Space>
</Space> </Space>
</LayoutHeader> </LayoutHeader>
@ -163,3 +225,44 @@ fn gen_search_all_options() -> Vec<AutoCompleteOption> {
})); }));
options options
} }
fn use_menu_value(change_theme: Callback<()>) -> RwSignal<String> {
use crate::pages::gen_guide_menu_data;
let guide = store_value(gen_guide_menu_data());
let navigate = use_navigate();
let loaction = use_location();
let menu_value = create_rw_signal({
let mut pathname = loaction.pathname.get_untracked();
if pathname.starts_with("/thaw/components/") {
pathname.drain(17..).collect()
} else if pathname.starts_with("/thaw/guide/") {
pathname.drain(12..).collect()
} else {
String::new()
}
});
_ = menu_value.watch(move |name| {
if name == "Dark" || name == "Light" {
change_theme.call(());
return;
} else if name == "github" {
_ = window().open_with_url("http://github.com/thaw-ui/thaw");
return;
}
let pathname = loaction.pathname.get_untracked();
if guide.with_value(|menu| {
menu.iter()
.any(|group| group.children.iter().any(|item| &item.value == name))
}) {
if !pathname.eq(&format!("/thaw/guide/{name}")) {
navigate(&format!("/guide/{name}"), Default::default());
}
} else if !pathname.eq(&format!("/thaw/components/{name}")) {
navigate(&format!("/components/{name}"), Default::default());
}
});
menu_value
}

View file

@ -1,5 +1,6 @@
use crate::components::SiteHeader; use crate::components::SiteHeader;
use leptos::*; use leptos::*;
use leptos_meta::Style;
use leptos_router::{use_location, use_navigate, Outlet}; use leptos_router::{use_location, use_navigate, Outlet};
use thaw::*; use thaw::*;
@ -26,10 +27,29 @@ pub fn ComponentsPage() -> impl IntoView {
} }
}); });
view! { view! {
<Style>
"
.demo-components__component {
width: 896px;
margin: 0 auto;
}
.demo-md-table-box {
overflow: auto;
}
@media screen and (max-width: 1200px) {
.demo-components__sider {
display: none;
}
.demo-components__component {
width: 100%;
}
}
"
</Style>
<Layout position=LayoutPosition::Absolute> <Layout position=LayoutPosition::Absolute>
<SiteHeader/> <SiteHeader/>
<Layout has_sider=true position=LayoutPosition::Absolute style="top: 64px;"> <Layout has_sider=true position=LayoutPosition::Absolute style="top: 64px;">
<LayoutSider> <LayoutSider class="demo-components__sider">
<Menu value=select_name> <Menu value=select_name>
{gen_menu_data().into_view()} {gen_menu_data().into_view()}

View file

@ -1,5 +1,6 @@
use crate::components::SiteHeader; use crate::components::SiteHeader;
use leptos::*; use leptos::*;
use leptos_meta::Style;
use leptos_router::{use_location, use_navigate, Outlet}; use leptos_router::{use_location, use_navigate, Outlet};
use thaw::*; use thaw::*;
@ -25,10 +26,29 @@ pub fn GuidePage() -> impl IntoView {
selected selected
}); });
view! { view! {
<Style>
"
.demo-components__component {
width: 896px;
margin: 0 auto;
}
.demo-md-table-box {
overflow: auto;
}
@media screen and (max-width: 1200px) {
.demo-guide__sider {
display: none;
}
.demo-components__component {
width: 100%;
}
}
"
</Style>
<Layout position=LayoutPosition::Absolute> <Layout position=LayoutPosition::Absolute>
<SiteHeader/> <SiteHeader/>
<Layout has_sider=true position=LayoutPosition::Absolute style="top: 64px;"> <Layout has_sider=true position=LayoutPosition::Absolute style="top: 64px;">
<LayoutSider> <LayoutSider class="demo-guide__sider">
<Menu value=selected> <Menu value=selected>
{gen_guide_menu_data().into_view()} {gen_guide_menu_data().into_view()}

View file

@ -124,7 +124,7 @@ pub fn include_md(_token_stream: proc_macro::TokenStream) -> proc_macro::TokenSt
#(#demos)* #(#demos)*
view! { view! {
<div style="width: 896px; margin: 0 auto;"> <div class="demo-components__component">
#body #body
</div> </div>
} }

View file

@ -83,6 +83,7 @@ fn iter_nodes<'a>(node: &'a AstNode<'a>, demos: &mut Vec<String>) -> TokenStream
let header_children: Vec<TokenStream> = children.drain(0..header_index).collect(); let header_children: Vec<TokenStream> = children.drain(0..header_index).collect();
quote!( quote!(
<div class="demo-md-table-box">
<Table single_column=true> <Table single_column=true>
<thead> <thead>
#(#header_children)* #(#header_children)*
@ -91,6 +92,7 @@ fn iter_nodes<'a>(node: &'a AstNode<'a>, demos: &mut Vec<String>) -> TokenStream
#(#children)* #(#children)*
</tbody> </tbody>
</Table> </Table>
</div>
) )
} }
NodeValue::TableRow(_) => { NodeValue::TableRow(_) => {