|
1 | | -use leptos::prelude::*; |
2 | | -use leptos_style::Style; |
| 1 | +use leptos::{html, prelude::*}; |
| 2 | +use leptos_node_ref::AnyNodeRef; |
| 3 | +use radix_leptos_primitive::Primitive; |
3 | 4 |
|
4 | | -pub struct UseVisuallyHiddenProps { |
5 | | - style: Style, |
6 | | -} |
7 | | - |
8 | | -pub struct UseVisuallyHiddenAttrs { |
9 | | - style: Style, |
10 | | -} |
11 | | - |
12 | | -pub fn use_visually_hidden(props: UseVisuallyHiddenProps) -> UseVisuallyHiddenAttrs { |
13 | | - UseVisuallyHiddenAttrs { |
14 | | - style: props.style.with_defaults([ |
15 | | - // See: https://github.com/twbs/bootstrap/blob/master/scss/mixins/_screen-reader.scss |
16 | | - ("position", "absolute"), |
17 | | - ("border", "0px"), |
18 | | - ("width", "1px"), |
19 | | - ("height", "1px"), |
20 | | - ("padding", "0px"), |
21 | | - ("margin", "-1px"), |
22 | | - ("overflow", "hidden"), |
23 | | - ("clip", "rect(0, 0, 0, 0)"), |
24 | | - ("white-space", "nowrap"), |
25 | | - ("word-wrap", "normal"), |
26 | | - ]), |
27 | | - } |
28 | | -} |
| 5 | +/* ------------------------------------------------------------------------------------------------- |
| 6 | + * VisuallyHidden |
| 7 | + * -----------------------------------------------------------------------------------------------*/ |
29 | 8 |
|
| 9 | +/// A component that visually hides its children while keeping them accessible |
| 10 | +/// to screen reader users. Matches the React `VisuallyHidden` component’s |
| 11 | +/// default styles and behavior. |
30 | 12 | #[component] |
| 13 | +#[allow(non_snake_case)] |
31 | 14 | pub fn VisuallyHidden( |
32 | | - #[prop(into, optional)] style: Style, |
33 | | - #[prop(optional)] children: Option<Children>, |
34 | | -) -> impl IntoView { |
35 | | - let UseVisuallyHiddenAttrs { style } = use_visually_hidden(UseVisuallyHiddenProps { style }); |
| 15 | + /// The content to be visually hidden but still accessible to screen readers. |
| 16 | + children: TypedChildrenFn<impl IntoView + 'static>, |
| 17 | + |
| 18 | + /// If `true`, the `Primitive` is rendered as the child element rather than wrapped. |
| 19 | + #[prop(into, optional)] |
| 20 | + as_child: MaybeProp<bool>, |
36 | 21 |
|
| 22 | + /// A reference to the underlying DOM node. |
| 23 | + #[prop(into, optional)] |
| 24 | + node_ref: AnyNodeRef, |
| 25 | +) -> impl IntoView { |
| 26 | + // See: https://github.com/twbs/bootstrap/blob/main/scss/mixins/_visually-hidden.scss |
37 | 27 | view! { |
38 | | - <span style=style> |
39 | | - {children.map(|children| children())} |
40 | | - </span> |
| 28 | + <Primitive |
| 29 | + element=html::span |
| 30 | + children=children |
| 31 | + as_child=as_child |
| 32 | + node_ref=node_ref |
| 33 | + |
| 34 | + // visually hide this content but keep it available to assistive tech |
| 35 | + style:position="absolute" |
| 36 | + style:border="0px" |
| 37 | + style:width="1px" |
| 38 | + style:height="1px" |
| 39 | + style:padding="0px" |
| 40 | + style:margin="-1px" |
| 41 | + style:overflow="hidden" |
| 42 | + style:clip="rect(0, 0, 0, 0)" |
| 43 | + style:white-space="nowrap" |
| 44 | + style:word-wrap="normal" |
| 45 | + /> |
41 | 46 | } |
42 | 47 | } |
43 | 48 |
|
44 | | -#[component] |
45 | | -pub fn VisuallyHiddenAsChild<R, RV>( |
46 | | - #[prop(into, optional)] style: Style, |
47 | | - render: R, |
48 | | -) -> impl IntoView |
49 | | -where |
50 | | - R: Fn(UseVisuallyHiddenAttrs) -> RV, |
51 | | - RV: IntoView, |
52 | | -{ |
53 | | - let attrs = use_visually_hidden(UseVisuallyHiddenProps { style }); |
| 49 | +/* -----------------------------------------------------------------------------------------------*/ |
54 | 50 |
|
55 | | - render(attrs) |
| 51 | +pub mod primitive { |
| 52 | + pub use super::*; |
| 53 | + pub use VisuallyHidden as Root; |
56 | 54 | } |
0 commit comments