Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catalog accessibility indicator updates #1487

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions src/components/accessibility-indicator.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,20 @@ const AccessibilityIndicator = ({widget = {}}) => {
}
}

let descriptionRender = ''
if (widget.accessibility.keyboard.toLowerCase() != 'unavailable' || widget.accessibility.screen_reader.toLowerCase() != 'unavailable') {
descriptionRender = widget.accessibility.description
}
else {
descriptionRender = 'No accessibility information is provided for this widget.'
}

return (
<div className='feature-list accessibility-options'>
<div className='list-holder'>
<span className='feature-heading'>Accessibility:</span>
<ul>
<li>
<li className={`accessibility-indicator ${widget.accessibility?.keyboard.toLowerCase() != 'unavailable' ? 'show' : ''}`}>
<div className='icon-spacer'>
<KeyboardIcon color='#5a5a5a'/>
</div>
Expand All @@ -30,16 +38,19 @@ const AccessibilityIndicator = ({widget = {}}) => {
</span>
</span>
</li>
<li>
<li className={`accessibility-indicator ${widget.accessibility?.screen_reader.toLowerCase() != 'unavailable' ? 'show' : ''}`}>
<div className='icon-spacer'>
<ScreenReaderIcon color='#5a5a5a'/>
</div>
<span>Screen reader is&nbsp;
<span>Screen readers are&nbsp;
<span id='screen-reader-access-level' className={`highlighted ${widget.accessibility?.screen_reader.toLowerCase()}`}>
{`${accessLevelToText(widget.accessibility?.screen_reader)} supported`}
</span>
</span>
</li>
<li className={`accessibility-description ${descriptionRender.length > 0 ? 'show' : ''}`}>
{descriptionRender}
</li>
</ul>
</div>
</div>
Expand Down
131 changes: 101 additions & 30 deletions src/components/catalog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,27 @@ const Catalog = ({widgets = [], isLoading = true}) => {
const [state, setState] = useState({
searchText: '',
showingFilters: false,
showingAccessibility: false,
activeFilters: [],
showMobileFilters: false
showMobileFilters: false,
showMobileAccessibilityFilters: false
})
const totalWidgets = widgets.length

// collect all unique features and supported data
const filters = useMemo(() => {
const filters = new Set()
const features = new Set()
const accessibility = new Set()
widgets.forEach(w => {
w.meta_data.features.forEach(f => {filters.add(f)})
w.meta_data.supported_data.forEach(f => {filters.add(f)})
if(w.meta_data.hasOwnProperty('accessibility_keyboard')) filters.add('Keyboard Accessible')
if(w.meta_data.hasOwnProperty('accessibility_reader')) filters.add('Screen Reader Accessible')
w.meta_data.features.forEach(f => {features.add(f)})
w.meta_data.supported_data.forEach(f => {features.add(f)})
if(w.meta_data.hasOwnProperty('accessibility_keyboard')) accessibility.add('Keyboard Accessible')
if(w.meta_data.hasOwnProperty('accessibility_reader')) accessibility.add('Screen Reader Accessible')
})
return Array.from(filters)
return {
features: Array.from(features),
accessibility: Array.from(accessibility)
}
},
[widgets]
)
Expand Down Expand Up @@ -72,6 +78,15 @@ const Catalog = ({widgets = [], isLoading = true}) => {
setState({...state, activeFilters: newFilters, showMobileFilters: false})
}

const accessibilityLinkClickHandler = () => {
if (state.showingAccessibility){
setState({...state, showingAccessibility: !state.showingAccessibility, activeFilters: []})
}
else {
setState({...state, showingAccessibility: !state.showingAccessibility})
}
}

const filterLinkClickHandler = () => {
if(state.showingFilters){
setState({...state, showingFilters: !state.showingFilters, activeFilters: []})
Expand All @@ -92,7 +107,7 @@ const Catalog = ({widgets = [], isLoading = true}) => {

let mobileFilterRender = null
if (state.showMobileFilters) {
const mobileFilterOptionsRender = filters.map(filter => (
const mobileFilterOptionsRender = filters.features.map(filter => (
<label key={filter}>
<input type='checkbox'
className='filter-button'
Expand All @@ -112,14 +127,51 @@ const Catalog = ({widgets = [], isLoading = true}) => {
{ mobileFilterOptionsRender }
</div>
)
} else if (state.showMobileAccessibilityFilters) {
const mobileFilterOptionsRender = filters.accessibility.map(filter => (
<label key={filter}>
<input type='checkbox'
className='filter-button'
checked={state.activeFilters.includes(filter)}
readOnly={true}
onClick={ () => toggleFilter(filter) }
/>
{filter}
</label>
))

mobileFilterRender = (
<div
id='filter-dropdown'
className='mobile-only accessibility'
aria-hidden={!isMobileDevice()}>
{ mobileFilterOptionsRender }
</div>
)
}

const filterOptionsRender = filters.map((filter, index) => {
const filterOptionsRender = filters.features.map((filter, index) => {
const isEnabled = state.activeFilters.includes(filter)
const filterOptionClickHandler = () => toggleFilter(filter)
return <button key={index}
className={'feature-button' + (isEnabled ? ' selected' : '')}
aria-label={`Filter by ${filter}. ${isEnabled ? 'Selected.' : ''}`}
aria-hidden={!state.showingFilters}
disabled={!state.showingFilters}
onClick={ filterOptionClickHandler }>
{filter}
</button>
}
)

const accessibilityOptionsRender = filters.accessibility.map((filter, index) => {
const isEnabled = state.activeFilters.includes(filter)
const filterOptionClickHandler = () => toggleFilter(filter)
return <button key={index}
className={'feature-button' + (isEnabled ? ' selected' : '')}
aria-label={`Filter by ${filter}. ${isEnabled ? 'Selected.' : ''}`}
aria-hidden={!state.showingAccessibility}
disabled={!state.showingAccessibility}
onClick={ filterOptionClickHandler }>
{ filter == 'Keyboard Accessible' ? <KeyboardIcon color='#000' /> : '' }
{ filter == 'Screen Reader Accessible' ? <ScreenReaderIcon color='#000' /> : '' }
Expand Down Expand Up @@ -203,40 +255,59 @@ const Catalog = ({widgets = [], isLoading = true}) => {

<div className='top'>
<h1>Widget Catalog</h1>
<button
className='filter-toggle cancel_button desktop-only'
onClick={ filterLinkClickHandler }>
{state.showingFilters ? 'Clear Filters' : 'Filter by feature'}
</button>
<div className={'search' + (state.searchText === '' ? '' : ' not-empty')}>
<input value={state.searchText} onChange={(e) => {setState({...state, searchText: e.target.value})}} type='text'/>
<div className='search-icon'>
<svg viewBox='0 0 250.313 250.313'>
<path d='m244.19 214.6l-54.379-54.378c-0.289-0.289-0.628-0.491-0.93-0.76 10.7-16.231 16.945-35.66 16.945-56.554 0-56.837-46.075-102.91-102.91-102.91s-102.91 46.075-102.91 102.91c0 56.835 46.074 102.91 102.91 102.91 20.895 0 40.323-6.245 56.554-16.945 0.269 0.301 0.47 0.64 0.759 0.929l54.38 54.38c8.169 8.168 21.413 8.168 29.583 0 8.168-8.169 8.168-21.413 0-29.582zm-141.28-44.458c-37.134 0-67.236-30.102-67.236-67.235 0-37.134 30.103-67.236 67.236-67.236 37.132 0 67.235 30.103 67.235 67.236s-30.103 67.235-67.235 67.235z'
clipRule='evenodd'
fillRule='evenodd'/>
</svg>
<aside>
<span className='label'>Filter by:</span>
<button
className={`filter-toggle desktop-only ${state.showingFilters ? 'close-mode' : ''}`}
aria-label={state.showingFilters ? 'Feature filters drawer open' : 'Filter catalog by features'}
onClick={ filterLinkClickHandler }>
Feature</button>
<button
className={`filter-toggle desktop-only ${state.showingAccessibility ? 'close-mode' : ''}`}
aria-label={state.showingAccessibility ? 'Accessibility filters drawer open' : 'Filter catalog by accessibility'}
onClick={ accessibilityLinkClickHandler }>
Accessibility</button>
<div className={'search' + (state.searchText === '' ? '' : ' not-empty')}>
<input value={state.searchText} onChange={(e) => {setState({...state, searchText: e.target.value})}} type='text'/>
<div className='search-icon'>
<svg viewBox='0 0 250.313 250.313'>
<path d='m244.19 214.6l-54.379-54.378c-0.289-0.289-0.628-0.491-0.93-0.76 10.7-16.231 16.945-35.66 16.945-56.554 0-56.837-46.075-102.91-102.91-102.91s-102.91 46.075-102.91 102.91c0 56.835 46.074 102.91 102.91 102.91 20.895 0 40.323-6.245 56.554-16.945 0.269 0.301 0.47 0.64 0.759 0.929l54.38 54.38c8.169 8.168 21.413 8.168 29.583 0 8.168-8.169 8.168-21.413 0-29.582zm-141.28-44.458c-37.134 0-67.236-30.102-67.236-67.235 0-37.134 30.103-67.236 67.236-67.236 37.132 0 67.235 30.103 67.235 67.236s-30.103 67.235-67.235 67.235z'
clipRule='evenodd'
fillRule='evenodd'/>
</svg>
</div>
{ searchCloseRender }
</div>
{ searchCloseRender }
</div>
</aside>

</div>

<div aria-hidden={!isMobileDevice()} id='active-filters' className='mobile-only'>
<button id='add-filter'
onClick={ () => { setState({...state, showMobileFilters: !state.showMobileFilters}) } }>
<div aria-hidden={!isMobileDevice()} className='mobile-filter-select mobile-only'>
<button className='add-filter'
onClick={ () => { setState({...state, showMobileFilters: !state.showMobileFilters, showMobileAccessibilityFilters: false}) } }>
{state.activeFilters.length ? 'Filters' : 'Filter by Feature'}
</button>
<div>
<button className='add-filter'
onClick={ () => { setState({...state, showMobileAccessibilityFilters: !state.showMobileAccessibilityFilters, showMobileFilters: false}) } }>
{state.activeFilters.length ? 'Accessibility' : 'Filter by Accessibility'}
</button>
<div className='active-filters'>
{ state.activeFilters.join(', ') }
</div>
</div>
{ mobileFilterRender }
<div id='filters-container'
className={`ready ${state.showingFilters ? 'open' : 'closed'}`}>
<div className='filter-labels-container'>
className={`ready ${state.showingFilters ? 'open' : 'closed'}`} aria-hidden={!state.showingFilters}>
<div className='filter-labels-container' disabled={!state.showingFilters}>
{ filterOptionsRender }
</div>
</div>
<div id='filters-container'
className={`ready ${state.showingAccessibility ? 'open' : 'closed'}`} aria-hidden={!state.showingAccessibility}>
<div className='filter-labels-container accessibility' disabled={!state.showingAccessibility}>
{ accessibilityOptionsRender }
</div>
</div>

{ featuredWidgetsRender }

Expand Down
Loading
Loading