From 2cdcd43dac540867930bbd11d4cba9fa3c02facf Mon Sep 17 00:00:00 2001 From: Mathieu Suen Date: Tue, 13 Jun 2023 13:38:13 +0200 Subject: [PATCH] SONAR-19526 Improve accessibility of FlagMessage --- .../src/components/FlagMessage.tsx | 74 ++++++++----------- .../components/__tests__/FlagMessage-test.tsx | 14 ++-- .../nav/component/AnalysisStatus.tsx | 4 +- .../apps/code/components/CodeAppRenderer.tsx | 6 +- .../__tests__/ComponentMeasures-it.tsx | 2 +- .../drilldown/FilesView.tsx | 13 +--- .../component-measures/sidebar/Sidebar.tsx | 6 +- .../issues/components/BulkChangeModal.tsx | 10 +-- .../js/apps/issues/components/IssuesApp.tsx | 15 +--- .../ComponentSourceSnippetGroupViewer.tsx | 6 +- .../js/apps/issues/sidebar/ListStyleFacet.tsx | 12 +-- .../ApplicationNonCaycProjectWarning.tsx | 8 +- .../branches/CleanAsYouCodeWarning.tsx | 5 +- .../apps/overview/branches/NoCodeWarning.tsx | 6 +- .../components/IgnoredConditionWarning.tsx | 6 +- .../components/DuplicationPopup.tsx | 5 +- .../js/components/rules/RuleDescription.tsx | 9 +-- 17 files changed, 57 insertions(+), 144 deletions(-) diff --git a/server/sonar-web/design-system/src/components/FlagMessage.tsx b/server/sonar-web/design-system/src/components/FlagMessage.tsx index 72ef3a9808f..5823faae568 100644 --- a/server/sonar-web/design-system/src/components/FlagMessage.tsx +++ b/server/sonar-web/design-system/src/components/FlagMessage.tsx @@ -28,64 +28,51 @@ import { FlagErrorIcon, FlagInfoIcon, FlagSuccessIcon, FlagWarningIcon } from '. export type Variant = 'error' | 'warning' | 'success' | 'info'; interface Props { - ariaLabel: string; variant: Variant; } -interface VariantInformation { - backGroundColor: ThemeColors; - borderColor: ThemeColors; - icon: JSX.Element; - role: string; -} - -function getVariantInfo(variant: Variant): VariantInformation { - const variantList: Record = { +function getVariantInfo(variant: Variant) { + const variantList = { error: { icon: , borderColor: 'errorBorder', backGroundColor: 'errorBackground', - role: 'alert', }, warning: { icon: , borderColor: 'warningBorder', backGroundColor: 'warningBackground', - role: 'alert', }, success: { icon: , borderColor: 'successBorder', backGroundColor: 'successBackground', - role: 'status', }, info: { icon: , borderColor: 'infoBorder', backGroundColor: 'infoBackground', - role: 'status', }, - }; + } as const; return variantList[variant]; } export function FlagMessage(props: Props & React.HTMLAttributes) { - const { ariaLabel, className, variant, ...domProps } = props; + const { className, variant, ...domProps } = props; const variantInfo = getVariantInfo(variant); return ( - - {variantInfo.icon} - {props.children} - +
+
{variantInfo.icon}
+
{props.children}
+
); } @@ -93,32 +80,33 @@ export function FlagMessage(props: Props & React.HTMLAttributes) FlagMessage.displayName = 'FlagMessage'; // so that tests don't see the obfuscated production name export const StyledFlag = styled.div<{ - variantInfo: VariantInformation; + backGroundColor: ThemeColors; + borderColor: ThemeColors; }>` ${tw`sw-inline-flex`} ${tw`sw-min-h-10`} ${tw`sw-rounded-1`} - border: ${({ variantInfo }) => themeBorder('default', variantInfo.borderColor)}; + border: ${({ borderColor }) => themeBorder('default', borderColor)}; background-color: ${themeColor('flagMessageBackground')}; -`; -const StyledFlagInner = styled.div` - ${tw`sw-flex sw-items-stretch`} - ${tw`sw-box-border`} -`; + & > .flag-inner { + ${tw`sw-flex sw-items-stretch`} + ${tw`sw-box-border`} + } -const StyledFlagIcon = styled.div<{ variantInfo: VariantInformation }>` - ${tw`sw-flex sw-justify-center sw-items-center`} - ${tw`sw-rounded-l-1`} - ${tw`sw-px-3`} - background-color: ${({ variantInfo }) => themeColor(variantInfo.backGroundColor)}; -`; + & .flag-icon { + ${tw`sw-flex sw-justify-center sw-items-center`} + ${tw`sw-rounded-l-1`} + ${tw`sw-px-3`} + background-color: ${({ backGroundColor }) => themeColor(backGroundColor)}; + } -const StyledFlagContent = styled.div` - ${tw`sw-flex sw-flex-auto sw-items-center`} - ${tw`sw-overflow-auto`} - ${tw`sw-text-left`} - ${tw`sw-mx-3 sw-my-2`} - ${tw`sw-body-sm`} - color: ${themeContrast('flagMessageBackground')}; + & .flag-content { + ${tw`sw-flex sw-flex-auto sw-items-center`} + ${tw`sw-overflow-auto`} + ${tw`sw-text-left`} + ${tw`sw-mx-3 sw-my-2`} + ${tw`sw-body-sm`} + color: ${themeContrast('flagMessageBackground')}; + } `; diff --git a/server/sonar-web/design-system/src/components/__tests__/FlagMessage-test.tsx b/server/sonar-web/design-system/src/components/__tests__/FlagMessage-test.tsx index b51dddcad2a..0d1e0dadede 100644 --- a/server/sonar-web/design-system/src/components/__tests__/FlagMessage-test.tsx +++ b/server/sonar-web/design-system/src/components/__tests__/FlagMessage-test.tsx @@ -23,21 +23,21 @@ import { FCProps } from '../../types/misc'; import { FlagMessage, Variant } from '../FlagMessage'; it.each([ - ['error', 'alert', '1px solid rgb(249,112,102)'], - ['warning', 'alert', '1px solid rgb(248,205,92)'], - ['success', 'status', '1px solid rgb(50,213,131)'], - ['info', 'status', '1px solid rgb(110,185,228)'], -])('should render properly for "%s" variant', (variant: Variant, expectedRole, color) => { + ['error', '1px solid rgb(249,112,102)'], + ['warning', '1px solid rgb(248,205,92)'], + ['success', '1px solid rgb(50,213,131)'], + ['info', '1px solid rgb(110,185,228)'], +])('should render properly for "%s" variant', (variant: Variant, color) => { renderFlagMessage({ variant }); - const item = screen.getByRole(expectedRole); + const item = screen.getByRole('status'); expect(item).toBeInTheDocument(); expect(item).toHaveStyle({ border: color }); }); function renderFlagMessage(props: Partial> = {}) { return render( - + This is an error! ); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/AnalysisStatus.tsx b/server/sonar-web/src/main/js/app/components/nav/component/AnalysisStatus.tsx index 069ed2dffb3..4d8953398fa 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/AnalysisStatus.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/AnalysisStatus.tsx @@ -63,7 +63,7 @@ export function AnalysisStatus(props: HeaderMetaProps) { if (currentTask?.status === TaskStatuses.Failed) { return ( <> - + {translate('project_navigation.analysis_status.failed')} {translate('project_navigation.analysis_status.details_link')} @@ -84,7 +84,7 @@ export function AnalysisStatus(props: HeaderMetaProps) { if (warnings.length > 0) { return ( <> - + {translate('project_navigation.analysis_status.warnings')} {translate('project_navigation.analysis_status.details_link')} diff --git a/server/sonar-web/src/main/js/apps/code/components/CodeAppRenderer.tsx b/server/sonar-web/src/main/js/apps/code/components/CodeAppRenderer.tsx index d790deab426..67fc4ee4697 100644 --- a/server/sonar-web/src/main/js/apps/code/components/CodeAppRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/CodeAppRenderer.tsx @@ -120,11 +120,7 @@ export default function CodeAppRenderer(props: Props) { {!canBrowseAllChildProjects && isPortfolio && ( - + {translate('code_viewer.not_all_measures_are_shown')} byText(`x_of_y_shown.${x}.${y}`), showAllBtn: byRole('button', { name: 'component_measures.hidden_best_score_metrics_show_label', diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.tsx b/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.tsx index 5c98cb047f4..69a0dda1d35 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.tsx +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.tsx @@ -181,18 +181,7 @@ export default class FilesView extends React.PureComponent { view={this.props.view} /> {hidingBestMeasures && this.props.paging && ( - + {translateWithParameters( 'component_measures.hidden_best_score_metrics', formatMeasure( diff --git a/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.tsx b/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.tsx index 67075eabf84..f8d68f61eb5 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.tsx +++ b/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.tsx @@ -90,11 +90,7 @@ export default function Sidebar(props: Props) { }} > {!canBrowseAllChildProjects && isPortfolioLike(qualifier) && ( - + {translate('component_measures.not_all_measures_are_shown')} {
{limitReached && ( - + { {this.renderCommentField()} {issues.length > 0 && this.renderNotificationsField()} {issues.length === 0 && ( - - {translate('issue_bulk_change.no_match')} - + {translate('issue_bulk_change.no_match')} )}
diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx b/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx index f281d730592..6843a7d2b93 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx @@ -1031,7 +1031,6 @@ export class App extends React.PureComponent { const warning = !canBrowseAllChildProjects && isPortfolioLike(qualifier) && ( { ) : ( {checkAll && paging && paging.total > MAX_PAGE_SIZE && ( - + { )} {cannotShowOpenIssue && (!paging || paging.total > 0) && ( - + {translateWithParameters( 'issues.cannot_open_issue_max_initial_X_fetched', MAX_INITAL_FETCH diff --git a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/ComponentSourceSnippetGroupViewer.tsx b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/ComponentSourceSnippetGroupViewer.tsx index 413b72c5689..47d82f53de2 100644 --- a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/ComponentSourceSnippetGroupViewer.tsx +++ b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/ComponentSourceSnippetGroupViewer.tsx @@ -281,11 +281,7 @@ export default class ComponentSourceSnippetGroupViewer extends React.PureCompone return ( <> {issueIsClosed && ( - +
extends React.Component, State> { /> {mightHaveMoreResults && this.state.showFullList && ( - + {translate('facet_might_have_more_results')} )} @@ -382,11 +378,7 @@ export class ListStyleFacet extends React.Component, State> { {searchMaxResults && ( - + {translate('facet_might_have_more_results')} )} diff --git a/server/sonar-web/src/main/js/apps/overview/branches/ApplicationNonCaycProjectWarning.tsx b/server/sonar-web/src/main/js/apps/overview/branches/ApplicationNonCaycProjectWarning.tsx index 0cbadd8fc01..8e7d0139efb 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/ApplicationNonCaycProjectWarning.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/ApplicationNonCaycProjectWarning.tsx @@ -38,13 +38,7 @@ export default function ApplicationNonCaycProjectWarning({ projects, caycStatus return ( {caycStatus === CaycStatus.NonCompliant ? ( - + {translateWithParameters( 'overview.quality_gate.application.non_cayc.projects_x', projects.length diff --git a/server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarning.tsx b/server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarning.tsx index d54f177c953..a0bb6333134 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarning.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarning.tsx @@ -34,10 +34,7 @@ export default function CleanAsYouCodeWarning({ component }: Props) { return ( <> - + {translate('overview.quality_gate.conditions.cayc.warning')} {component.qualityGate ? ( diff --git a/server/sonar-web/src/main/js/apps/overview/branches/NoCodeWarning.tsx b/server/sonar-web/src/main/js/apps/overview/branches/NoCodeWarning.tsx index 19a939a74c4..07ad44e7ed0 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/NoCodeWarning.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/NoCodeWarning.tsx @@ -83,11 +83,7 @@ export function NoCodeWarning({ branchLike, component, measures }: Props) { } /* eslint-enable no-lonely-if */ - return ( - - {title} - - ); + return {title}; } export default React.memo(NoCodeWarning); diff --git a/server/sonar-web/src/main/js/apps/overview/components/IgnoredConditionWarning.tsx b/server/sonar-web/src/main/js/apps/overview/components/IgnoredConditionWarning.tsx index a3055cf6e9f..21d076bd71b 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/IgnoredConditionWarning.tsx +++ b/server/sonar-web/src/main/js/apps/overview/components/IgnoredConditionWarning.tsx @@ -25,11 +25,7 @@ import { translate } from '../../../helpers/l10n'; export default function IgnoredConditionWarning() { return ( - + {translate('overview.quality_gate.ignored_conditions')} { return (
{inRemovedComponent && ( - + {translate('duplications.dups_found_on_deleted_resource')} )} diff --git a/server/sonar-web/src/main/js/components/rules/RuleDescription.tsx b/server/sonar-web/src/main/js/components/rules/RuleDescription.tsx index 582a7251403..9f8a6d41a41 100644 --- a/server/sonar-web/src/main/js/components/rules/RuleDescription.tsx +++ b/server/sonar-web/src/main/js/components/rules/RuleDescription.tsx @@ -128,14 +128,7 @@ export default class RuleDescription extends React.PureComponent { {translate('coding_rules.description_context.title')} {defaultContext && ( - + {translateWithParameters( 'coding_rules.description_context.default_information', defaultContext.displayName -- 2.39.5