Skip to content

Commit

Permalink
Merge pull request #253 from delta10/a11y/240-assetselect-locationselect
Browse files Browse the repository at this point in the history
a11y: assetselect and locationselect fixes
  • Loading branch information
justiandevs authored Dec 11, 2024
2 parents 87e2371 + bd14302 commit 637ddbc
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 16 deletions.
16 changes: 15 additions & 1 deletion src/app/[locale]/incident/add/components/FeatureListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type FeatureListItemProps = {
setError: Dispatch<SetStateAction<string | null>>
dialogRef: RefObject<HTMLDialogElement>
configUrl?: string
setFocusedItemId: Dispatch<SetStateAction<number | null>>
}

export const FeatureListItem = ({
Expand All @@ -24,6 +25,7 @@ export const FeatureListItem = ({
setError,
dialogRef,
configUrl,
setFocusedItemId,
}: FeatureListItemProps) => {
const t = useTranslations('describe_add.map')
const { formState, updateForm } = useFormStore()
Expand Down Expand Up @@ -85,7 +87,19 @@ export const FeatureListItem = ({
// TODO: iets van een label toevoegen zodat voor een SR duidelijk wordt om welke lantaarnpaal, adres etc het gaat?
return featureDescription ? (
<li className="py-4 border-t bordercolor-gray-200">
<FormField className="flex flex-row items-center gap-2">
<FormField
className="flex flex-row items-center gap-2"
onFocus={(e) => {
setTimeout(() => {
setFocusedItemId(featureId)
}, 10)
}}
onBlur={(e) => {
setTimeout(() => {
setFocusedItemId(null)
}, 0)
}}
>
{!formState.selectedFeatures.some(
(featureItem) => featureItem.id === featureId
) ? (
Expand Down
75 changes: 63 additions & 12 deletions src/app/[locale]/incident/add/components/MapDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
} from '@/components'
import { useConfig } from '@/hooks/useConfig'
import {
IconChevronDown,
IconCurrentLocation,
IconMinus,
IconPlus,
Expand Down Expand Up @@ -67,10 +68,12 @@ const MapDialog = ({
const t = useTranslations('describe_add.map')
const [marker, setMarker] = useState<[number, number] | []>([])
const [error, setError] = useState<string | null>(null)
const [focusedItemId, setFocusedItemId] = useState<number | null>(null)
const { formState, updateForm } = useFormStore()
const { dialogMap } = useMap()
const { loading, config } = useConfig()
const dialogRef = useRef<HTMLDialogElement>(null)
const mapContainerRef = useRef<HTMLDivElement>(null)
const [isMapSelected, setIsMapSelected] = useState<boolean | null>(null)
const [mapFeatures, setMapFeatures] = useState<FeatureCollection | null>()
const { setValue } = useFormContext()
Expand Down Expand Up @@ -269,7 +272,15 @@ const MapDialog = ({
dialogRef.current?.showModal()
},
(locationError) => {
setError(locationError.message)
// For documentation see: https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPositionError.
// We map a custom error message here to the locationError.code
const locationErrors: { [key: number]: string } = {
1: t('current_location_permission_error'),
2: t('current_location_position_error'),
3: t('current_location_timeout_error'),
}

setError(locationErrors[locationError.code])
dialogRef.current?.showModal()
}
)
Expand Down Expand Up @@ -322,7 +333,7 @@ const MapDialog = ({
<Dialog.Trigger asChild>{trigger}</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay />
<Dialog.Content className="fixed inset-0 z-[1000] grid grid-cols-1 md:grid-cols-3 purmerend-theme background-white">
<Dialog.Content className="fixed inset-0 z-[1000] grid md:grid-cols-3 purmerend-theme background-white overflow-scroll">
<VisuallyHidden.Root>
{/* TODO: Overleggen welke titel hier het meest vriendelijk is voor de gebruiker, multi-language support integreren */}
<Dialog.Title>
Expand All @@ -332,7 +343,14 @@ const MapDialog = ({
</Dialog.Title>
<Dialog.Description>{t('dialog_description')}</Dialog.Description>
</VisuallyHidden.Root>
<AlertDialog type="error" ref={dialogRef} style={{ marginTop: 128 }}>
<AlertDialog
type="error"
ref={dialogRef}
style={{
margin: '128px auto 0',
maxWidth: 'calc(100% - 32px)',
}}
>
<form method="dialog" className="map-alert-dialog__content">
<Paragraph>{error}</Paragraph>
<ButtonGroup>
Expand All @@ -346,8 +364,8 @@ const MapDialog = ({
</ButtonGroup>
</form>
</AlertDialog>
<div className="col-span-1 p-4 flex flex-col max-h-screen gap-4">
<div className="flex flex-col overflow-hidden gap-4">
<div className="col-span-1 p-4 flex flex-col min-h-[100vh] max-h-[100vh] md:max-h-screen gap-4">
<div className="flex flex-col overflow-scroll md:overflow-hidden gap-4">
<Heading level={1}>
{field?.meta.language.title
? field.meta.language.title
Expand All @@ -357,6 +375,28 @@ const MapDialog = ({
updatePosition={updatePosition}
setIsMapSelected={setIsMapSelected}
/>
<div className="block md:hidden">
<Alert>
<div className="flex flex-row items-center">
<Paragraph>{t('scroll_for_map')}</Paragraph>
<IconButton
appearance="secondary-action-button"
label={t('scroll_to_map_button')}
onClick={() =>
mapContainerRef.current?.scrollIntoView({
behavior: 'smooth',
block: 'center',
})
}
className="ml-2"
>
<Icon>
<IconChevronDown />
</Icon>
</IconButton>
</div>
</Alert>
</div>
{isAssetSelect &&
dialogMap &&
config &&
Expand All @@ -375,6 +415,7 @@ const MapDialog = ({
field={field}
setError={setError}
dialogRef={dialogRef}
setFocusedItemId={setFocusedItemId}
/>
))}
</ul>
Expand All @@ -398,14 +439,18 @@ const MapDialog = ({
</div>
</div>
{config && (
<div className="col-span-1 md:col-span-2 relative">
<div
className="col-span-1 md:col-span-2 min-h-[100vh] max-h-[50vh] md:max-h-screen relative"
ref={mapContainerRef}
>
<Map
{...viewState}
id="dialogMap"
onClick={(e) => handleMapClick(e)}
onMove={(evt) => setViewState(evt.viewState)}
style={{ blockSize: '100%', inlineSize: '100%' }}
mapStyle={mapStyle}
scrollZoom={false}
attributionControl={false}
maxBounds={
config.base.map.maxBounds as [
Expand Down Expand Up @@ -436,13 +481,19 @@ const MapDialog = ({
onClick={(e) => handleFeatureMarkerClick(e, feature)}
>
{!formState.selectedFeatures.some(
(featureItem) => featureItem.id === feature.id
(featureItem) => featureItem.id === id
) ? (
<Icon>
<img
src={field?.meta.featureTypes[0].icon.iconUrl}
/>
</Icon>
focusedItemId === id ? (
<Icon>
<div className="focused-map-marker"></div>
</Icon>
) : (
<Icon>
<img
src={field?.meta.featureTypes[0].icon.iconUrl}
/>
</Icon>
)
) : (
<Icon>
<img
Expand Down
11 changes: 10 additions & 1 deletion src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@
position: absolute;
right: 1em;
bottom: 1em;
gap: 0 !important;
gap: 0.5rem !important;
display: flex;
flex-direction: column;
}

.map-alert-dialog__content {
Expand All @@ -138,6 +140,13 @@
);
}

.focused-map-marker {
width: 42px;
height: 42px;
border-radius: 999px;
background-color: red;
}

/* colors */
.background-gray-200 {
background-color: var(--basis-color-gray-200);
Expand Down
7 changes: 6 additions & 1 deletion translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,14 @@
"close_alert_notification": "Close notification",
"address_search_label": "Search by address",
"outside_max_bound_error": "Your location is outside the map bounds and is therefore not visible.",
"current_location_permission_error": "Failed to retrieve location data because the page does not have the necessary permissions. Check if location usage is allowed in the settings or if the website's policy is blocking it.",
"current_location_timeout_error": "Failed to retrieve location data because it took too long. Ensure that your device has a good connection and try again.",
"current_location_position_error": "Failed to retrieve location data because an internal error occurred while determining the position. Try again later or check your device settings.",
"max_number_of_assets_error": "You can select at most {max, plural, one {# object} other {# objects}}.",
"go_further_without_selected_object": "Continue without object",
"zoom_for_object": "Zoom in to see the objects",
"zoom_for_object": "Zoom in on the map to see the objects",
"scroll_for_map": "Scroll down to display the map",
"scroll_to_map_button": "Scroll down",
"map_zoom-in_button_label": "Zoom in on the map",
"map_zoom-out_button_label": "Zoom out on the map",
"map_close_button_label": "Close the map",
Expand Down
7 changes: 6 additions & 1 deletion translations/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,16 @@
"dialog_description": "Kies een locatie op de kaart voor de locatie van uw melding.",
"current_location": "Mijn locatie",
"outside_max_bound_error": "Uw locatie valt buiten de kaart en is daardoor niet te zien.",
"current_location_permission_error": "Het ophalen van locatiegegevens is mislukt omdat de pagina niet over de benodigde toestemmingen beschikt. Controleer of locatiegebruik is toegestaan in de instellingen of of het beleid van de website dit blokkeert.",
"current_location_timeout_error": "Het ophalen van locatiegegevens duurde te lang. Zorg ervoor dat uw apparaat een goede verbinding heeft en probeer het opnieuw.",
"current_location_position_error": "Het ophalen van locatiegegevens is mislukt omdat een interne fout optrad bij het bepalen van de positie. Probeer het later opnieuw of controleer uw apparaatinstellingen.",
"close_alert_notification": "Sluit melding",
"address_search_label": "Zoek op adres",
"max_number_of_assets_error": "U kunt maximaal {max, plural, one {# object} other {# objecten}} selecteren.",
"go_further_without_selected_object": "Ga verder zonder object",
"zoom_for_object": "Zoom in om de objecten te zien",
"zoom_for_object": "Zoom in op de kaart om de objecten te zien",
"scroll_for_map": "Scroll naar onder om de kaart te weergeven",
"scroll_to_map_button": "Naar beneden",
"map_zoom-in_button_label": "Zoom in op de kaart",
"map_zoom-out_button_label": "Zoom uit op de kaart",
"map_close_button_label": "Sluit de kaart",
Expand Down

0 comments on commit 637ddbc

Please sign in to comment.