refactor: breadcrumb

This commit is contained in:
luoxiao 2024-06-04 10:13:37 +08:00
parent 60f67bc56a
commit bba3f00657
7 changed files with 129 additions and 140 deletions

View file

@ -143,6 +143,10 @@ pub(crate) fn gen_menu_data() -> Vec<MenuGroupOption> {
value: "/components/avatar".into(), value: "/components/avatar".into(),
label: "Avatar".into(), label: "Avatar".into(),
}, },
MenuItemOption {
value: "/components/breadcrumb".into(),
label: "Breadcrumb".into(),
},
MenuItemOption { MenuItemOption {
value: "/components/button".into(), value: "/components/button".into(),
label: "Button".into(), label: "Button".into(),
@ -239,10 +243,6 @@ pub(crate) fn gen_menu_data() -> Vec<MenuGroupOption> {
value: "/components/back-top".into(), value: "/components/back-top".into(),
label: "Back Top".into(), label: "Back Top".into(),
}, },
MenuItemOption {
value: "/components/breadcrumb".into(),
label: "Breadcrumb".into(),
},
MenuItemOption { MenuItemOption {
value: "/components/loading-bar".into(), value: "/components/loading-bar".into(),
label: "Loading Bar".into(), label: "Loading Bar".into(),

View file

@ -3,21 +3,17 @@
```rust demo ```rust demo
view! { view! {
<Breadcrumb> <Breadcrumb>
<BreadcrumbItem>"Leptos"</BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbItem>"UI"</BreadcrumbItem> <BreadcrumbButton>"Leptos"</BreadcrumbButton>
<BreadcrumbItem>"Thaw"</BreadcrumbItem> </BreadcrumbItem>
</Breadcrumb> <BreadcrumbDivider />
} <BreadcrumbItem>
``` <BreadcrumbButton>"UI"</BreadcrumbButton>
</BreadcrumbItem>
### Separator <BreadcrumbDivider />
<BreadcrumbItem>
```rust demo <BreadcrumbButton current=true>"Thaw"</BreadcrumbButton>
view! { </BreadcrumbItem>
<Breadcrumb separator=">">
<BreadcrumbItem>"Leptos"</BreadcrumbItem>
<BreadcrumbItem>"UI"</BreadcrumbItem>
<BreadcrumbItem>"Thaw"</BreadcrumbItem>
</Breadcrumb> </Breadcrumb>
} }
``` ```

View file

@ -1,41 +1,82 @@
.thaw-breadcrumb > ul { .thaw-breadcrumb__list {
list-style: none; list-style-type: none;
padding: 0; display: flex;
margin: 0; align-items: center;
margin: 0px;
padding: 0px;
} }
.thaw-breadcrumb-item { .thaw-breadcrumb-item {
display: inline-flex; display: flex;
align-items: center; align-items: center;
color: var(--colorNeutralForeground2);
box-sizing: border-box;
flex-wrap: nowrap;
} }
.thaw-breadcrumb-item__separator { .thaw-breadcrumb-button {
margin: 0 8px; align-items: center;
color: var(--thaw-font-color); box-sizing: border-box;
display: inline-flex;
justify-content: center;
text-decoration-line: none;
vertical-align: middle;
margin: 0px;
overflow: hidden;
border: var(--strokeWidthThin) solid var(--colorNeutralStroke1);
font-family: var(--fontFamilyBase);
outline-style: none;
border-radius: var(--borderRadiusMedium);
font-size: var(--fontSizeBase300);
line-height: var(--lineHeightBase300);
transition-duration: var(--durationFaster);
transition-property: background, border, color;
transition-timing-function: var(--curveEasyEase);
flex-wrap: nowrap;
min-width: unset;
height: 32px;
color: var(--colorNeutralForeground2);
background-color: var(--colorSubtleBackground);
border-color: transparent;
font-weight: var(--fontWeightRegular);
padding: var(--spacingHorizontalSNudge);
} }
.thaw-breadcrumb .thaw-breadcrumb-button:hover {
.thaw-breadcrumb-item:last-child color: var(--colorNeutralForeground2Hover);
.thaw-breadcrumb-item__separator { background-color: var(--colorSubtleBackgroundHover);
display: none;
}
.thaw-breadcrumb-item__link {
padding: 4px;
border-radius: 3px;
transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
color: var(--thaw-font-color);
cursor: pointer; cursor: pointer;
} }
.thaw-breadcrumb .thaw-breadcrumb-button:hover:active {
.thaw-breadcrumb-item:not(:last-child) color: var(--colorNeutralForeground2Pressed);
.thaw-breadcrumb-item__link:hover { background-color: var(--colorSubtleBackgroundPressed);
color: var(--thaw-font-color-hover); outline-style: none;
background-color: var(--thaw-background-color-hover);
} }
.thaw-breadcrumb .thaw-breadcrumb-item:last-child .thaw-breadcrumb-item__link { .thaw-breadcrumb-button--current {
color: var(--thaw-font-color-hover); font-weight: var(--fontWeightSemibold);
}
.thaw-breadcrumb-button--current:hover {
color: var(--colorNeutralForeground2);
background-color: var(--colorTransparentBackground);
cursor: auto;
}
.thaw-breadcrumb-button--current:hover:active {
color: var(--colorNeutralForeground2);
background-color: var(--colorTransparentBackground);
outline-style: none;
}
.thaw-breadcrumb-divider {
font-size: 16px;
display: flex;
}
.thaw-breadcrumb-divider > svg {
display: inline;
line-height: 0;
} }

View file

@ -1,22 +0,0 @@
use super::use_breadcrumb_separator;
use leptos::*;
use thaw_utils::{class_list, OptionalProp};
#[component]
pub fn BreadcrumbItem(
#[prop(optional, into)] class: OptionalProp<MaybeSignal<String>>,
children: Children,
) -> impl IntoView {
let breadcrumb_separator = use_breadcrumb_separator();
view! {
<li class="thaw-breadcrumb-item">
<span class=class_list![
"thaw-breadcrumb-item__link", class.map(| c | move || c.get())
]>{children()}</span>
<span class="thaw-breadcrumb-item__separator">
{move || breadcrumb_separator.0.get()}
</span>
</li>
}
}

View file

@ -1,55 +1,58 @@
mod breadcrumb_item;
mod theme;
pub use theme::BreadcrumbTheme;
use crate::{use_theme, Theme};
pub use breadcrumb_item::BreadcrumbItem;
use leptos::*; use leptos::*;
use thaw_utils::{class_list, mount_style, OptionalProp}; use thaw_utils::{class_list, mount_style};
#[component] #[component]
pub fn Breadcrumb( pub fn Breadcrumb(
#[prop(default = MaybeSignal::Static("/".to_string()),into)] separator: MaybeSignal<String>, #[prop(optional, into)] class: MaybeProp<String>,
#[prop(optional, into)] class: OptionalProp<MaybeSignal<String>>,
children: Children, children: Children,
) -> impl IntoView { ) -> impl IntoView {
mount_style("breadcrumb", include_str!("./breadcrumb.css")); mount_style("breadcrumb", include_str!("./breadcrumb.css"));
let theme = use_theme(Theme::light);
let css_vars = create_memo(move |_| {
let mut css_vars = String::new();
theme.with(|theme| {
css_vars.push_str(&format!(
"--thaw-font-color: {};",
theme.breadcrumb.item_font_color
));
css_vars.push_str(&format!(
"--thaw-font-color-hover: {};",
theme.breadcrumb.item_font_color_hover
));
css_vars.push_str(&format!(
"--thaw-background-color-hover: {};",
theme.breadcrumb.item_background_color_hover
));
});
css_vars
});
view! { view! {
<Provider value=BreadcrumbSeparatorInjection(separator)>
<nav <nav
class=class_list!["thaw-breadcrumb", class.map(| c | move || c.get())] class=class_list!["thaw-breadcrumb", class]
style=move || css_vars.get()
> >
<ul>{children()}</ul> <ol role="list" class="thaw-breadcrumb__list">{children()}</ol>
</nav> </nav>
</Provider>
} }
} }
#[derive(Clone)] #[component]
pub(crate) struct BreadcrumbSeparatorInjection(MaybeSignal<String>); pub fn BreadcrumbItem(
#[prop(optional, into)] class: MaybeProp<String>,
pub(crate) fn use_breadcrumb_separator() -> BreadcrumbSeparatorInjection { children: Children,
expect_context() ) -> impl IntoView {
view! {
<li class=class_list!["thaw-breadcrumb-item", class]>
{children()}
</li>
}
}
#[component]
pub fn BreadcrumbButton(
#[prop(optional, into)] class: MaybeProp<String>,
#[prop(optional, into)] current: MaybeSignal<bool>,
children: Children,
) -> impl IntoView {
view! {
<button
class=class_list!["thaw-breadcrumb-button", ("thaw-breadcrumb-button--current", move || current.get()), class]
aria-disabled=move || current.get().then(|| "true")
aria-current=move || current.get().then(|| "page")
>
{children()}
</button>
}
}
#[component]
pub fn BreadcrumbDivider(#[prop(optional, into)] class: MaybeProp<String>) -> impl IntoView {
view! {
<li class=class_list!["thaw-breadcrumb-divider", class] aria-hidden="true">
<svg fill="currentColor" aria-hidden="true" width="1em" height="1em" viewBox="0 0 20 20">
<path d="M7.65 4.15c.2-.2.5-.2.7 0l5.49 5.46c.21.22.21.57 0 .78l-5.49 5.46a.5.5 0 0 1-.7-.7L12.8 10 7.65 4.85a.5.5 0 0 1 0-.7Z" fill="currentColor"></path>
</svg>
</li>
}
} }

View file

@ -1,26 +0,0 @@
use crate::theme::ThemeMethod;
#[derive(Clone)]
pub struct BreadcrumbTheme {
pub item_font_color: String,
pub item_font_color_hover: String,
pub item_background_color_hover: String,
}
impl ThemeMethod for BreadcrumbTheme {
fn light() -> Self {
Self {
item_font_color: "#767c82".into(),
item_font_color_hover: "#333639".into(),
item_background_color_hover: "#2e333817".into(),
}
}
fn dark() -> Self {
Self {
item_font_color: "#ffffff85".into(),
item_font_color_hover: "#ffffffd1".into(),
item_background_color_hover: "#ffffff1f".into(),
}
}
}

View file

@ -4,7 +4,7 @@ mod common;
use self::common::CommonTheme; use self::common::CommonTheme;
use crate::{ use crate::{
mobile::{NavBarTheme, TabbarTheme}, mobile::{NavBarTheme, TabbarTheme},
AlertTheme, AnchorTheme, AutoCompleteTheme, BackTopTheme, BreadcrumbTheme, CalendarTheme, AlertTheme, AnchorTheme, AutoCompleteTheme, BackTopTheme, CalendarTheme,
ColorPickerTheme, DatePickerTheme, InputTheme, MessageTheme, PopoverTheme, ProgressTheme, ColorPickerTheme, DatePickerTheme, InputTheme, MessageTheme, PopoverTheme, ProgressTheme,
ScrollbarTheme, SelectTheme, SkeletionTheme, SpinnerTheme, TableTheme, TimePickerTheme, ScrollbarTheme, SelectTheme, SkeletionTheme, SpinnerTheme, TableTheme, TimePickerTheme,
UploadTheme, UploadTheme,
@ -34,7 +34,6 @@ pub struct Theme {
pub tabbar: TabbarTheme, pub tabbar: TabbarTheme,
pub auto_complete: AutoCompleteTheme, pub auto_complete: AutoCompleteTheme,
pub color_picker: ColorPickerTheme, pub color_picker: ColorPickerTheme,
pub breadcrumb: BreadcrumbTheme,
pub progress: ProgressTheme, pub progress: ProgressTheme,
pub calendar: CalendarTheme, pub calendar: CalendarTheme,
pub time_picker: TimePickerTheme, pub time_picker: TimePickerTheme,
@ -63,7 +62,6 @@ impl Theme {
tabbar: TabbarTheme::light(), tabbar: TabbarTheme::light(),
auto_complete: AutoCompleteTheme::light(), auto_complete: AutoCompleteTheme::light(),
color_picker: ColorPickerTheme::light(), color_picker: ColorPickerTheme::light(),
breadcrumb: BreadcrumbTheme::light(),
progress: ProgressTheme::light(), progress: ProgressTheme::light(),
calendar: CalendarTheme::light(), calendar: CalendarTheme::light(),
time_picker: TimePickerTheme::light(), time_picker: TimePickerTheme::light(),
@ -91,7 +89,6 @@ impl Theme {
tabbar: TabbarTheme::dark(), tabbar: TabbarTheme::dark(),
auto_complete: AutoCompleteTheme::dark(), auto_complete: AutoCompleteTheme::dark(),
color_picker: ColorPickerTheme::dark(), color_picker: ColorPickerTheme::dark(),
breadcrumb: BreadcrumbTheme::dark(),
progress: ProgressTheme::dark(), progress: ProgressTheme::dark(),
calendar: CalendarTheme::dark(), calendar: CalendarTheme::dark(),
time_picker: TimePickerTheme::dark(), time_picker: TimePickerTheme::dark(),