Skip to content

Commit 5e1a10b

Browse files
Add more role helpers
1 parent 12e227d commit 5e1a10b

1 file changed

Lines changed: 81 additions & 6 deletions

File tree

packages/dom/src/role_helpers.rs

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use aria_query::{
55
ELEMENT_ROLES,
66
};
77
use wasm_bindgen::JsCast;
8-
use web_sys::{Element, HtmlInputElement, HtmlOptionElement, Node};
8+
use web_sys::{Element, HtmlElement, HtmlInputElement, HtmlOptionElement, Node};
99

1010
use crate::types::ByRoleOptionsCurrent;
1111

@@ -100,12 +100,73 @@ static ELEMENT_ROLE_LIST: LazyLock<Vec<ElementRole>> = LazyLock::new(|| {
100100
result
101101
});
102102

103-
pub fn _is_subtree_inaccessible(_element: &Element) -> bool {
104-
todo!()
103+
pub fn is_subtree_inaccessible(element: &Element) -> bool {
104+
if element
105+
.dyn_ref::<HtmlElement>()
106+
.is_some_and(|html_element| html_element.hidden())
107+
{
108+
return true;
109+
}
110+
111+
if element.get_attribute("aria-hidden") == Some("true".into()) {
112+
return true;
113+
}
114+
115+
let window = element
116+
.owner_document()
117+
.expect("Element should have owner document.")
118+
.default_view()
119+
.expect("Owner document should have default view.");
120+
121+
if window
122+
.get_computed_style(element)
123+
.expect("Element should be valid.")
124+
.expect("Computed style should exist.")
125+
.get_property_value("display")
126+
.expect("Computed style should have display.")
127+
== "none"
128+
{
129+
return true;
130+
}
131+
132+
false
105133
}
106134

107-
pub fn is_inaccessible(_element: &Element) -> bool {
108-
todo!()
135+
// Partial implementation https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion
136+
// which should only be used for elements with a non-presentational role i.e.
137+
// `role="none"` and `role="presentation"` will not be excluded.
138+
//
139+
// Implements aria-hidden semantics (i.e. parent overrides child)
140+
// Ignores "Child Presentational: True" characteristics.
141+
pub fn is_inaccessible(element: &Element) -> bool {
142+
let window = element
143+
.owner_document()
144+
.expect("Element should have owner document.")
145+
.default_view()
146+
.expect("Owner document should have default view.");
147+
148+
// Since visibility is inherited we can exit early.
149+
if window
150+
.get_computed_style(element)
151+
.expect("Element should be valid.")
152+
.expect("Computed style should exist.")
153+
.get_property_value("visibility")
154+
.expect("Computed style should have visibility.")
155+
== "hidden"
156+
{
157+
return true;
158+
}
159+
160+
let mut current_element = Some(element.clone());
161+
while let Some(element) = current_element.as_ref() {
162+
if is_subtree_inaccessible(element) {
163+
return true;
164+
}
165+
166+
current_element = element.parent_element();
167+
}
168+
169+
false
109170
}
110171

111172
pub fn get_implicit_aria_roles(current_node: &Element) -> Vec<AriaRoleDefinitionKey> {
@@ -118,8 +179,22 @@ pub fn get_implicit_aria_roles(current_node: &Element) -> Vec<AriaRoleDefinition
118179
vec![]
119180
}
120181

121-
pub fn get_roles(_container: &Node) -> Vec<String> {
182+
pub fn get_roles(_container: Node) -> Vec<String> {
183+
fn _flatten_dom(node: Node) -> Vec<Node> {
184+
let nodes = vec![node.clone()];
185+
if let Some(_element) = node.dyn_ref::<Element>() {
186+
todo!()
187+
// nodes.extend(element.children());
188+
}
189+
nodes
190+
}
191+
122192
todo!()
193+
// flatten_dom(contaier).into_iter().filter(|_element| {
194+
// // TODO
195+
// false
196+
// })
197+
//.fold(init, f)
123198
}
124199

125200
pub fn log_roles() {

0 commit comments

Comments
 (0)