✨(frontend) improve modal a11y: structure, labels, and title
added aria-label, structured text in p, and added title for better accessibility Signed-off-by: Cyril <c.gromoff@gmail.com>
This commit is contained in:
@@ -463,12 +463,14 @@ test.describe('Doc Editor', () => {
|
||||
await expect(
|
||||
page.getByRole('button', {
|
||||
name: 'Download',
|
||||
exact: true,
|
||||
}),
|
||||
).toBeVisible();
|
||||
|
||||
void page
|
||||
.getByRole('button', {
|
||||
name: 'Download',
|
||||
exact: true,
|
||||
})
|
||||
.click();
|
||||
|
||||
|
||||
@@ -38,7 +38,9 @@ test.describe('Doc Export', () => {
|
||||
).toBeVisible();
|
||||
await expect(page.getByRole('combobox', { name: 'Format' })).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Close the modal' }),
|
||||
page.getByRole('button', {
|
||||
name: 'Close the download modal',
|
||||
}),
|
||||
).toBeVisible();
|
||||
await expect(page.getByTestId('doc-export-download-button')).toBeVisible();
|
||||
});
|
||||
|
||||
@@ -149,7 +149,7 @@ test.describe('Document grid item options', () => {
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Confirm deletion',
|
||||
name: 'Delete document',
|
||||
})
|
||||
.click();
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ test.describe('Doc Header', () => {
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Confirm deletion',
|
||||
name: 'Delete document',
|
||||
})
|
||||
.click();
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ test.describe('Document search', () => {
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.getByLabel('Search modal').getByText('search'),
|
||||
page.getByRole('heading', { name: 'Search docs' }),
|
||||
).toBeVisible();
|
||||
|
||||
const inputSearch = page.getByPlaceholder('Type the name of a document');
|
||||
@@ -79,7 +79,7 @@ test.describe('Document search', () => {
|
||||
|
||||
await page.keyboard.press('Control+k');
|
||||
await expect(
|
||||
page.getByLabel('Search modal').getByText('search'),
|
||||
page.getByRole('heading', { name: 'Search docs' }),
|
||||
).toBeVisible();
|
||||
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
@@ -30,15 +30,23 @@ export const AlertModal = ({
|
||||
isOpen={isOpen}
|
||||
size={ModalSize.MEDIUM}
|
||||
onClose={onClose}
|
||||
aria-describedby="alert-modal-title"
|
||||
title={
|
||||
<Text $size="h6" $align="flex-start" $variation="1000">
|
||||
<Text
|
||||
$size="h6"
|
||||
as="h1"
|
||||
$margin="0"
|
||||
id="alert-modal-title"
|
||||
$align="flex-start"
|
||||
$variation="1000"
|
||||
>
|
||||
{title}
|
||||
</Text>
|
||||
}
|
||||
rightActions={
|
||||
<>
|
||||
<Button
|
||||
aria-label={t('Close the modal')}
|
||||
aria-label={`${t('Cancel')} - ${title}`}
|
||||
color="secondary"
|
||||
fullWidth
|
||||
onClick={() => onClose()}
|
||||
@@ -55,12 +63,11 @@ export const AlertModal = ({
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Box
|
||||
aria-label={t('Confirmation button')}
|
||||
className="--docs--alert-modal"
|
||||
>
|
||||
<Box className="--docs--alert-modal">
|
||||
<Box>
|
||||
<Text $variation="600">{description}</Text>
|
||||
<Text $variation="600" as="p">
|
||||
{description}
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
</Modal>
|
||||
|
||||
@@ -19,10 +19,11 @@ export const ModalConfirmDownloadUnsafe = ({
|
||||
isOpen
|
||||
closeOnClickOutside
|
||||
onClose={() => onClose()}
|
||||
aria-describedby="modal-confirm-download-unsafe-title"
|
||||
rightActions={
|
||||
<>
|
||||
<Button
|
||||
aria-label={t('Close the modal')}
|
||||
aria-label={t('Cancel the download')}
|
||||
color="secondary"
|
||||
onClick={() => onClose()}
|
||||
>
|
||||
@@ -31,6 +32,7 @@ export const ModalConfirmDownloadUnsafe = ({
|
||||
<Button
|
||||
aria-label={t('Download')}
|
||||
color="danger"
|
||||
data-testid="modal-download-unsafe-button"
|
||||
onClick={() => {
|
||||
if (onConfirm) {
|
||||
void onConfirm();
|
||||
@@ -45,6 +47,8 @@ export const ModalConfirmDownloadUnsafe = ({
|
||||
size={ModalSize.SMALL}
|
||||
title={
|
||||
<Text
|
||||
as="h1"
|
||||
id="modal-confirm-download-unsafe-title"
|
||||
$gap="0.7rem"
|
||||
$size="h6"
|
||||
$align="flex-start"
|
||||
|
||||
@@ -133,10 +133,11 @@ export const ModalExport = ({ onClose, doc }: ModalExportProps) => {
|
||||
closeOnClickOutside
|
||||
onClose={() => onClose()}
|
||||
hideCloseButton
|
||||
aria-describedby="modal-export-title"
|
||||
rightActions={
|
||||
<>
|
||||
<Button
|
||||
aria-label={t('Close the modal')}
|
||||
aria-label={t('Cancel the download')}
|
||||
color="secondary"
|
||||
fullWidth
|
||||
onClick={() => onClose()}
|
||||
@@ -165,6 +166,9 @@ export const ModalExport = ({ onClose, doc }: ModalExportProps) => {
|
||||
$width="100%"
|
||||
>
|
||||
<Text
|
||||
as="h1"
|
||||
$margin="0"
|
||||
id="modal-export-title"
|
||||
$size="h6"
|
||||
$variation="1000"
|
||||
$align="flex-start"
|
||||
@@ -186,7 +190,7 @@ export const ModalExport = ({ onClose, doc }: ModalExportProps) => {
|
||||
$gap="1rem"
|
||||
className="--docs--modal-export-content"
|
||||
>
|
||||
<Text $variation="600" $size="sm">
|
||||
<Text $variation="600" $size="sm" as="p">
|
||||
{t('Download your document in a .docx or .pdf format.')}
|
||||
</Text>
|
||||
<Select
|
||||
|
||||
@@ -56,10 +56,11 @@ export const ModalRemoveDoc = ({
|
||||
closeOnClickOutside
|
||||
hideCloseButton
|
||||
onClose={() => onClose()}
|
||||
aria-describedby="modal-remove-doc-title"
|
||||
rightActions={
|
||||
<>
|
||||
<Button
|
||||
aria-label={t('Close the delete modal')}
|
||||
aria-label={t('Cancel the deletion')}
|
||||
color="secondary"
|
||||
fullWidth
|
||||
onClick={() => onClose()}
|
||||
@@ -67,7 +68,7 @@ export const ModalRemoveDoc = ({
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
aria-label={t('Confirm deletion')}
|
||||
aria-label={t('Delete document')}
|
||||
color="danger"
|
||||
fullWidth
|
||||
onClick={() =>
|
||||
@@ -90,8 +91,9 @@ export const ModalRemoveDoc = ({
|
||||
>
|
||||
<Text
|
||||
$size="h6"
|
||||
as="h6"
|
||||
$margin={{ all: '0' }}
|
||||
as="h1"
|
||||
id="modal-remove-doc-title"
|
||||
$margin="0"
|
||||
$align="flex-start"
|
||||
$variation="1000"
|
||||
>
|
||||
@@ -104,12 +106,9 @@ export const ModalRemoveDoc = ({
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<Box
|
||||
aria-label={t('Content modal to delete document')}
|
||||
className="--docs--modal-remove-doc"
|
||||
>
|
||||
<Box className="--docs--modal-remove-doc">
|
||||
{!isError && (
|
||||
<Text $size="sm" $variation="600" $display="inline-block">
|
||||
<Text $size="sm" $variation="600" $display="inline-block" as="p">
|
||||
<Trans t={t}>
|
||||
This document and <strong>any sub-documents</strong> will be
|
||||
permanently deleted. This action is irreversible.
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
|
||||
import { Box } from '@/components';
|
||||
import { Box, Text } from '@/components';
|
||||
import ButtonCloseModal from '@/components/modal/ButtonCloseModal';
|
||||
import { QuickSearch } from '@/components/quick-search';
|
||||
import { Doc, useDocUtils } from '@/docs/doc-management';
|
||||
@@ -65,6 +65,7 @@ const DocSearchModalGlobal = ({
|
||||
closeOnClickOutside
|
||||
size={isDesktop ? ModalSize.LARGE : ModalSize.FULL}
|
||||
hideCloseButton
|
||||
aria-describedby="doc-search-modal-title"
|
||||
>
|
||||
<Box
|
||||
aria-label={t('Search modal')}
|
||||
@@ -72,6 +73,14 @@ const DocSearchModalGlobal = ({
|
||||
$justify="space-between"
|
||||
className="--docs--doc-search-modal"
|
||||
>
|
||||
<Text
|
||||
as="h1"
|
||||
$margin="0"
|
||||
id="doc-search-modal-title"
|
||||
className="sr-only"
|
||||
>
|
||||
{t('Search docs')}
|
||||
</Text>
|
||||
<Box $position="absolute" $css="top: 12px; right: 12px;">
|
||||
<ButtonCloseModal
|
||||
aria-label={t('Close the search modal')}
|
||||
|
||||
@@ -135,12 +135,20 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => {
|
||||
isOpen
|
||||
closeOnClickOutside
|
||||
data-testid="doc-share-modal"
|
||||
aria-label={t('Share modal')}
|
||||
aria-describedby="doc-share-modal-title"
|
||||
size={isDesktop ? ModalSize.LARGE : ModalSize.FULL}
|
||||
onClose={onClose}
|
||||
title={
|
||||
<Box $direction="row" $justify="space-between" $align="center">
|
||||
<Box $align="flex-start">{t('Share the document')}</Box>
|
||||
<Text
|
||||
as="h1"
|
||||
id="doc-share-modal-title"
|
||||
$align="flex-start"
|
||||
$size="small"
|
||||
$weight="600"
|
||||
>
|
||||
{t('Share the document')}
|
||||
</Text>
|
||||
<ButtonCloseModal
|
||||
aria-label={t('Close the share modal')}
|
||||
onClick={onClose}
|
||||
@@ -199,6 +207,7 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => {
|
||||
$textAlign="center"
|
||||
$variation="600"
|
||||
$size="sm"
|
||||
as="p"
|
||||
>
|
||||
{t(
|
||||
'You can view this document but need additional access to see its members or modify settings.',
|
||||
|
||||
@@ -69,10 +69,11 @@ export const ModalConfirmationVersion = ({
|
||||
isOpen
|
||||
closeOnClickOutside
|
||||
onClose={() => onClose()}
|
||||
aria-describedby="modal-confirmation-version-title"
|
||||
rightActions={
|
||||
<>
|
||||
<Button
|
||||
aria-label={t('Close the modal')}
|
||||
aria-label={`${t('Cancel')} - ${t('Warning')}`}
|
||||
color="secondary"
|
||||
fullWidth
|
||||
onClick={() => onClose()}
|
||||
@@ -102,20 +103,24 @@ export const ModalConfirmationVersion = ({
|
||||
}
|
||||
size={ModalSize.SMALL}
|
||||
title={
|
||||
<Text $size="h6" $align="flex-start" $variation="1000">
|
||||
<Text
|
||||
as="h1"
|
||||
$margin="0"
|
||||
id="modal-confirmation-version-title"
|
||||
$size="h6"
|
||||
$align="flex-start"
|
||||
$variation="1000"
|
||||
>
|
||||
{t('Warning')}
|
||||
</Text>
|
||||
}
|
||||
>
|
||||
<Box
|
||||
aria-label={t('Modal confirmation to restore the version')}
|
||||
className="--docs--modal-confirmation-version"
|
||||
>
|
||||
<Box className="--docs--modal-confirmation-version">
|
||||
<Box>
|
||||
<Text $variation="600">
|
||||
<Text $variation="600" as="p">
|
||||
{t('Your current document will revert to this version.')}
|
||||
</Text>
|
||||
<Text $variation="600">
|
||||
<Text $variation="600" as="p">
|
||||
{t('If a member is editing, his works can be lost.')}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
@@ -48,6 +48,7 @@ export const ModalSelectVersion = ({
|
||||
closeOnClickOutside={true}
|
||||
size={ModalSize.EXTRA_LARGE}
|
||||
onClose={onClose}
|
||||
aria-describedby="modal-select-version-title"
|
||||
>
|
||||
<NoPaddingStyle />
|
||||
<Box
|
||||
@@ -58,6 +59,14 @@ export const ModalSelectVersion = ({
|
||||
$maxHeight="calc(100vh - 2em - 12px)"
|
||||
$overflow="hidden"
|
||||
>
|
||||
<Text
|
||||
as="h1"
|
||||
$margin="0"
|
||||
id="modal-select-version-title"
|
||||
className="sr-only"
|
||||
>
|
||||
{t('Version history')}
|
||||
</Text>
|
||||
<Box
|
||||
$css={css`
|
||||
display: flex;
|
||||
|
||||
@@ -272,6 +272,7 @@
|
||||
"Close the search modal": "Such-Modal schließen",
|
||||
"Close the share modal": "Freigabe-Modal schließen",
|
||||
"Close the version history modal": "Versionsverlauf-Modal schließen",
|
||||
"Close the download modal": "Download-Modal schließen",
|
||||
"Collaborate": "Zusammenarbeiten",
|
||||
"Collaborate and write in real time, without layout constraints.": "In Echtzeit und ohne Layout-Beschränkungen schreiben und zusammenarbeiten.",
|
||||
"Collaborative writing, Simplified.": "Kollaboratives Schreiben, vereinfacht.",
|
||||
@@ -463,6 +464,9 @@
|
||||
"Close the search modal": "Close the search modal",
|
||||
"Close the share modal": "Close the share modal",
|
||||
"Close the version history modal": "Close the version history modal",
|
||||
"Close the download modal": "Close the download modal",
|
||||
"Cancel the deletion": "Cancel the deletion",
|
||||
"Cancel the download": "Cancel the download",
|
||||
"Open actions menu for document: {{title}}": "Open actions menu for document: {{title}}",
|
||||
"Open the menu of actions for the document: {{title}}": "Open the menu of actions for the document: {{title}}",
|
||||
"Share with {{count}} users_one": "Share with {{count}} user",
|
||||
@@ -505,10 +509,13 @@
|
||||
"Close the search modal": "Cerrar modal de búsqueda",
|
||||
"Close the share modal": "Cerrar modal de compartir",
|
||||
"Close the version history modal": "Cerrar modal de historial de versiones",
|
||||
"Close the download modal": "Cerrar modal de descarga",
|
||||
"Collaborate": "Colabora",
|
||||
"Collaborate and write in real time, without layout constraints.": "Colaborar y escribir en tiempo real, sin restricciones de diseño.",
|
||||
"Collaborative writing, Simplified.": "Escritura colaborativa, más sencilla.",
|
||||
"Confirm deletion": "Confirmar borrado",
|
||||
"Cancel the deletion": "Cancelar la eliminación",
|
||||
"Cancel the download": "Cancelar la descarga",
|
||||
"Connected": "Conectado",
|
||||
"Content modal to delete document": "Modal para eliminar el documento",
|
||||
"Content modal to export the document": "Ventana emergente para exportar el documento",
|
||||
@@ -704,6 +711,8 @@
|
||||
"Collaborative writing, Simplified.": "L'écriture collaborative simplifiée.",
|
||||
"Confirm": "Confirmez",
|
||||
"Confirm deletion": "Confirmer la suppression",
|
||||
"Cancel the deletion": "Annuler la suppression",
|
||||
"Cancel the download": "Annuler le téléchargement",
|
||||
"Confirmation button": "Bouton de confirmation",
|
||||
"Connected": "Connecté",
|
||||
"Content modal to delete document": "Contenu modal pour supprimer le document",
|
||||
@@ -1088,10 +1097,13 @@
|
||||
"Close the search modal": "Sluit het zoek venster",
|
||||
"Close the share modal": "Sluit het delen venster",
|
||||
"Close the version history modal": "Sluit het versiehistorie venster",
|
||||
"Close the download modal": "Sluit het download venster",
|
||||
"Collaborate": "Samenwerken",
|
||||
"Collaborate and write in real time, without layout constraints.": "Samenwerken en schrijven in realtime, zonder lay-out beperkingen.",
|
||||
"Collaborative writing, Simplified.": "Vereenvoudigd samenwerkend",
|
||||
"Confirm deletion": "Bevestig verwijdering",
|
||||
"Cancel the deletion": "Annuleer de verwijdering",
|
||||
"Cancel the download": "Annuleer de download",
|
||||
"Connected": "Verbonden",
|
||||
"Content modal to delete document": "Content venster om het document te verwijderen",
|
||||
"Content modal to export the document": "Content venster om document te exporteren",
|
||||
|
||||
@@ -82,3 +82,16 @@ main ::-webkit-scrollbar-thumb:hover,
|
||||
nextjs-portal {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Screen reader only - visually hidden but accessible to screen readers */
|
||||
.sr-only {
|
||||
position: absolute !important;
|
||||
width: 1px !important;
|
||||
height: 1px !important;
|
||||
padding: 0 !important;
|
||||
margin: -1px !important;
|
||||
overflow: hidden !important;
|
||||
clip-path: inset(50%) !important;
|
||||
white-space: nowrap !important;
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user