packages/app: switch to using theme config

This commit is contained in:
Patrik Oldsberg
2020-05-15 09:29:03 +02:00
parent 77d989f383
commit 30c082bc40
3 changed files with 46 additions and 148 deletions
+10 -48
View File
@@ -14,8 +14,6 @@
* limitations under the License.
*/
import { CssBaseline, ThemeProvider } from '@material-ui/core';
import { lightTheme, darkTheme } from '@backstage/theme';
import { createApp } from '@backstage/core';
import React, { FC } from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
@@ -23,7 +21,6 @@ import Root from './components/Root';
import AlertDisplay from './components/AlertDisplay';
import * as plugins from './plugins';
import apis, { alertApiForwarder } from './apis';
import { ThemeContextType, ThemeContext, useThemeType } from './ThemeContext';
const app = createApp({
apis,
@@ -33,50 +30,15 @@ const app = createApp({
const AppProvider = app.getProvider();
const AppComponent = app.getRootComponent();
const App: FC<{}> = () => {
const [theme, toggleTheme] = useThemeType(
localStorage.getItem('theme') || 'auto',
);
let backstageTheme = lightTheme;
switch (theme) {
case 'light':
backstageTheme = lightTheme;
break;
case 'dark':
backstageTheme = darkTheme;
break;
default:
if (!window.matchMedia) {
backstageTheme = lightTheme;
break;
}
backstageTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
? darkTheme
: lightTheme;
break;
}
const themeContext: ThemeContextType = {
theme,
toggleTheme,
};
return (
<AppProvider>
<ThemeContext.Provider value={themeContext}>
<ThemeProvider theme={backstageTheme}>
<CssBaseline>
<AlertDisplay forwarder={alertApiForwarder} />
<Router>
<Root>
<AppComponent />
</Root>
</Router>
</CssBaseline>
</ThemeProvider>
</ThemeContext.Provider>
</AppProvider>
);
};
const App: FC<{}> = () => (
<AppProvider>
<AlertDisplay forwarder={alertApiForwarder} />
<Router>
<Root>
<AppComponent />
</Root>
</Router>
</AppProvider>
);
export default App;
-69
View File
@@ -1,69 +0,0 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useState, useEffect } from 'react';
export type ThemeContextType = {
theme: string;
toggleTheme: () => void;
};
export const ThemeContext = React.createContext<ThemeContextType>({
theme: 'light',
toggleTheme: () => {},
});
export function useThemeType(themeId: string): [string, () => void] {
const [theme, setTheme] = useState(themeId);
useEffect(() => {
if (!window.matchMedia) {
return () => {};
}
const mql = window.matchMedia('(prefers-color-scheme: dark)');
const darkListener = (event: MediaQueryListEvent) => {
if (localStorage.getItem('theme') === 'auto') {
if (event.matches) {
setTheme('dark');
} else {
setTheme('light');
}
setTheme('auto');
}
};
mql.addListener(darkListener);
return () => {
mql.removeListener(darkListener);
};
});
function toggleTheme() {
if (theme === 'light') {
setTheme('dark');
localStorage.setItem('theme', 'dark');
} else if (theme === 'dark') {
if (!window.matchMedia) {
setTheme('light');
localStorage.setItem('theme', 'light');
setTheme('light');
return;
}
setTheme('auto');
localStorage.setItem('theme', 'auto');
setTheme('auto');
} else {
setTheme('light');
localStorage.setItem('theme', 'light');
}
}
return [theme, toggleTheme];
}
@@ -15,42 +15,47 @@
*/
import React, { FC } from 'react';
import { SidebarItem } from '@backstage/core';
import { ThemeContext } from '../../ThemeContext';
import { useObservable } from 'react-use';
import { SidebarItem, useApi, appThemeApiRef } from '@backstage/core';
import WbSunnyIcon from '@material-ui/icons/WbSunny';
import Brightness2Icon from '@material-ui/icons/Brightness2';
import ToggleOnIcon from '@material-ui/icons/ToggleOn';
const ToggleThemeSidebarItem: FC<{}> = () => {
return (
<ThemeContext.Consumer>
{themeContext => {
let text = 'Auto';
let icon = ToggleOnIcon;
switch (themeContext.theme) {
case 'dark':
text = 'Dark mode';
icon = Brightness2Icon;
break;
case 'light':
text = 'Light mode';
icon = WbSunnyIcon;
break;
default:
text = 'Auto';
icon = ToggleOnIcon;
break;
}
return (
<SidebarItem
text={text}
onClick={themeContext.toggleTheme}
icon={icon}
/>
);
}}
</ThemeContext.Consumer>
const ToggleThemeSidebarItem: FC<{}> = () => {
const appThemeApi = useApi(appThemeApiRef);
const themeId = useObservable(
appThemeApi.activeThemeId$(),
appThemeApi.getActiveThemeId(),
);
let text = 'Auto';
let icon = ToggleOnIcon;
switch (themeId) {
case 'dark':
text = 'Dark mode';
icon = Brightness2Icon;
break;
case 'light':
text = 'Light mode';
icon = WbSunnyIcon;
break;
default:
text = 'Auto';
icon = ToggleOnIcon;
break;
}
const handleToggle = () => {
if (!themeId) {
appThemeApi.setActiveThemeId('light');
} else if (themeId === 'light') {
appThemeApi.setActiveThemeId('dark');
} else {
appThemeApi.setActiveThemeId(undefined);
}
};
return <SidebarItem text={text} onClick={handleToggle} icon={icon} />;
};
export default ToggleThemeSidebarItem;