Skip to content
Open
Show file tree
Hide file tree
Changes from all 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/.qa-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',
'../addon-toolbar/manager.js'
],
webpackFinal: async (config, {configType}) => {
return webpack(config, configType, __dirname);
Expand Down
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',
'../addon-toolbar/manager.js'
],
webpackFinal: async (config, {configType}) => {
return webpack(config, configType, __dirname);
Expand Down
32 changes: 32 additions & 0 deletions samples/sampler/addon-toolbar/ColorPicker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {useGlobals} from '@storybook/api';
import PropTypes from 'prop-types';
import React, {useCallback} from 'react'; // eslint-disable-line

import {BACKGROUND_DEFAULT_VALUE, TEXT_ADDON_ID, TEXT_DEFAULT_VALUE} from "./constants";

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

const getDefaultColor = () => {
if (colorPickerType === TEXT_ADDON_ID) return TEXT_DEFAULT_VALUE;
return BACKGROUND_DEFAULT_VALUE;
};

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

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

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

export default ColorPicker;
38 changes: 38 additions & 0 deletions samples/sampler/addon-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, {memo} from 'react'; // eslint-disable-line

import ColorPicker from './ColorPicker';

const ToolbarButton = 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;
7 changes: 7 additions & 0 deletions samples/sampler/addon-toolbar/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const BACKGROUND_ADDON_ID = 'component background color';
export const BACKGROUND_DEFAULT_VALUE = '#7d848c';

export const TEXT_ADDON_ID = 'component text color';
export const TEXT_DEFAULT_VALUE = '#e6e6e6';

export const TOOLBAR_ADDON_ID = 'toolbar-colors';
24 changes: 24 additions & 0 deletions samples/sampler/addon-toolbar/manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {addons, types} from '@storybook/addons';
import React from 'react'; // eslint-disable-line

import {BACKGROUND_ADDON_ID, TEXT_ADDON_ID, TOOLBAR_ADDON_ID} from './constants';
import ToolbarButton from './ToolbarButton';

addons.register(TOOLBAR_ADDON_ID, () => {
const renderBackgroundColorButton = () => <ToolbarButton colorPickerType={BACKGROUND_ADDON_ID} />;
const renderTextColorButton = () => <ToolbarButton colorPickerType={TEXT_ADDON_ID} />;

addons.add(BACKGROUND_ADDON_ID, {
title: BACKGROUND_ADDON_ID,
type: types.TOOL,
match: ({viewMode}) => !!(viewMode && viewMode.match(/^(story|docs)$/)),
render: renderBackgroundColorButton
});

addons.add(TEXT_ADDON_ID, {
title: BACKGROUND_ADDON_ID,
type: types.TOOL,
match: ({viewMode}) => !!(viewMode && viewMode.match(/^(story|docs)$/)),
render: renderTextColorButton
});
});
51 changes: 50 additions & 1 deletion samples/sampler/src/ThemeEnvironment/ThemeEnvironment.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ThemeDecorator from '@enact/sandstone/ThemeDecorator';
import PropTypes from 'prop-types';

import css from './ThemeEnvironment.module.less';
import {BACKGROUND_ADDON_ID, TEXT_ADDON_ID} from "../../addon-toolbar/constants";

const reloadPage = () => {
const {protocol, host, pathname} = window.parent.location;
Expand Down Expand Up @@ -43,11 +44,57 @@ const PanelsBase = kind({

const Theme = ThemeDecorator({overlay: false}, PanelsBase);

const getPropFromURL = (propName) => {
propName = propName.replaceAll(' ', '+');
const locationParams = window.parent.location.search;

const propNameStartIndex = locationParams.indexOf(propName);
const propValueStartIndex = locationParams.indexOf(':', propNameStartIndex);
let propValueEndIndex = locationParams.indexOf(';', propValueStartIndex);
let lastCharacter = '';

if (propNameStartIndex > -1) {
if (propName.includes('color')) {
const startIndex = locationParams.indexOf('(', propValueStartIndex);
const endIndex = locationParams.indexOf(')', startIndex);

return '#' + locationParams.substring(startIndex + 1, endIndex);
}

if (propValueEndIndex === -1) {
propValueEndIndex = locationParams.indexOf(locationParams.at(-1), propValueStartIndex);
lastCharacter = locationParams.at(-1);
}

return locationParams.substring(propValueStartIndex + 1, propValueEndIndex) + lastCharacter;
}

return null;
};

const getRGBColor = (color) => {
const hexColor = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);

if (hexColor) {
const red = parseInt(hexColor[1], 16);
const green = parseInt(hexColor[2], 16);
const blue = parseInt(hexColor[3], 16);

return `${red}, ${green}, ${blue}`;
}

return null;
};

const StorybookDecorator = (story, config = {}) => {
// Executing `story` here allows the story controls to register and render before the global variable below.
const sample = story();

const backgroundColorFromURL = getPropFromURL('component background color');
const textColorFromURL = getPropFromURL('component text color');

const {globals} = config;
const backgroundColor = globals[BACKGROUND_ADDON_ID], textColor = globals[TEXT_ADDON_ID];

const componentName = config.kind.replace(/^([^/]+)\//, '');

Expand All @@ -74,7 +121,9 @@ const StorybookDecorator = (story, config = {}) => {
textSize={JSON.parse(globals['large text']) ? 'large' : 'normal'}
highContrast={JSON.parse(globals['high contrast'])}
style={{
'--sand-env-background': globals.background === 'default' ? '' : globals.background
'--sand-env-background': globals.background === 'default' ? '' : globals.background,
'--sand-component-bg-color': backgroundColor || backgroundColorFromURL,
'--sand-component-text-color-rgb': getRGBColor(textColor) || getRGBColor(textColorFromURL)
}}
skin={globals.skin}
{...hasProps ? config.parameters.props : null}
Expand Down