Skip to content

Commit

Permalink
Added a ThemeSelector for optionally showing/changing content based o…
Browse files Browse the repository at this point in the history
…n JS or Sass theming language
  • Loading branch information
cchaos committed Sep 29, 2021
1 parent dea0bd4 commit 963e589
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 4 deletions.
36 changes: 35 additions & 1 deletion src-docs/src/components/guide_page/guide_page.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import {
EuiPageHeader,
EuiPageContent,
EuiPageContentBody,
EuiSpacer,
} from '../../../../src/components';

import { LanguageSelector } from '../with_theme';

const GuidePageComponent = ({
children,
title,
Expand All @@ -18,6 +21,11 @@ const GuidePageComponent = ({
location,
match,
history,
description,
rightSideItems: _rightSideItems,
tabs: _tabs,
notice,
showThemeLanguageToggle,
}) => {
const betaBadge = isBeta ? (
<EuiBetaBadge
Expand Down Expand Up @@ -78,16 +86,37 @@ const GuidePageComponent = ({
});
};

const renderNotice = () => {
if (notice) {
return (
<>
<EuiPageContentBody role="region" aria-label="Notice" restrictWidth>
{notice}
</EuiPageContentBody>
<EuiSpacer size="l" />
</>
);
}
};

const rightSideItems = _rightSideItems || [];
if (showThemeLanguageToggle) {
rightSideItems.push(<LanguageSelector />);
}

return (
<>
{renderNotice()}
<EuiPageHeader
restrictWidth
pageTitle={
<>
{title} {betaBadge}
</>
}
tabs={renderTabs()}
tabs={renderTabs() || _tabs}
description={description}
rightSideItems={rightSideItems}
>
{intro}
</EuiPageHeader>
Expand Down Expand Up @@ -127,6 +156,11 @@ GuidePageComponent.propTypes = {
location: PropTypes.object,
match: PropTypes.object,
history: PropTypes.object,
description: PropTypes.node,
notice: PropTypes.node,
tabs: PropTypes.arrayOf(PropTypes.object),
rightSideItems: PropTypes.arrayOf(PropTypes.node),
showThemeLanguageToggle: PropTypes.bool,
};

export const GuidePage = withRouter(GuidePageComponent);
2 changes: 2 additions & 0 deletions src-docs/src/components/guide_page/guide_page_header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ export const GuidePageHeader: React.FunctionComponent<GuidePageHeaderProps> = ({

return (
<EuiHeader
role="region"
aria-label="EUI Docs app bar"
position="fixed"
theme="dark"
sections={[
Expand Down
2 changes: 1 addition & 1 deletion src-docs/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ export { GuideSectionContainer as GuideSection } from './guide_section/guide_sec

export { GuideSectionTypes } from './guide_section/guide_section_types';

export { ThemeProvider, ThemeContext } from './with_theme';
export { ThemeProvider, ThemeContext, LanguageSelector } from './with_theme';
1 change: 1 addition & 0 deletions src-docs/src/components/with_theme/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { ThemeProvider, ThemeContext } from './theme_context';
export { LanguageSelector } from './language_selector';
71 changes: 71 additions & 0 deletions src-docs/src/components/with_theme/language_selector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { useContext, useState } from 'react';

import {
EuiButtonGroup,
EuiIcon,
EuiLink,
EuiText,
EuiTourStep,
} from '../../../../src/components';

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

const NOTIF_STORAGE_KEY = 'js_vs_sass_notification';

export const LanguageSelector = ({
onChange,
}: {
onChange?: (id: string) => void;
}) => {
const themeContext = useContext(ThemeContext);
const toggleIdSelected = themeContext.themeLanguage;
const onLanguageChange = (optionId: string) => {
themeContext.changeThemeLanguage(optionId as THEME_LANGUAGES['id']);
onChange?.(optionId);
setTourIsOpen(false);
localStorage.setItem(NOTIF_STORAGE_KEY, 'dismissed');
};

const [isTourOpen, setTourIsOpen] = useState(
localStorage.getItem(NOTIF_STORAGE_KEY) !== 'dismissed'
);

const onTourDismiss = () => {
setTourIsOpen(false);
localStorage.setItem(NOTIF_STORAGE_KEY, 'dismissed');
};

return (
// @ts-ignore Fixes for tour in another PR
<EuiTourStep
content={
<EuiText style={{ maxWidth: 320 }}>
<p>Select your preferred styling language with this toggle button.</p>
</EuiText>
}
isStepOpen={isTourOpen}
onFinish={onTourDismiss}
step={1}
stepsTotal={1}
title={
<>
<EuiIcon type="bell" size="s" /> &nbsp; Theming update
</>
}
footerAction={<EuiLink onClick={onTourDismiss}>Got it!</EuiLink>}
>
<EuiButtonGroup
buttonSize="m"
color="accent"
legend="Language selector"
options={theme_languages}
idSelected={toggleIdSelected}
onChange={(id) => onLanguageChange(id)}
/>
</EuiTourStep>
);
};
45 changes: 43 additions & 2 deletions src-docs/src/components/with_theme/theme_context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,43 @@ import { EuiThemeProvider } from '../../../../src/services';
import { EuiThemeAmsterdam } from '../../../../src/themes/eui-amsterdam/theme';
import { EuiThemeDefault } from '../../../../src/themes/eui/theme';

export const STYLE_STORAGE_KEY = 'js_vs_sass_preference';

export type THEME_LANGUAGES = {
id: 'language--js' | 'language--sass';
label: string;
title: string;
};

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

const THEME_NAMES = EUI_THEMES.map(({ value }) => value);
const THEME_LANGS = theme_languages.map(({ id }) => id);

const defaultState = {
theme: THEME_NAMES[2],
themeLanguage: THEME_LANGS[0],
// eslint-disable-next-line @typescript-eslint/no-unused-vars
changeThemeLanguage: (language: THEME_LANGUAGES['id']) => {},
theme: THEME_NAMES[0],
changeTheme: (themeValue: EUI_THEME['value']) => {
applyTheme(themeValue);
},
};

interface State {
theme: EUI_THEME['value'];
themeLanguage: THEME_LANGUAGES['id'];
}

export const ThemeContext = React.createContext(defaultState);
Expand All @@ -25,12 +51,19 @@ export class ThemeProvider extends React.Component<object, State> {
constructor(props: object) {
super(props);

let themeLanguage = localStorage.getItem(
STYLE_STORAGE_KEY
) as THEME_LANGUAGES['id'];
if (!themeLanguage || !THEME_LANGS.includes(themeLanguage))
themeLanguage = defaultState.themeLanguage;

let theme = localStorage.getItem('theme');
if (!theme || !THEME_NAMES.includes(theme)) theme = defaultState.theme;
applyTheme(theme);

this.state = {
theme,
themeLanguage,
};
}

Expand All @@ -41,14 +74,22 @@ export class ThemeProvider extends React.Component<object, State> {
});
};

changeThemeLanguage = (language: THEME_LANGUAGES['id']) => {
this.setState({ themeLanguage: language }, () => {
localStorage.setItem(STYLE_STORAGE_KEY, language);
});
};

render() {
const { children } = this.props;
const { theme } = this.state;
const { theme, themeLanguage } = this.state;
return (
<ThemeContext.Provider
value={{
theme,
themeLanguage,
changeTheme: this.changeTheme,
changeThemeLanguage: this.changeThemeLanguage,
}}
>
<EuiThemeProvider
Expand Down

0 comments on commit 963e589

Please sign in to comment.