Skip to content

Commit 0867d8a

Browse files
Copilot0xrinegade
andcommitted
Fix onboarding popup dark theme contrast - ensure text visibility
Co-authored-by: 0xrinegade <[email protected]>
1 parent 304679d commit 0867d8a

File tree

3 files changed

+341
-0
lines changed

3 files changed

+341
-0
lines changed

src/styles/components.css

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,8 +955,81 @@
955955
background-color: rgba(0, 0, 0, 0.95);
956956
}
957957

958+
/* Explicit dark theme styles for onboarding modal text visibility */
959+
.dark .onboarding-modal {
960+
background: var(--color-background);
961+
color: var(--color-foreground);
962+
}
963+
964+
.dark .onboarding-title {
965+
color: var(--color-foreground-bright) !important;
966+
}
967+
968+
.dark .onboarding-subtitle {
969+
color: var(--color-foreground-muted) !important;
970+
}
971+
972+
.dark .language-description {
973+
color: var(--color-foreground-muted) !important;
974+
}
975+
976+
.dark .welcome-description,
977+
.dark .wallet-description,
978+
.dark .trading-description {
979+
color: var(--color-foreground-muted) !important;
980+
}
981+
982+
.dark .language-feature,
983+
.dark .wallet-feature,
984+
.dark .reward-benefit {
985+
color: var(--color-foreground) !important;
986+
}
987+
988+
.dark .feature-item {
989+
color: var(--color-foreground) !important;
990+
}
991+
958992
.dark .language-dropdown {
959993
background-color: var(--color-background);
994+
border-color: var(--color-border);
995+
}
996+
997+
.dark .language-trigger {
998+
background-color: var(--color-background);
999+
border-color: var(--color-border);
1000+
color: var(--color-foreground) !important;
1001+
}
1002+
1003+
.dark .language-trigger:hover {
1004+
background-color: var(--color-background-alt);
1005+
border-color: var(--color-border);
1006+
color: var(--color-foreground) !important;
1007+
}
1008+
1009+
.dark .language-country {
1010+
color: var(--color-foreground-muted) !important;
1011+
}
1012+
1013+
.dark .language-arrow {
1014+
color: var(--color-foreground-muted) !important;
1015+
}
1016+
1017+
.dark .language-option {
1018+
color: var(--color-foreground) !important;
1019+
}
1020+
1021+
.dark .language-option:hover {
1022+
background-color: var(--color-background-alt);
1023+
}
1024+
1025+
.dark .checkmark {
1026+
color: var(--color-success) !important;
1027+
}
1028+
1029+
.dark .language-feature span:not(.checkmark),
1030+
.dark .wallet-feature span:not(.checkmark),
1031+
.dark .reward-benefit span:not(.checkmark) {
1032+
color: var(--color-foreground) !important;
9601033
}
9611034

9621035
.dark .feature-item:hover {
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import OnboardingModal from '../components/OnboardingModal';
4+
5+
// Mock the SwigWalletProvider
6+
jest.mock('../contexts/SwigWalletProvider', () => ({
7+
useSwigWallet: () => ({
8+
publicKey: null,
9+
connected: false,
10+
wallet: null
11+
})
12+
}));
13+
14+
// Mock the SwigWalletButton
15+
jest.mock('../components/SwigWalletButton', () => ({
16+
SwigWalletButton: () => <button>Connect Wallet</button>
17+
}));
18+
19+
// Mock the LanguageSelector
20+
jest.mock('../components/LanguageSelector', () => ({
21+
__esModule: true,
22+
default: ({ currentLocale, onLanguageChange }) => (
23+
<select
24+
value={currentLocale}
25+
onChange={(e) => onLanguageChange(e.target.value)}
26+
data-testid="language-selector"
27+
>
28+
<option value="en">English</option>
29+
<option value="es">Spanish</option>
30+
<option value="fr">French</option>
31+
</select>
32+
)
33+
}));
34+
35+
// Mock reward transactions
36+
jest.mock('../utils/rewardTransactions', () => ({
37+
createUserRewardsAccount: jest.fn(),
38+
hasUserRewardsAccount: jest.fn()
39+
}));
40+
41+
// Mock constants
42+
jest.mock('../constants/rewardConstants', () => ({
43+
REWARD_CONSTANTS: {
44+
REWARD_RATES: {
45+
PER_TRADE: 10,
46+
PER_VOTE: 5
47+
}
48+
},
49+
UI_CONFIG: {}
50+
}));
51+
52+
describe('OnboardingModal Dark Theme', () => {
53+
const mockOnComplete = jest.fn();
54+
const mockOnSkip = jest.fn();
55+
56+
beforeEach(() => {
57+
// Add dark class to document body for testing
58+
document.body.className = 'dark';
59+
});
60+
61+
afterEach(() => {
62+
document.body.className = '';
63+
jest.clearAllMocks();
64+
});
65+
66+
test('renders language selection step with proper dark theme text contrast', () => {
67+
render(
68+
<OnboardingModal
69+
isOpen={true}
70+
onComplete={mockOnComplete}
71+
onSkip={mockOnSkip}
72+
/>
73+
);
74+
75+
// Check that the title is visible
76+
const title = screen.getByText('Select Your Language');
77+
expect(title).toBeInTheDocument();
78+
expect(title).toHaveClass('onboarding-title');
79+
80+
// Check that the subtitle is visible
81+
const subtitle = screen.getByText('Choose your preferred language for the best experience');
82+
expect(subtitle).toBeInTheDocument();
83+
expect(subtitle).toHaveClass('onboarding-subtitle');
84+
85+
// Check that the description is visible
86+
const description = screen.getByText(/Select your preferred language to customize your experience/);
87+
expect(description).toBeInTheDocument();
88+
89+
// Check that checkmarks and features are visible
90+
const checkmarks = screen.getAllByText('✓');
91+
expect(checkmarks).toHaveLength(3);
92+
93+
const features = [
94+
'Interface translated to your language',
95+
'Localized currency and date formats',
96+
'Automatically saved preference'
97+
];
98+
99+
features.forEach(feature => {
100+
expect(screen.getByText(feature)).toBeInTheDocument();
101+
});
102+
103+
// Check that language selector is present
104+
expect(screen.getByTestId('language-selector')).toBeInTheDocument();
105+
});
106+
107+
test('dark theme classes are applied correctly', () => {
108+
const { container } = render(
109+
<OnboardingModal
110+
isOpen={true}
111+
onComplete={mockOnComplete}
112+
onSkip={mockOnSkip}
113+
/>
114+
);
115+
116+
// Check that the modal has the correct structure for dark theme
117+
const modal = container.querySelector('.onboarding-modal');
118+
expect(modal).toBeInTheDocument();
119+
120+
const overlay = container.querySelector('.onboarding-overlay');
121+
expect(overlay).toBeInTheDocument();
122+
expect(overlay).toHaveClass('visible');
123+
});
124+
});

test-onboarding.html

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Onboarding Modal Test</title>
7+
<link rel="stylesheet" href="./src/styles/components.css">
8+
<link rel="stylesheet" href="./src/styles/vscode-dark-theme.css">
9+
<style>
10+
body {
11+
margin: 0;
12+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
13+
background: #1e1e1e;
14+
color: #d4d4d4;
15+
}
16+
17+
/* CSS Variables from theme */
18+
:root.dark {
19+
--color-background: #1e1e1e;
20+
--color-background-alt: #252526;
21+
--color-foreground: #d4d4d4;
22+
--color-foreground-muted: #969696;
23+
--color-foreground-bright: #ffffff;
24+
--color-border: #3e3e42;
25+
--color-primary: #007acc;
26+
--color-success: #73c991;
27+
--font-size-3xl: 1.875rem;
28+
--font-size-lg: 1.125rem;
29+
--font-size-base: 1rem;
30+
--spacing-3: 0.75rem;
31+
--spacing-8: 2rem;
32+
--font-weight-bold: 700;
33+
--font-weight-medium: 500;
34+
--line-height-tight: 1.25;
35+
--line-height-relaxed: 1.625;
36+
--font-family-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
37+
}
38+
39+
html {
40+
--color-background: #1e1e1e;
41+
--color-background-alt: #252526;
42+
--color-foreground: #d4d4d4;
43+
--color-foreground-muted: #969696;
44+
--color-foreground-bright: #ffffff;
45+
--color-border: #3e3e42;
46+
--color-primary: #007acc;
47+
--color-success: #73c991;
48+
--font-size-3xl: 1.875rem;
49+
--font-size-lg: 1.125rem;
50+
--font-size-base: 1rem;
51+
--spacing-3: 0.75rem;
52+
--spacing-8: 2rem;
53+
--font-weight-bold: 700;
54+
--font-weight-medium: 500;
55+
--line-height-tight: 1.25;
56+
--line-height-relaxed: 1.625;
57+
--font-family-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
58+
}
59+
60+
.dark .onboarding-modal {
61+
background: var(--color-background);
62+
color: var(--color-foreground);
63+
}
64+
65+
.dark .onboarding-title {
66+
color: var(--color-foreground-bright) !important;
67+
}
68+
69+
.dark .onboarding-subtitle {
70+
color: var(--color-foreground-muted) !important;
71+
}
72+
73+
.dark .language-description {
74+
color: var(--color-foreground-muted) !important;
75+
}
76+
77+
.dark .language-feature {
78+
color: var(--color-foreground) !important;
79+
}
80+
81+
.dark .checkmark {
82+
color: var(--color-success) !important;
83+
}
84+
85+
button {
86+
background: var(--color-primary);
87+
color: white;
88+
border: none;
89+
padding: 10px 20px;
90+
border-radius: 4px;
91+
cursor: pointer;
92+
margin: 10px;
93+
}
94+
</style>
95+
</head>
96+
<body class="dark">
97+
<div class="onboarding-overlay visible">
98+
<div class="onboarding-modal visible">
99+
<!-- Header -->
100+
<div class="onboarding-header">
101+
<button class="onboarding-close" aria-label="Close onboarding">×</button>
102+
</div>
103+
104+
<!-- Content -->
105+
<div class="onboarding-content">
106+
<h1 class="onboarding-title">Select Your Language</h1>
107+
<p class="onboarding-subtitle">Choose your preferred language for the best experience</p>
108+
<div class="onboarding-body">
109+
<div class="onboarding-language">
110+
<div class="language-icon">LANG</div>
111+
<p class="language-description">
112+
Select your preferred language to customize your experience on OpenSVM P2P Exchange.
113+
This setting will be remembered for future visits.
114+
</p>
115+
<div class="language-features">
116+
<div class="language-feature">
117+
<span class="checkmark"></span>
118+
<span>Interface translated to your language</span>
119+
</div>
120+
<div class="language-feature">
121+
<span class="checkmark"></span>
122+
<span>Localized currency and date formats</span>
123+
</div>
124+
<div class="language-feature">
125+
<span class="checkmark"></span>
126+
<span>Automatically saved preference</span>
127+
</div>
128+
</div>
129+
</div>
130+
</div>
131+
</div>
132+
133+
<!-- Actions -->
134+
<div class="onboarding-actions">
135+
<div class="actions-left"></div>
136+
<div class="actions-right">
137+
<button class="btn-text">Skip</button>
138+
<button class="btn-primary">Next</button>
139+
</div>
140+
</div>
141+
</div>
142+
</div>
143+
</body>
144+
</html>

0 commit comments

Comments
 (0)