✨(frontend) improve share modal button accessibility
Added aria-labels to remove and invite buttons Signed-off-by: Cyril <c.gromoff@gmail.com>
This commit is contained in:
@@ -6,6 +6,11 @@ and this project adheres to
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- ♿(frontend) improve accessibility:
|
||||||
|
- ♿(frontend) improve share modal button accessibility #1626
|
||||||
|
|
||||||
## [3.10.0] - 2025-11-18
|
## [3.10.0] - 2025-11-18
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ test.describe('Document create member', () => {
|
|||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
await page.getByRole('menuitem', { name: 'Administrator' }).click();
|
await page.getByRole('menuitem', { name: 'Administrator' }).click();
|
||||||
await page.getByRole('button', { name: 'Invite' }).click();
|
await page.getByRole('button', { name: /^Invite / }).click();
|
||||||
|
|
||||||
// Check invitation added
|
// Check invitation added
|
||||||
await expect(
|
await expect(
|
||||||
@@ -135,7 +135,7 @@ test.describe('Document create member', () => {
|
|||||||
(response) =>
|
(response) =>
|
||||||
response.url().includes('/invitations/') && response.status() === 201,
|
response.url().includes('/invitations/') && response.status() === 201,
|
||||||
);
|
);
|
||||||
await page.getByRole('button', { name: 'Invite' }).click();
|
await page.getByRole('button', { name: /^Invite / }).click();
|
||||||
|
|
||||||
// Check invitation sent
|
// Check invitation sent
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ test.describe('Document create member', () => {
|
|||||||
response.url().includes('/invitations/') && response.status() === 400,
|
response.url().includes('/invitations/') && response.status() === 400,
|
||||||
);
|
);
|
||||||
|
|
||||||
await page.getByRole('button', { name: 'Invite' }).click();
|
await page.getByRole('button', { name: /^Invite / }).click();
|
||||||
await expect(
|
await expect(
|
||||||
page.getByText(`"${email}" is already invited to the document.`),
|
page.getByText(`"${email}" is already invited to the document.`),
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
@@ -191,7 +191,7 @@ test.describe('Document create member', () => {
|
|||||||
response.url().includes('/invitations/') && response.status() === 201,
|
response.url().includes('/invitations/') && response.status() === 201,
|
||||||
);
|
);
|
||||||
|
|
||||||
await page.getByRole('button', { name: 'Invite' }).click();
|
await page.getByRole('button', { name: /^Invite / }).click();
|
||||||
|
|
||||||
// Check invitation sent
|
// Check invitation sent
|
||||||
const responseCreateInvitation = await responsePromiseCreateInvitation;
|
const responseCreateInvitation = await responsePromiseCreateInvitation;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export const addNewMember = async (
|
|||||||
// Choose a role
|
// Choose a role
|
||||||
await page.getByLabel('doc-role-dropdown').click();
|
await page.getByLabel('doc-role-dropdown').click();
|
||||||
await page.getByRole('menuitem', { name: role }).click();
|
await page.getByRole('menuitem', { name: role }).click();
|
||||||
await page.getByRole('button', { name: 'Invite' }).click();
|
await page.getByRole('button', { name: /^Invite / }).click();
|
||||||
|
|
||||||
return users[index].email;
|
return users[index].email;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -108,6 +108,12 @@ export const DocShareAddMemberList = ({
|
|||||||
afterInvite?.();
|
afterInvite?.();
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
|
const inviteLabel =
|
||||||
|
selectedUsers.length === 1
|
||||||
|
? t('Invite {{name}}', {
|
||||||
|
name: selectedUsers[0].full_name || selectedUsers[0].email,
|
||||||
|
})
|
||||||
|
: t('Invite {{count}} members', { count: selectedUsers.length });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@@ -143,7 +149,11 @@ export const DocShareAddMemberList = ({
|
|||||||
currentRole={invitationRole}
|
currentRole={invitationRole}
|
||||||
onSelectRole={setInvitationRole}
|
onSelectRole={setInvitationRole}
|
||||||
/>
|
/>
|
||||||
<Button onClick={() => void onInvite()} disabled={isLoading}>
|
<Button
|
||||||
|
onClick={() => void onInvite()}
|
||||||
|
disabled={isLoading}
|
||||||
|
aria-label={inviteLabel}
|
||||||
|
>
|
||||||
{t('Invite')}
|
{t('Invite')}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Button } from '@openfun/cunningham-react';
|
import { Button } from '@openfun/cunningham-react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { css } from 'styled-components';
|
import { css } from 'styled-components';
|
||||||
|
|
||||||
import { Box, Icon, Text } from '@/components';
|
import { Box, Icon, Text } from '@/components';
|
||||||
@@ -10,6 +11,7 @@ type Props = {
|
|||||||
onRemoveUser?: (user: User) => void;
|
onRemoveUser?: (user: User) => void;
|
||||||
};
|
};
|
||||||
export const DocShareAddMemberListItem = ({ user, onRemoveUser }: Props) => {
|
export const DocShareAddMemberListItem = ({ user, onRemoveUser }: Props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { spacingsTokens, colorsTokens, fontSizesTokens } =
|
const { spacingsTokens, colorsTokens, fontSizesTokens } =
|
||||||
useCunninghamTheme();
|
useCunninghamTheme();
|
||||||
|
|
||||||
@@ -42,6 +44,9 @@ export const DocShareAddMemberListItem = ({ user, onRemoveUser }: Props) => {
|
|||||||
size="nano"
|
size="nano"
|
||||||
onClick={() => onRemoveUser?.(user)}
|
onClick={() => onRemoveUser?.(user)}
|
||||||
icon={<Icon $variation="600" $size="sm" iconName="close" />}
|
icon={<Icon $variation="600" $size="sm" iconName="close" />}
|
||||||
|
aria-label={t('Remove {{name}} from the invite list', {
|
||||||
|
name: user.full_name || user.email,
|
||||||
|
})}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user