diff --git a/src/components/asset-panel/asset-panel.css b/src/components/asset-panel/asset-panel.css index 8ff5ca4cb3d41a9f37e87a15f0ef3b2f63a749f7..25d13588d8c2452f749820b58057da47b1ba9100 100644 --- a/src/components/asset-panel/asset-panel.css +++ b/src/components/asset-panel/asset-panel.css @@ -6,7 +6,7 @@ flex-grow: 1; border: 1px solid $ui-pane-border; border-top-right-radius: $space; - background: $ui-pane-gray; + background: white; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.85rem; } diff --git a/src/components/asset-panel/icon--add-sound-lib.svg b/src/components/asset-panel/icon--add-sound-lib.svg new file mode 100644 index 0000000000000000000000000000000000000000..1293940a90e2144058488f01201108bc8cc6724e Binary files /dev/null and b/src/components/asset-panel/icon--add-sound-lib.svg differ diff --git a/src/components/asset-panel/icon--add-sound-record.svg b/src/components/asset-panel/icon--add-sound-record.svg new file mode 100644 index 0000000000000000000000000000000000000000..b82e7a412b1360dc05f7bf464cbda917b1023e64 Binary files /dev/null and b/src/components/asset-panel/icon--add-sound-record.svg differ diff --git a/src/components/asset-panel/selector.css b/src/components/asset-panel/selector.css index 3050409c1f790e430872afae7dca879cad1de6f0..ef5bba68d8978fad0cd7742601e57ecdd969d64a 100644 --- a/src/components/asset-panel/selector.css +++ b/src/components/asset-panel/selector.css @@ -1,27 +1,48 @@ -/* Need to use a fixed height for the new container to make list scrollable */ -$new-height: 60px; +@import "../../css/colors.css"; .wrapper { - width: 250px; + width: 150px; position: relative; + display: flex; + flex-direction: column; + justify-content: space-between; + background: $ui-background-blue; } -.new-item { - background: white; - border-bottom: 1px solid #ddd; - height: $new-height; +.new-buttons { display: flex; + flex-direction: column; align-items: center; - padding-left: 1.75rem; + justify-content: space-around; + margin: 1.25rem 0; + color: $motion-primary; +} + +.new-button { + display: flex; + flex-direction: column; + align-items: center; + font-size: 0.6rem; cursor: pointer; - font-size: 0.85rem; + transition: 0.2s; +} + +.new-button:hover { + transform: scale(1.2); +} + +.new-button + .new-button { + margin-top: 1.25rem; +} + +.new-button-icon + .new-button-label { + margin-top: 0.5rem; } .list-area { - position: absolute; - width: 100%; - top: 60px; - height: calc(100% - $new-height); + /* Must have some height (recalculated by flex-grow) in order to scroll */ + height: 0; + flex-grow: 1; overflow-y: scroll; } @@ -30,9 +51,3 @@ $new-height: 60px; min-height: 5rem; margin: 1rem auto; } - -.delete-button { - position: absolute; - top: 2px; - right: 2px; -} diff --git a/src/components/asset-panel/selector.jsx b/src/components/asset-panel/selector.jsx index 0ddc2bb51202771fc9861ac603174bb28716773f..a9c448751469dce065af7ac950b4d775b1053f07 100644 --- a/src/components/asset-panel/selector.jsx +++ b/src/components/asset-panel/selector.jsx @@ -8,22 +8,15 @@ const styles = require('./selector.css'); const Selector = props => { const { + buttons, items, - newText, selectedItemIndex, onDeleteClick, - onItemClick, - onNewClick + onItemClick } = props; return ( <Box className={styles.wrapper}> - <Box - className={styles.newItem} - onClick={onNewClick} - > - {newText} - </Box> <Box className={styles.listArea}> {items.map((item, index) => ( <SpriteSelectorItem @@ -39,19 +32,39 @@ const Selector = props => { /> ))} </Box> + <Box className={styles.newButtons}> + {buttons.map(({text, img, onClick}, index) => ( + <Box + className={styles.newButton} + key={index} + onClick={onClick} + > + <img + className={styles.newButtonIcon} + src={img} + /> + <Box className={styles.newButtonLabel}> + {text} + </Box> + </Box> + ))} + </Box> </Box> ); }; Selector.propTypes = { + buttons: PropTypes.arrayOf(PropTypes.shape({ + text: PropTypes.string.isRequired, + img: PropTypes.string.isRequired, + onClick: PropTypes.func.isRequired + })), items: PropTypes.arrayOf(PropTypes.shape({ url: PropTypes.string, name: PropTypes.string.isRequired })), - newText: PropTypes.string.isRequired, onDeleteClick: PropTypes.func.isRequired, onItemClick: PropTypes.func.isRequired, - onNewClick: PropTypes.func, selectedItemIndex: PropTypes.number.isRequired }; diff --git a/src/components/gui/gui.css b/src/components/gui/gui.css index 821f55014c396082dcab28e5440987644ffba418..de9c7f9ec3918a67cfdb2b65661f9277b5dd5676 100644 --- a/src/components/gui/gui.css +++ b/src/components/gui/gui.css @@ -1,4 +1,5 @@ @import "../../css/units.css"; +@import "../../css/colors.css"; .page-wrapper { height: 100%; @@ -6,7 +7,7 @@ .body-wrapper { height: calc(100% - $menu-bar-height); - background-color: #e8edf1; + background-color: $ui-background-blue; } .flex-wrapper { diff --git a/src/components/record-modal/record-modal.css b/src/components/record-modal/record-modal.css index 0f82c659420c44de5c0b9bd4b640d9bce7fc6a38..b880daf78f01c935e7942054f48a59d452b87179 100644 --- a/src/components/record-modal/record-modal.css +++ b/src/components/record-modal/record-modal.css @@ -74,7 +74,7 @@ $sides: 5rem; } .body { - background: $ui-pane-gray; + background: white; padding: 1.5rem 2.25rem; } @@ -84,8 +84,8 @@ $sides: 5rem; } .meter-container, .waveform-container { - background: white; - border: 1px solid #ddd; + background: $ui-pane-gray; + border: 1px solid $ui-pane-border; border-radius: 5px; padding: 3px; diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index af73857e75f5a2427da74c69e9f2ebc5b65769be..855c1d26665669b8f5fb68c8757367b358242716 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -5,6 +5,7 @@ const bindAll = require('lodash.bindall'); const VM = require('scratch-vm'); const AssetPanel = require('../components/asset-panel/asset-panel.jsx'); +const addCostumeIcon = require('../components/asset-panel/icon--add-sound-lib.svg'); const {connect} = require('react-redux'); @@ -64,12 +65,16 @@ class CostumeTab extends React.Component { return ( <AssetPanel + buttons={[{ + text: addText, + img: addCostumeIcon, + onClick: addFunc + }]} items={target.costumes || []} newText={addText} selectedItemIndex={this.state.selectedCostumeIndex} onDeleteClick={this.handleDeleteCostume} onItemClick={this.handleSelectCostume} - onNewClick={addFunc} /> ); } diff --git a/src/containers/sound-tab.jsx b/src/containers/sound-tab.jsx index 1828caf92f6dff32d2db6e1b9eae120460b498b3..e7e780d0b2c97470aba158a9ca14e7e2a052860f 100644 --- a/src/containers/sound-tab.jsx +++ b/src/containers/sound-tab.jsx @@ -6,6 +6,9 @@ const VM = require('scratch-vm'); const AssetPanel = require('../components/asset-panel/asset-panel.jsx'); const soundIcon = require('../components/asset-panel/icon--sound.svg'); +const addSoundFromLibraryIcon = require('../components/asset-panel/icon--add-sound-lib.svg'); +const addSoundFromRecordingIcon = require('../components/asset-panel/icon--add-sound-record.svg'); + const RecordModal = require('./record-modal.jsx'); const {connect} = require('react-redux'); @@ -53,7 +56,9 @@ class SoundTab extends React.Component { const { editingTarget, sprites, - stage + stage, + onNewSoundFromLibraryClick, + onNewSoundFromRecordingClick } = this.props; const target = editingTarget && sprites[editingTarget] ? sprites[editingTarget] : stage; @@ -71,15 +76,22 @@ class SoundTab extends React.Component { return ( <AssetPanel + buttons={[{ + text: 'Record Sound', + img: addSoundFromRecordingIcon, + onClick: onNewSoundFromRecordingClick + }, { + text: 'Add Sound', + img: addSoundFromLibraryIcon, + onClick: onNewSoundFromLibraryClick + }]} items={sounds.map(sound => ({ url: soundIcon, ...sound }))} - newText={'Add Sound'} selectedItemIndex={this.state.selectedSoundIndex} onDeleteClick={this.handleDeleteSound} onItemClick={this.handleSelectSound} - onNewClick={this.props.onSoundRecorder} > {this.props.soundRecorderVisible ? ( <RecordModal /> @@ -91,7 +103,8 @@ class SoundTab extends React.Component { SoundTab.propTypes = { editingTarget: PropTypes.string, - onSoundRecorder: PropTypes.func.isRequired, + onNewSoundFromLibraryClick: PropTypes.func.isRequired, + onNewSoundFromRecordingClick: PropTypes.func.isRequired, soundRecorderVisible: PropTypes.bool, sprites: PropTypes.shape({ id: PropTypes.shape({ @@ -116,11 +129,11 @@ const mapStateToProps = state => ({ }); const mapDispatchToProps = dispatch => ({ - onNewSoundClick: e => { + onNewSoundFromLibraryClick: e => { e.preventDefault(); dispatch(openSoundLibrary()); }, - onSoundRecorder: () => { + onNewSoundFromRecordingClick: () => { dispatch(openSoundRecorder()); } }); diff --git a/src/css/colors.css b/src/css/colors.css index 15bd89d8e2faa1e84f8dc4f419bde5684e0c63fd..036efe3f2843547931b76a2037b781ce82027bc3 100644 --- a/src/css/colors.css +++ b/src/css/colors.css @@ -1,5 +1,6 @@ $ui-pane-border: #D9D9D9; $ui-pane-gray: #F9F9F9; +$ui-background-blue: #e8edf1; $motion-primary: #4C97FF; $motion-tertiary: #3373CC;