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

[Docs] Add ThemeLanguages and new Breakpoints page #5227

Merged
merged 21 commits into from
Oct 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
"test-docker": "node ./scripts/test-docker.js",
"sync-docs": "node ./scripts/docs-sync.js",
"build-docs": "cross-env BABEL_MODULES=false cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=4096 webpack --config=src-docs/webpack.config.js",
"build": "yarn extract-i18n-strings && node ./scripts/compile-clean.js && node ./scripts/compile-eui.js && node ./scripts/compile-scss.js $npm_package_name",
"build": "yarn extract-i18n-strings && node ./scripts/compile-clean.js && node ./scripts/compile-eui.js && yarn compile-scss",
"build-pack": "yarn build && npm pack",
"compile-icons": "node ./scripts/compile-icons.js && prettier --write --loglevel=warn \"./src/components/icon/assets/**/*.tsx\"",
"compile-scss": "node ./scripts/compile-scss.js $npm_package_name",
"extract-i18n-strings": "node ./scripts/babel/fetch-i18n-strings",
"lint": "yarn tsc --noEmit && yarn lint-es && yarn lint-sass",
"lint-fix": "yarn lint-es-fix",
Expand Down
34 changes: 23 additions & 11 deletions scripts/compile-scss.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ const postcssConfigurationWithMinification = {
],
};

async function compileScssFiles(
async function compileScssFiles({
sourcePattern,
destinationDirectory,
docsVariablesDirectory,
packageName
) {
}) {
try {
await mkdir(destinationDirectory);
} catch (err) {
Expand All @@ -44,13 +45,14 @@ async function compileScssFiles(

try {
const { name } = path.parse(inputFilename);
const outputFilenames = await compileScssFile(
const outputFilenames = await compileScssFile({
inputFilename,
path.join(destinationDirectory, `eui_${name}.css`),
path.join(destinationDirectory, `eui_${name}.json`),
path.join(destinationDirectory, `eui_${name}.json.d.ts`),
outputCssFilename: path.join(destinationDirectory, `eui_${name}.css`),
outputVarsFilename: path.join(destinationDirectory, `eui_${name}.json`),
outputVarTypesFilename: path.join(destinationDirectory, `eui_${name}.json.d.ts`),
outputDocsVarsFilename: path.join(docsVariablesDirectory, `eui_${name}.json`),
packageName
);
});

console.log(
chalk`{green ✔} Finished compiling {gray ${inputFilename}} to ${outputFilenames
Expand All @@ -68,13 +70,14 @@ async function compileScssFiles(
);
}

async function compileScssFile(
async function compileScssFile({
inputFilename,
outputCssFilename,
outputVarsFilename,
outputVarTypesFilename,
outputDocsVarsFilename,
packageName
) {
}) {
const outputCssMinifiedFilename = outputCssFilename.replace(
/\.css$/,
'.min.css'
Expand Down Expand Up @@ -111,18 +114,22 @@ async function compileScssFile(
to: outputCssMinifiedFilename,
});

const jsonVars = JSON.stringify(extractedVars, undefined, 2)

await Promise.all([
writeFile(outputCssFilename, postprocessedCss),
writeFile(outputCssMinifiedFilename, postprocessedMinifiedCss),
writeFile(outputVarsFilename, JSON.stringify(extractedVars, undefined, 2)),
writeFile(outputVarsFilename, jsonVars),
writeFile(outputVarTypesFilename, extractedVarTypes),
writeFile(outputDocsVarsFilename, jsonVars),
]);

return [
outputCssFilename,
outputCssMinifiedFilename,
outputVarsFilename,
outputVarTypesFilename,
outputDocsVarsFilename
];
}

Expand All @@ -134,5 +141,10 @@ if (require.main === module) {
process.exit(1);
}

compileScssFiles(path.join('src', 'theme_*.scss'), 'dist', euiPackageName);
compileScssFiles({
sourcePattern: path.join('src', 'theme_*.scss'),
destinationDirectory: 'dist',
docsVariablesDirectory: 'src-docs/src/views/theme/_json',
packageName: euiPackageName
});
}
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"
Comment on lines +146 to +147
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh thanks for fixing this! The axe-devtools complaint about our sticky top bar always bugged me :) @1Copenut, do you have any extra suggestions for this region/label, or does this look good to you?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this role="region" addition. It frames that control bar nicely. What do you think about spelling out the name like "EUI Documentation theme and apps" ? Users who benefit the most from aria labels may not think of this in terms of a bar, but more of what it allows them to do or learn about EUI.

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';
70 changes: 70 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,70 @@
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 (
<EuiTourStep
cchaos marked this conversation as resolved.
Show resolved Hide resolved
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: 'CSS-in-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
Loading