Improve menu accessibility (#44)

This commit adds 2 new attributes to the MenuItem component: 'disabled' and 'href'.
'href' is used for specifying links associated with menu items. This is required to
make menu links accessible and navigable using keyboard. Currently, 'disabled' is
also used only for accessibility purposes: if a MenuItem is not disabled, a tabindex
attribute is added to help with keyboard navigation.

Additionally, an alt text is added to the logo image.
This commit is contained in:
Nikita Baksalyar 2020-10-07 09:10:03 +01:00 committed by GitHub
parent 4a2e6d2245
commit 2fd69c2d98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 3 deletions

View file

@ -106,56 +106,69 @@ impl Component for App {
/>
<MenuItem
text={html!("Button")}
href="#button"
onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::Button))
/>
<MenuItem
text={html!("Button Group")}
onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::ButtonGroup))
href="#bgroup"
onclick=self.link
.callback(|_| Msg::GoToMenu(DocMenu::ButtonGroup))
/>
<MenuItem
text={html!("Callout")}
href="#callout"
onclick=self.link
.callback(|_| Msg::GoToMenu(DocMenu::Callout))
/>
<MenuItem
text={html!("Card")}
href="#card"
onclick=self.link
.callback(|_| Msg::GoToMenu(DocMenu::Card))
/>
<MenuItem
text={html!("Collapse")}
href="#collapse"
onclick=self.link
.callback(|_| Msg::GoToMenu(DocMenu::Collapse))
/>
<MenuItem
text={html!("Divider")}
href="#divider"
onclick=self.link
.callback(|_| Msg::GoToMenu(DocMenu::Divider))
/>
<MenuItem
text={html!("Icon")}
href="#icon"
onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::Icon))
/>
<MenuItem
text={html!("Menu")}
href="#menu"
onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::Menu))
/>
<MenuItem
text={html!("ProgressBar")}
href="#progress-bar"
onclick=self.link
.callback(|_| Msg::GoToMenu(DocMenu::ProgressBar))
/>
<MenuItem
text={html!("Switch")}
href="#switch"
onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::Switch))
/>
<MenuItem
text={html!("Text")}
href="#text"
onclick=self.link
.callback(|_| Msg::GoToMenu(DocMenu::Text))
/>
<MenuItem
text={html!("Tree")}
href="#tree"
onclick=self.link.callback(|_| Msg::GoToMenu(DocMenu::Tree))
/>
// NOTE: thanks to keep this list of <MenuItem> sorted

View file

@ -1 +1 @@
<svg width="17.895mm" height="20.47mm" version="1.1" viewBox="0 0 17.895 20.47" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-52.12 -47.149)"><circle cx="61.221" cy="57.026" r="6.6146" fill="#ffefb8" stroke-width=".26458"/><g stroke-width=".26458"><path d="m60.171 47.622 0.576-0.33179a1.0583 1.0583 0 0 1 1.0687 0.0071l7.4168 4.4035a1.0583 1.0583 0 0 1 0.51779 0.91017v8.8493a1.0583 1.0583 0 0 1-0.51805 0.91017l-7.4163 4.4037a1.0583 1.0583 0 0 1-1.0687 0.0071l-7.6647-4.4132a1.0583 1.0583 0 0 1-0.53022-0.91731v-8.8302a1.0583 1.0583 0 0 1 0.53022-0.91731l7.0882-4.0812zm0.84005 0.127-0.13203-0.22939v-0.26458h0.99007l-0.84746 0.48789a0.53128 0.53128 0 0 0-0.01058 0.0061zm-7.6644 4.413a0.52917 0.52917 0 0 0-0.26511 0.45852v8.8302a0.52917 0.52917 0 0 0 0.26511 0.45852l7.665 4.4132a0.52917 0.52917 0 0 0 0.53393-0.0034l7.4163-4.4037a0.52917 0.52917 0 0 0 0.25929-0.45508v-8.8493a0.52917 0.52917 0 0 0-0.25903-0.45508l-7.4165-4.4035a0.52917 0.52917 0 0 0-0.52388-0.0095l-7.6748 4.4191z"/><path d="m61.683 52.204 3.8333 2.3006v5.3266l-4.2291 2.5374-0.13388-0.07514-3.9635-2.2296a0.79375 0.79375 0 0 1-0.40481-0.69215v-4.8723l4.1002-2.3064a0.79375 0.79375 0 0 1 0.79772 0.01138zm3.3041 2.6001-3.5766-2.1458a0.26458 0.26458 0 0 0-0.26591-4e-3l-3.8304 2.1545v4.5627a0.26458 0.26458 0 0 0 0.13494 0.23045l3.8296 2.1545 3.7084-2.2251v-4.7276z"/><path d="m52.657 52.697 0.25665-0.46276 6.9421 3.8484-0.25665 0.46276z"/><path d="m58.742 56.136 0.25664-0.46276 6.9421 3.8484-0.25665 0.46276z"/><path d="m61.283 52.273-4.2333 2.3812v5.0271l4.2333-2.3812zm7.9375 0-4.2333 2.3812v5.2917l4.2333-2.3812z"/><path d="m69.221 57.3-4.2333 2.3812v5.0271l4.2333-2.3812z"/><path d="m65.517 59.417-4.2333 2.3812v5.0271l4.2333-2.3812z"/></g><g fill="none" stroke="#444" stroke-linecap="round" stroke-width="1.5875"><path d="m61.283 57.3-8.3698-5.066"/><path d="m61.283 57.3 7.9375-5.0271"/><path d="m61.283 57.3v9.525"/></g><circle cx="61.221" cy="57.291" r="1.8521" fill="#ffd707" stroke="#444" stroke-width="1.0583"/></g></svg>
<svg role="img" aria-label="Yewprint logo" width="17.895mm" height="20.47mm" version="1.1" viewBox="0 0 17.895 20.47" xmlns="http://www.w3.org/2000/svg"><title>Yewprint</title><g transform="translate(-52.12 -47.149)"><circle cx="61.221" cy="57.026" r="6.6146" fill="#ffefb8" stroke-width=".26458"/><g stroke-width=".26458"><path d="m60.171 47.622 0.576-0.33179a1.0583 1.0583 0 0 1 1.0687 0.0071l7.4168 4.4035a1.0583 1.0583 0 0 1 0.51779 0.91017v8.8493a1.0583 1.0583 0 0 1-0.51805 0.91017l-7.4163 4.4037a1.0583 1.0583 0 0 1-1.0687 0.0071l-7.6647-4.4132a1.0583 1.0583 0 0 1-0.53022-0.91731v-8.8302a1.0583 1.0583 0 0 1 0.53022-0.91731l7.0882-4.0812zm0.84005 0.127-0.13203-0.22939v-0.26458h0.99007l-0.84746 0.48789a0.53128 0.53128 0 0 0-0.01058 0.0061zm-7.6644 4.413a0.52917 0.52917 0 0 0-0.26511 0.45852v8.8302a0.52917 0.52917 0 0 0 0.26511 0.45852l7.665 4.4132a0.52917 0.52917 0 0 0 0.53393-0.0034l7.4163-4.4037a0.52917 0.52917 0 0 0 0.25929-0.45508v-8.8493a0.52917 0.52917 0 0 0-0.25903-0.45508l-7.4165-4.4035a0.52917 0.52917 0 0 0-0.52388-0.0095l-7.6748 4.4191z"/><path d="m61.683 52.204 3.8333 2.3006v5.3266l-4.2291 2.5374-0.13388-0.07514-3.9635-2.2296a0.79375 0.79375 0 0 1-0.40481-0.69215v-4.8723l4.1002-2.3064a0.79375 0.79375 0 0 1 0.79772 0.01138zm3.3041 2.6001-3.5766-2.1458a0.26458 0.26458 0 0 0-0.26591-4e-3l-3.8304 2.1545v4.5627a0.26458 0.26458 0 0 0 0.13494 0.23045l3.8296 2.1545 3.7084-2.2251v-4.7276z"/><path d="m52.657 52.697 0.25665-0.46276 6.9421 3.8484-0.25665 0.46276z"/><path d="m58.742 56.136 0.25664-0.46276 6.9421 3.8484-0.25665 0.46276z"/><path d="m61.283 52.273-4.2333 2.3812v5.0271l4.2333-2.3812zm7.9375 0-4.2333 2.3812v5.2917l4.2333-2.3812z"/><path d="m69.221 57.3-4.2333 2.3812v5.0271l4.2333-2.3812z"/><path d="m65.517 59.417-4.2333 2.3812v5.0271l4.2333-2.3812z"/></g><g fill="none" stroke="#444" stroke-linecap="round" stroke-width="1.5875"><path d="m61.283 57.3-8.3698-5.066"/><path d="m61.283 57.3 7.9375-5.0271"/><path d="m61.283 57.3v9.525"/></g><circle cx="61.221" cy="57.291" r="1.8521" fill="#ffd707" stroke="#444" stroke-width="1.0583"/></g></svg>

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -65,6 +65,14 @@ impl ConditionalClass {
None
}
}
pub fn and<U>(&self, optb: Option<U>) -> Option<U> {
if self.0 {
optb
} else {
None
}
}
}
impl Deref for ConditionalClass {

View file

@ -68,7 +68,10 @@ pub struct MenuItemProps {
pub active: ConditionalClass,
#[prop_or_default]
pub class: Option<String>,
// TODO: pub disabled: bool,
#[prop_or_default]
pub disabled: ConditionalClass,
#[prop_or_default]
pub href: Option<String>,
#[prop_or_default]
pub label: Option<yew::virtual_dom::VNode>,
#[prop_or_default]
@ -112,10 +115,13 @@ impl Component for MenuItem {
class=(
"bp3-menu-item",
self.props.active.map_some("bp3-active"),
self.props.disabled.map_some("bp3-disabled"),
self.props.intent
.or_else(|| self.props.active.map_some(Intent::Primary)),
self.props.class.clone(),
)
href?={(!self.props.disabled).and(self.props.href.clone())}
tabIndex?={(!self.props.disabled).map_some(0)}
onclick={self.props.onclick.clone()}
>
<Icon icon={self.props.icon} />