From 5aeed16a227d13f8c7632a578c8bb84613fbb836 Mon Sep 17 00:00:00 2001 From: Stanislav <31501873+stanislavhh@users.noreply.github.com> Date: Thu, 12 Sep 2024 10:38:19 +0200 Subject: [PATCH] SONAR-22301 Fix accessibility issues on project overview page (#11729) --- .../src/components/icons/TrendIcon.tsx | 78 +++++++++---------- .../design-system/src/theme/light.ts | 2 +- .../overview/branches/AnalysisVariations.tsx | 10 +-- .../branches/QualityGateCondition.tsx | 21 ++++- .../__tests__/ProjectActivityApp-it.tsx | 6 +- .../activity-graph/AddGraphMetric.tsx | 9 +-- .../activity-graph/GraphsHeader.tsx | 49 ++++-------- .../resources/org/sonar/l10n/core.properties | 2 +- 8 files changed, 82 insertions(+), 95 deletions(-) diff --git a/server/sonar-web/design-system/src/components/icons/TrendIcon.tsx b/server/sonar-web/design-system/src/components/icons/TrendIcon.tsx index cd93d9c6ff3..331c0b513d9 100644 --- a/server/sonar-web/design-system/src/components/icons/TrendIcon.tsx +++ b/server/sonar-web/design-system/src/components/icons/TrendIcon.tsx @@ -17,9 +17,15 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import { + IconArrowDownRight, + IconArrowUpRight, + IconEqual, + IconProps, +} from '@sonarsource/echoes-react'; import { themeColor } from '../../helpers/theme'; -import { CustomIcon, IconProps } from './Icon'; +import { ThemeColors } from '../../types'; export const enum TrendDirection { Down = 'down', @@ -40,46 +46,40 @@ interface Props extends IconProps { } export function TrendIcon(props: Readonly) { - const theme = useTheme(); const { direction, type, ...iconProps } = props; - const fill = themeColor( - ( - { - [TrendType.Positive]: 'iconTrendPositive', - [TrendType.Negative]: 'iconTrendNegative', - [TrendType.Neutral]: 'iconTrendNeutral', - [TrendType.Disabled]: 'iconTrendDisabled', - } as const - )[type], - )({ theme }); + if (direction === TrendDirection.Up) { + return ( + + + + ); + } + + if (direction === TrendDirection.Down) { + return ( + + + + ); + } return ( - - {direction === TrendDirection.Up && ( - - )} - {direction === TrendDirection.Down && ( - - )} - {direction === TrendDirection.Equal && ( - - - - - )} - + + + ); } + +const ICON_COLORS: Record = { + [TrendType.Positive]: 'iconTrendPositive', + [TrendType.Negative]: 'iconTrendNegative', + [TrendType.Neutral]: 'iconTrendNeutral', + [TrendType.Disabled]: 'iconTrendDisabled', +}; + +const TrendIconWrapper = styled.span<{ + trendType: TrendType; +}>` + color: ${({ trendType }) => themeColor(ICON_COLORS[trendType])}; +`; diff --git a/server/sonar-web/design-system/src/theme/light.ts b/server/sonar-web/design-system/src/theme/light.ts index ddc35bf7215..ef98fce9ac9 100644 --- a/server/sonar-web/design-system/src/theme/light.ts +++ b/server/sonar-web/design-system/src/theme/light.ts @@ -420,7 +420,7 @@ export const lightTheme = { iconNegativeUpdate: COLORS.red[300], iconTrendPositive: COLORS.green[400], iconTrendNegative: COLORS.red[400], - iconTrendNeutral: COLORS.blue[400], + iconTrendNeutral: COLORS.blue[600], iconTrendDisabled: COLORS.blueGrey[400], iconError: danger.default, iconWarning: COLORS.yellow[600], diff --git a/server/sonar-web/src/main/js/apps/overview/branches/AnalysisVariations.tsx b/server/sonar-web/src/main/js/apps/overview/branches/AnalysisVariations.tsx index afcd4b455a9..9c05d456efe 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/AnalysisVariations.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/AnalysisVariations.tsx @@ -67,15 +67,7 @@ function Variation(props: Readonly) { trendIconDirection = variation > 0 ? TrendDirection.Up : TrendDirection.Down; trendIconType = variation > 0 === isGoodIfGrowing ? TrendType.Positive : TrendType.Negative; } - const variationIcon = ( - - ); + const variationIcon = ; const variationToDisplay = formattedValue.startsWith('-') ? formattedValue : `+${formattedValue}`; diff --git a/server/sonar-web/src/main/js/apps/overview/branches/QualityGateCondition.tsx b/server/sonar-web/src/main/js/apps/overview/branches/QualityGateCondition.tsx index 1f4bbdcaede..e5c87c3ab8e 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/QualityGateCondition.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/QualityGateCondition.tsx @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import styled from '@emotion/styled'; import { LinkBox, TextMuted } from 'design-system'; import * as React from 'react'; import { Path } from 'react-router-dom'; @@ -107,7 +108,11 @@ export class QualityGateCondition extends React.PureComponent { }; if (METRICS_TO_URL_MAPPING[metricKey]) { - return {children}; + return ( + + {children} + + ); } const url = isIssueMeasure(condition.measure.metric.key) @@ -122,7 +127,11 @@ export class QualityGateCondition extends React.PureComponent { listView: true, }); - return {children}; + return ( + + {children} + + ); } getPrimaryText = () => { @@ -173,7 +182,7 @@ export class QualityGateCondition extends React.PureComponent { {this.getPrimaryText()} - + , ); @@ -181,3 +190,9 @@ export class QualityGateCondition extends React.PureComponent { } export default withMetricsContext(QualityGateCondition); + +const StyledMutedText = styled(TextMuted)` + .link-box-wrapper:hover & { + color: unset; + } +`; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-it.tsx b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-it.tsx index 4cf9ca58475..1e29192a079 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-it.tsx +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-it.tsx @@ -111,7 +111,7 @@ describe('rendering', () => { renderProjectActivityAppContainer(); await ui.appLoaded(); - expect(ui.graphTypeIssues.get()).toBeInTheDocument(); + expect(ui.graphTypeSelect.get()).toHaveValue('project_activity.graphs.issues'); }); it('should render new code legend for applications', async () => { @@ -402,7 +402,7 @@ describe('data loading', () => { renderProjectActivityAppContainer(); await ui.appLoaded(); - expect(ui.graphTypeCustom.get()).toBeInTheDocument(); + expect(ui.graphTypeSelect.get()).toHaveValue('project_activity.graphs.custom'); }); it('should correctly fetch the top level component when dealing with sub portfolios', async () => { @@ -756,8 +756,6 @@ function getPageObject() { const ui = { // Graph types. graphTypeSelect: byLabelText('project_activity.graphs.choose_type'), - graphTypeIssues: byText('project_activity.graphs.issues'), - graphTypeCustom: byText('project_activity.graphs.custom'), // Graphs. graphs: byLabelText('project_activity.graphs.explanation_x', { exact: false }), diff --git a/server/sonar-web/src/main/js/components/activity-graph/AddGraphMetric.tsx b/server/sonar-web/src/main/js/components/activity-graph/AddGraphMetric.tsx index b79add8c0f4..1ef69f5ddf1 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/AddGraphMetric.tsx +++ b/server/sonar-web/src/main/js/components/activity-graph/AddGraphMetric.tsx @@ -19,7 +19,7 @@ */ import { Button, IconChevronDown } from '@sonarsource/echoes-react'; -import { Dropdown, TextMuted } from 'design-system'; +import { Dropdown } from 'design-system'; import { sortBy } from 'lodash'; import * as React from 'react'; import { MetricKey, MetricType } from '~sonar-aligned/types/metrics'; @@ -165,10 +165,9 @@ export default class AddGraphMetric extends React.PureComponent { } > ); diff --git a/server/sonar-web/src/main/js/components/activity-graph/GraphsHeader.tsx b/server/sonar-web/src/main/js/components/activity-graph/GraphsHeader.tsx index 8390f89174f..b50b4413050 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/GraphsHeader.tsx +++ b/server/sonar-web/src/main/js/components/activity-graph/GraphsHeader.tsx @@ -18,14 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { - Button, - ButtonGroup, - DropdownMenu, - DropdownMenuAlign, - IconChevronDown, -} from '@sonarsource/echoes-react'; -import { TextMuted } from 'design-system'; +import { ButtonGroup, InputSize, Select } from '@sonarsource/echoes-react'; import * as React from 'react'; import { translate } from '../../helpers/l10n'; import { GraphType } from '../../types/project-activity'; @@ -66,34 +59,24 @@ export default function GraphsHeader(props: Props) { const noCustomGraph = props.onAddCustomMetric === undefined || props.onRemoveCustomMetric === undefined; - const options = React.useMemo(() => { - const types = getGraphTypes(noCustomGraph); - - return types.map((type) => { - const label = translate('project_activity.graphs', type); - - return ( - handleGraphChange(type)}> - {label} - - ); - }); - }, [noCustomGraph, handleGraphChange]); - return (
- - - + +