Skip to content

Commit

Permalink
Add accessible icon
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielleHuisman committed Jul 6, 2024
1 parent 7572dca commit 4821f13
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 1 deletion.
13 changes: 13 additions & 0 deletions packages/primitives/leptos/accessible-icon/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" }
13 changes: 13 additions & 0 deletions packages/primitives/leptos/accessible-icon/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<p align="center">
<a href="../../../../logo.svg" alt="Rust Radix logo">
<img src="../../../../logo.svg" width="300" height="200">
</a>
</p>

<h1 align="center">radix-leptos-accessible-icon</h1>

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).
36 changes: 36 additions & 0 deletions packages/primitives/leptos/accessible-icon/src/accessible_icon.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
#[prop(optional)] children: Option<ChildrenFn>,
) -> impl IntoView {
let label = Signal::derive(move || label.get());

view! {
{children.map(|children| map_children(children().as_children()))}
<VisuallyHidden>{label}</VisuallyHidden>
}
}

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()
}
11 changes: 11 additions & 0 deletions packages/primitives/leptos/accessible-icon/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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 <https://www.radix-ui.com/primitives/docs/utilities/accessible-icon> 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::*;
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub fn VisuallyHidden(
// TODO: replace with style:<name> 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()
)]);

Expand Down
1 change: 1 addition & 0 deletions stories/leptos/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
14 changes: 13 additions & 1 deletion stories/leptos/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -21,6 +22,14 @@ pub fn App() -> impl IntoView {
<li>
<A href="/">Index</A>
</li>
<li>
Accessible Icon

<ul class="ms-4">
<li><A href="/accessible-icon/styled">Styled</A></li>
<li><A href="/accessible-icon/chromatic">Chromatic</A></li>
</ul>
</li>
<li>
Arrow

Expand Down Expand Up @@ -104,6 +113,9 @@ pub fn App() -> impl IntoView {
<Routes>
<Route path="/" view=Index />

<Route path="/accessible-icon/styled" view=accessible_icon::Styled />
<Route path="/accessible-icon/chromatic" view=accessible_icon::Chromatic />

<Route path="/arrow/styled" view=arrow::Styled />
<Route path="/arrow/custom-sizes" view=arrow::CustomSizes />
<Route path="/arrow/custom-arrow" view=arrow::CustomArrow />
Expand Down
1 change: 1 addition & 0 deletions stories/leptos/src/primitives.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod accessible_icon;
pub mod arrow;
pub mod avatar;
pub mod collection;
Expand Down
35 changes: 35 additions & 0 deletions stories/leptos/src/primitives/accessible_icon.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use leptos::*;
use radix_leptos_accessible_icon::*;

#[component]
pub fn Styled() -> impl IntoView {
view! {
<button type="button">
<AccessibleIcon label="Close">
<CrossIcon />
</AccessibleIcon>
</button>
}
}

#[component]
pub fn Chromatic() -> impl IntoView {
view! {
<p>
Some text with an inline accessible icon{" "}
<AccessibleIcon label="Close">
<CrossIcon attr:class="inline-block" />
</AccessibleIcon>
</p>
}
}

#[component]
fn CrossIcon(#[prop(attrs)] attrs: Vec<(&'static str, Attribute)>) -> impl IntoView {
view! {
<svg viewBox="0 0 32 32" width=24 height=24 fill="none" stroke="currentColor">
<path d="M2 30 L30 2 M30 30 L2 2" />
</svg>
}
.attrs(attrs)
}

0 comments on commit 4821f13

Please sign in to comment.