From a6132a2b9dbd06473949c6d9c941261f33aaeb73 Mon Sep 17 00:00:00 2001 From: Konnor Rogers Date: Wed, 24 May 2023 16:32:25 -0400 Subject: [PATCH 1/3] feat: add accessibility improvements --- src/ninja-header.ts | 31 ++++++++++++++++++++++---- src/ninja-keys.ts | 53 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 77 insertions(+), 7 deletions(-) diff --git a/src/ninja-header.ts b/src/ninja-header.ts index b43b693..c21d2e0 100644 --- a/src/ninja-header.ts +++ b/src/ninja-header.ts @@ -20,7 +20,7 @@ export class NinjaHeader extends LitElement { background: transparent; caret-color: var(--ninja-accent-color); color: var(--ninja-text-color); - outline: none; + outline: transparent; font-family: var(--ninja-font-family); } .search::placeholder { @@ -62,7 +62,23 @@ export class NinjaHeader extends LitElement { hideBreadcrumbs = false; @property() - breadcrumbHome = 'Home'; + breadcrumbHome = "Home"; + + /** Maps to `aria-expanded` */ + @property({type: Boolean}) + expanded = false; + + /** Maps to `aria-controls` */ + @property() + controls = ''; + + /** Maps to `aria-label` on */ + @property() + searchLabel = ''; + + /** Maps to `aria-activedescendant` */ + @property() + activeDescendant = '' @property({type: Array}) breadcrumbs: string[] = []; @@ -84,7 +100,7 @@ export class NinjaHeader extends LitElement { ` ); } - breadcrumbs = html` From 196d5973fdc3981921a4867679391a069f09e4c7 Mon Sep 17 00:00:00 2001 From: Konnor Rogers Date: Wed, 24 May 2023 22:55:47 -0400 Subject: [PATCH 2/3] use aria-labelledby --- src/base-styles.ts | 23 +++++++++++++++++++++++ src/ninja-header.ts | 9 ++++++--- src/ninja-keys.ts | 9 ++++++++- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/base-styles.ts b/src/base-styles.ts index af69fcd..574ff68 100644 --- a/src/base-styles.ts +++ b/src/base-styles.ts @@ -1,7 +1,18 @@ import {css} from 'lit'; export const baseStyles = css` + :host *, + :host *::before, + :host *::after { + box-sizing: inherit; + } + + [hidden] { + display: none !important; + } :host { + box-sizing: border-box; + --ninja-width: 640px; --ninja-backdrop-filter: none; --ninja-overflow-background: rgba(255, 255, 255, 0.5); @@ -181,4 +192,16 @@ export const baseStyles = css` .ninja-examplekey.backspace { opacity: 0.7; } + + .visually-hidden:not(:focus-within) { + position: absolute !important; + width: 1px !important; + height: 1px !important; + clip: rect(0 0 0 0) !important; + clip-path: inset(50%) !important; + border: none !important; + overflow: hidden !important; + white-space: nowrap !important; + padding: 0 !important; + } `; diff --git a/src/ninja-header.ts b/src/ninja-header.ts index c21d2e0..9e50017 100644 --- a/src/ninja-header.ts +++ b/src/ninja-header.ts @@ -72,7 +72,7 @@ export class NinjaHeader extends LitElement { @property() controls = ''; - /** Maps to `aria-label` on */ + /** Maps to `aria-labelledby` on */ @property() searchLabel = ''; @@ -125,14 +125,17 @@ export class NinjaHeader extends LitElement { ${ref(this._inputRef)} placeholder="${this.placeholder}" class="search" - aria-label="${this.searchLabel}" + aria-labelledby="search-label" aria-expanded="${this.expanded}" - /* Should map to any elements that will get updated when this changes */ aria-controls="${this.controls} breadcrumb-list" aria-autocomplete="list" aria-activedescendant="${this.activeDescendant}" role="combobox" /> + + + ${this.searchLabel} + `; } diff --git a/src/ninja-keys.ts b/src/ninja-keys.ts index 33bf20c..49a2501 100644 --- a/src/ninja-keys.ts +++ b/src/ninja-keys.ts @@ -28,7 +28,10 @@ export class NinjaKeys extends LitElement { */ @property({type: Boolean}) disableHotkeys = false; + /** Maps to `aria-labelledby` for search input */ @property({attribute: "search-label"}) searchLabel = "Search for actions" + + /** Maps to `aria-labelledby` for listbox */ @property({attribute: "listbox-label"}) listboxLabel = "List of actions" /** @@ -473,10 +476,14 @@ export class NinjaKeys extends LitElement { class="actions-list" role="listbox" part="actions-list" - aria-label="${this.listboxLabel}" + aria-labelledby="listbox-label" > ${itemTemplates} + + + ${this.listboxLabel} + ${footerHtml} From 9ab4ec71aef24f9a370047f2f2a9dc2446a4efb3 Mon Sep 17 00:00:00 2001 From: Konnor Rogers Date: Fri, 26 May 2023 13:33:49 -0400 Subject: [PATCH 3/3] fix more --- src/base-styles.ts | 27 +++++++++++++++------------ src/ninja-header.ts | 13 ++++++++----- src/ninja-keys.ts | 12 +++++++----- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/base-styles.ts b/src/base-styles.ts index 574ff68..222f1f2 100644 --- a/src/base-styles.ts +++ b/src/base-styles.ts @@ -1,5 +1,19 @@ import {css} from 'lit'; +export const visuallyHidden = css` + .visually-hidden:not(:focus-within) { + position: absolute !important; + width: 1px !important; + height: 1px !important; + clip: rect(0 0 0 0) !important; + clip-path: inset(50%) !important; + border: none !important; + overflow: hidden !important; + white-space: nowrap !important; + padding: 0 !important; + } +` + export const baseStyles = css` :host *, :host *::before, @@ -144,10 +158,10 @@ export const baseStyles = css` } .group-header { - height: 1.375em; line-height: 1.375em; padding-left: 1.25em; padding-top: 0.5em; + padding-bottom: 0.5em; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; @@ -193,15 +207,4 @@ export const baseStyles = css` opacity: 0.7; } - .visually-hidden:not(:focus-within) { - position: absolute !important; - width: 1px !important; - height: 1px !important; - clip: rect(0 0 0 0) !important; - clip-path: inset(50%) !important; - border: none !important; - overflow: hidden !important; - white-space: nowrap !important; - padding: 0 !important; - } `; diff --git a/src/ninja-header.ts b/src/ninja-header.ts index 9e50017..e55dcfa 100644 --- a/src/ninja-header.ts +++ b/src/ninja-header.ts @@ -1,10 +1,11 @@ import {LitElement, html, css, TemplateResult} from 'lit'; import {customElement, property} from 'lit/decorators.js'; import {ref, createRef} from 'lit/directives/ref.js'; +import { visuallyHidden } from './base-styles'; @customElement('ninja-header') export class NinjaHeader extends LitElement { - static override styles = css` + static override styles = [visuallyHidden, css` :host { flex: 1; position: relative; @@ -53,7 +54,7 @@ export class NinjaHeader extends LitElement { display: flex; border-bottom: var(--ninja-separate-border); } - `; + `]; @property() placeholder = ''; @@ -133,9 +134,11 @@ export class NinjaHeader extends LitElement { role="combobox" /> - - ${this.searchLabel} - +
+ + ${this.searchLabel} + +
`; } diff --git a/src/ninja-keys.ts b/src/ninja-keys.ts index 49a2501..fde23d3 100644 --- a/src/ninja-keys.ts +++ b/src/ninja-keys.ts @@ -12,11 +12,11 @@ import {INinjaAction} from './interfaces/ininja-action.js'; import {NinjaHeader} from './ninja-header.js'; import {NinjaAction} from './ninja-action.js'; import {footerHtml} from './ninja-footer.js'; -import {baseStyles} from './base-styles.js'; +import {baseStyles,visuallyHidden} from './base-styles.js'; @customElement('ninja-keys') export class NinjaKeys extends LitElement { - static override styles = [baseStyles]; + static override styles = [visuallyHidden, baseStyles]; /** * Search placeholder text @@ -481,9 +481,11 @@ export class NinjaKeys extends LitElement { ${itemTemplates} - - ${this.listboxLabel} - +
+ + ${this.listboxLabel} + +
${footerHtml}