Skip to content

Commit

Permalink
[src-docs continued] refactor locale out from redux and store it in…
Browse files Browse the repository at this point in the history
… ThemeContext

- might as well since we're already handling localStorage things there, saves us from waterfalling props unnecessarily
  • Loading branch information
cee-chen committed Sep 25, 2024
1 parent 87f1fa7 commit 8dc0bc5
Show file tree
Hide file tree
Showing 13 changed files with 70 additions and 124 deletions.
3 changes: 0 additions & 3 deletions packages/eui/src-docs/src/actions/action_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,4 @@ export default {
// Example nav actions
REGISTER_SECTION: 'REGISTER_SECTION',
UNREGISTER_SECTION: 'UNREGISTER_SECTION',

// Locale actions
TOGGLE_LOCALE: 'TOGGLE_LOCALE',
};
1 change: 0 additions & 1 deletion packages/eui/src-docs/src/actions/index.js

This file was deleted.

8 changes: 0 additions & 8 deletions packages/eui/src-docs/src/actions/locale_actions.js

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,5 @@ export class GuidePageChrome extends Component {

GuidePageChrome.propTypes = {
currentRoute: PropTypes.object.isRequired,
onToggleLocale: PropTypes.func.isRequired,
selectedLocale: PropTypes.string.isRequired,
navigation: PropTypes.array.isRequired,
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,7 @@ import { VersionSwitcher } from './version_switcher';

const GITHUB_URL = 'https://github.com/elastic/eui';

export type GuidePageHeaderProps = {
onToggleLocale: () => {};
selectedLocale: string;
};

export const GuidePageHeader: React.FunctionComponent<GuidePageHeaderProps> = ({
onToggleLocale,
selectedLocale,
}) => {
export const GuidePageHeader = () => {
const isMobileSize = useIsWithinBreakpoints(['xs', 's']);

const logo = useMemo(() => {
Expand Down Expand Up @@ -112,18 +104,9 @@ export const GuidePageHeader: React.FunctionComponent<GuidePageHeaderProps> = ({
}, [codesandbox, github]);

const rightSideItems = isMobileSize
? [
<GuideThemeSelector
onToggleLocale={onToggleLocale}
selectedLocale={selectedLocale}
/>,
mobileMenu,
]
? [<GuideThemeSelector />, mobileMenu]
: [
<GuideThemeSelector
onToggleLocale={onToggleLocale}
selectedLocale={selectedLocale}
/>,
<GuideThemeSelector />,
github,
<GuideFigmaLink key="figma" />,
codesandbox,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,7 @@ import {
EuiSwitchEvent,
} from '../../../../src/components';

type GuideThemeSelectorProps = {
onToggleLocale: Function;
selectedLocale: string;
};

export const GuideThemeSelector: React.FunctionComponent<
GuideThemeSelectorProps
> = ({ onToggleLocale, selectedLocale }) => {
export const GuideThemeSelector = () => {
const context = useContext(ThemeContext);
const euiThemeContext = useEuiTheme();
const colorMode = context.colorMode ?? euiThemeContext.colorMode;
Expand Down Expand Up @@ -65,9 +58,9 @@ export const GuideThemeSelector: React.FunctionComponent<
},
location.host.includes('803') && {
label: 'i18n testing',
checked: selectedLocale === 'en-xa',
checked: context.i18n === 'en-xa',
onChange: (e: EuiSwitchEvent) =>
onToggleLocale(e.target.checked ? 'en-xa' : 'en'),
context.setContext({ i18n: e.target.checked ? 'en-xa' : 'en' }),
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,30 @@ import React, { useContext } from 'react';

import { EuiButtonGroup } from '../../../../src/components';

import {
ThemeContext,
theme_languages,
THEME_LANGUAGES,
} from './theme_context';
import { ThemeContext } from './theme_context';

export const THEME_LANGUAGES = ['language--js', 'language--sass'] as const;

export type ThemeLanguages = {
id: (typeof THEME_LANGUAGES)[number];
label: string;
title: string;
};

export const themeLanguagesOptions: ThemeLanguages[] = [
{
id: 'language--js',
label: 'CSS-in-JS',
title: 'Language selector: CSS-in-JS',
},
{
id: 'language--sass',
label: 'Sass',
title: 'Language selector: Sass',
},
];

const ids = themeLanguagesOptions.map(({ id }) => id);

export const LanguageSelector = ({
onChange,
Expand All @@ -17,7 +36,7 @@ export const LanguageSelector = ({
const toggleIdSelected = themeContext.themeLanguage;
const onLanguageChange = (optionId: string) => {
themeContext.setContext({
themeLanguage: optionId as THEME_LANGUAGES['id'],
themeLanguage: optionId as ThemeLanguages['id'],
});
onChange?.(optionId);
};
Expand All @@ -27,8 +46,10 @@ export const LanguageSelector = ({
buttonSize="m"
color="accent"
legend="Language selector"
options={theme_languages}
idSelected={toggleIdSelected}
options={themeLanguagesOptions}
idSelected={
ids.includes(toggleIdSelected) ? toggleIdSelected : 'language--js'
}
onChange={(id) => onLanguageChange(id)}
/>
);
Expand Down
53 changes: 20 additions & 33 deletions packages/eui/src-docs/src/components/with_theme/theme_context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,44 +26,28 @@ EUI_THEMES.forEach((theme) => {
});
const THEME_NAMES = EUI_THEMES.map(({ value }) => value);

const URL_PARAM_KEY = 'themeLanguage';
export type THEME_LANGUAGES = {
id: 'language--js' | 'language--sass';
label: string;
title: string;
};
export const theme_languages: THEME_LANGUAGES[] = [
{
id: 'language--js',
label: 'CSS-in-JS',
title: 'Language selector: CSS-in-JS',
},
{
id: 'language--sass',
label: 'Sass',
title: 'Language selector: Sass',
},
];
const THEME_LANGS = theme_languages.map(({ id }) => id);
import { type ThemeLanguages } from './language_selector';

export type ThemeContextType = {
theme?: EUI_THEME['value'];
colorMode?: EuiThemeColorModeStandard;
highContrastMode?: boolean;
themeLanguage: THEME_LANGUAGES['id'];
i18n?: 'en' | 'en-xa';
themeLanguage: ThemeLanguages['id']; // TODO: Can likely be deleted once Sass is fully deprecated
setContext: (context: Partial<State>) => void;
};
export const ThemeContext = React.createContext<ThemeContextType>({
theme: undefined,
colorMode: undefined,
highContrastMode: undefined,
themeLanguage: THEME_LANGS[0],
themeLanguage: 'language--js',
i18n: 'en',
setContext: () => {},
});

type State = Pick<
ThemeContextType,
'theme' | 'colorMode' | 'highContrastMode' | 'themeLanguage'
'theme' | 'colorMode' | 'highContrastMode' | 'themeLanguage' | 'i18n'
>;

export class ThemeProvider extends React.Component<PropsWithChildren, State> {
Expand All @@ -81,12 +65,15 @@ export class ThemeProvider extends React.Component<PropsWithChildren, State> {
? localStorage.getItem('highContrastMode') === 'true'
: undefined;

const i18n = (localStorage.getItem('i18n') as any) || 'en';

const themeLanguage = this.getThemeLanguage();

this.state = {
theme,
colorMode,
highContrastMode,
i18n,
themeLanguage,
};
}
Expand All @@ -100,6 +87,7 @@ export class ThemeProvider extends React.Component<PropsWithChildren, State> {
'theme',
'colorMode',
'highContrastMode',
'i18n',
'themeLanguage',
] as const;

Expand All @@ -123,41 +111,40 @@ export class ThemeProvider extends React.Component<PropsWithChildren, State> {
// to specific docs, e.g. ?themeLanguage=js, ?themeLanguage=sass
// Note that because of our hash router, this logic only works on page load/full reload
const urlParams = window?.location?.href?.split('?')[1]; // Note: we can't use location.search because of our hash router
const fromUrlParam = new URLSearchParams(urlParams).get(URL_PARAM_KEY);
const fromUrlParam = new URLSearchParams(urlParams).get('themeLanguage');
// Otherwise, obtain it from localStorage
const fromLocalStorage = localStorage.getItem(URL_PARAM_KEY);
const fromLocalStorage = localStorage.getItem('themeLanguage');

let themeLanguage = (
const themeLanguage = (
fromUrlParam ? `language--${fromUrlParam}` : fromLocalStorage
) as THEME_LANGUAGES['id'];
) as ThemeLanguages['id'];

// If not set by either param or storage, or an invalid value, use the default
if (!themeLanguage || !THEME_LANGS.includes(themeLanguage))
themeLanguage = THEME_LANGS[0];

return themeLanguage;
return themeLanguage || 'language--js';
};

setThemeLanguageParam = (languageKey: THEME_LANGUAGES['id']) => {
setThemeLanguageParam = (languageKey: ThemeLanguages['id']) => {
const languageValue = languageKey.replace('language--', ''); // Make our params more succinct
const hash = window?.location?.hash?.split('?'); // Note: we can't use location.search because of our hash router

const queryParams = hash[1];
const params = new URLSearchParams(queryParams);
params.set(URL_PARAM_KEY, languageValue);
params.set('themeLanguage', languageValue);

window.location.hash = `${hash[0]}?${params.toString()}`;
};

render() {
const { children } = this.props;
const { theme, colorMode, highContrastMode, themeLanguage } = this.state;
const { theme, colorMode, highContrastMode, i18n, themeLanguage } =
this.state;
return (
<ThemeContext.Provider
value={{
theme,
colorMode,
highContrastMode,
i18n,
themeLanguage,
setContext: this.setContext,
}}
Expand Down
1 change: 0 additions & 1 deletion packages/eui/src-docs/src/services/theme/theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@ export function applyTheme(newTheme, colorMode = 'LIGHT') {
Object.keys(themes).forEach((theme) =>
Object.values(themes[theme]).forEach((cssFile) => cssFile.unuse())
);
console.log(newTheme, themes[newTheme]?.[colorMode]);
themes[newTheme]?.[colorMode]?.use();
}
7 changes: 1 addition & 6 deletions packages/eui/src-docs/src/store/configure_store.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,13 @@ import thunk from 'redux-thunk';

import Routes from '../routes';

import localeReducer from './reducers/locale_reducer';
import themeReducer from './reducers/theme_reducer';

/**
* @param {Object} initialState An object defining the application's initial
* state.
*/
export default function configureStore(initialState) {
function rootReducer(state = {}, action) {
function rootReducer() {
return {
theme: themeReducer(state.theme, action),
locale: localeReducer(state.locale, action),
routes: Routes,
};
}
Expand Down
8 changes: 0 additions & 8 deletions packages/eui/src-docs/src/store/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
export function getTheme(state) {
return state.theme.theme;
}

export function getRoutes(state) {
return state.routes;
}

export function getLocale(state) {
return state.locale.locale;
}
26 changes: 11 additions & 15 deletions packages/eui/src-docs/src/views/app_context.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import React, { useContext } from 'react';
import { Helmet } from 'react-helmet';
import { useSelector } from 'react-redux';
import createCache from '@emotion/cache';
import { ThemeContext } from '../components';
import { translateUsingPseudoLocale } from '../services';
import { getLocale } from '../store';

import { EuiContext, EuiProvider } from '../../../src/components';
import {
Expand Down Expand Up @@ -33,18 +31,7 @@ const utilityCache = createCache({
});

export const AppContext = ({ children }) => {
const { theme, colorMode, highContrastMode } = useContext(ThemeContext);
const locale = useSelector((state) => getLocale(state));

const mappingFuncs = {
'en-xa': translateUsingPseudoLocale,
};

const i18n = {
mappingFunc: mappingFuncs[locale],
formatNumber: (value) => new Intl.NumberFormat(locale).format(value),
locale,
};
const { theme, colorMode, highContrastMode, i18n } = useContext(ThemeContext);

const isLocalDev = window.location.host.includes('803');
setEuiDevProviderWarning(isLocalDev ? 'error' : 'warn'); // Note: this can't be in a useEffect, otherwise it fires too late for style memoization warnings to error on page reload
Expand Down Expand Up @@ -85,7 +72,16 @@ export const AppContext = ({ children }) => {
rel="stylesheet"
/>
</Helmet>
<EuiContext i18n={i18n}>{children}</EuiContext>
<EuiContext
i18n={{
locale: i18n,
mappingFunc:
i18n === 'en-xa' ? translateUsingPseudoLocale : undefined,
formatNumber: (value) => new Intl.NumberFormat(i18n).format(value),
}}
>
{children}
</EuiContext>
</EuiProvider>
);
};
Loading

0 comments on commit 8dc0bc5

Please sign in to comment.