feat: color theming for monitors based on block category

This commit is contained in:
Andy O'Neill committed 2023-02-23 16:37:48 -05:00
1 parent bb618d09cb
commit 563dffb34a
11 files changed
+123 -30

No files matched your search

+8 -2
View File
@@ -10,7 +10,10 @@ const DefaultMonitor = ({categoryColor, label, value}) => (
</div>
<div
className={styles.value}
style={{background: categoryColor}}
style={{
background: categoryColor.background,
color: categoryColor.text
}}
>
{value}
</div>
@@ -19,7 +22,10 @@ const DefaultMonitor = ({categoryColor, label, value}) => (
);
DefaultMonitor.propTypes = {
categoryColor: PropTypes.string.isRequired,
categoryColor: PropTypes.shape({
background: PropTypes.string.isRequired,
text: PropTypes.string.isRequired
}).isRequired,
label: PropTypes.string.isRequired,
value: PropTypes.oneOfType([
PropTypes.string,
+8 -2
View File
@@ -6,7 +6,10 @@ const LargeMonitor = ({categoryColor, value}) => (
<div className={styles.largeMonitor}>
<div
className={styles.largeValue}
style={{background: categoryColor}}
style={{
background: categoryColor.background,
color: categoryColor.text
}}
>
{value}
</div>
@@ -14,7 +17,10 @@ const LargeMonitor = ({categoryColor, value}) => (
);
LargeMonitor.propTypes = {
categoryColor: PropTypes.string,
categoryColor: PropTypes.shape({
background: PropTypes.string.isRequired,
text: PropTypes.string.isRequired
}).isRequired,
value: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number
@@ -41,7 +41,10 @@ class ListMonitorScroller extends React.Component {
<div
className={styles.listValue}
dataIndex={index}
style={{background: this.props.categoryColor}}
style={{
background: this.props.categoryColor.background,
color: this.props.categoryColor.text
}}
onClick={this.props.draggable ? this.handleEventFactory(index) : null}
>
{this.props.draggable && this.props.activeIndex === index ? (
@@ -51,6 +54,7 @@ class ListMonitorScroller extends React.Component {
autoComplete={false}
className={classNames(styles.listInput, 'no-drag')}
spellCheck={false}
style={{color: this.props.categoryColor.text}}
type="text"
value={this.props.activeValue}
onBlur={this.props.onDeactivate}
@@ -97,7 +101,10 @@ class ListMonitorScroller extends React.Component {
ListMonitorScroller.propTypes = {
activeIndex: PropTypes.number,
activeValue: PropTypes.string,
categoryColor: PropTypes.string,
categoryColor: PropTypes.shape({
background: PropTypes.string.isRequired,
text: PropTypes.string.isRequired
}).isRequired,
draggable: PropTypes.bool,
height: PropTypes.number,
onActivate: PropTypes.func,
+4 -1
View File
@@ -54,7 +54,10 @@ const ListMonitor = ({draggable, label, width, height, value, onResizeMouseDown,
ListMonitor.propTypes = {
activeIndex: PropTypes.number,
categoryColor: PropTypes.string.isRequired,
categoryColor: PropTypes.shape({
background: PropTypes.string.isRequired,
text: PropTypes.string.isRequired
}).isRequired,
draggable: PropTypes.bool.isRequired,
height: PropTypes.number,
label: PropTypes.string.isRequired,
-5
View File
@@ -42,7 +42,6 @@
align-items: center;
min-width: 40px;
text-align: center;
color: white;
margin: 0 5px;
border-radius: calc($space / 2);
padding: 0 2px;
@@ -55,7 +54,6 @@
min-width: 3rem;
padding: 0.1rem 0.25rem;
text-align: center;
color: white;
font-size: 1rem;
white-space: pre-wrap;
transform: translateZ(0); /* Fixes flickering in Safari */
@@ -115,7 +113,6 @@
.list-value {
min-width: 40px;
text-align: left;
color: white;
margin: 0 3px;
border-radius: calc($space / 2);
border: 1px solid $ui-black-transparent;
@@ -161,7 +158,6 @@
padding: 3px 5px;
border: 0;
background: none;
color: $ui-white;
outline: none;
font-size: 0.75rem;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
@@ -174,7 +170,6 @@
padding: 0;
padding-right: 5px;
cursor: pointer;
color: $ui-white;
}
.add-button {
+22 -13
View File
@@ -10,17 +10,19 @@ import DefaultMonitor from './default-monitor.jsx';
import LargeMonitor from './large-monitor.jsx';
import SliderMonitor from '../../containers/slider-monitor.jsx';
import ListMonitor from '../../containers/list-monitor.jsx';
import {getColorsForTheme} from '../../lib/themes/index.js';
import styles from './monitor.css';
const categories = {
data: '#FF8C1A',
sensing: '#5CB1D6',
sound: '#CF63CF',
looks: '#9966FF',
motion: '#4C97FF',
list: '#FC662C',
extension: '#0FBD8C'
// Map category name to color name used in scratch-blocks Blockly.Colours
const categoryColorMap = {
data: 'data',
sensing: 'sensing',
sound: 'sounds',
looks: 'looks',
motion: 'motion',
list: 'data_lists',
extension: 'pen'
};
const modes = {
@@ -30,6 +32,14 @@ const modes = {
list: ListMonitor
};
const getCategoryColor = (theme, category) => {
const colors = getColorsForTheme(theme);
return {
background: colors[categoryColorMap[category]].primary,
text: colors.text
};
};
const MonitorComponent = props => (
<ContextMenuTrigger
disable={!props.draggable}
@@ -49,7 +59,7 @@ const MonitorComponent = props => (
onDoubleClick={props.mode === 'list' || !props.draggable ? null : props.onNextMode}
>
{React.createElement(modes[props.mode], {
categoryColor: categories[props.category],
categoryColor: getCategoryColor(props.theme, props.category),
...props
})}
</Box>
@@ -122,12 +132,10 @@ const MonitorComponent = props => (
);
MonitorComponent.categories = categories;
const monitorModes = Object.keys(modes);
MonitorComponent.propTypes = {
category: PropTypes.oneOf(Object.keys(categories)),
category: PropTypes.oneOf(Object.keys(categoryColorMap)),
componentRef: PropTypes.func.isRequired,
draggable: PropTypes.bool.isRequired,
label: PropTypes.string.isRequired,
@@ -140,7 +148,8 @@ MonitorComponent.propTypes = {
onSetModeToDefault: PropTypes.func,
onSetModeToLarge: PropTypes.func,
onSetModeToSlider: PropTypes.func,
onSliderPromptOpen: PropTypes.func
onSliderPromptOpen: PropTypes.func,
theme: PropTypes.string.isRequired
};
MonitorComponent.defaultProps = {
+8 -2
View File
@@ -12,7 +12,10 @@ const SliderMonitor = ({categoryColor, isDiscrete, label, min, max, value, onSli
</div>
<div
className={styles.value}
style={{background: categoryColor}}
style={{
background: categoryColor.background,
color: categoryColor.text
}}
>
{value}
</div>
@@ -33,7 +36,10 @@ const SliderMonitor = ({categoryColor, isDiscrete, label, min, max, value, onSli
);
SliderMonitor.propTypes = {
categoryColor: PropTypes.string.isRequired,
categoryColor: PropTypes.shape({
background: PropTypes.string.isRequired,
text: PropTypes.string.isRequired
}).isRequired,
isDiscrete: PropTypes.bool,
label: PropTypes.string.isRequired,
max: PropTypes.number,
+6
View File
@@ -213,6 +213,7 @@ class Monitor extends React.Component {
min={this.props.min}
mode={this.props.mode}
targetId={this.props.targetId}
theme={this.props.theme}
width={this.props.width}
onDragEnd={this.handleDragEnd}
onExport={isList ? this.handleExport : null}
@@ -250,6 +251,7 @@ Monitor.propTypes = {
resizeMonitorRect: PropTypes.func.isRequired,
spriteName: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
targetId: PropTypes.string,
theme: PropTypes.string,
toolboxXML: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
value: PropTypes.oneOfType([
PropTypes.string,
@@ -264,8 +266,12 @@ Monitor.propTypes = {
x: PropTypes.number,
y: PropTypes.number
};
Monitor.defaultProps = {
theme: 'standard'
};
const mapStateToProps = state => ({
monitorLayout: state.scratchGui.monitorLayout,
theme: state.scratchGui.theme.theme,
// render on toolbox updates since changes to the blocks could affect monitor labels, i.e. updated locale
toolboxXML: state.scratchGui.toolbox.toolboxXML,
vm: state.scratchGui.vm
-3
View File
@@ -70,9 +70,6 @@ const blockColors = {
tertiary: '#FF3355',
quaternary: '#FFE5EA'
},
// For productionizing: we should look into making this field be the color of the text on the blocks
// e.g. move and steps in move (10) steps, and rename this property below for controlling the text inside
// of inputs e.g. 10
text: '#000000',
textFieldText: '#000000', // Text inside of inputs e.g. 90 in [point in direction (90)]
toolboxText: '#000000', // Toolbox text, color picker text (used to be #575E75)
@@ -11,6 +11,9 @@ describe('MonitorListComponent', () => {
monitors: {},
savedMonitorPositions: {}
},
theme: {
theme: 'standard'
},
toolbox: {
toolboxXML: ''
},
+55
View File
@@ -0,0 +1,55 @@
import React from 'react';
import {shallow} from 'enzyme';
import DefaultMonitor from '../../../src/components/monitor/default-monitor';
import Monitor from '../../../src/components/monitor/monitor';
jest.mock('../../../src/lib/themes/default-colors');
jest.mock('../../../src/lib/themes/dark-mode');
describe('Monitor Component', () => {
test('it selects the correct colors based on default theme', () => {
const noop = () => {};
const wrapper = shallow(<Monitor
category="motion"
// eslint-disable-next-line react/jsx-no-bind
componentRef={noop}
draggable={false}
label="My label"
mode="default"
// eslint-disable-next-line react/jsx-no-bind
onDragEnd={noop}
// eslint-disable-next-line react/jsx-no-bind
onNextMode={noop}
theme="standard"
/>);
const defaultMonitor = wrapper.find(DefaultMonitor);
// selects colors from mock value in src/lib/themes/__mocks__/default-colors.js
expect(defaultMonitor.props().categoryColor).toEqual({background: '#111111', text: '#444444'});
});
test('it selects the correct colors based on dark mode theme', () => {
const noop = () => {};
const wrapper = shallow(<Monitor
category="motion"
// eslint-disable-next-line react/jsx-no-bind
componentRef={noop}
draggable={false}
label="My label"
mode="default"
// eslint-disable-next-line react/jsx-no-bind
onDragEnd={noop}
// eslint-disable-next-line react/jsx-no-bind
onNextMode={noop}
theme="dark-mode"
/>);
const defaultMonitor = wrapper.find(DefaultMonitor);
// selects colors from mock value in src/lib/themes/__mocks__/dark-mode.js
expect(defaultMonitor.props().categoryColor).toEqual({background: '#AAAAAA', text: '#BBBBBB'});
});
});