packages/app: switch to using theme config
This commit is contained in:
+10
-48
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user