mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-22 14:09:21 -05:00
feat: adds Link component
This commit is contained in:
parent
7b29f7da37
commit
5879a2df86
10 changed files with 244 additions and 6 deletions
|
@ -86,13 +86,14 @@ fn TheRouter() -> impl IntoView {
|
|||
<Route path=path!("/image") view=ImageMdPage/>
|
||||
<Route path=path!("/input") view=InputMdPage/>
|
||||
<Route path=path!("/layout") view=LayoutMdPage/>
|
||||
<Route path=path!("/link") view=LinkMdPage/>
|
||||
<Route path=path!("/loading-bar") view=LoadingBarMdPage/>
|
||||
<Route path=path!("/message-bar") view=MessageBarMdPage/>
|
||||
<Route path=path!("/nav") view=NavMdPage/>
|
||||
<Route path=path!("/pagination") view=PaginationMdPage/>
|
||||
<Route path=path!("/popover") view=PopoverMdPage/>
|
||||
}.into_inner()}
|
||||
{view!{
|
||||
<Route path=path!("/pagination") view=PaginationMdPage/>
|
||||
<Route path=path!("/popover") view=PopoverMdPage/>
|
||||
<Route path=path!("/progress-bar") view=ProgressBarMdPage/>
|
||||
<Route path=path!("/radio") view=RadioMdPage/>
|
||||
<Route path=path!("/scrollbar") view=ScrollbarMdPage/>
|
||||
|
@ -107,10 +108,10 @@ fn TheRouter() -> impl IntoView {
|
|||
<Route path=path!("/tag") view=TagMdPage/>
|
||||
<Route path=path!("/text") view=TextMdPage/>
|
||||
<Route path=path!("/textarea") view=TextareaMdPage/>
|
||||
<Route path=path!("/time-picker") view=TimePickerMdPage/>
|
||||
<Route path=path!("/toast") view=ToastMdPage />
|
||||
}.into_inner()}
|
||||
{view!{
|
||||
<Route path=path!("/time-picker") view=TimePickerMdPage/>
|
||||
<Route path=path!("/toast") view=ToastMdPage />
|
||||
<Route path=path!("/tooltip") view=TooltipMdPage />
|
||||
<Route path=path!("/upload") view=UploadMdPage/>
|
||||
}.into_inner()}
|
||||
|
|
|
@ -220,6 +220,10 @@ pub(crate) fn gen_nav_data() -> Vec<NavGroupOption> {
|
|||
value: "/components/layout",
|
||||
label: "Layout",
|
||||
},
|
||||
NavItemOption {
|
||||
value: "/components/link",
|
||||
label: "Link",
|
||||
},
|
||||
NavItemOption {
|
||||
value: "/components/loading-bar",
|
||||
label: "Loading Bar",
|
||||
|
|
|
@ -47,6 +47,7 @@ pub fn include_md(_token_stream: proc_macro::TokenStream) -> proc_macro::TokenSt
|
|||
"ImageMdPage" => "../../thaw/src/image/docs/mod.md",
|
||||
"InputMdPage" => "../../thaw/src/input/docs/mod.md",
|
||||
"LayoutMdPage" => "../../thaw/src/layout/docs/mod.md",
|
||||
"LinkMdPage" => "../../thaw/src/link/docs/mod.md",
|
||||
"LoadingBarMdPage" => "../../thaw/src/loading_bar/docs/mod.md",
|
||||
"MenuMdPage" => "../../thaw/src/menu/docs/mod.md",
|
||||
"MessageBarMdPage" => "../../thaw/src/message_bar/docs/mod.md",
|
||||
|
|
|
@ -160,9 +160,9 @@ fn iter_nodes<'a>(
|
|||
let NodeLink { url, title } = node_link;
|
||||
|
||||
quote!(
|
||||
<a href=#url title=#title>
|
||||
<Link href=#url attr:title=#title>
|
||||
#(#children)*
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
NodeValue::Image(_) => quote!("Image todo!!!"),
|
||||
|
|
|
@ -24,6 +24,7 @@ mod icon;
|
|||
mod image;
|
||||
mod input;
|
||||
mod layout;
|
||||
mod link;
|
||||
mod loading_bar;
|
||||
mod menu;
|
||||
mod message_bar;
|
||||
|
@ -75,6 +76,7 @@ pub use icon::*;
|
|||
pub use image::*;
|
||||
pub use input::*;
|
||||
pub use layout::*;
|
||||
pub use link::*;
|
||||
pub use loading_bar::*;
|
||||
pub use menu::*;
|
||||
pub use message_bar::*;
|
||||
|
|
79
thaw/src/link/docs/mod.md
Normal file
79
thaw/src/link/docs/mod.md
Normal file
|
@ -0,0 +1,79 @@
|
|||
# Link
|
||||
|
||||
```rust demo
|
||||
view! {
|
||||
<Space>
|
||||
<Link href="http://example.com">
|
||||
"This is a link"
|
||||
</Link>
|
||||
<Link>
|
||||
"This is a link"
|
||||
</Link>
|
||||
<Link span=true>
|
||||
"This is a link"
|
||||
</Link>
|
||||
</Space>
|
||||
}
|
||||
```
|
||||
|
||||
### Inline
|
||||
|
||||
```rust demo
|
||||
view! {
|
||||
<div>
|
||||
"This is an "
|
||||
<Link href="http://example.com" inline=true>
|
||||
"inline link"
|
||||
</Link>
|
||||
" used alongside other text."
|
||||
</div>
|
||||
}
|
||||
```
|
||||
|
||||
### Disabled
|
||||
|
||||
```rust demo
|
||||
view! {
|
||||
<Space>
|
||||
<Link href="http://example.com" disabled=true>
|
||||
"This is a link"
|
||||
</Link>
|
||||
<Link disabled=true>
|
||||
"This is a link"
|
||||
</Link>
|
||||
<Link span=true disabled=true>
|
||||
"This is a link"
|
||||
</Link>
|
||||
</Space>
|
||||
}
|
||||
```
|
||||
|
||||
### Disabled Focusable
|
||||
|
||||
```rust demo
|
||||
view! {
|
||||
<Space>
|
||||
<Link href="http://example.com" disabled_focusable=true>
|
||||
"This is a link"
|
||||
</Link>
|
||||
<Link disabled_focusable=true>
|
||||
"This is a link"
|
||||
</Link>
|
||||
<Link span=true disabled_focusable=true>
|
||||
"This is a link"
|
||||
</Link>
|
||||
</Space>
|
||||
}
|
||||
```
|
||||
|
||||
### Link Props
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| class | `MaybeProp<String>` | `Default::default()` | |
|
||||
| span | `bool` | `false` | |
|
||||
| href | `Option<MaybeSignal<String>>` | `None` | |
|
||||
| inline | `MaybeSignal<bool>` | `false` | If true, changes styling when the link is being used alongside other text content. |
|
||||
| disabled | `MaybeSignal<bool>` | `false` | Whether the link is disabled. |
|
||||
| disabled_focusable | `MaybeSignal<bool>` | `false` | When set, allows the link to be focusable even when it has been disabled. |
|
||||
| children | `Children` | | |
|
69
thaw/src/link/link.css
Normal file
69
thaw/src/link/link.css
Normal file
|
@ -0,0 +1,69 @@
|
|||
.thaw-link {
|
||||
display: inline;
|
||||
background-color: transparent;
|
||||
color: var(--colorBrandForegroundLink);
|
||||
font-size: inherit;
|
||||
font-weight: var(--fontWeightRegular);
|
||||
font-family: var(--fontFamilyBase);
|
||||
text-align: left;
|
||||
overflow: inherit;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
user-select: text;
|
||||
text-overflow: inherit;
|
||||
text-decoration-thickness: var(--strokeWidthThin);
|
||||
text-decoration-line: none;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.thaw-link--disabled {
|
||||
color: var(--colorNeutralForegroundDisabled);
|
||||
}
|
||||
|
||||
button.thaw-link {
|
||||
border-style: none;
|
||||
font-size: var(--fontSizeBase300);
|
||||
}
|
||||
|
||||
span.thaw-link,
|
||||
.thaw-link--inline {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
.thaw-link:hover {
|
||||
color: var(--colorBrandForegroundLinkHover);
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
.thaw-link--disabled:hover {
|
||||
color: var(--colorNeutralForegroundDisabled);
|
||||
}
|
||||
|
||||
.thaw-link--disabled:not(span):hover {
|
||||
text-decoration-line: none;
|
||||
}
|
||||
|
||||
.thaw-link:active {
|
||||
color: var(--colorBrandForegroundLinkPressed);
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
.thaw-link--disabled:active {
|
||||
color: var(--colorNeutralForegroundDisabled);
|
||||
}
|
||||
|
||||
.thaw-link--disabled:not(span):active {
|
||||
text-decoration-line: none;
|
||||
}
|
||||
|
||||
.thaw-link:focus-visible {
|
||||
outline-style: none;
|
||||
}
|
||||
|
||||
.thaw-link:not(.thaw-link--disabled):focus-visible,
|
||||
.thaw-link--disabled-focusable:focus-visible {
|
||||
text-decoration-style: double;
|
||||
text-decoration-line: underline;
|
||||
text-decoration-color: var(--colorStrokeFocus2);
|
||||
}
|
70
thaw/src/link/link.rs
Normal file
70
thaw/src/link/link.rs
Normal file
|
@ -0,0 +1,70 @@
|
|||
use leptos::{either::EitherOf3, prelude::*};
|
||||
use thaw_utils::{class_list, mount_style};
|
||||
|
||||
#[component]
|
||||
pub fn Link(
|
||||
#[prop(optional, into)] class: MaybeProp<String>,
|
||||
#[prop(optional)] span: bool,
|
||||
/// If true, changes styling when the link is being used alongside other text content.
|
||||
#[prop(optional, into)]
|
||||
inline: MaybeSignal<bool>,
|
||||
#[prop(optional, into)] href: Option<MaybeSignal<String>>,
|
||||
/// Whether the link is disabled.
|
||||
#[prop(optional, into)]
|
||||
disabled: MaybeSignal<bool>,
|
||||
/// When set, allows the link to be focusable even when it has been disabled.
|
||||
#[prop(optional, into)]
|
||||
disabled_focusable: MaybeSignal<bool>,
|
||||
children: Children,
|
||||
) -> impl IntoView {
|
||||
mount_style("link", include_str!("./link.css"));
|
||||
|
||||
let link_disabled = Memo::new(move |_| disabled.get() || disabled_focusable.get());
|
||||
let class = class_list![
|
||||
"thaw-link",
|
||||
("thaw-link--inline", move || inline.get()),
|
||||
("thaw-link--disabled", move || link_disabled.get()),
|
||||
("thaw-link--disabled-focusable", move || link_disabled.get()),
|
||||
class
|
||||
];
|
||||
|
||||
let tabindex = Memo::new(move |_| {
|
||||
if disabled_focusable.get() {
|
||||
Some("0")
|
||||
} else if disabled.get() {
|
||||
Some("-1")
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(href) = href {
|
||||
EitherOf3::A(view! {
|
||||
<a
|
||||
role="link"
|
||||
class=class
|
||||
href=href
|
||||
tabindex=tabindex
|
||||
aria-disabled=move || link_disabled.get().then_some("true")
|
||||
>
|
||||
{children()}
|
||||
</a>
|
||||
})
|
||||
} else if span {
|
||||
EitherOf3::B(view! {
|
||||
<span class=class>
|
||||
{children()}
|
||||
</span>
|
||||
})
|
||||
} else {
|
||||
EitherOf3::C(view! {
|
||||
<button
|
||||
class=class
|
||||
disabled=move || disabled.get().then_some("")
|
||||
aria-disabled=move || link_disabled.get().then_some("true")
|
||||
>
|
||||
{children()}
|
||||
</button>
|
||||
})
|
||||
}
|
||||
}
|
3
thaw/src/link/mod.rs
Normal file
3
thaw/src/link/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
mod link;
|
||||
|
||||
pub use link::*;
|
|
@ -68,6 +68,9 @@ pub struct ColorTheme {
|
|||
pub color_brand_stroke_1: String,
|
||||
pub color_brand_stroke_2: String,
|
||||
pub color_brand_stroke_2_contrast: String,
|
||||
pub color_brand_foreground_link: String,
|
||||
pub color_brand_foreground_link_hover: String,
|
||||
pub color_brand_foreground_link_pressed: String,
|
||||
|
||||
pub color_stroke_focus_2: String,
|
||||
|
||||
|
@ -188,6 +191,9 @@ impl ColorTheme {
|
|||
color_brand_stroke_1: "#0f6cbd".into(),
|
||||
color_brand_stroke_2: "#b4d6fa".into(),
|
||||
color_brand_stroke_2_contrast: "#b4d6fa".into(),
|
||||
color_brand_foreground_link: "#115ea3".into(),
|
||||
color_brand_foreground_link_hover: "#0f548c".into(),
|
||||
color_brand_foreground_link_pressed: "#0c3b5e".into(),
|
||||
|
||||
color_stroke_focus_2: "#000000".into(),
|
||||
|
||||
|
@ -308,6 +314,9 @@ impl ColorTheme {
|
|||
color_brand_stroke_1: "#479ef5".into(),
|
||||
color_brand_stroke_2: "#0e4775".into(),
|
||||
color_brand_stroke_2_contrast: "#0e4775".into(),
|
||||
color_brand_foreground_link: "#479ef5".into(),
|
||||
color_brand_foreground_link_hover: "#62abf5".into(),
|
||||
color_brand_foreground_link_pressed: "#2886de".into(),
|
||||
|
||||
color_stroke_focus_2: "#ffffff".into(),
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue