Skip to content

Commit

Permalink
Merge pull request #77 from LuisValgoi/feat-theme-switch
Browse files Browse the repository at this point in the history
[Issue-58] Change Colors / Theme Programmatically
  • Loading branch information
LuisValgoi authored and MarcusNotheis committed Oct 21, 2020
1 parent bc2db14 commit 8339feb
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 11 deletions.
4 changes: 2 additions & 2 deletions packages/ui5-webcomponents-react-seed/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@
"test:coverage": "npm run test -- --watchAll=false --coverage",
"lint": "eslint --quiet .",
"lint:fix": "eslint . --fix",
"prettier": "./node_modules/.bin/prettier --config .prettierrc --check 'src/**/*.js'",
"prettier:fix": "./node_modules/.bin/prettier --config .prettierrc --write 'src/**/*.js'",
"prettier": "./node_modules/.bin/prettier --config .prettierrc --check \"src/**/*.js\"",
"prettier:fix": "./node_modules/.bin/prettier --config .prettierrc --write \"src/**/*.js\"",
"eject": "react-scripts eject",
"push:pre": "npm-run-all --parallel test:ci lint prettier",
"publish:clean": "rm -rf ./template/src ./template/server ./template/.vscode ./template/public && rm -f ./template/.editorconfig ./template/.env.development ./template/.env.production ./template/.eslintignore ./template/.eslintrc.js ./template/.prettierrc ./template/commitlint.config.js ./template/jest.config.json ./template/PULL_REQUEST_TEMPLATE.md ./template/README.md ./template/webpack.config.js",
Expand Down
6 changes: 0 additions & 6 deletions packages/ui5-webcomponents-react-seed/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@
"rtl": false
}
</script>
<style>
* {
--sapBackgroundColor: white;
--sapLinkColor: #0077ff;
}
</style>
</head>

<body>
Expand Down
1 change: 0 additions & 1 deletion packages/ui5-webcomponents-react-seed/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ code {

#root {
width: 100%;
background-color: 'var(--sapBackgroundColor)';
height: 100%;
display: flex;
flex-direction: column;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { spacing } from '@ui5/webcomponents-react-base';
import { Icon } from '@ui5/webcomponents-react/lib/Icon';
import { Button } from '@ui5/webcomponents-react/lib/Button';
import { ButtonDesign } from '@ui5/webcomponents-react/lib/ButtonDesign';
import { Dialog } from '@ui5/webcomponents-react/lib/Dialog';
import { FlexBox } from '@ui5/webcomponents-react/lib/FlexBox';
import { FlexBoxDirection } from '@ui5/webcomponents-react/lib/FlexBoxDirection';
import { FlexBoxAlignItems } from '@ui5/webcomponents-react/lib/FlexBoxAlignItems';
import { FlexBoxJustifyContent } from '@ui5/webcomponents-react/lib/FlexBoxJustifyContent';
import { Text } from '@ui5/webcomponents-react/lib/Text';

const KEYBOARD_KEYS = {
ESCAPE: 27,
};

const style = {
warning: {
width: '1.5rem',
height: '1.5rem',
color: '#feb60a',
},
error: {
width: '1.5rem',
height: '1.5rem',
color: '#ff5254',
},
information: {
width: '1.5rem',
height: '1.5rem',
color: 'black',
},
text: {
lineHeight: '20px',
},
};

const _getHeaderIcon = (type) => {
switch (type) {
case Type.Warning:
return _getHeaderWarningIcon();
case Type.Error:
return _getHeaderErrorIcon();
default:
return _getHeaderInfoIcon();
}
};

const _getHeaderWarningIcon = () => {
return <Icon name="message-warning" style={style.warning} />;
};

const _getHeaderErrorIcon = () => {
return <Icon name="message-error" style={style.error} />;
};

const _getHeaderInfoIcon = () => {
return <Icon name="message-information" style={style.information} />;
};

const _handleAvoidEscapeClosing = (avoidEscapeClose) => {
document.addEventListener(
'keydown',
(e) => {
if (e.keyCode === KEYBOARD_KEYS.ESCAPE && avoidEscapeClose) {
e.stopPropagation();
}
},
true,
);
};

const InformationDialog = ({ dialogRef, avoidEscapeClose, headerText, innerText, closeButtonText, children, onClose, type }) => {
const { t } = useTranslation();

useEffect(() => {
_handleAvoidEscapeClosing(avoidEscapeClose);
});

const _onClose = () => {
onClose && onClose();
if (dialogRef.current) {
dialogRef.current.close();
}
};

const _getFooter = () => {
return (
<FlexBox alignItems={FlexBoxAlignItems.Center} direction={FlexBoxDirection.RowReverse} style={spacing.sapUiTinyMargin}>
<Button design={ButtonDesign.Transparent} onClick={_onClose}>
{closeButtonText ? closeButtonText : t('app.generics.close')}
</Button>
</FlexBox>
);
};

const _getHeader = () => {
return (
<FlexBox alignItems={FlexBoxAlignItems.Center} justifyContent={FlexBoxJustifyContent.Center} style={spacing.sapUiContentPadding}>
{_getHeaderIcon(type)}
<Text tooltip={headerText} wrapping style={{ ...spacing.sapUiTinyMarginBegin, ...style.text }}>
{headerText}
</Text>
</FlexBox>
);
};

return (
<Dialog ref={dialogRef} slot="header" header={_getHeader()} footer={_getFooter()} onAfterClose={_onClose} data-testid="information-dialog">
<div style={{ ...spacing.sapUiContentPadding }}>
<FlexBox direction={FlexBoxDirection.Column}>
{innerText ? (
<Text tooltip={innerText} wrapping style={{ ...spacing.sapUiTinyMarginBegin, ...style.text }}>
{innerText}
</Text>
) : (
children
)}
</FlexBox>
</div>
</Dialog>
);
};

export default InformationDialog;

export const Type = {
Warning: 'WARNING',
Error: 'ERROR',
Info: 'INFO',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';

import '@testing-library/jest-dom/extend-expect';
import { render, screen } from '../../util/TestSetup';
import InformationDialog, { Type } from './InformationDialog';

describe('InformationDialog.js Test Suite', () => {
test('should render', () => {
const dialog = <InformationDialog avoidEscapeClose type={Type.Warning} headerText={'Header text'} closeButtonText={'Close'} innerText={'Inner text'} />;
render(dialog);
const infoDialog = screen.getByTestId('information-dialog');
expect(infoDialog).toBeInTheDocument();
});

test('should render child when not inner text is passed', () => {
const dialog = (
<InformationDialog avoidEscapeClose type={Type.Warning} headerText={'Header text'} closeButtonText={'Close'}>
<div data-testid="information-dialog-child"></div>
</InformationDialog>
);
render(dialog);
const child = screen.getByTestId('information-dialog-child');
expect(child).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { AvatarShape } from '@ui5/webcomponents-react/lib/AvatarShape';
import { AvatarSize } from '@ui5/webcomponents-react/lib/AvatarSize';
import BrowserProvider from '../../util/browser/BrowserProvider';
import PopoverListItems from '../Popover/List/PopoverListItems';
import ThemeSwitch from '../ThemeSwitch/ThemeSwitch';

const style = {
shell: {
Expand All @@ -24,6 +25,7 @@ const Shell = ({ title, ...props }) => {
const { t } = useTranslation();
const history = useHistory();
const popoverConfigItemsRef = useRef(null);
const themeSwitchRef = useRef(null);
const popoverItems = [
{
children: t('shell.button.user.settings.item.languageSwitch'),
Expand All @@ -33,7 +35,7 @@ const Shell = ({ title, ...props }) => {
{
children: t('shell.button.user.settings.item.themeSwitch'),
icon: 'customize',
onClick: () => alert('activate theme switch dialog'),
onClick: () => themeSwitchRef.current.open(),
},
];

Expand All @@ -51,6 +53,7 @@ const Shell = ({ title, ...props }) => {
/>
<div data-testid="emptySpace-wrapper" style={style.emptySpace} />
<PopoverListItems popoverRef={popoverConfigItemsRef} title={t('shell.button.user.settings')} items={popoverItems} />
<ThemeSwitch dialogRef={themeSwitchRef} />
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';

import { Option } from '@ui5/webcomponents-react/lib/Option';
import { Select } from '@ui5/webcomponents-react/lib/Select';
import { setTheme } from '@ui5/webcomponents-base/dist/config/Theme.js';
import InformationDialog from '../InformationDialog/InformationDialog';
import Constants from '../../util/Constants';

const style = {
select: {
width: '100%',
},
};

const themeOptions = [
{ value: 'sap_fiori_3', title: 'shell.button.user.settings.item.themeSwitch.option.default' },
{ value: 'sap_fiori_3_dark', title: 'shell.button.user.settings.item.themeSwitch.option.dark' },
{ value: 'sap_belize', title: 'shell.button.user.settings.item.themeSwitch.option.belize' },
{ value: 'sap_fiori_3_hcb', title: 'shell.button.user.settings.item.themeSwitch.option.highContrastBlack' },
{ value: 'sap_fiori_3_hcw', title: 'shell.button.user.settings.item.themeSwitch.option.highContrastWhite' },
];

const ThemeSwitch = ({ dialogRef, storedTheme = localStorage.getItem(Constants.SEED.SELECTED_THEME) }) => {
const { t } = useTranslation();

useEffect(() => {
setTheme(storedTheme ? storedTheme : themeOptions[0].value);
});

const onChange = (event) => {
localStorage.setItem(Constants.SEED.SELECTED_THEME, event.detail.selectedOption.dataset.value);
setTheme(event.detail.selectedOption.dataset.value);
};

return (
<InformationDialog dialogRef={dialogRef} headerText={t('shell.button.user.settings.item.themeSwitch.title')}>
<Select onChange={onChange} style={style.select} data-testid="language-switch-wrapper">
{themeOptions &&
themeOptions.map((option) => {
return (
<Option key={option.value} data-value={option.value} selected={option.value === storedTheme}>
{t(option.title)}
</Option>
);
})}
</Select>
</InformationDialog>
);
};

export default ThemeSwitch;
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';

import '@testing-library/jest-dom/extend-expect';
import { getTheme } from '@ui5/webcomponents-base/dist/config/Theme.js';
import { render, screen } from '../../util/TestSetup';

import ThemeSwitch from './ThemeSwitch';

describe('ThemeSwitch.js Test Suite', () => {
test('Should render', () => {
const dialog = <ThemeSwitch />;
render(dialog);
const infoDialog = screen.getByTestId('language-switch-wrapper');
expect(infoDialog).toBeInTheDocument();
});

test('Should load sap_fiori_3 as default theme', () => {
render(<ThemeSwitch />);
const currentTheme = getTheme();
expect(currentTheme).toBe('sap_fiori_3');
});

test('Should load black contrast theme', () => {
const themeSet = 'sap_fiori_3_hcb';
render(<ThemeSwitch storedTheme={themeSet} />);
const currentTheme = getTheme();
expect(currentTheme).toBe(themeSet);
});

test('Should load belize theme', () => {
const themeSet = 'sap_belize';
render(<ThemeSwitch storedTheme={themeSet} />);
const currentTheme = getTheme();
expect(currentTheme).toBe(themeSet);
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"app.generics.close": "Close",
"helmet.title.app": "TodoList App",
"helmet.title.error": "Buggy Component - TodoList App",
"helmet.title.notfound": "NotFound - TodoList App",
Expand All @@ -7,6 +8,12 @@
"shell.button.user.settings": "User Settings",
"shell.button.user.settings.item.languageSwitch": "Language Switch",
"shell.button.user.settings.item.themeSwitch": "Theme Switch",
"shell.button.user.settings.item.themeSwitch.option.default": "Default",
"shell.button.user.settings.item.themeSwitch.option.dark": "Dark",
"shell.button.user.settings.item.themeSwitch.option.highContrastBlack": "High Contrast Black",
"shell.button.user.settings.item.themeSwitch.option.highContrastWhite": "High Contrast White",
"shell.button.user.settings.item.themeSwitch.option.belize": "Belize",
"shell.button.user.settings.item.themeSwitch.title": "Theme Switch",
"page.error.text": "Ops! There was an error in loading this page",
"page.error.alt": "Error",
"page.notfound.text": "Hmmm, we could find this URL",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const style = {
},
reloadButton: {
cursor: 'pointer',
color: 'var(--sapLinkColor)',
},
};

Expand Down
3 changes: 3 additions & 0 deletions packages/ui5-webcomponents-react-seed/src/util/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ export default {
GET_TODO_BY_ID: 'GET_TODO_BY_ID',
},
},
SEED: {
SELECTED_THEME: 'SELECTED_THEME',
},
};

0 comments on commit 8339feb

Please sign in to comment.