Skip to content

Commit 3768042

Browse files
authored
fix: improve color contrast to meet WCAG 4.5:1 minimum (#1539)
Assisted-by: Claude Opus 4.6 Signed-off-by: Oleksii Orel <oorel@redhat.com>
1 parent 506f798 commit 3768042

15 files changed

Lines changed: 170 additions & 46 deletions

File tree

packages/dashboard-frontend/src/Layout/ErrorReporter/Issue/index.module.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,8 @@
5454
background-color: var(--pf-t--global--color--nonstatus--red--default);
5555
border-radius: 3px;
5656
}
57+
58+
:global(.pf-v6-theme-dark) .errorMessage {
59+
color: var(--pf-t--global--text--color--regular);
60+
background-color: rgb(185 80 80);
61+
}

packages/dashboard-frontend/src/components/BackupStatusBadge/__tests__/__snapshots__/index.spec.tsx.snap

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ exports[`BackupStatusBadge icon rendering should render CheckCircleIcon for succ
2525
>
2626
<span
2727
aria-label="Backup status: Success"
28-
className="pf-v6-c-label pf-m-green pf-m-filled backupStatusBadge size-md"
28+
className="pf-v6-c-label pf-m-green pf-m-filled backupStatusBadge"
2929
data-testid="backup-status-badge"
3030
>
3131
<span
@@ -93,7 +93,7 @@ exports[`BackupStatusBadge icon rendering should render ExclamationTriangleIcon
9393
>
9494
<span
9595
aria-label="Backup status: Failed"
96-
className="pf-v6-c-label pf-m-orange pf-m-filled backupStatusBadge size-md"
96+
className="pf-v6-c-label pf-m-orange pf-m-filled backupStatusBadge"
9797
data-testid="backup-status-badge"
9898
>
9999
<span
@@ -164,7 +164,7 @@ exports[`BackupStatusBadge icon rendering should render InfoCircleIcon for never
164164
>
165165
<span
166166
aria-label="Backup status: Never"
167-
className="pf-v6-c-label pf-m-filled backupStatusBadge size-md"
167+
className="pf-v6-c-label pf-m-filled backupStatusBadge"
168168
data-testid="backup-status-badge"
169169
>
170170
<span
@@ -232,7 +232,7 @@ exports[`BackupStatusBadge icon rendering should render animated InProgressIcon
232232
>
233233
<span
234234
aria-label="Backup status: In Progress"
235-
className="pf-v6-c-label pf-m-blue pf-m-filled backupStatusBadge size-md"
235+
className="pf-v6-c-label pf-m-blue pf-m-filled backupStatusBadge"
236236
data-testid="backup-status-badge"
237237
>
238238
<span
@@ -304,7 +304,7 @@ exports[`BackupStatusBadge snapshots failed status 1`] = `
304304
>
305305
<span
306306
aria-label="Backup status: Failed"
307-
className="pf-v6-c-label pf-m-orange pf-m-filled backupStatusBadge size-md"
307+
className="pf-v6-c-label pf-m-orange pf-m-filled backupStatusBadge"
308308
data-testid="backup-status-badge"
309309
>
310310
<span
@@ -372,7 +372,7 @@ exports[`BackupStatusBadge snapshots in-progress status 1`] = `
372372
>
373373
<span
374374
aria-label="Backup status: In Progress"
375-
className="pf-v6-c-label pf-m-blue pf-m-filled backupStatusBadge size-md"
375+
className="pf-v6-c-label pf-m-blue pf-m-filled backupStatusBadge"
376376
data-testid="backup-status-badge"
377377
>
378378
<span
@@ -444,7 +444,7 @@ exports[`BackupStatusBadge snapshots never status 1`] = `
444444
>
445445
<span
446446
aria-label="Backup status: Never"
447-
className="pf-v6-c-label pf-m-filled backupStatusBadge size-md"
447+
className="pf-v6-c-label pf-m-filled backupStatusBadge"
448448
data-testid="backup-status-badge"
449449
>
450450
<span
@@ -515,7 +515,7 @@ exports[`BackupStatusBadge snapshots success status 1`] = `
515515
>
516516
<span
517517
aria-label="Backup status: Success"
518-
className="pf-v6-c-label pf-m-green pf-m-filled backupStatusBadge size-md"
518+
className="pf-v6-c-label pf-m-green pf-m-filled backupStatusBadge"
519519
data-testid="backup-status-badge"
520520
>
521521
<span

packages/dashboard-frontend/src/components/BackupStatusBadge/index.module.css

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,10 @@
1111
*/
1212

1313
.backupStatusBadge {
14+
font-weight: bold;
1415
text-transform: capitalize;
1516
}
1617

17-
.size-md {
18-
font-size: var(--pf-v5-global--FontSize--sm);
19-
}
20-
2118
.rotate {
2219
animation-name: spinnerRotate;
2320
animation-duration: 1s;

packages/dashboard-frontend/src/components/BackupStatusBadge/index.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,7 @@ export function BackupStatusBadge(props: Props): React.ReactElement {
122122
const icon = getStatusIcon(status);
123123
const tooltipContent = getTooltipContent(status, lastBackupTime, backupImageUrl);
124124

125-
const sizeClassName = styles['size-md'] || '';
126-
const className = `${styles.backupStatusBadge} ${sizeClassName}`.trim();
125+
const className = styles.backupStatusBadge;
127126

128127
const statusLabel = BACKUP_STATUS_LABELS[status];
129128

packages/dashboard-frontend/src/components/BasicViewer/index.module.css

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,3 @@
2121
height: 100%;
2222
border: 1px solid var(--pf-t--global--border--color--default);
2323
}
24-
25-
html:not(.pf-v6-theme-dark) .basicViewer > div > div > div > div {
26-
opacity: 0.8;
27-
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2+
3+
exports[`DevfileViewer snapshot with light theme 1`] = `
4+
<div
5+
className="devfileViewer"
6+
>
7+
<div
8+
className="cm-theme-light codeMirror"
9+
id="devfile-viewer-id"
10+
/>
11+
</div>
12+
`;
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright (c) 2018-2025 Red Hat, Inc.
3+
* This program and the accompanying materials are made
4+
* available under the terms of the Eclipse Public License 2.0
5+
* which is available at https://www.eclipse.org/legal/epl-2.0/
6+
*
7+
* SPDX-License-Identifier: EPL-2.0
8+
*
9+
* Contributors:
10+
* Red Hat, Inc. - initial API and implementation
11+
*/
12+
13+
import React from 'react';
14+
15+
import { DevfileViewer } from '@/components/DevfileViewer';
16+
import { useTheme } from '@/contexts/ThemeContext';
17+
import getComponentRenderer, { screen } from '@/services/__mocks__/getComponentRenderer';
18+
19+
jest.mock('@/contexts/ThemeContext', () => ({
20+
useTheme: jest.fn(),
21+
}));
22+
23+
const mockUseTheme = useTheme as jest.Mock;
24+
25+
const { createSnapshot, renderComponent } = getComponentRenderer(getComponent);
26+
27+
const sampleDevfile = 'schemaVersion: 2.2.0\nmetadata:\n name: test-workspace';
28+
29+
describe('DevfileViewer', () => {
30+
beforeEach(() => {
31+
mockUseTheme.mockReturnValue({
32+
themePreference: 'LIGHT',
33+
isDarkTheme: false,
34+
setThemePreference: jest.fn(),
35+
});
36+
});
37+
38+
afterEach(() => {
39+
jest.clearAllMocks();
40+
});
41+
42+
test('snapshot with light theme', () => {
43+
const snapshot = createSnapshot(sampleDevfile);
44+
expect(snapshot.toJSON()).toMatchSnapshot();
45+
});
46+
47+
test('renders content in light theme', () => {
48+
renderComponent(sampleDevfile);
49+
50+
const textbox = screen.getByRole('textbox');
51+
expect(textbox).toHaveTextContent('schemaVersion');
52+
});
53+
54+
test('renders content in dark theme', () => {
55+
mockUseTheme.mockReturnValue({
56+
themePreference: 'DARK',
57+
isDarkTheme: true,
58+
setThemePreference: jest.fn(),
59+
});
60+
61+
renderComponent(sampleDevfile);
62+
63+
const textbox = screen.getByRole('textbox');
64+
expect(textbox).toHaveTextContent('schemaVersion');
65+
});
66+
67+
test('handles content change', () => {
68+
const { reRenderComponent } = renderComponent(sampleDevfile);
69+
70+
const textbox = screen.getByRole('textbox');
71+
expect(textbox).toHaveTextContent('test-workspace');
72+
73+
const updatedDevfile = 'schemaVersion: 2.2.0\nmetadata:\n name: updated-workspace';
74+
reRenderComponent(updatedDevfile);
75+
76+
expect(textbox).toHaveTextContent('updated-workspace');
77+
});
78+
});
79+
80+
function getComponent(value: string): React.ReactElement {
81+
return <DevfileViewer id="devfile-viewer-id" isActive={true} isExpanded={true} value={value} />;
82+
}

packages/dashboard-frontend/src/components/DevfileViewer/index.module.css

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,3 @@
2323
height: 100%;
2424
border: 1px solid var(--pf-t--global--border--color--default);
2525
}
26-
27-
html:not(.pf-v6-theme-dark) .devfileViewer > div > div > div > div {
28-
opacity: 0.8;
29-
}

packages/dashboard-frontend/src/components/DevfileViewer/index.tsx

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const createLightTheme = () => {
4040
},
4141
'.cm-gutters': {
4242
backgroundColor: '#f7f7f7',
43-
color: '#999',
43+
color: '#636363',
4444
},
4545
'.cm-activeLineGutter': {
4646
backgroundColor: '#f7f7f7',
@@ -50,10 +50,25 @@ const createLightTheme = () => {
5050
);
5151
};
5252

53+
const createDarkGutterTheme = () => {
54+
return EditorView.theme(
55+
{
56+
'.cm-gutters': {
57+
backgroundColor: '#161b22',
58+
color: '#8b949e',
59+
},
60+
'.cm-activeLineGutter': {
61+
backgroundColor: '#161b22',
62+
},
63+
},
64+
{ dark: true },
65+
);
66+
};
67+
5368
const createLightHighlightStyle = () => {
5469
return HighlightStyle.define([
55-
{ tag: t.keyword, color: '#5e81ac' },
56-
{ tag: [t.string], color: '#5e81ac' },
70+
{ tag: t.keyword, color: '#4c7399' },
71+
{ tag: [t.string], color: '#4c7399' },
5772
{ tag: [t.variableName], color: '#008080' },
5873
{
5974
tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName],
@@ -66,6 +81,7 @@ export const DevfileViewer: React.FC<Props> = ({ value, id }) => {
6681
const { isDarkTheme } = useTheme();
6782

6883
const lightTheme = useMemo(() => createLightTheme(), []);
84+
const darkGutterTheme = useMemo(() => createDarkGutterTheme(), []);
6985
const lightHighlightStyle = useMemo(() => createLightHighlightStyle(), []);
7086

7187
const extensions = useMemo(() => {
@@ -74,9 +90,9 @@ export const DevfileViewer: React.FC<Props> = ({ value, id }) => {
7490
yaml(),
7591
];
7692
return isDarkTheme
77-
? baseExtensions
93+
? [darkGutterTheme, ...baseExtensions]
7894
: [lightTheme, syntaxHighlighting(lightHighlightStyle), ...baseExtensions];
79-
}, [isDarkTheme, lightTheme, lightHighlightStyle]);
95+
}, [isDarkTheme, darkGutterTheme, lightTheme, lightHighlightStyle]);
8096

8197
return (
8298
<div className={styles.devfileViewer}>

packages/dashboard-frontend/src/components/ExpandableWarning/__tests__/__snapshots__/index.spec.tsx.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ exports[`Expandable warning items should correctly render the component 1`] = `
8080
className="pf-v6-c-code-block__code"
8181
>
8282
<small
83-
className="pf-v6-c-content--small hideOverflow"
83+
className="pf-v6-c-content--small hideOverflow errorMessage"
8484
data-ouia-component-id="OUIA-Generated-Content-4"
8585
data-ouia-component-type="PF6/Content"
8686
data-ouia-safe={true}

0 commit comments

Comments
 (0)