From 4821f13ca81612c5f56e2a02077d4dfcff2aed7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABlle=20Huisman?= Date: Sat, 6 Jul 2024 16:45:36 +0200 Subject: [PATCH] Add accessible icon --- .../leptos/accessible-icon/Cargo.toml | 13 +++++++ .../leptos/accessible-icon/README.md | 13 +++++++ .../accessible-icon/src/accessible_icon.rs | 36 +++++++++++++++++++ .../leptos/accessible-icon/src/lib.rs | 11 ++++++ .../visually-hidden/src/visually_hidden.rs | 1 + stories/leptos/Cargo.toml | 1 + stories/leptos/src/app.rs | 14 +++++++- stories/leptos/src/primitives.rs | 1 + .../leptos/src/primitives/accessible_icon.rs | 35 ++++++++++++++++++ 9 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 packages/primitives/leptos/accessible-icon/Cargo.toml create mode 100644 packages/primitives/leptos/accessible-icon/README.md create mode 100644 packages/primitives/leptos/accessible-icon/src/accessible_icon.rs create mode 100644 packages/primitives/leptos/accessible-icon/src/lib.rs create mode 100644 stories/leptos/src/primitives/accessible_icon.rs diff --git a/packages/primitives/leptos/accessible-icon/Cargo.toml b/packages/primitives/leptos/accessible-icon/Cargo.toml new file mode 100644 index 00000000..fb1e2adc --- /dev/null +++ b/packages/primitives/leptos/accessible-icon/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "radix-leptos-accessible-icon" +description = "Leptos port of Radix Accessible Icon." + +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +version.workspace = true + +[dependencies] +leptos.workspace = true +radix-leptos-visually-hidden = { path = "../visually-hidden", version = "0.0.1" } diff --git a/packages/primitives/leptos/accessible-icon/README.md b/packages/primitives/leptos/accessible-icon/README.md new file mode 100644 index 00000000..fd73fe96 --- /dev/null +++ b/packages/primitives/leptos/accessible-icon/README.md @@ -0,0 +1,13 @@ +

+ + + +

+ +

radix-leptos-accessible-icon

+ +Makes icons accessible by adding a label. + +## Rust Radix + +[Rust Radix](https://github.com/RustForWeb/radix) is a Rust port of [Radix](https://www.radix-ui.com/primitives). diff --git a/packages/primitives/leptos/accessible-icon/src/accessible_icon.rs b/packages/primitives/leptos/accessible-icon/src/accessible_icon.rs new file mode 100644 index 00000000..29840caf --- /dev/null +++ b/packages/primitives/leptos/accessible-icon/src/accessible_icon.rs @@ -0,0 +1,36 @@ +use leptos::*; +use radix_leptos_visually_hidden::VisuallyHidden; + +#[component] +pub fn AccessibleIcon( + /// The accessible label for the icon. This label will be visually hidden but announced to screen reader users, + /// similar to `alt` text for `img` tags. + #[prop(into)] + label: MaybeSignal, + #[prop(optional)] children: Option, +) -> impl IntoView { + let label = Signal::derive(move || label.get()); + + view! { + {children.map(|children| map_children(children().as_children()))} + {label} + } +} + +fn map_children(children: &[View]) -> View { + children + .iter() + .map(|child| match child { + View::Element(element) => element + .clone() + .into_html_element() + // Accessibility + .attr("aria-hidden", "true") + // See: https://allyjs.io/tutorials/focusing-in-svg.html#making-svg-elements-focusable + .attr("focusable", "false") + .into_view(), + View::Component(component) => map_children(&component.children), + _ => child.into_view(), + }) + .collect_view() +} diff --git a/packages/primitives/leptos/accessible-icon/src/lib.rs b/packages/primitives/leptos/accessible-icon/src/lib.rs new file mode 100644 index 00000000..33c54fa8 --- /dev/null +++ b/packages/primitives/leptos/accessible-icon/src/lib.rs @@ -0,0 +1,11 @@ +//! Leptos port of [Radix Accessible Icon](https://www.radix-ui.com/primitives/docs/utilities/accessible-icon). +//! +//! Makes icons accessible by adding a label. +//! +//! See for the original documentation. +//! +//! See [`@radix-ui/react-accessible-icon`](https://www.npmjs.com/package/@radix-ui/react-accessible-icon) for the original package. + +mod accessible_icon; + +pub use accessible_icon::*; diff --git a/packages/primitives/leptos/visually-hidden/src/visually_hidden.rs b/packages/primitives/leptos/visually-hidden/src/visually_hidden.rs index e62f5081..7c25034d 100644 --- a/packages/primitives/leptos/visually-hidden/src/visually_hidden.rs +++ b/packages/primitives/leptos/visually-hidden/src/visually_hidden.rs @@ -11,6 +11,7 @@ pub fn VisuallyHidden( // TODO: replace with style: attributes once they work properly in Leptos (probably in 0.7?) let mut attrs = attrs.clone(); attrs.extend([ + // See: https://github.com/twbs/bootstrap/blob/master/scss/mixins/_screen-reader.scss ("style", "position: absolute; border: 0px; width: 1px; height: 1px; padding: 0px; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; word-wrap: normal;".into_attribute() )]); diff --git a/stories/leptos/Cargo.toml b/stories/leptos/Cargo.toml index 96612af9..40ce4450 100644 --- a/stories/leptos/Cargo.toml +++ b/stories/leptos/Cargo.toml @@ -15,6 +15,7 @@ console_error_panic_hook.workspace = true leptos = { workspace = true, features = ["csr"] } leptos_router = { workspace = true, features = ["csr"] } log.workspace = true +radix-leptos-accessible-icon = { path = "../../packages/primitives/leptos/accessible-icon" } radix-leptos-arrow = { path = "../../packages/primitives/leptos/arrow" } radix-leptos-avatar = { path = "../../packages/primitives/leptos/avatar" } radix-leptos-collection = { path = "../../packages/primitives/leptos/collection" } diff --git a/stories/leptos/src/app.rs b/stories/leptos/src/app.rs index f8724e2e..05774489 100644 --- a/stories/leptos/src/app.rs +++ b/stories/leptos/src/app.rs @@ -2,7 +2,8 @@ use leptos::*; use leptos_router::{Route, Router, Routes, A}; use crate::primitives::{ - arrow, avatar, collection, focus_scope, label, menu, popper, slot, visually_hidden, + accessible_icon, arrow, avatar, collection, focus_scope, label, menu, popper, slot, + visually_hidden, }; #[component] @@ -21,6 +22,14 @@ pub fn App() -> impl IntoView {
  • Index
  • +
  • + Accessible Icon + + +
  • Arrow @@ -104,6 +113,9 @@ pub fn App() -> impl IntoView { + + + diff --git a/stories/leptos/src/primitives.rs b/stories/leptos/src/primitives.rs index 0824abd6..e4d33043 100644 --- a/stories/leptos/src/primitives.rs +++ b/stories/leptos/src/primitives.rs @@ -1,3 +1,4 @@ +pub mod accessible_icon; pub mod arrow; pub mod avatar; pub mod collection; diff --git a/stories/leptos/src/primitives/accessible_icon.rs b/stories/leptos/src/primitives/accessible_icon.rs new file mode 100644 index 00000000..a0071d22 --- /dev/null +++ b/stories/leptos/src/primitives/accessible_icon.rs @@ -0,0 +1,35 @@ +use leptos::*; +use radix_leptos_accessible_icon::*; + +#[component] +pub fn Styled() -> impl IntoView { + view! { + + } +} + +#[component] +pub fn Chromatic() -> impl IntoView { + view! { +

    + Some text with an inline accessible icon{" "} + + + +

    + } +} + +#[component] +fn CrossIcon(#[prop(attrs)] attrs: Vec<(&'static str, Attribute)>) -> impl IntoView { + view! { + + + + } + .attrs(attrs) +}