feat(app): add theme color dropdown

This commit is contained in:
FaberVitale 2021-10-30 18:31:01 +02:00
parent fb1ec166d3
commit 482674b83b
4 changed files with 50 additions and 12 deletions

View File

@ -62,10 +62,12 @@ class App extends Component<Props> {
function mapStateToProps(state: StoreState) { function mapStateToProps(state: StoreState) {
const instances = state.instances; const instances = state.instances;
const id = getActiveInstance(instances); const id = getActiveInstance(instances);
const { themeColorPreference, ...themeData } = state.theme;
return { return {
options: instances.options[id], options: instances.options[id],
section: state.section, section: state.section,
theme: state.theme, theme: themeData,
notification: state.notification, notification: state.notification,
}; };
} }

View File

@ -48,6 +48,7 @@ import { MonitorStateMonitorState } from '../reducers/monitor';
import { LiftedAction, LiftedState } from '@redux-devtools/core'; import { LiftedAction, LiftedState } from '@redux-devtools/core';
import { Data } from '../reducers/reports'; import { Data } from '../reducers/reports';
import { prefersDarkColorScheme } from '../utils/media-queries'; import { prefersDarkColorScheme } from '../utils/media-queries';
import { ThemeColorPreference } from '../reducers/theme';
let monitorReducer: ( let monitorReducer: (
monitorProps: unknown, monitorProps: unknown,
@ -67,9 +68,9 @@ export function changeSection(section: string): ChangeSectionAction {
interface ChangeThemeFormData { interface ChangeThemeFormData {
readonly theme: Theme; readonly theme: Theme;
readonly scheme: Scheme; readonly scheme: Scheme;
readonly dark: boolean; readonly themeColorPreference: ThemeColorPreference;
} }
interface ChangeThemeData { export interface ChangeThemeData {
readonly formData: ChangeThemeFormData; readonly formData: ChangeThemeFormData;
} }
export interface ChangeThemeAction { export interface ChangeThemeAction {
@ -77,6 +78,7 @@ export interface ChangeThemeAction {
readonly theme: Theme; readonly theme: Theme;
readonly scheme: Scheme; readonly scheme: Scheme;
readonly dark: boolean; readonly dark: boolean;
readonly themeColorPreference: ThemeColorPreference;
} }
export interface ApplyMediaFeaturesPreferencesAction { export interface ApplyMediaFeaturesPreferencesAction {
@ -85,7 +87,21 @@ export interface ApplyMediaFeaturesPreferencesAction {
} }
export function changeTheme(data: ChangeThemeData): ChangeThemeAction { export function changeTheme(data: ChangeThemeData): ChangeThemeAction {
return { type: CHANGE_THEME, ...data.formData }; const { themeColorPreference } = data.formData;
let dark: boolean;
switch (themeColorPreference) {
case 'light':
dark = false;
break;
case 'dark':
dark = true;
break;
default:
dark = prefersDarkColorScheme();
}
return { type: CHANGE_THEME, ...data.formData, dark };
} }
/** /**

View File

@ -4,6 +4,10 @@ import { Container, Form } from '@redux-devtools/ui';
import { listSchemes, listThemes } from '@redux-devtools/ui/lib/utils/theme'; import { listSchemes, listThemes } from '@redux-devtools/ui/lib/utils/theme';
import { changeTheme } from '../../actions'; import { changeTheme } from '../../actions';
import { StoreState } from '../../reducers'; import { StoreState } from '../../reducers';
import {
defaultThemeColorPreference,
themeColorPreferences,
} from '../../reducers/theme';
type StateProps = ReturnType<typeof mapStateToProps>; type StateProps = ReturnType<typeof mapStateToProps>;
type DispatchProps = ResolveThunks<typeof actionCreators>; type DispatchProps = ResolveThunks<typeof actionCreators>;
@ -15,7 +19,8 @@ export class Themes extends Component<Props> {
const formData = { const formData = {
theme: theme.theme, theme: theme.theme,
scheme: theme.scheme, scheme: theme.scheme,
dark: !theme.light, themeColorPreference:
theme.themeColorPreference ?? defaultThemeColorPreference,
}; };
return ( return (
@ -33,8 +38,10 @@ export class Themes extends Component<Props> {
type: 'string', type: 'string',
enum: listSchemes(), enum: listSchemes(),
}, },
dark: { themeColorPreference: {
type: 'boolean', title: 'theme color',
type: 'string',
enum: themeColorPreferences as unknown as string[],
}, },
}, },
}} }}

View File

@ -1,15 +1,25 @@
import { Scheme, Theme } from '@redux-devtools/ui'; import { Theme, Scheme } from '@redux-devtools/ui';
import { import {
CHANGE_THEME, CHANGE_THEME,
APPLY_MEDIA_FEATURES_PREFERENCES, APPLY_MEDIA_FEATURES_PREFERENCES,
} from '../constants/actionTypes'; } from '../constants/actionTypes';
import { StoreAction } from '../actions'; import { StoreAction } from '../actions';
export const defaultThemeColorPreference = 'default';
export const themeColorPreferences = [
defaultThemeColorPreference,
'light',
'dark',
] as const;
export type ThemeColorPreference = typeof themeColorPreferences[number];
export interface ThemeState { export interface ThemeState {
readonly theme: Theme; readonly theme: Theme;
readonly scheme: Scheme; readonly scheme: Scheme;
readonly light: boolean; readonly light: boolean;
readonly latestChangeBy?: string; readonly themeColorPreference?: ThemeColorPreference;
} }
export default function theme( export default function theme(
@ -17,6 +27,7 @@ export default function theme(
theme: 'default' as const, theme: 'default' as const,
scheme: 'default' as const, scheme: 'default' as const,
light: true, light: true,
themeColorPreference: defaultThemeColorPreference,
}, },
action: StoreAction action: StoreAction
) { ) {
@ -25,18 +36,20 @@ export default function theme(
theme: action.theme, theme: action.theme,
scheme: action.scheme, scheme: action.scheme,
light: !action.dark, light: !action.dark,
latestChangeBy: CHANGE_THEME, themeColorPreference: action.themeColorPreference,
}; };
} }
if ( if (
action.type === APPLY_MEDIA_FEATURES_PREFERENCES && action.type === APPLY_MEDIA_FEATURES_PREFERENCES &&
state.latestChangeBy !== CHANGE_THEME (!state.themeColorPreference ||
state.themeColorPreference === defaultThemeColorPreference)
) { ) {
return { return {
...state, ...state,
themeColorPreference:
state.themeColorPreference ?? defaultThemeColorPreference,
light: !action.prefersDarkColorScheme, light: !action.prefersDarkColorScheme,
latestChangeBy: APPLY_MEDIA_FEATURES_PREFERENCES,
}; };
} }