Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Theme] Base theme setup #8030

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
31f6316
fix: ensure getComputed resolves Computed objects correctly
mgadewoll Sep 18, 2024
3d80291
feat: setup new theme package
mgadewoll Sep 18, 2024
5f0ae6d
feat: add experimental flag
mgadewoll Sep 19, 2024
c2e5538
feat: add theme switcher to Storybook
mgadewoll Sep 19, 2024
51b59f1
feat: udpate theme switcher to eui docs
mgadewoll Sep 19, 2024
0c61e90
build: use workspace reference for EUI dependency
mgadewoll Sep 19, 2024
13281dc
feat: add theme switcher to eui+ docs
mgadewoll Sep 19, 2024
9cdacbe
build: add eui-common internal module package
mgadewoll Sep 22, 2024
5f618e0
build: add eui-theme-base internal module package
mgadewoll Sep 22, 2024
04eab8c
refactor: use new module packages in eui package
mgadewoll Sep 22, 2024
03b49f3
refactor: use eui-theme-base package in eui-theme-berlin
mgadewoll Sep 22, 2024
8c9ca71
build: prevent generating i18ntokens.json when running build locally
mgadewoll Sep 22, 2024
89e722c
build: add esm and cjs export for common module
mgadewoll Sep 23, 2024
d481fb1
build: add esm and cjs export for theme-base module
mgadewoll Sep 23, 2024
08bef3a
build: add script for building workspace dependencies
mgadewoll Sep 23, 2024
b3e6f41
refactor: update sass imports
mgadewoll Sep 23, 2024
7642450
build: update dependencies
mgadewoll Sep 23, 2024
b07e110
build: update new_docs and release scripts
mgadewoll Sep 23, 2024
9bc5ca0
refactor: rename script
mgadewoll Sep 26, 2024
f0d424b
build: add build:workspaces script on pre-push hook
mgadewoll Sep 26, 2024
6e86fc0
refactor: separate out scss files and resolve circular scss dependency
mgadewoll Sep 26, 2024
43c9a3b
build: ensure common scss is part of package
mgadewoll Sep 30, 2024
75e2ad6
chore: rebase cleanup
mgadewoll Sep 30, 2024
c4410e4
refactor: rename theme
mgadewoll Oct 2, 2024
f263cd7
add eui-theme-common package
mgadewoll Oct 8, 2024
854540d
-remove eui-common package
mgadewoll Oct 8, 2024
3a16d83
chore: add min. README
mgadewoll Oct 8, 2024
ce4e8e1
build: add pre-push scripts
mgadewoll Oct 8, 2024
2532104
build: update workspaces script to ensure theme-common builds first
mgadewoll Oct 8, 2024
17179a7
chore: ignore eslint cache file
mgadewoll Oct 9, 2024
16bb57e
build: add missing dependencies
mgadewoll Oct 9, 2024
033ed1c
refactor: udpate sass import order
mgadewoll Oct 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .buildkite/scripts/pipelines/pipeline_deploy_new_docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ analytics_vault="secret/ci/elastic-eui/analytics"
export DOCS_BASE_URL="/${bucket_directory}"
export DOCS_GOOGLE_TAG_MANAGER_ID="$(retry 5 vault read -field=google_tag_manager_id "${analytics_vault}")"

yarn workspaces foreach -Rpt --from @elastic/eui-website run build
yarn workspace @elastic/eui-website run build:workspaces

echo "+++ Configuring environment for website deployment"

Expand Down
18 changes: 9 additions & 9 deletions .buildkite/scripts/pipelines/pipeline_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,53 +29,53 @@ COMMAND=""
case $TEST_TYPE in
lint)
echo "[TASK]: Running linters"
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui lint"
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui lint"
;;

unit:ts)
echo "[TASK]: Running .ts and .js unit tests"
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --testMatch=non-react"
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --testMatch=non-react"
;;

unit:tsx:16)
echo "[TASK]: Running Jest .tsx tests against React 16"
DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=jest_token_react16 "${buildkite_analytics_vault}")")
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --react-version=16 --testMatch=react"
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --react-version=16 --testMatch=react"
;;

unit:tsx:17)
echo "[TASK]: Running Jest .tsx tests against React 17"
DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=jest_token_react17 "${buildkite_analytics_vault}")")
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --react-version=17 --testMatch=react"
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --react-version=17 --testMatch=react"
;;

unit:tsx)
echo "[TASK]: Running Jest .tsx tests against React 18"
DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=jest_token_react18 "${buildkite_analytics_vault}")")
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --testMatch=react"
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --testMatch=react"
;;

cypress:16)
echo "[TASK]: Running Cypress tests against React 16"
DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=cypress_token_react16 "${buildkite_analytics_vault}")")
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048 --react-version=16"
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048 --react-version=16"
;;

cypress:17)
echo "[TASK]: Running Cypress tests against React 17"
DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=cypress_token_react17 "${buildkite_analytics_vault}")")
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048 --react-version=17"
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048 --react-version=17"
;;

cypress:18)
echo "[TASK]: Running Cypress tests against React 18"
DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=cypress_token_react18 "${buildkite_analytics_vault}")")
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048"
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048"
;;

cypress:a11y)
echo "[TASK]: Running Cypress accessibility tests against React 18"
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui run test-cypress-a11y --node-options=--max_old_space_size=2048"
COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui run test-cypress-a11y --node-options=--max_old_space_size=2048"
;;

*)
Expand Down
1 change: 1 addition & 0 deletions .buildkite/scripts/release/step_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ echo "+++ :yarn: Installing dependencies"
yarn

echo "+++ :yarn: Building @elastic/eui"
yarn build:workspaces
yarn build

echo "+++ :yarn: Built @elastic/eui"
3 changes: 2 additions & 1 deletion packages/docusaurus-theme/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@
"@docusaurus/theme-common": "^3.5.2",
"@docusaurus/utils-validation": "^3.5.2",
"@elastic/datemath": "^5.0.3",
"@elastic/eui": "94.5.0",
"@elastic/eui": "workspace:^",
"@elastic/eui-docgen": "workspace:^",
"@elastic/eui-theme-borealis": "workspace:^",
"@emotion/css": "^11.11.2",
"@emotion/react": "^11.11.4",
"@types/react-window": "^1.8.8",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ export const NavbarItem = (props: Props) => {
} = props;

const isBrowser = useIsBrowser();
const { theme } = useContext(AppThemeContext);
const { colorMode } = useContext(AppThemeContext);

const isDarkMode = theme === 'dark';
const isDarkMode = colorMode === 'dark';

const styles = useEuiMemoizedStyles(getStyles);
const cssStyles = [
Expand Down
58 changes: 47 additions & 11 deletions packages/docusaurus-theme/src/components/theme_context/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,39 @@ import {
useState,
} from 'react';
import useIsBrowser from '@docusaurus/useIsBrowser';
import { EUI_THEMES, EuiProvider, EuiThemeColorMode } from '@elastic/eui';
import {
EuiProvider,
EuiThemeAmsterdam,
EuiThemeColorMode,
} from '@elastic/eui';
import { EuiThemeBorealis } from '@elastic/eui-theme-borealis';

import { EuiThemeOverrides } from './theme_overrides';

const EUI_THEME_NAMES = EUI_THEMES.map(
({ value }) => value
) as EuiThemeColorMode[];
const EXPERIMENTAL_THEMES = [
{
text: 'Borealis',
value: EuiThemeBorealis.key,
provider: EuiThemeBorealis,
},
];

export const AVAILABLE_THEMES = [
{
text: 'Amsterdam',
value: EuiThemeAmsterdam.key,
provider: EuiThemeAmsterdam,
},
...EXPERIMENTAL_THEMES,
];

const EUI_COLOR_MODES = ['light', 'dark'] as EuiThemeColorMode[];

const defaultState = {
theme: EUI_THEME_NAMES[0] as EuiThemeColorMode,
changeTheme: (themeValue: EuiThemeColorMode) => {},
colorMode: EUI_COLOR_MODES[0] as EuiThemeColorMode,
changeColorMode: (colorMode: EuiThemeColorMode) => {},
theme: AVAILABLE_THEMES[0]!,
changeTheme: (themeValue: string) => {},
};

export const AppThemeContext = createContext(defaultState);
Expand All @@ -24,25 +46,39 @@ export const AppThemeProvider: FunctionComponent<PropsWithChildren> = ({
children,
}) => {
const isBrowser = useIsBrowser();
const [theme, setTheme] = useState<EuiThemeColorMode>(() => {
const [colorMode, setColorMode] = useState<EuiThemeColorMode>(() => {
if (isBrowser) {
return localStorage.getItem('theme') as EuiThemeColorMode ?? defaultState.theme;
return (
(localStorage.getItem('theme') as EuiThemeColorMode) ??
defaultState.colorMode
);
}

return defaultState.theme;
return defaultState.colorMode;
});

const [theme, setTheme] = useState(defaultState.theme);

const handleChangeTheme = (themeValue: string) => {
const themeObj = AVAILABLE_THEMES.find((t) => t.value === themeValue);

setTheme((currentTheme) => themeObj ?? currentTheme);
};

return (
<AppThemeContext.Provider
value={{
colorMode,
theme,
changeTheme: setTheme,
changeColorMode: setColorMode,
changeTheme: handleChangeTheme,
}}
>
<EuiProvider
globalStyles={false}
modify={EuiThemeOverrides}
colorMode={theme}
colorMode={colorMode}
theme={theme.provider}
>
{children}
</EuiProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { useContext, useEffect, useState } from 'react';
import { css } from '@emotion/react';
import {
EuiAvatar,
EuiButtonEmpty,
euiFocusRing,
EuiListGroup,
EuiListGroupItem,
EuiPopover,
useEuiMemoizedStyles,
useEuiTheme,
UseEuiTheme,
} from '@elastic/eui';

import { AppThemeContext, AVAILABLE_THEMES } from '../theme_context';

const getStyles = (euiThemeContext: UseEuiTheme) => {
const { euiTheme } = euiThemeContext;

return {
button: css`
padding: 0;
`,
listItem: css`
.euiListGroupItem__button:focus-visible {
// overriding the global "outset" style to ensure the focus style is not cut off
${euiFocusRing(euiThemeContext, 'inset', {
color: euiTheme.colors.primary,
})};
}
`,
};
};

export const ThemeSwitcher = () => {
const { euiTheme } = useEuiTheme();
const [currentTheme, setCurrentTheme] = useState(
AVAILABLE_THEMES[0]?.value ?? ''
);
const [isPopoverOpen, setPopoverOpen] = useState(false);
const { theme, changeTheme } = useContext(AppThemeContext);

useEffect(() => {
changeTheme(currentTheme);
}, [currentTheme]);

const styles = useEuiMemoizedStyles(getStyles);

const button = (
<EuiButtonEmpty
size="s"
color="text"
css={styles.button}
onClick={() => setPopoverOpen((isOpen) => !isOpen)}
aria-label={`${theme.text} theme`}
>
<EuiAvatar name={theme.text} size="s" color={euiTheme.colors.primary} />
</EuiButtonEmpty>
);

return (
<EuiPopover
isOpen={isPopoverOpen}
closePopover={() => setPopoverOpen(false)}
button={button}
panelPaddingSize="xs"
repositionOnScroll
aria-label="EUI theme list"
>
<EuiListGroup>
{AVAILABLE_THEMES &&
AVAILABLE_THEMES.map((theme) => {
const isCurrentTheme = currentTheme === theme.value;

const handleOnClick = () => {
setCurrentTheme(theme.value);
};

return (
<EuiListGroupItem
key={theme.value}
css={styles.listItem}
label={theme.text}
size="xs"
isActive={isCurrentTheme}
color={isCurrentTheme ? 'primary' : 'text'}
onClick={handleOnClick}
/>
);
})}
</EuiListGroup>
</EuiPopover>
);
};
12 changes: 6 additions & 6 deletions packages/docusaurus-theme/src/theme/ColorModeToggle/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ function ColorModeToggle({
onChange,
...rest
}: WrappedProps): JSX.Element {
const { theme, changeTheme } = useContext(AppThemeContext);
const { colorMode, changeColorMode } = useContext(AppThemeContext);

useEffect(() => {
changeTheme(value);
changeColorMode(value);
}, []);

const handleOnChange = (themeName: EuiThemeColorMode) => {
changeTheme(themeName);
onChange?.(themeName);
const handleOnChange = (colorMode: EuiThemeColorMode) => {
changeColorMode(colorMode);
onChange?.(colorMode);
};

return (
<OriginalColorModeToggle
value={theme}
value={colorMode}
onChange={handleOnChange}
{...rest}
/>
Expand Down
4 changes: 2 additions & 2 deletions packages/docusaurus-theme/src/theme/Logo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ function LogoThemedImage({
alt: string;
imageClassName?: string;
}) {
const { theme } = useContext(AppThemeContext);
const isDarkMode = theme === 'dark';
const { colorMode } = useContext(AppThemeContext);
const isDarkMode = colorMode === 'dark';

const styles = useEuiMemoizedStyles(getStyles);

Expand Down
24 changes: 23 additions & 1 deletion packages/docusaurus-theme/src/theme/Navbar/Content/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ import SearchBar from '@theme-original/SearchBar';
import NavbarMobileSidebarToggle from '@theme-original/Navbar/MobileSidebar/Toggle';
import NavbarLogo from '@theme-original/Navbar/Logo';
import NavbarSearch from '@theme-original/Navbar/Search';
import { euiFocusRing, useEuiMemoizedStyles, UseEuiTheme } from '@elastic/eui';
import {
euiFocusRing,
euiTextTruncate,
useEuiMemoizedStyles,
UseEuiTheme,
isExperimentalThemeEnabled,
} from '@elastic/eui';
import {
euiFormControlText,
euiFormVariables,
Expand All @@ -24,6 +30,7 @@ import {
import euiVersions from '@site/static/versions.json';

import { VersionSwitcher } from '../../../components/version_switcher';
import { ThemeSwitcher } from '../../../components/theme_switcher';

const DOCS_PATH = '/docs';

Expand Down Expand Up @@ -67,6 +74,10 @@ const getStyles = (euiThemeContext: UseEuiTheme) => {
@media (min-width: 997px) {
gap: ${euiTheme.size.l};
}
.navbar__link {
${euiTextTruncate()}
}
`,
navbarItemsRight: css`
gap: ${euiTheme.size.s};
Expand Down Expand Up @@ -125,6 +136,11 @@ const getStyles = (euiThemeContext: UseEuiTheme) => {
display: none;
}
`,
themeSwitcher: css`
@media (max-width: 996px) {
display: none;
}
`,
};
};

Expand Down Expand Up @@ -218,6 +234,12 @@ export default function NavbarContent(): JSX.Element {
)}
<NavbarColorModeToggle className="colorModeToggle" />
<NavbarItems items={rightItems} />

{isBrowser && isExperimentalThemeEnabled() && (
<div css={styles.themeSwitcher}>
<ThemeSwitcher />
</div>
)}
</>
}
/>
Expand Down
Loading