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

WRQ-1966: Storybook - Read custom colors from luna settings service #1610

Draft
wants to merge 16 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 13 commits
Commits
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 samples/sampler/.storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ module.exports = {
'@enact/storybook-utils/addons/actions',
'@enact/storybook-utils/addons/controls',
'@enact/storybook-utils/addons/docs',
'@enact/storybook-utils/addons/toolbars'
'@enact/storybook-utils/addons/toolbars',
'../colors-toolbar/manager.js'
],
webpackFinal: async (config, {configType}) => {
return webpack(config, configType, __dirname);
Expand Down
30 changes: 29 additions & 1 deletion samples/sampler/.storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,28 @@ import {themes} from '@storybook/theming';

import ThemeEnvironment from '../src/ThemeEnvironment';

// custom decorator imports
import {addDecorator} from '@storybook/react';
import {platform} from '@enact/webos/platform';

import {CustomStoryDecorator} from '../colors-toolbar/CustomStoryDecorator';

// if running in webos environment, render a list of color pickers in every story
export const GlobalDecorator = (Story) => {
if (platform.tv) {
return (
<div style={{padding: '21px'}}>
<CustomStoryDecorator />
<Story />
</div>
)
} else {
return <Story />;
}
};

addDecorator(GlobalDecorator);

// NOTE: Locales taken from strawman. Might need to add more in the future.
const locales = {
'local': '',
Expand Down Expand Up @@ -96,7 +118,13 @@ export const globalTypes = {
'debug aria': getBooleanType('debug aria'),
'debug layout': getBooleanType('debug layout'),
'debug spotlight': getBooleanType('debug spotlight'),
'debug sprites': getBooleanType('debug sprites')
'debug sprites': getBooleanType('debug sprites'),
// custom theme globalTypes
'componentBackgroundColor': 'string',
'focusBackgroundColor': 'string',
'popupBackgroundColor': 'string',
'subtitleTextColor': 'string',
'textColor': 'string'
};

export const decorators = [ThemeEnvironment];
52 changes: 52 additions & 0 deletions samples/sampler/colors-toolbar/ColorPicker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import PropTypes from 'prop-types';
import React, {useCallback} from 'react'; // eslint-disable-line
import {useGlobals} from '@storybook/api';

import {
BACKGROUNDCOLOR_ADDON_ID,
BACKGROUNDCOLOR_DEFAULT_VALUE,
FOCUSBGCOLOR_ADDON_ID,
FOCUSBGCOLOR_DEFAULT_VALUE,
POPUPBGCOLOR_ADDON_ID,
POPUPBGCOLOR_DEFAULT_VALUE,
SUBTEXTCOLOR_DEFAULT_VALUE,
TEXT_ADDON_ID,
TEXT_DEFAULT_VALUE
} from './constants';

const ColorPicker = ({colorPickerType}) => {
const [globals, updateGlobals] = useGlobals();

const getDefaultColor = () => {
switch (colorPickerType) {
case BACKGROUNDCOLOR_ADDON_ID:
return BACKGROUNDCOLOR_DEFAULT_VALUE;
case FOCUSBGCOLOR_ADDON_ID:
return FOCUSBGCOLOR_DEFAULT_VALUE;
case POPUPBGCOLOR_ADDON_ID:
return POPUPBGCOLOR_DEFAULT_VALUE;
case TEXT_ADDON_ID:
return TEXT_DEFAULT_VALUE;
default:
return SUBTEXTCOLOR_DEFAULT_VALUE;
}
};

const handleColorChange = useCallback((ev) => {
updateGlobals({[colorPickerType]: ev.target.value});
}, [colorPickerType, updateGlobals]);

return (
<input
onChange={handleColorChange}
type="color"
value={globals[colorPickerType] || getDefaultColor()}
/>
);
};

ColorPicker.propTypes = {
colorPickerType: PropTypes.string
};

export default ColorPicker;
140 changes: 140 additions & 0 deletions samples/sampler/colors-toolbar/CustomStoryDecorator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// this component has been added as an alternative of built-in HTML color picker which does not work in webos environment
import LS2Request from '@enact/webos/LS2Request';
import {useCallback, useContext} from 'react';

import Button from '@enact/sandstone/Button';
import {ColorPicker as SandstoneColorPicker} from '@enact/sandstone/ColorPicker';
import Scroller from '@enact/sandstone/Scroller';

import {AppContext} from './constants';
adrian-cocoara-lgp marked this conversation as resolved.
Show resolved Hide resolved
import {generateStylesheet} from '../utils/generateStylesheet';

import css from './CustomStoryDecorator.module.less';

const request = new LS2Request();

export const CustomStoryDecorator = () => {
const {context, setContext} = useContext(AppContext);
const {componentBackgroundColor, focusBackgroundColor, popupBackgroundColor, subtitleTextColor, textColor} = context;

const onColorChange = useCallback((color, newColor) => {
// a copy of the context object is created
const newContext = Object.assign({}, context);
// update the color value on the newly created object with what gets received from `event` (handleBackgroundColor)
newContext[color] = newColor;
// generate the new stylesheet based on the updated color
newContext.colors = generateStylesheet(
newContext.backgroundColor,
newContext.componentBackgroundColor,
newContext.focusBackgroundColor,
newContext.popupBackgroundColor,
newContext.subtitleTextColor,
newContext.textColor
);
setContext(newContext);

request.send({
service: 'luna://com.webos.service.settings/',
method: 'setSystemSettings',
parameters: {
category: 'customUi',
settings: {
theme: JSON.stringify(newContext)
}
},
onSuccess: () => {
console.log('setSystemSettings onSuccess'); // eslint-disable-line no-console
}
});
}, [context, setContext]);

const handleComponentBgColor = useCallback((ev) => {
onColorChange('componentBackgroundColor', ev);
}, [onColorChange]);
const handleFocusBgColor = useCallback((ev) => {
onColorChange('focusBackgroundColor', ev);
}, [onColorChange]);
const handlePopupBgColor = useCallback((ev) => {
onColorChange('popupBackgroundColor', ev);
}, [onColorChange]);
const handleTextColor = useCallback((ev) => {
onColorChange('textColor', ev);
}, [onColorChange]);
const handleSubTextColor = useCallback((ev) => {
onColorChange('subtitleTextColor', ev);
}, [onColorChange]);

const handleResetButton = useCallback(() => {
// a copy of the context object is created
const newContext = Object.assign({}, context);
// generate the new stylesheet with default sandstone colors
newContext.colors = generateStylesheet(
newContext.backgroundColor,
newContext.componentBackgroundColor,
newContext.focusBackgroundColor,
newContext.popupBackgroundColor,
newContext.subtitleTextColor,
newContext.textColor
);
setContext(newContext);

request.send({
service: 'luna://com.webos.service.settings/',
method: 'setSystemSettings',
parameters: {
category: 'customUi',
settings: {
theme: JSON.stringify(newContext)
}
},
onSuccess: () => {
console.log('setSystemSettings onSuccess'); // eslint-disable-line no-console
}
});
}, []); // eslint-disable-line

return (
<div className={css.colorPickersBlock}>
<Scroller className={css.scrollerColors}>
<SandstoneColorPicker
className={css.colorPicker}
css={css}
color={componentBackgroundColor}
colorHandler={handleComponentBgColor}
text="Component Background Color"
/>
<SandstoneColorPicker
className={css.colorPicker}
css={css}
color={focusBackgroundColor}
colorHandler={handleFocusBgColor}
text="Focus Background Color"
/>
<SandstoneColorPicker
className={css.colorPicker}
css={css}
color={popupBackgroundColor}
colorHandler={handlePopupBgColor}
text="Popup Background Color"
/>
<SandstoneColorPicker
className={css.colorPicker}
css={css}
color={textColor}
colorHandler={handleTextColor}
text="Text Color"
/>
<SandstoneColorPicker
className={css.colorPicker}
css={css}
color={subtitleTextColor}
colorHandler={handleSubTextColor}
text="Subtitle Text Color"
/>
<div className={css.resetButtonBlock}>
<Button className={css.resetButton} css={css} onClick={handleResetButton}>Reset default colors</Button>
</div>
</Scroller>
</div>
);
};
51 changes: 51 additions & 0 deletions samples/sampler/colors-toolbar/CustomStoryDecorator.module.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// CustomStoryDecorator styles

@import '~@enact/sandstone/styles/mixins.less';

.colorPickersBlock {
width: 30%;
adrian-cocoara-lgp marked this conversation as resolved.
Show resolved Hide resolved
height: 65%;
position: absolute;
right: 51px;
bottom: 51px;
background: #2e3239;
border-radius: 30px;
padding: 12px;
}

.colorPicker {
color: #e6e6e6;
0x64 marked this conversation as resolved.
Show resolved Hide resolved

.focus({
--sand-focus-bg-color-rgb: 230, 230, 230;
})
}

.colorPopup {
--sand-overlay-bg-color-rgb: 87, 94, 102;
--sand-text-color-rgb: 230, 230, 230;
}

.colorPickerSliders {
.colorSlider {
--sand-focus-bg-color-rgb: 230, 230, 230;
}
}

.scrollerColors {
--sand-progress-color-rgb: 230, 230, 230;
}

.resetButtonBlock {
border-top: 3px solid #e6e6e6;
padding-top: 9px;
}

.resetButton {
--sand-component-bg-color: #7D848C;
--sand-component-text-color-rgb: 230, 230, 230;

.focus({
--sand-focus-bg-color-rgb: 230, 230, 230;
})
}
38 changes: 38 additions & 0 deletions samples/sampler/colors-toolbar/ToolbarButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {IconButton, Icons, TooltipLinkList, WithTooltip} from '@storybook/components';
import PropTypes from 'prop-types';
import React from 'react';

import ColorPicker from './ColorPicker';

const ToolbarButton = React.memo(({active = true, buttonName, colorPickerType, tooltipName}) => {
const tooltipLink = {
center: <ColorPicker colorPickerType={colorPickerType} />,
id: colorPickerType,
key: colorPickerType,
left: <span style={{color: 'white'}}>{tooltipName || colorPickerType}</span>,
title: true
};

const tooltip = <TooltipLinkList links={[tooltipLink]} />;

return (
<WithTooltip closeOnClick tooltip={tooltip} placement="bottom" trigger="click">
<IconButton
active={active}
key={colorPickerType}
style={{display:'flex', flexDirection:'column'}}
>
<Icons /> {buttonName || colorPickerType}
</IconButton>
</WithTooltip>
);
});

ToolbarButton.prototypes = {
active: PropTypes.boolean,
buttonName: PropTypes.string,
colorPickerType: PropTypes.string.isRequired,
tooltipName: PropTypes.string
};

export default ToolbarButton;
29 changes: 29 additions & 0 deletions samples/sampler/colors-toolbar/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {createContext} from 'react';

export const customColorsContext = {
activeTheme: 'defaultTheme',
componentBackgroundColor: '#7D848C',
focusBackgroundColor: '#E6E6E6',
popupBackgroundColor: '#575E66',
subtitleTextColor: '#ABAEB3',
textColor: '#E6E6E6'
};

export const AppContext = createContext(null);

export const BACKGROUNDCOLOR_ADDON_ID = "componentBackgroundColor";
export const BACKGROUNDCOLOR_DEFAULT_VALUE = "#7D848C";

export const FOCUSBGCOLOR_ADDON_ID = "focusBackgroundColor";
export const FOCUSBGCOLOR_DEFAULT_VALUE = '#E6E6E6';

export const POPUPBGCOLOR_ADDON_ID = "popupBackgroundColor";
export const POPUPBGCOLOR_DEFAULT_VALUE = '#575E66';

export const TEXT_ADDON_ID = "textColor";
export const TEXT_DEFAULT_VALUE = "#E6E6E6";

export const SUBTEXTCOLOR_ADDON_ID = "subtitleTextColor";
export const SUBTEXTCOLOR_DEFAULT_VALUE = "#ABAEB3";

export const TOOLBAR_ADDON_ID = "toolbar-colors";
Loading
Loading