forked from deephaven/web-client-ui
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Theme Plugin Loading (deephaven#1524)
- First pass at base theme variables `theme_default_dark.scss` and `theme_default_light.scss` - Swapped a few places `--dh-background-color`. This is only consumed in a few places and is set to the original `#1a171a` color in theme_default_dark, so shouldn't result in any display changes by default. - Loading custom themes from a new `ThemePlugin` type. 2 sample themes can be found in this DRAFT PR: deephaven/deephaven-plugins#65 ### Testing Setup Theme Plugins Locally - Checkout the draft plugins PR: deephaven/deephaven-plugins#65 - Configure docker-compose for Community to load from checked out plugins directory e.g `START_OPTS=-Xmx4g -Ddeephaven.jsPlugins.resourceBase=/plugin-dev` and map a volume `/Users/jdoe/code/deephaven-plugins/plugins:/plugin-dev` - `docker-compose up` (note, this has to be restarted any time plugins config changes) Run web ui locally - On initial load - Nothing should look different in the UI. Inspect the `div id="root"` element. - Its first child should be `<style data-theme-key="default-dark">...` - Inspect the `<body>` el. There should be some `--dh-color-xxx` CSS variables loaded in the inspector. - In "Application" dev tools tab there should be an entry in localStorage `deephaven.themeCache` `{"themeKey":"default-dark","preloadStyleContent":":root{--dh-accent-color:#4c7dee;--dh-background-color:#1a171a}"}` - Switch default theme - In console run: `localStorage.setItem('deephaven.themeCache', '{"themeKey":"default-light"}')` and reload page Note: On the first page refresh, there will be a moment where the background shows the previously applied theme. Refreshing the page again should show the right color the entire time. This is due to how we are setting things via the console but won't be an issue once users can select themes from the UI. - UI should show white background in title bar (it won't look good, just proving we can switch color) - Its first child should be `<style data-theme-key="default-light">...` - Inspect the `<body>` el. There should be some `--dh-color-xxx` CSS variables loaded in the inspector. - In "Application" dev tools tab there should be an entry in localStorage `deephaven.themeCache` `{"themeKey":"default-light","preloadStyleContent":":root{--dh-accent-color:#4c7dee;--dh-background-color:#fdfdfd}"}` - Repeat, but this time run: `localStorage.setItem('deephaven.themeCache', '{"themeKey":"default-dark"}')` and reload page. Should see things go back to initial load state - Load custom themes There should be 4 custom themes provided by the plugins repo. They can be selected via the following: - `localStorage.setItem('deephaven.themeCache', '{"themeKey":"theme-multi-example_acme-dark"}')` - `localStorage.setItem('deephaven.themeCache', '{"themeKey":"theme-multi-example_acme-light"}')` - `localStorage.setItem('deephaven.themeCache', '{"themeKey":"theme-multi-example_acme-cool"}')` - `localStorage.setItem('deephaven.themeCache', '{"themeKey":"theme-single-example_single-dark"}')` - These should produce similar results as the default ones, except: - There should be 2 `style` tags under the `div id="root"`. The first will be either the dark or light base theme. The 2nd will correspond to the custom theme variables - Inspecting the body element should show additional `:root { ... }` css variables for the custom theme just above the base theme variables - localStorage should contain an entry like: `{"themeKey":"theme-multi-example_acme-light","preloadStyleContent":":root{--dh-accent-color:#4c7dee;--dh-background-color:#fdfdfd}"}` corresponding to the current theme. - Reloading the page should keep the same styling resolves deephaven#1530
- Loading branch information
Showing
33 changed files
with
1,165 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { ThemeProvider } from '@deephaven/components'; | ||
import { useContext, useMemo } from 'react'; | ||
import { getThemeDataFromPlugins } from '../plugins'; | ||
import { PluginsContext } from './PluginsBootstrap'; | ||
|
||
export interface ThemeBootstrapProps { | ||
children: React.ReactNode; | ||
} | ||
|
||
export function ThemeBootstrap({ children }: ThemeBootstrapProps): JSX.Element { | ||
// The `usePlugins` hook throws if the context value is null. Since this is | ||
// the state while plugins load asynchronously, we are using `useContext` | ||
// directly to avoid the exception. | ||
const pluginModules = useContext(PluginsContext); | ||
|
||
const themes = useMemo( | ||
() => | ||
pluginModules == null ? null : getThemeDataFromPlugins(pluginModules), | ||
[pluginModules] | ||
); | ||
|
||
return <ThemeProvider themes={themes}>{children}</ThemeProvider>; | ||
} | ||
|
||
export default ThemeBootstrap; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import { ThemeData } from '@deephaven/components'; | ||
import { DashboardPlugin, PluginModule, ThemePlugin } from '@deephaven/plugin'; | ||
import { getThemeDataFromPlugins } from './PluginUtils'; | ||
|
||
beforeEach(() => { | ||
document.body.removeAttribute('style'); | ||
document.head.innerHTML = ''; | ||
jest.clearAllMocks(); | ||
expect.hasAssertions(); | ||
}); | ||
|
||
describe('getThemeDataFromPlugins', () => { | ||
const themePluginSingleDark: ThemePlugin = { | ||
name: 'mock.themePluginNameA', | ||
type: 'ThemePlugin', | ||
themes: { | ||
name: 'mock.customDark', | ||
baseTheme: 'dark', | ||
styleContent: 'mock.styleContent', | ||
}, | ||
}; | ||
|
||
const themePluginSingleLight: ThemePlugin = { | ||
name: 'mock.themePluginNameB', | ||
type: 'ThemePlugin', | ||
themes: { | ||
name: 'mock.customLight', | ||
baseTheme: 'light', | ||
styleContent: 'mock.styleContent', | ||
}, | ||
}; | ||
|
||
const themePluginMultiConfig: ThemePlugin = { | ||
name: 'mock.themePluginNameC', | ||
type: 'ThemePlugin', | ||
themes: [ | ||
{ | ||
name: 'mock.customDark', | ||
baseTheme: 'dark', | ||
styleContent: 'mock.styleContent', | ||
}, | ||
{ | ||
name: 'mock.customLight', | ||
baseTheme: 'light', | ||
styleContent: 'mock.styleContent', | ||
}, | ||
{ | ||
name: 'mock.customUndefined', | ||
styleContent: 'mock.styleContent', | ||
}, | ||
], | ||
}; | ||
|
||
const otherPlugin: DashboardPlugin = { | ||
name: 'mock.otherPluginName', | ||
type: 'DashboardPlugin', | ||
component: () => null, | ||
}; | ||
|
||
const pluginMap = new Map<string, PluginModule>([ | ||
['mock.themePluginNameA', themePluginSingleDark], | ||
['mock.themePluginNameB', themePluginSingleLight], | ||
['mock.themePluginNameC', themePluginMultiConfig], | ||
['mock.otherPluginName', otherPlugin], | ||
]); | ||
|
||
it('should return theme data from plugins', () => { | ||
const actual = getThemeDataFromPlugins(pluginMap); | ||
const expected: ThemeData[] = [ | ||
{ | ||
name: 'mock.customDark', | ||
baseThemeKey: 'default-dark', | ||
themeKey: 'mock.themePluginNameA_mock.customDark', | ||
styleContent: 'mock.styleContent', | ||
}, | ||
{ | ||
name: 'mock.customLight', | ||
baseThemeKey: 'default-light', | ||
themeKey: 'mock.themePluginNameB_mock.customLight', | ||
styleContent: 'mock.styleContent', | ||
}, | ||
{ | ||
name: 'mock.customDark', | ||
baseThemeKey: 'default-dark', | ||
themeKey: 'mock.themePluginNameC_mock.customDark', | ||
styleContent: 'mock.styleContent', | ||
}, | ||
{ | ||
name: 'mock.customLight', | ||
baseThemeKey: 'default-light', | ||
themeKey: 'mock.themePluginNameC_mock.customLight', | ||
styleContent: 'mock.styleContent', | ||
}, | ||
{ | ||
name: 'mock.customUndefined', | ||
baseThemeKey: 'default-dark', | ||
themeKey: 'mock.themePluginNameC_mock.customUndefined', | ||
styleContent: 'mock.styleContent', | ||
}, | ||
]; | ||
|
||
expect(actual).toEqual(expected); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.