mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-23 06:19:22 -05:00
refactor: breadcrumb
This commit is contained in:
parent
60f67bc56a
commit
bba3f00657
7 changed files with 129 additions and 140 deletions
|
@ -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(),
|
||||||
|
|
|
@ -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>
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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(),
|
||||||
|
|
Loading…
Add table
Reference in a new issue