feat: allow arbitrary attributes for <A/> component (#1953)

This commit is contained in:
koopa 2023-10-27 21:30:30 +02:00 committed by GitHub
parent 3394e316b7
commit a11c6303e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -96,6 +96,10 @@ pub fn A<H>(
/// Sets the `id` attribute on the underlying `<a>` tag, making it easier to target.
#[prop(optional, into)]
id: Option<Oco<'static, str>>,
/// Arbitrary attributes to add to the `<a>`. Attributes can be added with the
/// `attr:` syntax in the `view` macro.
#[prop(attrs)]
attributes: Vec<(&'static str, Attribute)>,
/// The nodes or elements to be shown inside the link.
children: Children,
) -> impl IntoView
@ -115,6 +119,7 @@ where
class: Option<AttributeValue>,
#[allow(unused)] active_class: Option<Oco<'static, str>>,
id: Option<Oco<'static, str>>,
#[allow(unused)] attributes: Vec<(&'static str, Attribute)>,
children: Children,
) -> View {
#[cfg(not(any(feature = "hydrate", feature = "csr")))]
@ -147,9 +152,12 @@ where
#[cfg(feature = "ssr")]
{
// if we have `active_class`, the SSR optimization doesn't play nicely
// if we have `active_class` or arbitrary attributes,
// the SSR optimization doesn't play nicely
// so we use the builder instead
if let Some(active_class) = active_class {
let needs_builder =
active_class.is_some() || !attributes.is_empty();
if needs_builder {
let mut a = leptos::html::a()
.attr("href", move || href.get().unwrap_or_default())
.attr("target", target)
@ -165,11 +173,22 @@ where
class.map(|class| class.into_attribute_boxed()),
);
for class_name in active_class.split_ascii_whitespace() {
a = a.class(class_name.to_string(), move || is_active.get())
if let Some(active_class) = active_class {
for class_name in active_class.split_ascii_whitespace()
{
a = a.class(class_name.to_string(), move || {
is_active.get()
})
}
}
a.attr("id", id).child(children()).into_view()
a = a.attr("id", id).child(children());
for (attr_name, attr_value) in attributes {
a = a.attr(attr_name, attr_value);
}
a
}
// but keep the nice SSR optimization in most cases
else {
@ -184,37 +203,39 @@ where
{children()}
</a>
}
.into_view()
}
.into_view()
}
// the non-SSR version doesn't need the SSR optimizations
// DRY here to avoid WASM binary size bloat
#[cfg(not(feature = "ssr"))]
{
let a = view! {
let mut a = view! {
<a
href=move || href.get().unwrap_or_default()
target=target
prop:state={state.map(|s| s.to_js_value())}
prop:replace={replace}
aria-current=move || if is_active.get() { Some("page") } else { None }
prop:state=state.map(|s| s.to_js_value())
prop:replace=replace
aria-current=move || if is_active.get() { Some("a") } else { None }
class=class
id=id
>
{children()}
</a>
};
if let Some(active_class) = active_class {
let mut a = a;
for class_name in active_class.split_ascii_whitespace() {
a = a.class(class_name.to_string(), move || is_active.get())
}
a
} else {
a
}
.into_view()
for (attr_name, attr_value) in attributes {
a = a.attr(attr_name, attr_value);
}
a.into_view()
}
}
@ -228,6 +249,7 @@ where
class,
active_class,
id,
attributes,
children,
)
}