Skip to content

Commit 02b8eaa

Browse files
committed
chore: annouce search results in side navigation
INSTUI-4243
1 parent 90e8ce7 commit 02b8eaa

File tree

2 files changed

+56
-6
lines changed

2 files changed

+56
-6
lines changed

packages/__docs__/src/Nav/index.tsx

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { capitalizeFirstLetter } from '@instructure/ui-utils'
3434

3535
import { NavToggle } from '../NavToggle'
3636
import type { NavProps, NavState } from './props'
37+
import { Alert } from '@instructure/ui-alerts'
3738

3839
class Nav extends Component<NavProps, NavState> {
3940
_themeId: string
@@ -45,7 +46,8 @@ class Nav extends Component<NavProps, NavState> {
4546
this.state = {
4647
query: null,
4748
expandedSections: this.setExpandedSections(false, props.sections),
48-
userToggling: false
49+
userToggling: false,
50+
announcement: null
4951
}
5052

5153
this._themeId = '__themes'
@@ -79,15 +81,53 @@ class Nav extends Component<NavProps, NavState> {
7981
this.state.expandedSections
8082
)
8183

84+
if (!value && this.state.queryStr) {
85+
this.announceResults(-1)
86+
}
87+
8288
clearTimeout(this.searchTimeout!)
8389
this.searchTimeout = setTimeout(() => {
90+
this.setState(
91+
{
92+
query: value ? new RegExp(value, 'i') : null,
93+
queryStr: value,
94+
expandedSections,
95+
userToggling: false
96+
},
97+
() => {
98+
if (value) {
99+
this.announceResults(this.countSearchResults())
100+
}
101+
}
102+
)
103+
}, 500)
104+
}
105+
106+
announceResults(count: number) {
107+
const message =
108+
count === -1
109+
? 'Search cleared'
110+
: count === 0
111+
? 'No results'
112+
: `${count} ${count === 1 ? 'result' : 'results'} available below`
113+
setTimeout(() => {
84114
this.setState({
85-
query: value ? new RegExp(value, 'i') : null,
86-
queryStr: value,
87-
expandedSections,
88-
userToggling: false
115+
announcement: message
89116
})
90-
}, 500)
117+
}, 1000)
118+
}
119+
120+
countSearchResults(): number {
121+
const { sections } = this.props
122+
let count = 0
123+
Object.keys(sections).forEach((sectionId) => {
124+
const uniqueDocs = this.matchingDocsInSection(sectionId).filter(
125+
(docId: any, index: any, array: string | any[]) =>
126+
array.indexOf(docId) === index
127+
)
128+
count += uniqueDocs.length
129+
})
130+
return count
91131
}
92132

93133
handleToggleSection = (sectionId: string, expanded: boolean) => {
@@ -469,6 +509,15 @@ class Nav extends Component<NavProps, NavState> {
469509
elementRef={this.textInputRef}
470510
/>
471511
</View>
512+
<Alert
513+
liveRegion={() =>
514+
document.getElementById('flash-messages') as HTMLElement
515+
}
516+
liveRegionPoliteness="polite"
517+
screenReaderOnly
518+
>
519+
{this.state.announcement}
520+
</Alert>
472521
<View margin="medium none none" display="block">
473522
{hasMatches && matches}
474523
</View>

packages/__docs__/src/Nav/props.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ type NavState = {
5959
expandedSections: Record<string, any>
6060
userToggling: boolean
6161
queryStr?: string
62+
announcement: string | null
6263
}
6364
export type { NavProps, NavState }
6465
export { allowedProps, propTypes }

0 commit comments

Comments
 (0)