diff --git a/next.config.js b/next.config.js index f8ea6e0c..8c3fa614 100644 --- a/next.config.js +++ b/next.config.js @@ -7,7 +7,7 @@ const iniparser = require('iniparser'); const withBundleAnalyzer = require('@next/bundle-analyzer'); const CopyWebpackPlugin = require('copy-webpack-plugin'); -const { IgnorePlugin, NormalModuleReplacementPlugin } = require('webpack'); +const { IgnorePlugin } = require('webpack'); /** * If you are deploying your site under a directory other than `/` e.g. @@ -66,10 +66,7 @@ const nextConfig = { } return (context, callback) => { - if ( - context.request.indexOf('@elastic/eui') > -1 || - context.request.indexOf('react-ace') > -1 - ) { + if (context.request.indexOf('@elastic/eui') > -1) { return callback(); } @@ -77,13 +74,6 @@ const nextConfig = { }; }); - // Replace `react-ace` with an empty module on the server. - // https://webpack.js.org/loaders/null-loader/ - config.module.rules.push({ - test: /react-ace/, - use: 'null-loader', - }); - // Mock HTMLElement on the server-side const definePluginId = config.plugins.findIndex( p => p.constructor.name === 'DefinePlugin' @@ -99,18 +89,6 @@ const nextConfig = { config.plugins.push( new CopyWebpackPlugin({ patterns: themeConfig.copyConfig }), - // We don't want to load all highlight.js language - provide a mechanism to register just some. - // If you need to highlight more than just JSON, edit the file below. - new NormalModuleReplacementPlugin( - /^highlight\.js$/, - path.join(__dirname, `src/lib/highlight.ts`) - ), - - new NormalModuleReplacementPlugin( - /^lowlight$/, - path.join(__dirname, `src/lib/lowlight.ts`) - ), - // Moment ships with a large number of locales. Exclude them, leaving // just the default English locale. If you need other locales, see: // https://create-react-app.dev/docs/troubleshooting/#momentjs-locales-are-missing diff --git a/package.json b/package.json index 0ad7af98..03013f0f 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,9 @@ "dependencies": {}, "devDependencies": { "@elastic/datemath": "^5.0.3", - "@elastic/eui": "^41.3.0", + "@elastic/eui": "^43.1.1", + "@emotion/cache": "^11.7.1", + "@emotion/react": "^11.7.1", "@next/bundle-analyzer": "^12.0.4", "@types/node": "^16.11.10", "@typescript-eslint/eslint-plugin": "^5.5.0", diff --git a/src/components/chrome/index.tsx b/src/components/chrome/index.tsx index 451ea99b..0c127260 100644 --- a/src/components/chrome/index.tsx +++ b/src/components/chrome/index.tsx @@ -1,5 +1,6 @@ import React, { FunctionComponent, useState } from 'react'; import { useRouter } from 'next/router'; +import createCache from '@emotion/cache'; import { EuiSideNav, @@ -10,8 +11,11 @@ import { EuiErrorBoundary, EuiFlexGroup, EuiFlexItem, + EuiProvider, } from '@elastic/eui'; +import { useProvider } from '../provider'; + import { buildTopLinks } from '../navigation_links/top_links'; import { buildSolutionLinks } from '../navigation_links/solution_links'; import { buildExploreLinks } from '../navigation_links/explore_links'; @@ -60,6 +64,22 @@ const AppLogo: FunctionComponent<{ onClick: () => void }> = ({ onClick }) => ( */ const Chrome: FunctionComponent = ({ children }) => { const router = useRouter(); + const { colorMode } = useProvider(); + + /** + * This `@emotion/cache` instance is used to insert the global styles + * into the correct location in ``. Otherwise they would be + * inserted after the static CSS files, resulting in style clashes. + * Only necessary until EUI has converted all components to CSS-in-JS: + * https://github.com/elastic/eui/issues/3912 + */ + const emotionCache = createCache({ + key: 'eui-styles', + container: + typeof document !== 'undefined' + ? document.querySelector('meta[name="eui-styles-global"]') + : null, + }); const [isSideNavOpenOnMobile, setIsSideNavOpenOnMobile] = useState(false); @@ -84,29 +104,31 @@ const Chrome: FunctionComponent = ({ children }) => { ]; return ( - - - - { - setIsSideNavOpenOnMobile(false); - router.push('/'); - }} - /> - - + + + + { + setIsSideNavOpenOnMobile(false); + router.push('/'); + }} /> - - + + + + -
{children}
-
-
+
{children}
+ + + ); }; diff --git a/src/components/chrome/theme_switcher.tsx b/src/components/chrome/theme_switcher.tsx index 82fd59a5..5abb9e2d 100644 --- a/src/components/chrome/theme_switcher.tsx +++ b/src/components/chrome/theme_switcher.tsx @@ -7,28 +7,28 @@ import { EuiPopoverTitle, } from '@elastic/eui'; -import { setInitialTheme, setTheme, themeConfig } from '../../lib/theme'; +import { useProvider } from '../provider'; -const initialTheme = setInitialTheme(); +import { setTheme, themeConfig } from '../../lib/theme'; /** * Renders a dropdown menu for selecting the current theme. The selection * is set in localStorage, so that it persists between visits. */ const ThemeSwitcher: FunctionComponent = () => { + const { colorMode, setColorMode } = useProvider(); const [isPopoverOpen, setPopoverOpen] = useState(false); - const [theme, setThemeInState] = useState(initialTheme); const handleChangeTheme = (newTheme: string) => { setPopoverOpen(false); + setColorMode(newTheme); setTheme(newTheme); - setThemeInState(newTheme); }; const items = themeConfig.availableThemes.map(each => ( handleChangeTheme(each.id)}> {each.name} diff --git a/src/components/provider.tsx b/src/components/provider.tsx new file mode 100644 index 00000000..c3ff217f --- /dev/null +++ b/src/components/provider.tsx @@ -0,0 +1,32 @@ +import React, { + FunctionComponent, + createContext, + useContext, + useState, +} from 'react'; + +import { setInitialTheme } from '../lib/theme'; + +/** + * React context for storing theme-related data and callbacks. + * `colorMode` is `light` or `dark` and will be consumed by + * various downstream components, including `EuiProvider`. + */ +export const GlobalProvider = createContext<{ + colorMode?: string; + setColorMode?: (colorMode: string) => void; +}>({}); + +export const Provider: FunctionComponent = ({ children }) => { + const initialTheme = setInitialTheme(); + const [colorMode, setColorMode] = useState(initialTheme); + return ( + + {children} + + ); +}; + +export const useProvider = () => { + return useContext(GlobalProvider); +}; diff --git a/src/lib/highlight.ts b/src/lib/highlight.ts deleted file mode 100644 index dd23e13c..00000000 --- a/src/lib/highlight.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ - -/** - * This is referenced from webpack, and is loaded instead of the normal Highlight.js - * index. This allows us to register only some languages, which cuts down on the - * number of languages that we send to the client. - */ - -// @ts-ignore -const hljs = require('highlight.js/lib/highlight'); - -// Add whatever languages you need here. See also `./lowlight.ts` -hljs.registerLanguage('json', require('highlight.js/lib/languages/json')); - -module.exports = hljs; diff --git a/src/lib/lowlight.ts b/src/lib/lowlight.ts deleted file mode 100644 index 371e1468..00000000 --- a/src/lib/lowlight.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ - -/** - * This is referenced from webpack, and is loaded instead of the normal lowlight - * index. This allows us to register only some languages, which cuts down on the - * number of languages that we send to the client. - */ - -// @ts-ignore -const low = require('lowlight/lib/core'); - -// Add whatever languages you need here. See also `./highlight.ts` -low.registerLanguage('json', require('highlight.js/lib/languages/json')); - -module.exports = low; diff --git a/src/lib/theme.ts b/src/lib/theme.ts index 26c966db..9816164b 100644 --- a/src/lib/theme.ts +++ b/src/lib/theme.ts @@ -19,6 +19,7 @@ export function setTheme(newThemeName: string): void { for (const themeLink of getAllThemes()) { // Disable all theme links, except for the desired theme, which we enable themeLink.disabled = themeLink.dataset.theme !== newThemeName; + themeLink['aria-disabled'] = themeLink.dataset.theme !== newThemeName; } // Add a class to the `body` element that indicates which theme we're using. diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 0897874d..08bcdd3c 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -6,6 +6,7 @@ import { EuiErrorBoundary } from '@elastic/eui'; import './app.scss'; import Chrome from '../components/chrome'; +import { Provider } from '../components/provider'; /** * Next.js uses the App component to initialize pages. You can override it @@ -20,11 +21,13 @@ const EuiApp: FunctionComponent = ({ Component, pageProps }) => ( {/* You can override this in other pages - see page-2.tsx for an example */} Next.js EUI Starter - - - - - + + + + + + + ); diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx index dea304c3..c341a239 100644 --- a/src/pages/_document.tsx +++ b/src/pages/_document.tsx @@ -42,7 +42,10 @@ export default class MyDocument extends Document { render(): ReactElement { return ( - {themeConfig.availableThemes.map(each => themeLink(each))} + + + {themeConfig.availableThemes.map(each => themeLink(each))} +
diff --git a/yarn.lock b/yarn.lock index 0aa6c49b..96903bda 100644 --- a/yarn.lock +++ b/yarn.lock @@ -50,7 +50,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.9.2": version "7.16.3" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.3.tgz#b86f0db02a04187a3c17caa77de69840165d42d5" integrity sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ== @@ -72,10 +72,10 @@ dependencies: tslib "^1.9.3" -"@elastic/eui@^41.3.0": - version "41.3.0" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-41.3.0.tgz#6016229b4112d0f3f0f53a94573020dea42a6cc9" - integrity sha512-8BE/4ZG0V+V+f3czC9wcCPTIHjovDkCuw9QiEUWrnXuA3uCXCKAx9AzuA5s+OtxfaHf+ELItNqCoGuKKa59jvg== +"@elastic/eui@^43.1.1": + version "43.1.1" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-43.1.1.tgz#5a4526c0a3fad45dcbe470dc33d1d9b701904494" + integrity sha512-ilVAfhM2QtrA8RiG5vgVBOW5xqyjpDeMTH2c/Nf8vEYVgebmTnDAJuaDj5lHpk01oqt2jEEelZkD40XKY2376w== dependencies: "@types/chroma-js" "^2.0.0" "@types/lodash" "^4.14.160" @@ -116,6 +116,71 @@ uuid "^8.3.0" vfile "^4.2.0" +"@emotion/cache@^11.7.1": + version "11.7.1" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.7.1.tgz#08d080e396a42e0037848214e8aa7bf879065539" + integrity sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A== + dependencies: + "@emotion/memoize" "^0.7.4" + "@emotion/sheet" "^1.1.0" + "@emotion/utils" "^1.0.0" + "@emotion/weak-memoize" "^0.2.5" + stylis "4.0.13" + +"@emotion/hash@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" + integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== + +"@emotion/memoize@^0.7.4": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50" + integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ== + +"@emotion/react@^11.7.1": + version "11.7.1" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.7.1.tgz#3f800ce9b20317c13e77b8489ac4a0b922b2fe07" + integrity sha512-DV2Xe3yhkF1yT4uAUoJcYL1AmrnO5SVsdfvu+fBuS7IbByDeTVx9+wFmvx9Idzv7/78+9Mgx2Hcmr7Fex3tIyw== + dependencies: + "@babel/runtime" "^7.13.10" + "@emotion/cache" "^11.7.1" + "@emotion/serialize" "^1.0.2" + "@emotion/sheet" "^1.1.0" + "@emotion/utils" "^1.0.0" + "@emotion/weak-memoize" "^0.2.5" + hoist-non-react-statics "^3.3.1" + +"@emotion/serialize@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.2.tgz#77cb21a0571c9f68eb66087754a65fa97bfcd965" + integrity sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A== + dependencies: + "@emotion/hash" "^0.8.0" + "@emotion/memoize" "^0.7.4" + "@emotion/unitless" "^0.7.5" + "@emotion/utils" "^1.0.0" + csstype "^3.0.2" + +"@emotion/sheet@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.1.0.tgz#56d99c41f0a1cda2726a05aa6a20afd4c63e58d2" + integrity sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g== + +"@emotion/unitless@^0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" + integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== + +"@emotion/utils@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.0.0.tgz#abe06a83160b10570816c913990245813a2fd6af" + integrity sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA== + +"@emotion/weak-memoize@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" + integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== + "@eslint/eslintrc@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" @@ -2336,7 +2401,7 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -4494,6 +4559,11 @@ stylis@3.5.4: resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe" integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q== +stylis@4.0.13: + version "4.0.13" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91" + integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag== + stylus@^0.54.8: version "0.54.8" resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.8.tgz#3da3e65966bc567a7b044bfe0eece653e099d147"