diff --git a/CHANGELOG.md b/CHANGELOG.md
index 539c5aa3de57..1eb066f49315 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -65,6 +65,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- [Multiple Datasource] Able to Hide "Local Cluster" option from datasource DropDown ([#5827](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5827))
- [Multiple Datasource] Add api registry and allow it to be added into client config in data source plugin ([#5895](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5895))
- [Multiple Datasource] Refactor client and legacy client to use authentication registry ([#5881](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5881))
+- [Theme] Make theme and dark mode settings user/device specific (in local storage), with opt-out ([#5652](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5652))
### 🐛 Bug Fixes
diff --git a/docs/theme.md b/docs/theme.md
new file mode 100644
index 000000000000..293c65661c04
--- /dev/null
+++ b/docs/theme.md
@@ -0,0 +1,131 @@
+# Theme System
+
+## Basic concepts
+
+### Theme definitions in OUI
+
+Themes are defined in OUI via https://github.com/opensearch-project/oui/blob/main/src/themes/themes.ts. When Building OUI, there are several theming artifacts generated (beyond the react components) for each mode (light/dark) of each theme:
+
+1. Theme compiled stylesheets (e.g. `@elastic/eui/dist/eui_theme_dark.css`). Consumed as entry files in [/packages/osd-ui-shared-deps/webpack.config.js](/packages/osd-ui-shared-deps/webpack.config.js) and republished by `osd-ui-shared-deps` (e.g. [UiSharedDeps.darkCssDistFilename](/packages/osd-ui-shared-deps/index.js)).
+2. Theme compiled and minified stylesheets (e.g. `@elastic/eui/dist/eui_theme_dark.min.css`). These appear unused by OpenSearch Dashboards
+3. Theme computed SASS variables as JSON (e.g. `@elastic/eui/dist/eui_theme_dark.json`). Consumed by [/packages/osd-ui-shared-deps/theme.ts](/packages/osd-ui-shared-deps/theme.ts) and made available to other components via the mode and theme aware `euiThemeVars`. In general, these should not be consumed by any other component directly.
+4. Theme type definition file for SASS variables as JSON (e.g. `@elastic/eui/dist/eui_theme_dark.json.d.ts`)
+
+Note that all of these artifacts should ideally only be imported or used directly in one place (by `osd-ui-shared-deps`).
+
+In addition to these artifacts, OpenSearch Dashboards also makes heavy use of the theme SASS variables and mixins as defined in the source files (e.g. `@elastic/eui/src/theme_dark.scss`).
+
+### Theme definitions in OpenSearch Dashboards
+
+1. Theme tags are defined in [/packages/osd-optimizer/src/common/theme_tags.ts](/packages/osd-optimizer/src/common/theme_tags.ts) corresponding to each mode (light/dark) of each OUI theme.
+2. These tags must correspond to entrypoint SCSS files in [/src/core/public/core_app/styles/](/src/core/public/core_app/styles/_globals_v8dark.scss), because they are imported by all SCSS files as part of the `sass-loader` in [/packages/osd-optimizer/src/worker/webpack.config.ts](/packages/osd-optimizer/src/worker/webpack.config.ts) and [/packages/osd-optimizer/src/worker/theme_loader.ts](/packages/osd-optimizer/src/worker/theme_loader.ts). Note that the optimizer webpack will compile a separate stylesheet for each unique mode and theme combination.
+3. OUI SCSS source files are also imported by `osd-ui-framework`, which generates the legacy KUI stylesheets (e.g. [/packages/osd-ui-framework/src/kui_next_dark.scss](/packages/osd-ui-framework/src/kui_next_dark.scss)). KUI is a UI library that predates EUI/OUI, and should be deprecated and fully removed via [#1060](https://github.com/opensearch-project/OpenSearch-Dashboards/issues/1060). Because it's a legacy package it has its own build process that doesn't use webpack; it just [compiles the SCSS files with grunt](/packages/osd-ui-framework/Gruntfile.js). But similarly to 2., a separate stylesheet is generated for each mode and theme combination.
+
+### Thmemed assets in OpenSearch Dasboards
+
+In general, most themed assests can be found in [/src/core/server/core_app/assets](src/core/server/core_app/assets/fonts/readme.md) (it also includes non-themed assets such as `favicons`, which could easily be themed if desired in the future).
+
+Most of the graphics/images are only dark/light mode-specific, not theme-specific:
+
+1. `default_branding` marks
+2. `logos`
+
+This directory also includes legacy CSS files ([/src/core/server/core_app/assets/legacy_dark_theme.css](/src/core/server/core_app/assets/legacy_dark_theme.css) and [/src/core/server/core_app/assets/legacy_light_theme.css](/src/core/server/core_app/assets/legacy_light_theme.css)), which predate even KUI, and are still used by some plugins (notably `discover`). See [#4385](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4385) for an experiment in removing these. Unlike KUI, they don't rely on OUI themes at all.
+
+Finally, font assets are a bit of a special case. Theme-specific fonts are defined by OUI, but it doesn't include the font definitions directly. Instead, the font assets are in [/src/core/server/core_app/assets/fonts](/src/core/server/core_app/assets/fonts/readme.md). The corresponding `@font-face` style definitions are generated at runtime via [/src/core/server/rendering/views/fonts.tsx](/src/core/server/rendering/views/fonts.tsx).
+
+## Theme settings
+
+## Theme loading
+
+```mermaid
+sequenceDiagram
+ autonumber
+ critical Setup
+ core/server->>core/server/rendering: setup rendering service
+ core/server/rendering->>core/server: provide render() method
+ core/server->>core/server: setup legacy service
+ core/server->>legacy: create legacy server
+ legacy->>legacy: start ui mixin to
handle special routes
+ core/server->>core/server/core_app: setup core app
+ core/server/core_app->>core/server/core_app: register default routes
+ core/server/core_app->>core/server/core_app: register static asset dir routes
+ end
+ Browser->>core/server: OSD page request (e.g. /app/home#/ )
+ core/server->>core/server/core_app: request to default route
(via `http` service)
+ core/server/core_app->>core/server: call renderCoreApp()
+ core/server->>core/server/rendering: call render()
+ critical Initial page bootstrap
+ core/server/rendering->>core/server/rendering: get theme settings from config
+ core/server/rendering->>core/server/rendering: assign branding values \
(including dark mode)
+ core/server/rendering->>Browser: return static loading page template
+ Note over core/server/rendering,Browser: includes inlined font-face styles and static loading page styles
+ critical
(render blocking)
+ Browser->>Browser: define injection points
+ Browser->>Browser: load static loading page styles
+ Browser->>Browser: load font-face styles
+ Browser->>legacy: load startup.js special route
+ legacy->>legacy: build startup.js from template
+ Note over legacy: inject theme settings and font sources
+ legacy->>Browser: startup.js
+ critical startup.js
+ Browser->>Browser: get theme preferences from local storage
+ Browser->>Browser: set global theme tag
+ Browser->>Browser: inject theme-specific loading page styles
+ Browser->>Browser: inject theme-specific font css vars
+ end
+ end
+ Browser->>Browser: render loading/error page
(with loaders hidden)
+ Browser->>legacy: load bootstrap.js special route
+ legacy->>legacy: build bootstrap.js from template
+ legacy->>Browser: bootstrap.js
+ critical bootstrap.js
+ Browser->>Browser: toggle visibility of errors/loaders
+ Browser->>Browser: get theme preferences from local storage
+ Browser->>core/server/core_app: load js bundles
+ core/server/core_app->>Browser: (React application)
+ Browser->>core/server/core_app: load theme-specific stylesheets
(base, OUI, KUI, legacy)
+ core/server/core_app->>Browser: themed css
+ end
+ end
+```
+
+### Loading
+
+`src/legacy/ui/ui_render/ui_render_mixin.js` via `src/legacy/ui/ui_render/bootstrap/template.js.hbs` and `src/legacy/ui/ui_render/bootstrap/app_bootstrap.js`. Aliased in `src/legacy/ui/ui_mixin.js`, called by `src/legacy/server/osd_server.js`. Called by `src/core/server/legacy/legacy_service.ts` via `src/core/server/server.ts`
+
+### Injected style tags
+
+1. `src/core/server/rendering/views/styles.tsx` - depends on dark/light mode and injects style tag in head
+2. `src/core/server/rendering/views/fonts.tsx` - depends on theme version and injects font style tag in head
+3. Monaco editor styles
+4. Ace styles
+5. Ace TM overrides
+6. Ace error styles
+6. Component styles
+
+### Styleshsheets loaded
+
+Each of the following are loaded in the browser by the [bootstrap script](/src/legacy/ui/ui_render/bootstrap/template.js.hbs) in this order. Currently, these are never unloaded.
+
+1. Monaco editor styles (e.g. [/packages/osd-ui-shared-deps/target/osd-ui-shared-deps.css](/packages/osd-ui-shared-deps/target/osd-ui-shared-deps.css)), packaged by [/packages/osd-ui-shared-deps/webpack.config.js](/packages/osd-ui-shared-deps/webpack.config.js). In theory, this file could include styles from other shared dependencies, but currently `osd-monaco` is the only package that exports styles. Note that these are the default, un-themed styles; theming of monaco editors is handled by [/src/plugins/opensearch_dashboards_react/public/code_editor/editor_theme.ts](/src/plugins/opensearch_dashboards_react/public/code_editor/editor_theme.ts).
+2. Theme and mode-specific OUI styles (e.g. [](), compiled by `packages/osd-ui-shared-deps/webpack.config.js`).
+3. Theme and mode-specific KUI styles (e.g. `packages/osd-ui-framework/src/kui_next_dark.scss`, compiled by `packages/osd-ui-framework/Gruntfile.js`). Separate stylesheets for each theme version/dark mode combo (colors).
+4. Mode-specific legacy styles (e.g. [/src/core/server/core_app/assets/legacy_dark_theme.css](/src/core/server/core_app/assets/legacy_dark_theme.css))
+
+Component styles are not loaded as stylesheets.
+
+## Current theme usage
+
+### JSON/JS Vars
+
+1. Defined by `packages/osd-ui-shared-deps/theme.ts`
+ 1. Used by `src/plugins/charts/public/static/color_maps/color_maps.ts` to set vis colors
+ 2. Used by `src/plugins/discover/public/application/components/chart/histogram/histogram.tsx` to define Discover histogram Elastic Chart styling
+ 3. Used by `src/plugins/maps_legacy/public/map/opensearch_dashboards_map.js` and `src/plugins/region_map/public/choropleth_layer.js` for minor map UI styling (line color, empty shade)
+ 4. Used by `src/plugins/vis_type_vega/public/data_model/vega_parser.ts` for Vega/Vega-Lite theming
+2. Used by `src/plugins/vis_type_vislib/public/vislib/components/tooltip/tooltip.js` for tooltip spacing
+3. Used by `src/plugins/expressions/public/react_expression_renderer.tsx` to define padding options.
+4. Used by `src/core/server/rendering/views/theme.ts` to inject values into `src/core/server/rendering/views/styles.tsx`
+5. Used (incorrectly) to style a badge color in `src/plugins/index_pattern_management/public/components/create_button/create_button.tsx`
+6. Used by `src/plugins/opensearch_dashboards_react/public/code_editor/editor_theme.ts` to create Monaco theme styles
diff --git a/src/core/public/osd_bootstrap.test.ts b/src/core/public/osd_bootstrap.test.ts
index 806841287bee..e4209b460f86 100644
--- a/src/core/public/osd_bootstrap.test.ts
+++ b/src/core/public/osd_bootstrap.test.ts
@@ -34,6 +34,7 @@ import { __osdBootstrap__ } from './';
describe('osd_bootstrap', () => {
beforeAll(() => {
const metadata = {
+ branding: { darkMode: 'true' },
i18n: { translationsUrl: 'http://localhost' },
vars: { apmConfig: null },
};
diff --git a/src/core/public/osd_bootstrap.ts b/src/core/public/osd_bootstrap.ts
index f5571292b83a..ed64ed0bc2b5 100644
--- a/src/core/public/osd_bootstrap.ts
+++ b/src/core/public/osd_bootstrap.ts
@@ -38,6 +38,11 @@ export async function __osdBootstrap__() {
document.querySelector('osd-injected-metadata')!.getAttribute('data')!
);
+ const globals: any = typeof window === 'undefined' ? {} : window;
+ const themeTag: string = globals.__osdThemeTag__ || '';
+
+ injectedMetadata.branding.darkMode = themeTag.endsWith('dark');
+
let i18nError: Error | undefined;
const apmSystem = new ApmSystem(injectedMetadata.vars.apmConfig, injectedMetadata.basePath);
diff --git a/src/core/public/ui_settings/ui_settings_client.ts b/src/core/public/ui_settings/ui_settings_client.ts
index 8a5701de6b39..19637debf948 100644
--- a/src/core/public/ui_settings/ui_settings_client.ts
+++ b/src/core/public/ui_settings/ui_settings_client.ts
@@ -58,6 +58,13 @@ export class UiSettingsClient implements IUiSettingsClient {
this.defaults = cloneDeep(params.defaults);
this.cache = defaultsDeep({}, this.defaults, cloneDeep(params.initialSettings));
+ if (
+ this.cache['theme:enableUserControl']?.userValue ??
+ this.cache['theme:enableUserControl']?.value
+ ) {
+ this.cache = defaultsDeep(this.cache, this.getBrowserStoredSettings());
+ }
+
params.done$.subscribe({
complete: () => {
this.update$.complete();
@@ -173,6 +180,28 @@ You can use \`IUiSettingsClient.get("${key}", defaultValue)\`, which will just r
return this.updateErrors$.asObservable();
}
+ private getBrowserStoredSettings() {
+ const uiSettingsJSON = window.localStorage.getItem('uiSettings') || '{}';
+ try {
+ return JSON.parse(uiSettingsJSON);
+ } catch (error) {
+ this.updateErrors$.next(error);
+ }
+ return {};
+ }
+
+ private setBrowserStoredSettings(key: string, newVal: any) {
+ const oldSettings = this.getBrowserStoredSettings();
+ const newSettings = cloneDeep(oldSettings);
+ if (newVal === null) {
+ delete newSettings[key];
+ } else {
+ newSettings[key] = { userValue: newVal };
+ }
+ window.localStorage.setItem(`uiSettings`, JSON.stringify(newSettings));
+ return { settings: newSettings };
+ }
+
private assertUpdateAllowed(key: string) {
if (this.isOverridden(key)) {
throw new Error(
@@ -198,8 +227,18 @@ You can use \`IUiSettingsClient.get("${key}", defaultValue)\`, which will just r
this.setLocally(key, newVal);
try {
- const { settings } = await this.api.batchSet(key, newVal);
- this.cache = defaultsDeep({}, defaults, settings);
+ if (
+ this.cache['theme:enableUserControl']?.userValue ??
+ this.cache['theme:enableUserControl']?.value
+ ) {
+ const { settings } = this.cache[key]?.preferBrowserSetting
+ ? this.setBrowserStoredSettings(key, newVal)
+ : (await this.api.batchSet(key, newVal)) || {};
+ this.cache = defaultsDeep({}, defaults, this.getBrowserStoredSettings(), settings);
+ } else {
+ const { settings } = (await this.api.batchSet(key, newVal)) || {};
+ this.cache = defaultsDeep({}, defaults, settings);
+ }
this.saved$.next({ key, newValue: newVal, oldValue: initialVal });
return true;
} catch (error) {
diff --git a/src/core/server/rendering/__snapshots__/rendering_service.test.ts.snap b/src/core/server/rendering/__snapshots__/rendering_service.test.ts.snap
index ad92d759a832..01c238783ce5 100644
--- a/src/core/server/rendering/__snapshots__/rendering_service.test.ts.snap
+++ b/src/core/server/rendering/__snapshots__/rendering_service.test.ts.snap
@@ -8,7 +8,6 @@ Object {
"branding": Object {
"applicationTitle": "OpenSearch Dashboards",
"assetFolderUrl": "/mock-server-basepath/ui/default_branding",
- "darkMode": false,
"loadingLogo": Object {},
"logo": Object {},
"mark": Object {},
@@ -61,7 +60,6 @@ Object {
"branding": Object {
"applicationTitle": "OpenSearch Dashboards",
"assetFolderUrl": "/mock-server-basepath/ui/default_branding",
- "darkMode": false,
"loadingLogo": Object {},
"logo": Object {},
"mark": Object {},
@@ -114,7 +112,6 @@ Object {
"branding": Object {
"applicationTitle": "OpenSearch Dashboards",
"assetFolderUrl": "/mock-server-basepath/ui/default_branding",
- "darkMode": true,
"loadingLogo": Object {},
"logo": Object {},
"mark": Object {},
@@ -167,7 +164,6 @@ Object {
"branding": Object {
"applicationTitle": "OpenSearch Dashboards",
"assetFolderUrl": "/mock-server-basepath/ui/default_branding",
- "darkMode": true,
"loadingLogo": Object {},
"logo": Object {},
"mark": Object {},
@@ -224,7 +220,6 @@ Object {
"branding": Object {
"applicationTitle": "OpenSearch Dashboards",
"assetFolderUrl": "/ui/default_branding",
- "darkMode": false,
"loadingLogo": Object {},
"logo": Object {},
"mark": Object {},
@@ -277,7 +272,6 @@ Object {
"branding": Object {
"applicationTitle": "OpenSearch Dashboards",
"assetFolderUrl": "/mock-server-basepath/ui/default_branding",
- "darkMode": false,
"loadingLogo": Object {},
"logo": Object {},
"mark": Object {},
@@ -330,7 +324,6 @@ Object {
"branding": Object {
"applicationTitle": "OpenSearch Dashboards",
"assetFolderUrl": "/mock-server-basepath/ui/default_branding",
- "darkMode": false,
"loadingLogo": Object {},
"logo": Object {},
"mark": Object {},
diff --git a/src/core/server/rendering/rendering_service.tsx b/src/core/server/rendering/rendering_service.tsx
index acaee7f42bc5..6030db2fd873 100644
--- a/src/core/server/rendering/rendering_service.tsx
+++ b/src/core/server/rendering/rendering_service.tsx
@@ -95,20 +95,8 @@ export class RenderingService {
defaults: uiSettings.getRegistered(),
user: includeUserSettings ? await uiSettings.getUserProvided() : {},
};
- // Cannot use `uiSettings.get()` since a user might not be authenticated
- const darkMode =
- (settings.user?.['theme:darkMode']?.userValue ??
- uiSettings.getOverrideOrDefault('theme:darkMode')) ||
- false;
-
- // At the very least, the schema should define a default theme; the '' will be unreachable
- const themeVersion =
- (settings.user?.['theme:version']?.userValue ??
- uiSettings.getOverrideOrDefault('theme:version')) ||
- '';
const brandingAssignment = await this.assignBrandingConfig(
- darkMode,
opensearchDashboardsConfig as OpenSearchDashboardsConfigType
);
@@ -116,10 +104,9 @@ export class RenderingService {
strictCsp: http.csp.strict,
uiPublicUrl,
bootstrapScriptUrl: `${basePath}/bootstrap.js`,
+ startupScriptUrl: `${basePath}/startup.js`,
i18n: i18n.translate,
locale: i18n.getLocale(),
- darkMode,
- themeVersion,
injectedMetadata: {
version: env.packageInfo.version,
buildNumber: env.packageInfo.buildNum,
@@ -144,7 +131,6 @@ export class RenderingService {
uiSettings: settings,
},
branding: {
- darkMode,
assetFolderUrl: `${uiPublicUrl}/default_branding`,
logo: {
defaultUrl: brandingAssignment.logoDefault,
@@ -198,20 +184,16 @@ export class RenderingService {
/**
* Assign values for branding related configurations based on branding validation
- * by calling checkBrandingValid(). For dark mode URLs, add additional validation
- * to see if there is a valid default mode URL exist first. If URL is valid, pass in
+ * by calling checkBrandingValid(). If URL is valid, pass in
* the actual URL; if not, pass in undefined.
*
- * @param {boolean} darkMode
* @param {Readonly} opensearchDashboardsConfig
* @returns {BrandingAssignment} valid URLs or undefined assigned for each branding configs
*/
private assignBrandingConfig = async (
- darkMode: boolean,
opensearchDashboardsConfig: Readonly
): Promise => {
const brandingValidation: BrandingValidation = await this.checkBrandingValid(
- darkMode,
opensearchDashboardsConfig
);
const branding = opensearchDashboardsConfig.branding;
@@ -230,47 +212,18 @@ export class RenderingService {
: undefined;
// assign dark mode URLs based on brandingValidation function result
- let logoDarkmode = brandingValidation.isLogoDarkmodeValid
+ const logoDarkmode = brandingValidation.isLogoDarkmodeValid
? branding.logo.darkModeUrl
: undefined;
- let markDarkmode = brandingValidation.isMarkDarkmodeValid
+ const markDarkmode = brandingValidation.isMarkDarkmodeValid
? branding.mark.darkModeUrl
: undefined;
- let loadingLogoDarkmode = brandingValidation.isLoadingLogoDarkmodeValid
+ const loadingLogoDarkmode = brandingValidation.isLoadingLogoDarkmodeValid
? branding.loadingLogo.darkModeUrl
: undefined;
- /**
- * For dark mode URLs, we added another validation:
- * user can only provide a dark mode URL after providing a valid default mode URL,
- * If user provides a valid dark mode URL but fails to provide a valid default mode URL,
- * return undefined for the dark mode URL
- */
- if (logoDarkmode && !logoDefault) {
- this.logger
- .get('branding')
- .error('Must provide a valid logo default mode URL before providing a logo dark mode URL');
- logoDarkmode = undefined;
- }
-
- if (markDarkmode && !markDefault) {
- this.logger
- .get('branding')
- .error('Must provide a valid mark default mode URL before providing a mark dark mode URL');
- markDarkmode = undefined;
- }
-
- if (loadingLogoDarkmode && !loadingLogoDefault) {
- this.logger
- .get('branding')
- .error(
- 'Must provide a valid loading logo default mode URL before providing a loading logo dark mode URL'
- );
- loadingLogoDarkmode = undefined;
- }
-
// assign favicon based on brandingValidation function result
const favicon = brandingValidation.isFaviconValid ? branding.faviconUrl : undefined;
@@ -302,35 +255,30 @@ export class RenderingService {
* user inputs valid or invalid URLs by calling isUrlValid() function. Also
* check if title is valid by calling isTitleValid() function.
*
- * @param {boolean} darkMode
* @param {Readonly} opensearchDashboardsConfig
* @returns {BrandingValidation} indicate valid/invalid URL for each branding config
*/
private checkBrandingValid = async (
- darkMode: boolean,
opensearchDashboardsConfig: Readonly
): Promise => {
const branding = opensearchDashboardsConfig.branding;
const isLogoDefaultValid = await this.isUrlValid(branding.logo.defaultUrl, 'logo default');
- const isLogoDarkmodeValid = darkMode
- ? await this.isUrlValid(branding.logo.darkModeUrl, 'logo darkMode')
- : false;
+ const isLogoDarkmodeValid = await this.isUrlValid(branding.logo.darkModeUrl, 'logo darkMode');
const isMarkDefaultValid = await this.isUrlValid(branding.mark.defaultUrl, 'mark default');
- const isMarkDarkmodeValid = darkMode
- ? await this.isUrlValid(branding.mark.darkModeUrl, 'mark darkMode')
- : false;
+ const isMarkDarkmodeValid = await this.isUrlValid(branding.mark.darkModeUrl, 'mark darkMode');
const isLoadingLogoDefaultValid = await this.isUrlValid(
branding.loadingLogo.defaultUrl,
'loadingLogo default'
);
- const isLoadingLogoDarkmodeValid = darkMode
- ? await this.isUrlValid(branding.loadingLogo.darkModeUrl, 'loadingLogo darkMode')
- : false;
+ const isLoadingLogoDarkmodeValid = await this.isUrlValid(
+ branding.loadingLogo.darkModeUrl,
+ 'loadingLogo darkMode'
+ );
const isFaviconValid = await this.isUrlValid(branding.faviconUrl, 'favicon');
diff --git a/src/core/server/rendering/types.ts b/src/core/server/rendering/types.ts
index 45821c2b8228..ecf3e2a9674e 100644
--- a/src/core/server/rendering/types.ts
+++ b/src/core/server/rendering/types.ts
@@ -43,10 +43,9 @@ export interface RenderingMetadata {
strictCsp: ICspConfig['strict'];
uiPublicUrl: string;
bootstrapScriptUrl: string;
+ startupScriptUrl: string;
i18n: typeof i18n.translate;
locale: string;
- darkMode: boolean;
- themeVersion: string;
injectedMetadata: {
version: string;
buildNumber: number;
diff --git a/src/core/server/rendering/views/__snapshots__/template.test.tsx.snap b/src/core/server/rendering/views/__snapshots__/template.test.tsx.snap
index 36d073992ec8..1204752a6469 100644
--- a/src/core/server/rendering/views/__snapshots__/template.test.tsx.snap
+++ b/src/core/server/rendering/views/__snapshots__/template.test.tsx.snap
@@ -50,10 +50,6 @@ Array [
content="[object Object]/ui/favicons/browserconfig.xml"
name="msapplication-config"
/>,
- ,
null,
,
null,
+ ,
+ ,
,
@@ -83,7 +85,15 @@ Array [
>
+
+ ,
- ,
null,
,
null,
+ ,
+ ,
,
@@ -213,7 +232,15 @@ Array [
>
+
+ ,
- ,
null,
,
null,
+ ,
+ ,
,
@@ -343,7 +379,15 @@ Array [
>
+
+
,
@@ -366,7 +413,14 @@ Array [
>
+ ,
- ,
null,
,
null,
+ ,
+ ,
,
@@ -476,7 +532,15 @@ Array [
>
+
+
,
@@ -499,7 +566,14 @@ Array [
>
+ ,
- ,
null,
,
null,
+ ,
+ ,
,
@@ -609,7 +685,15 @@ Array [
>
+
+ ,
- ,
null,
,
null,
+ ,
+ ,
,
@@ -739,7 +832,15 @@ Array [
>
+
+ ,
- ,
null,
,
null,
+ ,
+ ,
,
@@ -869,7 +979,15 @@ Array [
>
+
+
,
@@ -892,7 +1013,14 @@ Array [
>
+ ,
- ,
null,
,
null,
+ ,
+ ,
,
@@ -1002,7 +1132,15 @@ Array [
>
+
+ ,
- ,
null,
,
null,
+ ,
+ ,
,
@@ -1132,7 +1279,15 @@ Array [
>
+
+ ,
- ,
null,
,
null,
+ ,
+ ,
,
@@ -1262,7 +1426,15 @@ Array [
>
+
+ ;
}
-export const Fonts: FunctionComponent = ({ url, theme }) => {
+export const Fonts: FunctionComponent = ({ url }) => {
// For next theme
const sourceSans3: FontFace = {
family: 'Source Sans 3',
@@ -532,9 +531,7 @@ export const Fonts: FunctionComponent = ({ url, theme }) => {
url('${url}/fonts/inter_ui/Inter-UI-italic.var.woff2') format('woff2');
}
*/
- const fontText = theme === 'v7' ? interUi : sourceSans3;
- const fontCode = theme === 'v7' ? roboto : sourceCodePro;
- const fontsDefinitionRules = [fontText, fontCode]
+ const fontsDefinitionRules = [interUi, sourceSans3, roboto, sourceCodePro]
.flatMap(({ family, variants }) =>
variants.map(({ style, weight, format, sources, unicodeRange }) => {
const src = sources
@@ -557,36 +554,11 @@ export const Fonts: FunctionComponent = ({ url, theme }) => {
)
.join('\n');
- /*
- * The default fonts are added as CSS variables, overriding OUI's, and then
- * the CSS variables are consumed.
- */
- const fontRules = `
- :root {
- --font-text: "${fontText.family}", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
- sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
-
- --font-code: "${fontCode.family}", Consolas, Menlo, Courier, monospace;
-
- --oui-font-family: var(--font-text);
- --oui-code-font-family: var(--font-code);
- }
-
- code, pre, kbd, samp {
- font-family: var(--font-code);
- }
- html, input, textarea, select, button {
- font-family: var(--font-text);
- }
-
- `;
-
return (
diff --git a/src/core/server/rendering/views/styles.tsx b/src/core/server/rendering/views/styles.tsx
index c3edbfe01bfd..5d44fa69a6b2 100644
--- a/src/core/server/rendering/views/styles.tsx
+++ b/src/core/server/rendering/views/styles.tsx
@@ -32,28 +32,11 @@
import React, { FunctionComponent } from 'react';
-import { RenderingMetadata } from '../types';
-import { getThemeDefinition, ThemeColorSchemes } from './theme';
-
-interface Props {
- darkMode: RenderingMetadata['darkMode'];
- theme: RenderingMetadata['themeVersion'];
-}
-
-export const Styles: FunctionComponent = ({ theme, darkMode }) => {
- const themeDefinition = getThemeDefinition(
- theme,
- darkMode ? ThemeColorSchemes.DARK : ThemeColorSchemes.LIGHT
- );
-
+export const Styles: FunctionComponent = () => {
return (