Skip to content

Commit 5002240

Browse files
Ensure conformance with WCAG 2.1 guidelines (#191)
## Description <!--- Describe your changes --> Addressing some minor accessibility issues that ensure conformance with WCAG 2.1 AA guidelines ## Motivation and Context <!--- Why is this change required? What problem does it solve? --> Added some minor markup to improve usability for assistive technologies, like screen readers. <!--- If it fixes an open issue, please link to the issue here. --> [PP-3573](https://ebce-lyrasis.atlassian.net/browse/PP-3573) ## How Has This Been Tested? <!--- Please describe in detail how you tested your changes. --> Manually tested addition of `lang` attribute. Added unit test to ensure `h1` element renders. <!--- Include details of your testing environment, and the tests you ran to --> <!--- see how your change affects other areas of the code, etc. --> ## Checklist: <!--- Go over all the following points, and put an `x` in all the boxes that apply. --> <!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> - [ ] I have updated the documentation accordingly. - [x] All new and existing tests passed. [PP-3573]: https://ebce-lyrasis.atlassian.net/browse/PP-3573?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
1 parent 6c9cb73 commit 5002240

3 files changed

Lines changed: 88 additions & 76 deletions

File tree

src/components/Header.tsx

Lines changed: 82 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -134,88 +134,94 @@ export class Header extends React.Component<HeaderProps, HeaderState> {
134134
const logoOnly = this.props.logoOnly ?? false;
135135

136136
return (
137-
<Navbar fluid={true}>
138-
<Navbar.Header>
139-
<img src={palaceLogoUrl} alt={title()} />
137+
<header>
138+
<h1 className="visually-hidden">{title("")}</h1>
139+
<Navbar fluid={true}>
140+
<Navbar.Header>
141+
<img src={palaceLogoUrl} alt={title()} />
142+
{!logoOnly && (
143+
<>
144+
{this.props.libraries && this.props.libraries.length > 0 && (
145+
<EditableInput
146+
elementType="select"
147+
ref={this.libraryRef}
148+
value={currentLibrary}
149+
onChange={this.changeLibrary}
150+
aria-label="Select a library"
151+
>
152+
{(!this.context.library || !currentLibrary) && (
153+
<option aria-selected={false}>Select a library</option>
154+
)}
155+
{this.props.libraries.map((library) => (
156+
<option
157+
key={library.short_name}
158+
value={library.short_name}
159+
aria-selected={currentLibrary === library.short_name}
160+
>
161+
{library.name || library.short_name}
162+
</option>
163+
))}
164+
</EditableInput>
165+
)}
166+
<Navbar.Toggle />
167+
</>
168+
)}
169+
</Navbar.Header>
170+
140171
{!logoOnly && (
141-
<>
142-
{this.props.libraries && this.props.libraries.length > 0 && (
143-
<EditableInput
144-
elementType="select"
145-
ref={this.libraryRef}
146-
value={currentLibrary}
147-
onChange={this.changeLibrary}
148-
aria-label="Select a library"
149-
>
150-
{(!this.context.library || !currentLibrary) && (
151-
<option aria-selected={false}>Select a library</option>
172+
<Navbar.Collapse className="menu">
173+
{currentLibrary && (
174+
<Nav>
175+
{this.renderLinkItem(
176+
dashboardLinkItem,
177+
currentPathname,
178+
currentLibrary
152179
)}
153-
{this.props.libraries.map((library) => (
154-
<option
155-
key={library.short_name}
156-
value={library.short_name}
157-
aria-selected={currentLibrary === library.short_name}
158-
>
159-
{library.name || library.short_name}
160-
</option>
161-
))}
162-
</EditableInput>
180+
{libraryNavItems.map((item) =>
181+
this.renderNavItem(item, currentPathname, currentLibrary)
182+
)}
183+
{libraryLinkItems.map((item) =>
184+
this.renderLinkItem(item, currentPathname, currentLibrary)
185+
)}
186+
</Nav>
163187
)}
164-
<Navbar.Toggle />
165-
</>
166-
)}
167-
</Navbar.Header>
168-
169-
{!logoOnly && (
170-
<Navbar.Collapse className="menu">
171-
{currentLibrary && (
172-
<Nav>
173-
{this.renderLinkItem(
174-
dashboardLinkItem,
175-
currentPathname,
176-
currentLibrary
188+
<Nav className="pull-right">
189+
{sitewideLinkItems.map((item) =>
190+
this.renderLinkItem(item, currentPathname)
177191
)}
178-
{libraryNavItems.map((item) =>
179-
this.renderNavItem(item, currentPathname, currentLibrary)
180-
)}
181-
{libraryLinkItems.map((item) =>
182-
this.renderLinkItem(item, currentPathname, currentLibrary)
192+
{this.context.admin.email && (
193+
<li className="dropdown">
194+
<Button
195+
className="account-dropdown-toggle transparent"
196+
type="button"
197+
aria-haspopup="true"
198+
aria-expanded={this.state.showAccountDropdown}
199+
callback={this.toggleAccountDropdown}
200+
content={
201+
<span>
202+
{this.context.admin.email} <GenericWedgeIcon />
203+
</span>
204+
}
205+
/>
206+
{this.state.showAccountDropdown && (
207+
<ul className="dropdown-menu">
208+
{this.displayPermissions(
209+
isSystemAdmin,
210+
isLibraryManager
211+
)}
212+
{this.renderLinkItem(accountLink, currentPathname)}
213+
<li>
214+
<a href="/admin/sign_out">Sign out</a>
215+
</li>
216+
</ul>
217+
)}
218+
</li>
183219
)}
184220
</Nav>
185-
)}
186-
<Nav className="pull-right">
187-
{sitewideLinkItems.map((item) =>
188-
this.renderLinkItem(item, currentPathname)
189-
)}
190-
{this.context.admin.email && (
191-
<li className="dropdown">
192-
<Button
193-
className="account-dropdown-toggle transparent"
194-
type="button"
195-
aria-haspopup="true"
196-
aria-expanded={this.state.showAccountDropdown}
197-
callback={this.toggleAccountDropdown}
198-
content={
199-
<span>
200-
{this.context.admin.email} <GenericWedgeIcon />
201-
</span>
202-
}
203-
/>
204-
{this.state.showAccountDropdown && (
205-
<ul className="dropdown-menu">
206-
{this.displayPermissions(isSystemAdmin, isLibraryManager)}
207-
{this.renderLinkItem(accountLink, currentPathname)}
208-
<li>
209-
<a href="/admin/sign_out">Sign out</a>
210-
</li>
211-
</ul>
212-
)}
213-
</li>
214-
)}
215-
</Nav>
216-
</Navbar.Collapse>
217-
)}
218-
</Navbar>
221+
</Navbar.Collapse>
222+
)}
223+
</Navbar>
224+
</header>
219225
);
220226
}
221227

src/components/__tests__/Header-test.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ describe("Header", () => {
4242
});
4343

4444
describe("rendering", () => {
45+
it("renders h1 heading", () => {
46+
const heading = wrapper.find("h1");
47+
expect(heading.text()).to.equal(title());
48+
});
49+
4550
it("shows the brand name", () => {
4651
expect(wrapper.containsMatchingElement(<img alt={title()} />)).to.equal(
4752
true

src/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class CirculationAdmin {
2727
div.id = "opds-catalog";
2828
div.className = "palace";
2929
document.getElementsByTagName("body")[0].appendChild(div);
30+
document.documentElement.lang = "en";
3031

3132
const catalogEditorPath =
3233
"/admin/web(/collection/:collectionUrl)(/book/:bookUrl)(/tab/:tab)";

0 commit comments

Comments
 (0)