Commit 2154286b authored by Enrique Alcantara's avatar Enrique Alcantara

Add badge sr-only text to inline avatars

Add additional information for screen-reader
form factor in the inline avatars component
parent da4f16bf
......@@ -15,7 +15,7 @@ import getAlertsQuery from '~/graphql_shared/queries/get_alerts.query.graphql';
import { fetchPolicies } from '~/lib/graphql';
import { convertToSnakeCase } from '~/lib/utils/text_utility';
import { joinPaths, visitUrl } from '~/lib/utils/url_utility';
import { s__, __ } from '~/locale';
import { s__, __, n__ } from '~/locale';
import AlertStatus from '~/vue_shared/alert_details/components/alert_status.vue';
import {
tdClass,
......@@ -32,8 +32,11 @@ const TH_TEST_ID = { 'data-testid': 'alert-management-severity-sort' };
const TWELVE_HOURS_IN_MS = 12 * 60 * 60 * 1000;
const MAX_VISIBLE_ASSIGNEES = 4;
export default {
trackAlertListViewsOptions,
MAX_VISIBLE_ASSIGNEES,
i18n: {
noAlertsMsg: s__(
'AlertManagement|No alerts available to display. See %{linkStart}enabling alert management%{linkEnd} for more information on adding alerts to the list.',
......@@ -258,6 +261,13 @@ export default {
this.serverErrorMessage = '';
this.isErrorAlertDismissed = true;
},
assigneesBadgeSrOnlyText(item) {
return n__(
'%d additional assignee',
'%d additional assignees',
item.assignees.nodes.length - MAX_VISIBLE_ASSIGNEES,
);
},
},
};
</script>
......@@ -365,10 +375,11 @@ export default {
<gl-avatars-inline
:avatars="item.assignees.nodes"
:collapsed="true"
:max-visible="4"
:max-visible="$options.MAX_VISIBLE_ASSIGNEES"
:avatar-size="24"
badge-tooltip-prop="name"
:badge-tooltip-max-chars="100"
:badge-sr-only-text="assigneesBadgeSrOnlyText(item)"
>
<template #avatar="{ avatar }">
<gl-avatar-link
......
......@@ -12,7 +12,7 @@ import {
} from '@gitlab/ui';
import { isValidSlaDueAt } from 'ee_else_ce/vue_shared/components/incidents/utils';
import { visitUrl, mergeUrlParams, joinPaths } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import { s__, n__ } from '~/locale';
import { INCIDENT_SEVERITY } from '~/sidebar/components/severity/constants';
import SeverityToken from '~/sidebar/components/severity/severity.vue';
import Tracking from '~/tracking';
......@@ -38,6 +38,8 @@ import {
import getIncidentsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql';
import getIncidents from '../graphql/queries/get_incidents.query.graphql';
const MAX_VISIBLE_ASSIGNEES = 4;
export default {
trackIncidentCreateNewOptions,
trackIncidentListViewsOptions,
......@@ -94,6 +96,7 @@ export default {
thAttr: TH_PUBLISHED_TEST_ID,
},
],
MAX_VISIBLE_ASSIGNEES,
components: {
GlLoadingIcon,
GlTable,
......@@ -295,6 +298,13 @@ export default {
errorAlertDismissed() {
this.isErrorAlertDismissed = true;
},
assigneesBadgeSrOnlyText(item) {
return n__(
'%d additional assignee',
'%d additional assignees',
item.assignees.nodes.length - MAX_VISIBLE_ASSIGNEES,
);
},
isValidSlaDueAt,
},
};
......@@ -391,10 +401,11 @@ export default {
<gl-avatars-inline
:avatars="item.assignees.nodes"
:collapsed="true"
:max-visible="4"
:max-visible="$options.MAX_VISIBLE_ASSIGNEES"
:avatar-size="24"
badge-tooltip-prop="name"
:badge-tooltip-max-chars="100"
:badge-sr-only-text="assigneesBadgeSrOnlyText(item)"
>
<template #avatar="{ avatar }">
<gl-avatar-link
......
<script>
import { GlAvatarLink, GlAvatar, GlAvatarsInline, GlTooltipDirective } from '@gitlab/ui';
import { n__ } from '~/locale';
export const MAX_VISIBLE_AVATARS_DEFAULT = 3;
export const MAX_VISIBLE_AVATARS_COLLAPSED = 2;
......@@ -36,6 +37,13 @@ export default {
firstApprover() {
return this.approvers[0];
},
approversBadgeSrOnlyText() {
return n__(
'%d additional approver',
'%d additional approvers',
this.approvers.length - this.maxVisible,
);
},
},
avatarSize: 24,
badgeTooltipMaxChars: 50,
......@@ -52,6 +60,7 @@ export default {
:avatar-size="$options.avatarSize"
badge-tooltip-prop="name"
:badge-tooltip-max-chars="$options.badgeTooltipMaxChars"
:badge-sr-only-text="approversBadgeSrOnlyText"
>
<template #avatar="{ avatar }">
<gl-avatar-link v-gl-tooltip target="_blank" :href="avatar.web_url" :title="avatar.name">
......
......@@ -255,6 +255,13 @@ export default {
hasPipelineNodes(item) {
return item.pipelines?.nodes;
},
assigneesBadgeSrOnlyText(item) {
return n__(
'%d additional assignee',
'%d additional assignees',
item.assignees.nodes.length - this.$options.assigneesVisible,
);
},
},
assigneesVisible: ASSIGNEES_VISIBLE,
avatarSize: AVATAR_SIZE,
......@@ -361,6 +368,7 @@ export default {
:avatars="item.assignees.nodes"
:avatar-size="$options.avatarSize"
:max-visible="$options.assigneesVisible"
:badge-sr-only-text="assigneesBadgeSrOnlyText(item)"
collapsed
>
<template #avatar="{ avatar }">
......
......@@ -2,6 +2,7 @@
import { __, n__ } from '~/locale';
import DrawerAvatarsList from '../shared/drawer_avatars_list.vue';
import DrawerSectionHeader from '../shared/drawer_section_header.vue';
import { DRAWER_MAXIMUM_AVATARS } from '../../constants';
export default {
components: {
......@@ -19,6 +20,13 @@ export default {
committersHeaderText() {
return n__('%d commit author', '%d commit authors', this.committers.length);
},
committersBadgeSrOnlyText() {
return n__(
'%d additional committer',
'%d additional committers',
this.committers.length - DRAWER_MAXIMUM_AVATARS,
);
},
},
i18n: {
header: __('Change made by'),
......@@ -33,6 +41,7 @@ export default {
:header="committersHeaderText"
:empty-header="$options.i18n.emptyHeader"
:avatars="committers"
:badge-sr-only-text="committersBadgeSrOnlyText"
/>
</div>
</template>
<script>
import { __, n__ } from '~/locale';
import { DRAWER_AVATAR_SIZE } from '../../constants';
import { DRAWER_AVATAR_SIZE, DRAWER_MAXIMUM_AVATARS } from '../../constants';
import DrawerAvatarsList from '../shared/drawer_avatars_list.vue';
import DrawerSectionHeader from '../shared/drawer_section_header.vue';
......@@ -28,6 +28,20 @@ export default {
approversHeaderText() {
return n__('%d approver', '%d approvers', this.approvers.length);
},
commentersBadgeSrOnlyText() {
return n__(
'%d additional commenter',
'%d additional commenters',
this.commenters.length - DRAWER_MAXIMUM_AVATARS,
);
},
approversBadgeSrOnlyText() {
return n__(
'%d additional approver',
'%d additional approvers',
this.approvers.length - DRAWER_MAXIMUM_AVATARS,
);
},
hasCommenters() {
return this.commenters.length > 0;
},
......@@ -50,6 +64,7 @@ export default {
:header="commentersHeaderText"
:empty-header="$options.i18n.commentersEmptyHeader"
:avatars="commenters"
:badge-sr-only-text="commentersBadgeSrOnlyText"
data-testid="commenters-avatar-list"
/>
<drawer-avatars-list
......@@ -57,6 +72,7 @@ export default {
:header="approversHeaderText"
:empty-header="$options.i18n.approversEmptyHeader"
:avatars="approvers"
:badge-sr-only-text="approversBadgeSrOnlyText"
data-testid="approvers-avatar-list"
/>
</div>
......
<script>
import { GlAvatarLink, GlAvatar, GlAvatarsInline, GlTooltipDirective } from '@gitlab/ui';
import { sprintf, __ } from '~/locale';
import { sprintf, __, n__ } from '~/locale';
import { PRESENTABLE_APPROVERS_LIMIT } from '../../constants';
export default {
......@@ -36,6 +36,13 @@ export default {
approvers: this.amountOfApproversOverLimit,
});
},
approversBadgeSrOnlyText() {
return n__(
'%d additional approver',
'%d additional approvers',
this.amountOfApproversOverLimit,
);
},
},
PRESENTABLE_APPROVERS_LIMIT,
strings: {
......@@ -61,6 +68,7 @@ export default {
:collapsed="true"
:max-visible="$options.PRESENTABLE_APPROVERS_LIMIT"
:avatar-size="24"
:badge-sr-only-text="approversBadgeSrOnlyText"
class="gl-display-inline-flex gl-lg-display-none! gl-ml-3"
badge-tooltip-prop="name"
>
......
......@@ -26,6 +26,10 @@ export default {
required: false,
default: '',
},
badgeSrOnlyText: {
type: String,
required: true,
},
},
computed: {
isEmpty() {
......@@ -53,6 +57,7 @@ export default {
:avatars="avatars"
:max-visible="$options.DRAWER_MAXIMUM_AVATARS"
:avatar-size="$options.DRAWER_AVATAR_SIZE"
:badge-sr-only-text="badgeSrOnlyText"
class="gl-flex-wrap gl-w-full!"
badge-tooltip-prop="name"
>
......
......@@ -24,6 +24,7 @@ const SYMBOL = {
ISSUE: '#',
EPIC: '&',
};
const MAX_VISIBLE_ASSIGNEES = 2;
const TH_TEST_ID = { 'data-testid': 'header' };
......@@ -141,8 +142,16 @@ export default {
labelTarget(name) {
return mergeUrlParams({ 'label_name[]': name }, this.endpoints.issuesPage);
},
assigneesBadgeSrOnlyText(assignees) {
return n__(
'%d additional assignee',
'%d additional assignees',
assignees.length - MAX_VISIBLE_ASSIGNEES,
);
},
},
avatarSize: 24,
MAX_VISIBLE_ASSIGNEES,
};
</script>
<template>
......@@ -213,7 +222,8 @@ export default {
<gl-avatars-inline
:avatars="value"
:avatar-size="$options.avatarSize"
:max-visible="2"
:max-visible="$options.MAX_VISIBLE_ASSIGNEES"
:badge-sr-only-text="assigneesBadgeSrOnlyText(value)"
collapsed
>
<template #avatar="{ avatar }">
......
......@@ -13,6 +13,7 @@ import {
GlTooltipDirective,
} from '@gitlab/ui';
import produce from 'immer';
import { n__ } from '~/locale';
import getAlertsQuery from '~/graphql_shared/queries/get_alerts.query.graphql';
import { convertToSnakeCase } from '~/lib/utils/text_utility';
import { joinPaths } from '~/lib/utils/url_utility';
......@@ -23,6 +24,8 @@ import AlertFilters from './alert_filters.vue';
import AlertStatus from './alert_status.vue';
import { DEFAULT_FILTERS, FIELDS, MESSAGES, STATUSES, DOMAIN, CLOSED } from './constants';
const MAX_VISIBLE_ASSIGNEES = 4;
export default {
PAGE_SIZE,
DOMAIN,
......@@ -32,6 +35,7 @@ export default {
STATUSES,
CLOSED,
},
MAX_VISIBLE_ASSIGNEES,
components: {
AlertDrawer,
AlertStatus,
......@@ -166,6 +170,13 @@ export default {
this.isAlertDrawerOpen = true;
this.selectedAlert = data;
},
assigneesBadgeSrOnlyText(assignees) {
return n__(
'%d additional assignee',
'%d additional assignees',
assignees.length - MAX_VISIBLE_ASSIGNEES,
);
},
},
};
</script>
......@@ -255,10 +266,11 @@ export default {
data-testid="assigneesField"
:avatars="item.assignees.nodes"
:collapsed="true"
:max-visible="4"
:max-visible="$options.MAX_VISIBLE_ASSIGNEES"
:avatar-size="24"
badge-tooltip-prop="name"
:badge-tooltip-max-chars="100"
:badge-sr-only-text="assigneesBadgeSrOnlyText(item.assignees.nodes)"
>
<template #avatar="{ avatar }">
<gl-avatar-link
......
......@@ -5,6 +5,7 @@ exports[`ApproversColumn component when a list with more than three approvers is
<gl-avatars-inline-stub
avatars="[object Object],[object Object],[object Object],[object Object]"
avatarsize="24"
badgesronlytext="2 additional approvers"
badgetooltipmaxchars="50"
badgetooltipprop="name"
collapsed="true"
......@@ -37,6 +38,7 @@ exports[`ApproversColumn component when a list with three approvers is passed ma
<gl-avatars-inline-stub
avatars="[object Object],[object Object],[object Object]"
avatarsize="24"
badgesronlytext="0 additional approvers"
badgetooltipmaxchars="50"
badgetooltipprop="name"
collapsed="true"
......@@ -50,6 +52,7 @@ exports[`ApproversColumn component when a list with two approvers is passed matc
<gl-avatars-inline-stub
avatars="[object Object],[object Object]"
avatarsize="24"
badgesronlytext="-1 additional approvers"
badgetooltipmaxchars="50"
badgetooltipprop="name"
collapsed="true"
......
......@@ -16,6 +16,7 @@ exports[`MergeRequest component when there are approvers matches snapshot 1`] =
<gl-avatars-inline-stub
avatars="[object Object]"
avatarsize="24"
badgesronlytext="-1 additional approvers"
badgetooltipprop="name"
class="gl-display-inline-flex gl-lg-display-none! gl-ml-3"
collapsed="true"
......
......@@ -17,7 +17,10 @@ describe('DrawerAvatarsList component', () => {
const createComponent = (mountFn = shallowMount, propsData = {}) => {
return mountFn(DrawerAvatarsList, {
propsData,
propsData: {
badgeSrOnlyText: 'additional approvers',
...propsData,
},
});
};
......
......@@ -41767,6 +41767,18 @@ msgstr ""
msgid "added a Zoom call to this issue"
msgstr ""
msgid "additional approvers"
msgstr ""
msgid "additional assignees"
msgstr ""
msgid "additional commenters"
msgstr ""
msgid "additional committers"
msgstr ""
msgid "ago"
msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment