Skip to content

Commit ed56872

Browse files
committed
Add a notification for dark mode
1 parent 59f5e7f commit ed56872

File tree

6 files changed

+87
-1
lines changed

6 files changed

+87
-1
lines changed

ui/frontend/Notifications.module.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,7 @@ $space: 0.25em;
3535
padding-top: 0.5em;
3636
gap: 0.5em;
3737
}
38+
39+
.swapTheme {
40+
width: 100%;
41+
}

ui/frontend/Notifications.tsx

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import { Portal } from 'react-portal';
33

44
import { Close } from './Icon';
55
import { useAppDispatch, useAppSelector } from './hooks';
6-
import { seenRustSurvey2023 } from './reducers/notifications';
6+
import { swapTheme } from './reducers/configuration';
7+
import { seenDarkMode, seenRustSurvey2023 } from './reducers/notifications';
78
import { allowLongRun, wsExecuteKillCurrent } from './reducers/output/execute';
89
import * as selectors from './selectors';
10+
import { Theme } from './types';
911

1012
import * as styles from './Notifications.module.css';
1113

@@ -15,13 +17,61 @@ const Notifications: React.FC = () => {
1517
return (
1618
<Portal>
1719
<div className={styles.container}>
20+
<DarkModeNotification />
1821
<RustSurvey2023Notification />
1922
<ExcessiveExecutionNotification />
2023
</div>
2124
</Portal>
2225
);
2326
};
2427

28+
const DarkModeNotification: React.FC = () => {
29+
const showIt = useAppSelector(selectors.showDarkModeSelector);
30+
31+
const dispatch = useAppDispatch();
32+
const seenIt = useCallback(() => dispatch(seenDarkMode()), [dispatch]);
33+
const swapToLight = useCallback(() => dispatch(swapTheme(Theme.Light)), [dispatch]);
34+
const swapToDark = useCallback(() => dispatch(swapTheme(Theme.Dark)), [dispatch]);
35+
const swapToSystem = useCallback(() => dispatch(swapTheme(Theme.System)), [dispatch]);
36+
37+
return showIt ? (
38+
<Notification onClose={seenIt}>
39+
<p>The playground now has a dark mode! Sample the themes here:</p>
40+
41+
<table>
42+
<tr>
43+
<th>
44+
<button className={styles.swapTheme} onClick={swapToSystem}>
45+
System
46+
</button>
47+
</th>
48+
<td>Use your system's preference</td>
49+
</tr>
50+
51+
<tr>
52+
<th>
53+
<button className={styles.swapTheme} onClick={swapToLight}>
54+
Light
55+
</button>
56+
</th>
57+
<td>The classic playground style</td>
58+
</tr>
59+
60+
<tr>
61+
<th>
62+
<button className={styles.swapTheme} onClick={swapToDark}>
63+
Dark
64+
</button>
65+
</th>
66+
<td>Reduce the number of photons hitting your eyeballs</td>
67+
</tr>
68+
</table>
69+
70+
<p>You can change the current UI theme (and the editor's theme) in the configuration menu.</p>
71+
</Notification>
72+
) : null;
73+
};
74+
2575
const RustSurvey2023Notification: React.FC = () => {
2676
const showIt = useAppSelector(selectors.showRustSurvey2023Selector);
2777

ui/frontend/reducers/configuration.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,22 @@ const slice = createSlice({
124124
changeProcessAssembly: (state, action: PayloadAction<ProcessAssembly>) => {
125125
state.processAssembly = action.payload;
126126
},
127+
128+
swapTheme: (state, action: PayloadAction<Theme>) => {
129+
state.theme = action.payload;
130+
switch (action.payload) {
131+
case Theme.Light: {
132+
state.ace.theme = 'github';
133+
state.monaco.theme = 'vs';
134+
break;
135+
}
136+
case Theme.Dark: {
137+
state.ace.theme = 'github_dark';
138+
state.monaco.theme = 'vscode-dark-plus';
139+
break;
140+
}
141+
}
142+
},
127143
},
128144
});
129145

@@ -143,6 +159,7 @@ export const {
143159
changePairCharacters,
144160
changePrimaryAction,
145161
changeProcessAssembly,
162+
swapTheme,
146163
} = slice.actions;
147164

148165
export const changeEdition =

ui/frontend/reducers/notifications.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface State {
1111
seenMonacoEditorAvailable: boolean; // expired
1212
seenRustSurvey2022: boolean; // expired
1313
seenRustSurvey2023: boolean;
14+
seenDarkMode: boolean;
1415
}
1516

1617
const initialState: State = {
@@ -22,6 +23,7 @@ const initialState: State = {
2223
seenMonacoEditorAvailable: true,
2324
seenRustSurvey2022: true,
2425
seenRustSurvey2023: false,
26+
seenDarkMode: false,
2527
};
2628

2729
const slice = createSlice({
@@ -30,6 +32,9 @@ const slice = createSlice({
3032
reducers: {
3133
notificationSeen: (state, action: PayloadAction<Notification>) => {
3234
switch (action.payload) {
35+
case Notification.DarkMode: {
36+
state.seenDarkMode = true;
37+
}
3338
case Notification.RustSurvey2023: {
3439
state.seenRustSurvey2023 = true;
3540
}
@@ -40,6 +45,7 @@ const slice = createSlice({
4045

4146
const { notificationSeen } = slice.actions;
4247

48+
export const seenDarkMode = () => notificationSeen(Notification.DarkMode);
4349
export const seenRustSurvey2023 = () => notificationSeen(Notification.RustSurvey2023);
4450

4551
export default slice.reducer;

ui/frontend/selectors/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,13 @@ const notificationsSelector = (state: State) => state.notifications;
357357

358358
const NOW = new Date();
359359

360+
const DARK_MODE_END = new Date('2024-10-15T00:00:00Z');
361+
const DARK_MODE_OPEN = NOW <= DARK_MODE_END;
362+
export const showDarkModeSelector = createSelector(
363+
notificationsSelector,
364+
notifications => DARK_MODE_OPEN && !notifications.seenDarkMode,
365+
);
366+
360367
const RUST_SURVEY_2023_END = new Date('2024-01-15T00:00:00Z');
361368
const RUST_SURVEY_2023_OPEN = NOW <= RUST_SURVEY_2023_END;
362369
export const showRustSurvey2023Selector = createSelector(
@@ -365,6 +372,7 @@ export const showRustSurvey2023Selector = createSelector(
365372
);
366373

367374
export const anyNotificationsToShowSelector = createSelector(
375+
showDarkModeSelector,
368376
showRustSurvey2023Selector,
369377
excessiveExecutionSelector,
370378
(...allNotifications) => allNotifications.some(n => n),

ui/frontend/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,5 +165,6 @@ export enum Focus {
165165
}
166166

167167
export enum Notification {
168+
DarkMode = 'dark-mode',
168169
RustSurvey2023 = 'rust-survey-2023',
169170
}

0 commit comments

Comments
 (0)