Skip to content

Commit ce43b33

Browse files
geoffreygarrettDanielleHuisman
authored andcommitted
Update Accessible Icon to Leptos 0.7
1 parent 991b165 commit ce43b33

File tree

4 files changed

+125
-63
lines changed

4 files changed

+125
-63
lines changed

book/src/primitives/utilities/accessible-icon.md

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,72 +4,129 @@ Makes icons accessible by adding a label.
44

55
## Features
66

7-
- Quickly make any icon accessible by wrapping it and providing a meaningful label.
8-
- No visual difference, but announced correctly by screen readers.
7+
- Quickly make any icon accessible by wrapping it and providing a meaningful label.
8+
- No visual difference, but announced correctly by screen readers.
99

1010
## Installation
1111

12-
Install the component from your command line.
13-
1412
{{#tabs global="framework" }}
1513
{{#tab name="Leptos" }}
1614

1715
```shell
1816
cargo add radix-leptos-accessible-icon
1917
```
2018

21-
- [View on crates.io](https://crates.io/crates/radix-leptos-accessible-icon)
22-
- [View on docs.rs](https://docs.rs/radix-leptos-accessible-icon/latest/radix_leptos_accessible_icon/)
23-
- [View source](https://github.com/RustForWeb/radix/tree/main/packages/primitives/leptos/accessible-icon)
19+
- [View on crates.io](https://crates.io/crates/radix-leptos-accessible-icon)
20+
- [View on docs.rs](https://docs.rs/radix-leptos-accessible-icon/latest/radix_leptos_accessible_icon/)
21+
- [View source](https://github.com/RustForWeb/radix/tree/main/packages/primitives/leptos/accessible-icon)
22+
23+
{{#endtab }}
24+
{{#tab name="Yew" }}
25+
26+
```shell
27+
# TODO: Implement an official Yew crate for accessible icons if missing
28+
# cargo add radix-yew-accessible-icon (when available)
29+
```
30+
31+
- TODO: Provide crates.io, docs.rs, and source links when available.
2432

2533
{{#endtab }}
2634
{{#endtabs }}
2735

2836
## Anatomy
2937

30-
Import the component.
31-
3238
{{#tabs global="framework" }}
3339
{{#tab name="Leptos" }}
3440

3541
```rust,ignore
3642
use leptos::*;
37-
use radix_leptos_accessible_icon::*;
43+
use radix_leptos_accessible_icon::primitive as AccessibleIcon;
3844
3945
#[component]
4046
fn Anatomy() -> impl IntoView {
4147
view! {
42-
<AccessibleIcon />
48+
<AccessibleIcon::Root label="Close">
49+
// Your icon element here (e.g., <svg>)
50+
// aria-hidden="true", focusable="false" are applied automatically
51+
<svg viewBox="0 0 24 24">
52+
// path definitions...
53+
</svg>
54+
</AccessibleIcon::Root>
4355
}
4456
}
4557
```
4658

59+
{{#endtab }}
60+
{{#tab name="Yew" }}
61+
62+
```rust,ignore
63+
// TODO: Provide a Yew example when the crate is available or supported
64+
use yew::prelude::*;
65+
66+
// Possibly something like this in the future:
67+
// use radix_yew_accessible_icon::primitive as AccessibleIcon;
68+
```
69+
4770
{{#endtab }}
4871
{{#endtabs }}
4972

5073
## API Reference
5174

5275
### Root
5376

54-
Contains the icon to make accessible.
77+
Contains the icon you want to make accessible.
5578

5679
{{#tabs global="framework" }}
5780
{{#tab name="Leptos" }}
5881

59-
| Prop | Type | Default |
60-
| ------- | ---------------- | ------- |
61-
| `label` | `Signal<String>` | - |
82+
| Prop | Type | Default | Description |
83+
|------------|------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------|
84+
| `label` | `MaybeProp<String>` || The accessible label for the icon. It will be visually hidden but announced to screen readers. |
85+
| `children` | `TypedChildren<impl IntoView + 'static>` || Your icon (SVG or similar). Extra attributes like `aria-hidden="true"` and `focusable="false"` are automatically applied. |
86+
87+
{{#endtab }}
88+
{{#tab name="Yew" }}
89+
90+
| Prop | Type | Default | Description |
91+
|-------|------|---------|-----------------------|
92+
| label | TODO | - | TODO for Yew support. |
93+
| child | TODO | - | TODO for Yew support. |
6294

6395
{{#endtab }}
6496
{{#endtabs }}
6597

6698
## Accessibility
6799

68-
Most icons or icon systems come with no accessibility built-in. For example, the same visual **cross** icon may in fact mean **"close"** or **"delete"**.
69-
This component lets you give meaning to icons used throughout your app.
100+
Most icons or icon systems come with no accessibility built-in. For example, the same visual **cross** icon might mean *
101+
*"close"** or **"delete"**. By wrapping your icon in `<AccessibleIcon::Root>` (Leptos/Yew), you provide a meaningful
102+
label that screen readers will announce, while the icon itself is hidden from assistive technology via
103+
`aria-hidden="true"`.
104+
105+
This is built with [Visually Hidden](../utilities/visually-hidden) so labels are hidden visually but still accessible to
106+
screen readers.
107+
108+
## Example (Leptos)
109+
110+
```rust,ignore
111+
use leptos::prelude::*;
112+
use radix_leptos_visually_hidden::primitive as VisuallyHidden;
113+
use radix_leptos_accessible_icon::primitive as AccessibleIcon;
114+
115+
#[component]
116+
fn CloseIcon() -> impl IntoView {
117+
view! {
118+
<AccessibleIcon::Root label="Close">
119+
<svg width="24" height="24" viewBox="0 0 24 24">
120+
<path d="M6 6 L18 18 M6 18 L18 6" stroke="currentColor" stroke-width="2" />
121+
</svg>
122+
</AccessibleIcon::Root>
123+
}
124+
}
125+
```
70126

71-
This is built with [Visually Hidden](./visually-hidden.md).
127+
> **Yew**: TODO – Provide a working example if/when the Yew version is complete.
72128
73129
## See Also
74130

75-
- [Radix documentation](https://www.radix-ui.com/primitives/docs/utilities/accessible-icon)
131+
- [Radix UI Accessible Icon documentation](https://www.radix-ui.com/primitives/docs/utilities/accessible-icon)
132+
- [Repository and more examples](https://github.com/RustForWeb/radix)

packages/primitives/leptos/accessible-icon/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
name = "radix-leptos-accessible-icon"
33
description = "Leptos port of Radix Accessible Icon."
44
homepage = "https://radix.rustforweb.org/primitives/utilities/accessible-icon.html"
5-
65
authors.workspace = true
76
edition.workspace = true
87
license.workspace = true
@@ -11,4 +10,4 @@ version.workspace = true
1110

1211
[dependencies]
1312
leptos.workspace = true
14-
radix-leptos-visually-hidden = { path = "../visually-hidden", version = "0.0.2" }
13+
radix-leptos-visually-hidden.workspace = true
Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,45 @@
1-
use leptos::{
2-
attr::{
3-
AriaHidden, Attr, NextAttribute, aria_hidden,
4-
custom::{CustomAttr, custom_attribute},
5-
},
6-
prelude::*,
7-
};
8-
use radix_leptos_visually_hidden::VisuallyHidden;
1+
use leptos::attr::{aria_hidden, custom::custom_attribute};
2+
use leptos::prelude::*;
3+
use radix_leptos_visually_hidden::primitive as VisuallyHidden;
94

10-
pub type AccessibleIconAttrs = (
11-
Attr<AriaHidden, &'static str>,
12-
CustomAttr<&'static str, &'static str>,
13-
);
5+
/* -------------------------------------------------------------------------------------------------
6+
* AccessibleIcon
7+
* -----------------------------------------------------------------------------------------------*/
148

15-
pub fn use_accessible_icon() -> AccessibleIconAttrs {
16-
aria_hidden("true").add_any_attr(custom_attribute("focusable", "false"))
17-
}
9+
#[allow(unused)]
10+
const NAME: &str = "AccessibleIcon";
1811

12+
/// A minimal port of Radix UI’s AccessibleIcon to Leptos.
13+
///
14+
/// - Uses [`TypedChildren`](leptos::prelude::TypedChildren) so attributes can pass through via `add_any_attr`,
15+
/// since `ChildrenFragment` and `AnyView` don’t support this in Leptos 0.7.3.
16+
/// - Applies `aria-hidden="true"` and `focusable="false"` to hide the icon from screen readers (the label is announced).
17+
/// - Does not enforce a single child or clone/modify SVGs like React’s `cloneElement`.
1918
#[component]
20-
pub fn AccessibleIcon<R, IV>(
21-
/// The accessible label for the icon. This label will be visually hidden but announced to screen reader users,
22-
/// similar to `alt` text for `img` tags.
23-
#[prop(into)]
24-
label: Signal<String>,
25-
render: R,
26-
) -> impl IntoView
27-
where
28-
R: Fn(AccessibleIconAttrs) -> IV,
29-
IV: IntoView,
30-
{
31-
let attrs = use_accessible_icon();
32-
19+
#[allow(non_snake_case)]
20+
pub fn AccessibleIcon(
21+
children: TypedChildren<impl IntoView + 'static>,
22+
/// A label announced by screen readers, hidden visually.
23+
#[prop(into, optional)] label: MaybeProp<String>,
24+
) -> impl IntoView {
25+
let label = Signal::derive(move || label.get());
3326
view! {
34-
{render(attrs)}
35-
<VisuallyHidden>{label}</VisuallyHidden>
27+
<>
28+
{children
29+
.into_inner()()
30+
.add_any_attr(aria_hidden("true"))
31+
.add_any_attr(custom_attribute("focusable", "false"))}
32+
<Show when=move || label.get().is_some()>
33+
<VisuallyHidden::Root>{label.get().unwrap_or_default()}</VisuallyHidden::Root>
34+
</Show>
35+
</>
3636
}
3737
}
38+
39+
40+
/* -----------------------------------------------------------------------------------------------*/
41+
42+
pub mod primitive {
43+
pub use super::*;
44+
pub use AccessibleIcon as Root;
45+
}

stories/leptos/src/primitives/accessible_icon.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
use leptos::prelude::*;
2-
use radix_leptos_accessible_icon::*;
2+
use radix_leptos_accessible_icon::primitive as AccessibleIcon;
33

44
#[component]
55
pub fn Styled() -> impl IntoView {
66
view! {
7-
<button type="button">
8-
<AccessibleIcon
7+
<button r#type="button">
8+
<AccessibleIcon::Root
99
label="Close"
10-
render=|attrs| view! {
11-
<CrossIcon {..attrs} />
12-
}
13-
/>
10+
>
11+
<CrossIcon />
12+
</AccessibleIcon::Root>
1413
</button>
1514
}
1615
}
@@ -20,12 +19,11 @@ pub fn Chromatic() -> impl IntoView {
2019
view! {
2120
<p>
2221
Some text with an inline accessible icon{" "}
23-
<AccessibleIcon
22+
<AccessibleIcon::Root
2423
label="Close"
25-
render=|attrs| view! {
26-
<CrossIcon {..attrs} attr:class="inline-block" />
27-
}
28-
/>
24+
>
25+
<CrossIcon attr:class="inline-block" />
26+
</AccessibleIcon::Root>
2927
</p>
3028
}
3129
}

0 commit comments

Comments
 (0)