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

UHF-8590: Search accessibility fix #711

Merged
merged 25 commits into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4610e6b
UHF-8590: Fixed labeling id
xkhaven Jul 11, 2023
f3bbe33
UHF-8590: Updated labels to field precise
xkhaven Jul 11, 2023
6092128
UHF-8590: Fixed label for accessibility
xkhaven Jul 12, 2023
bc345ed
UHF-8590: Fix accessibility
xkhaven Jul 12, 2023
9c17a89
UHF-8590: Fix button margin
xkhaven Jul 12, 2023
d0b255d
UHF-8590: Fix focus on search
xkhaven Jul 13, 2023
216d98b
UHF-8590: Fix labels to field precise
xkhaven Jul 13, 2023
6a166c4
UHF-8590: Fix aria-hidden
xkhaven Jul 13, 2023
2371828
UHF-8590: Fix margin
xkhaven Jul 13, 2023
9c746c0
UHF-8590: Add global translation
xkhaven Jul 14, 2023
1a0b0e9
UHF-8590: Fix label to field precise
xkhaven Jul 14, 2023
7d8d955
UHF-8590: Use global translation
xkhaven Jul 14, 2023
2b2c7c0
UHF-8590: Use global translation
xkhaven Jul 14, 2023
40f9b26
UHF-8590: Fix aria-hidden
xkhaven Jul 14, 2023
9fbc84e
UHF-8590: JS/CSS rebuild
xkhaven Jul 14, 2023
ec4ee36
UHF-8590: Add scroll to results to school search
jeremysteerio Aug 8, 2023
4415064
UHF-8590: Add scrolling to results in news archive
jeremysteerio Aug 8, 2023
4d4f7e4
UHF-8590: News archive accessiblity fixes
jeremysteerio Aug 8, 2023
eac9452
UHF-8590: Add scrollToResults-hook to district and project search
jeremysteerio Aug 10, 2023
ad3f4b8
UHF-8590: Fixed aria-hidden
xkhaven Aug 14, 2023
c430faf
UHF-8590: Remove important statement from styles
jeremysteerio Aug 15, 2023
3030e33
UHF-8590: Add back important rule to override hds inline styles
jeremysteerio Aug 16, 2023
93ae289
UHF-8590: Fix scroll behavior
jeremysteerio Aug 16, 2023
2ff0b98
UHF-8590: Merge remote-tracking branch 'origin/main' into UHF-8590_Se…
jeremysteerio Aug 16, 2023
b8866cf
UHF-8590: Fix news archive aria-hidden
jeremysteerio Aug 18, 2023
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
16 changes: 8 additions & 8 deletions dist/css/styles.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/js/district-and-project-search.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/js/job-search.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/js/linkedevents.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/js/news-archive.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/js/school-search.min.js

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ const FormContainer = () => {

const handleTitleChange = ({ target: { value } }: { target: { value: string } }) => setTitle(value);
const accordionInitiallyOpen = !!Object.keys(urlParams).find(param => Object.keys(ComponentMap).includes(param) && urlParams?.[param as keyof URLParams]?.length);
const residentialAreaLabel: string = Drupal.t('Select the residential area from the list', {}, { context: 'District and project search form label' });
const projectThemeLabel: string = Drupal.t('Project theme', {}, { context: 'District and project search form label' });
const projectStageLabel: string = Drupal.t('Project stage', {}, { context: 'District and project search form label' });
const projectTypeLabel: string = Drupal.t('Project type', {}, { context: 'District and project search form label' });

return (
<form onSubmit={handleSubmit}>
Expand All @@ -78,9 +82,9 @@ const FormContainer = () => {
value={districtSelection}
onChange={setDistrictFilter}
icon={<IconLocation />}
label={Drupal.t('Select the residential area from the list', {}, { context: 'District and project search form label' })}
label={residentialAreaLabel}
placeholder={Drupal.t('Select area', {}, { context: 'District and project search form label' })}
clearButtonAriaLabel={Drupal.t('Clear selection', {}, { context: 'District and project search clear button aria label' })}
clearButtonAriaLabel={Drupal.t('Clear @label selection', {'@label': residentialAreaLabel}, { context: 'React search clear selection label' })}
selectedItemRemoveButtonAriaLabel={Drupal.t('Remove item', {}, { context: 'District and project search remove item aria label' })}
toggleButtonAriaLabel={Drupal.t('Open the combobox', {}, { context: 'District and project search open dropdown aria label' })}
theme={{
Expand All @@ -102,17 +106,17 @@ const FormContainer = () => {
'--header-line-height': 'var(--lineheight-s)',
}}
>
<div className='district-project-search-form__filters'>
<div className='district-project-search-form__filters'>
<Combobox
multiselect
id={SearchComponents.THEME}
// @ts-ignore
options={themeOptions}
value={themeSelection}
onChange={setThemeFilter}
label={Drupal.t('Project theme', {}, { context: 'District and project search form label' })}
label={projectThemeLabel}
placeholder={Drupal.t('All themes', {}, { context: 'District and project search form label' })}
clearButtonAriaLabel={Drupal.t('Clear selection', {}, { context: 'District and project search clear button aria label' })}
clearButtonAriaLabel={Drupal.t('Clear @label selection', {'@label': projectThemeLabel}, { context: 'React search clear selection label' })}
selectedItemRemoveButtonAriaLabel={Drupal.t('Remove item', {}, { context: 'District and project search remove item aria label' })}
toggleButtonAriaLabel={Drupal.t('Open the combobox', {}, { context: 'District and project search open dropdown aria label' })}
theme={{
Expand All @@ -128,9 +132,9 @@ const FormContainer = () => {
options={phaseOptions}
value={phaseSelection}
onChange={setPhaseFilter}
label={Drupal.t('Project stage', {}, { context: 'District and project search form label' })}
label={projectStageLabel}
placeholder={Drupal.t('All stages', {}, { context: 'District and project search form label' })}
clearButtonAriaLabel={Drupal.t('Clear selection', {}, { context: 'District and project search clear button aria label' })}
clearButtonAriaLabel={Drupal.t('Clear @label selection', {'@label': projectStageLabel}, { context: 'React search clear selection label' })}
selectedItemRemoveButtonAriaLabel={Drupal.t('Remove item', {}, { context: 'District and project search remove item aria label' })}
toggleButtonAriaLabel={Drupal.t('Open the combobox', {}, { context: 'District and project search open dropdown aria label' })}
theme={{
Expand All @@ -146,9 +150,9 @@ const FormContainer = () => {
options={typeOptions}
value={typeSelection}
onChange={setTypeFilter}
label={Drupal.t('Project type', {}, { context: 'District and project search form label' })}
label={projectTypeLabel}
placeholder={Drupal.t('All types', {}, { context: 'District and project search form label' })}
clearButtonAriaLabel={Drupal.t('Clear selection', {}, { context: 'District and project search clear button aria label' })}
clearButtonAriaLabel={Drupal.t('Clear @label selection', {'@label': projectTypeLabel}, { context: 'React search clear selection label' })}
selectedItemRemoveButtonAriaLabel={Drupal.t('Remove item', {}, { context: 'District and project search remove item aria label' })}
toggleButtonAriaLabel={Drupal.t('Open the combobox', {}, { context: 'District and project search open dropdown aria label' })}
theme={{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { LoadingSpinner } from 'hds-react';
import { useAtomValue, useSetAtom } from 'jotai';
import useSWR from 'swr';
import { useEffect, SyntheticEvent } from 'react';
import { SyntheticEvent, createRef } from 'react';

import Pagination from '@/react/common/Pagination';
import ResultCard from '../components/results/ResultCard';
Expand All @@ -12,6 +12,7 @@ import Global from '../enum/Global';
import Settings from '../enum/Settings';
import type URLParams from '../types/URLParams';
import Result from '../types/Result';
import useScrollToResults from '@/react/common/hooks/useScrollToResults';

const ResultsContainer = (): JSX.Element => {
const { size } = Global;
Expand All @@ -20,6 +21,11 @@ const ResultsContainer = (): JSX.Element => {
const { error: initializationError } = useAtomValue(configurationsAtom);
const setPage = useSetAtom(setPageAtom);
const currentPage = useAtomValue(pageAtom);
const scrollTarget = createRef<HTMLDivElement>();

const choices = Boolean(window.location.search?.length);
useScrollToResults(scrollTarget, choices);

const fetcher = () => {
const proxyUrl = drupalSettings?.helfi_kymp_district_project_search?.elastic_proxy_url;
const url: string | undefined = proxyUrl || process.env.REACT_APP_ELASTIC_URL;
Expand All @@ -37,18 +43,6 @@ const ResultsContainer = (): JSX.Element => {
revalidateOnFocus: false,
});

useEffect(() => {
const el = document.getElementById('helfi-kymp-district-project-search');

if (el && window.location.search) {
const titleEl = el.querySelector<HTMLElement>('.district-project-search__results');
if (!titleEl) return;
titleEl.setAttribute('tabindex', '0');
titleEl.focus();
el.scrollIntoView({ behavior: 'smooth' });
titleEl.setAttribute('tabindex', '-1');
}
}, [data]);

if (!data && !error) {
return <LoadingSpinner />;
Expand All @@ -57,7 +51,7 @@ const ResultsContainer = (): JSX.Element => {
if (!data?.hits?.hits.length) {
return (
<div className="district-project-search__results">
<div className='district-project-search__listing__no-results'>
<div className='district-project-search__listing__no-results' ref={scrollTarget}>
<h2>{Drupal.t('Oh no! We did not find anything matching the search terms.', {}, { context: 'District and project search' })}</h2>
<p>{Drupal.t('Our website currently shows only some of the projects and residential areas of Helsinki. You can try again by removing some of the limiting search terms or by starting over.', {}, { context: 'District and project search' })}</p>
</div>
Expand All @@ -73,7 +67,7 @@ const ResultsContainer = (): JSX.Element => {
if (error || initializationError) {
console.warn(`Error loading data. ${ error || initializationError}`);
return (
<div className='district-project-search__results'>
<div className='district-project-search__results' ref={scrollTarget}>
{Drupal.t('The website encountered an unexpected error. Please try again later.')}
</div>
);
Expand All @@ -87,7 +81,7 @@ const ResultsContainer = (): JSX.Element => {
return (
<div className="district-project-search__results">
<div className="district-project-search__results_heading">
<div className="district-project-search__count__container">
<div className="district-project-search__count__container" ref={scrollTarget}>
<span className="district-project-search__count">
<span className="district-project-search__count-total">{total} </span>
<span className="district-project-search__count-label">{Drupal.t('search results', {}, { context: 'District and project search' })} </span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const SelectionsContainer = () => {
)}
<li className='hdbt-search__clear-all'>
<Button
aria-hidden={showClearButton ? 'true' : 'false'}
aria-hidden={showClearButton ? 'false' : 'true'}
className='hdbt-search__clear-all-button'
iconLeft={<IconCross className='hdbt-search__clear-all-icon' />}
onClick={resetForm}
Expand Down
18 changes: 8 additions & 10 deletions src/js/react/apps/job-search/containers/FormContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ const FormContainer = () => {
const showCheckboxes = showContinuous || showInternships || showSummerJobs || showYouthSummerJobs;

const taskAreasLabel: string = Drupal.t('Task area', {}, { context: 'Task areas filter label' });
const employmentRelationshipLabel: string = Drupal.t('Type of employment relationship', {}, { context: 'Employment filter label' });
const languageLabel: string = Drupal.t('Language', {}, { context: 'Language filter label' });

return (
<form className='job-search-form' onSubmit={handleSubmit} action={formAction}>
Expand All @@ -117,7 +119,7 @@ const FormContainer = () => {
{/* @ts-ignore */}
<Select
clearable
clearButtonAriaLabel={Drupal.t('Clear selection', {}, { context: 'Job search clear button aria label' })}
clearButtonAriaLabel={Drupal.t('Clear @label selection', {'@label': taskAreasLabel}, { context: 'React search clear selection label' })}
className='job-search-form__dropdown'
selectedItemRemoveButtonAriaLabel={Drupal.t(
'Remove item',
Expand All @@ -136,7 +138,7 @@ const FormContainer = () => {
<div className='job-search-form__filter job-search-form__dropdown--upper'>
{/* @ts-ignore */}
<Select
clearButtonAriaLabel={Drupal.t('Clear selection', {}, { context: 'Job search clear button aria label' })}
clearButtonAriaLabel={Drupal.t('Clear @label selection', {'@label': employmentRelationshipLabel}, { context: 'React search clear selection label' })}
className='job-search-form__dropdown'
selectedItemRemoveButtonAriaLabel={Drupal.t(
'Remove item',
Expand All @@ -149,10 +151,10 @@ const FormContainer = () => {
{ context: 'Employment filter placeholder' }
)}
multiselect
label={Drupal.t('Type of employment relationship', {}, { context: 'Employment filter label' })}
label={employmentRelationshipLabel}
options={employmentOptions}
value={employmentSelection}
id={SearchComponents.TASK_AREAS}
id={SearchComponents.EMPLOYMENT_RELATIONSHIP}
onChange={setEmploymentFilter}
/>
</div>
Expand Down Expand Up @@ -190,11 +192,7 @@ const FormContainer = () => {
<div className='job-search-form__dropdowns__lower'>
<div className='job-search-form__filter job-search-form__dropdown--upper'>
<Select
clearButtonAriaLabel={Drupal.t(
'Clear selection',
{},
{ context: 'Job search clear button aria label' }
)}
clearButtonAriaLabel={Drupal.t('Clear @label selection', {'@label': languageLabel}, { context: 'React search clear selection label' })}
className='job-search-form__dropdown'
clearable
selectedItemRemoveButtonAriaLabel={Drupal.t(
Expand All @@ -203,7 +201,7 @@ const FormContainer = () => {
{ context: 'Job search remove item aria label' }
)}
placeholder={Drupal.t('All languages', {}, { context: 'Language placeholder' })}
label={Drupal.t('Language', {}, { context: 'Language filter label' })}
label={languageLabel}
// @ts-ignore
options={languagesOptions}
value={languageSelection}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ const SelectionsContainer = () => {
)}
<li className='job-search-form__clear-all'>
<Button
aria-hidden={showClearButton ? 'true' : 'false'}
aria-hidden={showClearButton ? 'false' : 'true'}
className='job-search-form__clear-all-button'
iconLeft={<IconCross className='job-search-form__clear-all-icon' />}
onClick={resetForm}
Expand Down
1 change: 1 addition & 0 deletions src/js/react/apps/job-search/enum/SearchComponents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const SearchComponents = {
EMPLOYMENT: 'employment',
KEYWORD: 'keyword',
TASK_AREAS: 'task_areas',
EMPLOYMENT_RELATIONSHIP: 'employment_relationship',
CONTINUOUS: 'continuous',
INTERNSHIPS: 'internship',
LANGUAGE: 'language',
Expand Down
5 changes: 3 additions & 2 deletions src/js/react/apps/linkedevents/components/LocationFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ function LocationFilter() {
};

const locationHelper = Drupal.t('If you want to search for remote events, select only the option \'Internet (remote events)\'');
const selectVenueLabel: string = Drupal.t('Select a venue');

return (
<div className='hdbt-search__filter event-form__filter--location'>
<Select
className='hdbt-search__dropdown'
clearButtonAriaLabel={Drupal.t('Clear selections', {}, { context: 'Event search: clear button aria label' })}
clearButtonAriaLabel={Drupal.t('Clear @label selection', {'@label': selectVenueLabel}, { context: 'React search clear selection label' })}
helper={locationHelper}
label={Drupal.t('Select a venue')}
label={selectVenueLabel}
multiselect
// @ts-ignore
options={locationOptions}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ const FilterButton = ({ value, clearSelection }: FilterButtonProps) => (
{ context: 'Search: remove item aria label' }
)}
className='hdbt-search__remove-selection-button'
iconRight={<IconCross />}
iconRight={<IconCross className='hdbt-search__remove-selection-icon' />}
variant='supplementary'
onClick={clearSelection}
>
Expand All @@ -207,7 +207,7 @@ const ClearButton = ({ showClearButton, url }: ClearButtonProps) => {
return (
<li className='hdbt-search__clear-all'>
<Button
aria-hidden={showClearButton ? 'true' : 'false'}
aria-hidden={showClearButton ? 'false' : 'true'}
className='hdbt-search__clear-all-button'
iconLeft={<IconCross className='hdbt-search__clear-all-icon' />}
onClick={resetForm}
Expand Down
13 changes: 9 additions & 4 deletions src/js/react/apps/news-archive/components/Filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type FilterProps = {
stateKey: keyof URLParams;
};

const Filter = ({stateKey, options, ...rest}: FilterProps) => {
const Filter = ({label, options, stateKey, ...rest}: FilterProps) => {
const [params, setParams] = useAtom(stagedParamsAtom);
const valueIds = params?.[stateKey] || [];

Expand Down Expand Up @@ -39,14 +39,19 @@ const Filter = ({stateKey, options, ...rest}: FilterProps) => {
};

return (
/* @ts-ignore */
<Select
className='news-form__filter'
clearable
clearButtonAriaLabel={Drupal.t('Clear selection')}
clearButtonAriaLabel={Drupal.t('Clear @label selection', {'@label': label}, { context: 'React search clear selection label' })}
label={label}
onChange={onChange}
multiselect
selectedItemRemoveButtonAriaLabel={Drupal.t('Remove item')}
/* @ts-ignore */
selectedItemRemoveButtonAriaLabel={Drupal.t(
'Remove item',
{},
{ context: 'Job search remove item aria label' }
)}
options={options}
value={getValue()}
{...rest}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { ForwardedRef, forwardRef } from 'react';

type ResultsHeadingProps = {
choices: boolean;
total: number;
}

const ResultsHeading = ({ choices, total }: ResultsHeadingProps) => {
const ResultsHeading = forwardRef((props: ResultsHeadingProps, ref: ForwardedRef<HTMLDivElement>) => {
const { choices, total } = props;

const heading = choices ?
`${Drupal.t('News based on your choices', {}, {context: 'News archive heading'}) } (${total})` :
Drupal.t('All news items', {}, {context: 'News archive heading'});

return (
<div className='news-archive__heading'>
<div className='news-archive__heading' ref={ref}>
<h2 className='news-archive__title'>
{heading}
</h2>
</div>
);
};
});

export default ResultsHeading;
9 changes: 6 additions & 3 deletions src/js/react/apps/news-archive/containers/FormContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ const FormContainer = () => {
};

const loading = isLoading || isValidating;
const topicLabel = Drupal.t('Topics', {}, { context: 'News archive topics label' });
const neighbourhoodLabel = Drupal.t('City disctricts', {}, { context: 'News archive neighbourhoods label' });
const groupLabel = Drupal.t('Target groups', {}, { context: 'News archive groups label' });

return (
<div className='news-form-wrapper'>
Expand All @@ -75,13 +78,13 @@ const FormContainer = () => {
<h2>{Drupal.t('Filter news items', {}, {context: 'News archive filter results heading'})}</h2>
<div className='news-form__filters-container'>
{topicOptions && <Filter
label={Drupal.t('Topics', {}, { context: 'News archive topics label' })}
label={topicLabel}
placeholder={Drupal.t('All topics', {}, { context: 'News archive topics placeholder' })}
options={topicOptions}
stateKey='topic'
/>}
{neighbourhoodOptions && <Filter
label={Drupal.t('City disctricts', {}, { context: 'News archive neighbourhoods label' })}
label={neighbourhoodLabel}
placeholder={Drupal.t(
'All city disctricts',
{},
Expand All @@ -91,7 +94,7 @@ const FormContainer = () => {
stateKey='neighbourhoods'
/>}
{groupOptions && <Filter
label={Drupal.t('Target groups', {}, { context: 'News archive groups label' })}
label={groupLabel}
placeholder={Drupal.t('All target groups', {}, { context: 'News archive groups placeholder' })}
options={groupOptions}
stateKey='groups'
Expand Down
Loading