diff --git a/src/components/library-item/icon--play.svg b/src/components/library-item/icon--play.svg
new file mode 100644
index 000000000..7c4f45df7
--- /dev/null
+++ b/src/components/library-item/icon--play.svg
@@ -0,0 +1,27 @@
+
+
diff --git a/src/components/library-item/library-item.css b/src/components/library-item/library-item.css
index 5e726a363..128c9f93e 100644
--- a/src/components/library-item/library-item.css
+++ b/src/components/library-item/library-item.css
@@ -7,6 +7,7 @@
align-items: center;
justify-content: flex-start;
flex-basis: 160px;
+ position: relative;
height: 160px;
max-width: 160px;
margin: $space;
@@ -200,3 +201,45 @@
[dir="rtl"] .coming-soon-text {
transform: translate(calc(-2 * $space), calc(2 * $space));
}
+
+.play-button {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ overflow: hidden; /* Mask the icon animation */
+ width: 1.5rem;
+ height: 1.5rem;
+ background-color: $motion-primary;
+ color: $ui-white;
+ border-radius: 50%;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ user-select: none;
+ cursor: pointer;
+ transition: all 0.15s ease-out;
+}
+
+.play-button {
+ position: absolute;
+ position: absolute;
+ top: 0.125rem;
+ z-index: auto;
+}
+
+.play-button:focus {
+ outline: none;
+}
+
+.play-icon {
+ width: 50%;
+}
+
+[dir="ltr"] .play-button {
+ right: 0.125rem;
+ padding-left: .125rem;
+}
+
+[dir="rtl"] .play-button {
+ left: 0.125rem;
+ padding-right: .125rem;
+}
diff --git a/src/components/library-item/library-item.jsx b/src/components/library-item/library-item.jsx
index 5af6fb159..3101e4279 100644
--- a/src/components/library-item/library-item.jsx
+++ b/src/components/library-item/library-item.jsx
@@ -8,6 +8,11 @@ import classNames from 'classnames';
import bluetoothIconURL from './bluetooth.svg';
import internetConnectionIconURL from './internet-connection.svg';
+import playIcon from './icon--play.svg';
+
+const preventClick = e => {
+ e.stopPropagation();
+};
/* eslint-disable react/prefer-stateless-function */
class LibraryItemComponent extends React.PureComponent {
@@ -115,12 +120,16 @@ class LibraryItemComponent extends React.PureComponent {
onClick={this.props.onClick}
onFocus={this.props.onFocus}
onKeyPress={this.props.onKeyPress}
- onMouseEnter={this.props.onMouseEnter}
- onMouseLeave={this.props.onMouseLeave}
+ onMouseEnter={this.props.showPlayButton ? null : this.props.onMouseEnter}
+ onMouseLeave={this.props.showPlayButton ? null : this.props.onMouseLeave}
>
{/* Layers of wrapping is to prevent layout thrashing on animation */}
-
+
{this.props.name}
+ {this.props.showPlayButton ? (
+
+

+
+ ) : null}
);
}
@@ -158,11 +183,14 @@ LibraryItemComponent.propTypes = {
onFocus: PropTypes.func.isRequired,
onKeyPress: PropTypes.func.isRequired,
onMouseEnter: PropTypes.func.isRequired,
- onMouseLeave: PropTypes.func.isRequired
+ onMouseLeave: PropTypes.func.isRequired,
+ onPlay: PropTypes.func.isRequired,
+ showPlayButton: PropTypes.bool
};
LibraryItemComponent.defaultProps = {
- disabled: false
+ disabled: false,
+ showPlayButton: false
};
export default LibraryItemComponent;
diff --git a/src/components/library/library.jsx b/src/components/library/library.jsx
index 13736d60f..3be73b34c 100644
--- a/src/components/library/library.jsx
+++ b/src/components/library/library.jsx
@@ -187,6 +187,7 @@ class LibraryComponent extends React.Component {
internetConnectionRequired={dataItem.internetConnectionRequired}
key={typeof dataItem.name === 'string' ? dataItem.name : dataItem.rawURL}
name={dataItem.name}
+ showPlayButton={this.props.showPlayButton}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
onSelect={this.handleSelect}
@@ -227,12 +228,14 @@ LibraryComponent.propTypes = {
onItemMouseLeave: PropTypes.func,
onItemSelected: PropTypes.func,
onRequestClose: PropTypes.func,
+ showPlayButton: PropTypes.bool,
tags: PropTypes.arrayOf(PropTypes.shape(TagButton.propTypes)),
title: PropTypes.string.isRequired
};
LibraryComponent.defaultProps = {
- filterable: true
+ filterable: true,
+ showPlayButton: false
};
export default injectIntl(LibraryComponent);
diff --git a/src/containers/library-item.jsx b/src/containers/library-item.jsx
index 6177b916f..3ffa81485 100644
--- a/src/containers/library-item.jsx
+++ b/src/containers/library-item.jsx
@@ -15,6 +15,7 @@ class LibraryItem extends React.PureComponent {
'handleKeyPress',
'handleMouseEnter',
'handleMouseLeave',
+ 'handlePlay',
'rotateIcon',
'startRotatingIcons',
'stopRotatingIcons'
@@ -62,6 +63,10 @@ class LibraryItem extends React.PureComponent {
}, this.stopRotatingIcons);
}
}
+ handlePlay (e) {
+ e.stopPropagation(); // To prevent from bubbling back to handleClick
+ this.props.onMouseEnter(this.props.id);
+ }
startRotatingIcons () {
this.rotateIcon();
this.intervalId = setInterval(this.rotateIcon, 300);
@@ -105,12 +110,14 @@ class LibraryItem extends React.PureComponent {
insetIconURL={this.props.insetIconURL}
internetConnectionRequired={this.props.internetConnectionRequired}
name={this.props.name}
+ showPlayButton={this.props.showPlayButton}
onBlur={this.handleBlur}
onClick={this.handleClick}
onFocus={this.handleFocus}
onKeyPress={this.handleKeyPress}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
+ onPlay={this.handlePlay}
/>
);
}
@@ -143,7 +150,8 @@ LibraryItem.propTypes = {
]),
onMouseEnter: PropTypes.func.isRequired,
onMouseLeave: PropTypes.func.isRequired,
- onSelect: PropTypes.func.isRequired
+ onSelect: PropTypes.func.isRequired,
+ showPlayButton: PropTypes.bool
};
export default injectIntl(LibraryItem);
diff --git a/src/containers/sound-library.jsx b/src/containers/sound-library.jsx
index e49f1057a..677d93dfb 100644
--- a/src/containers/sound-library.jsx
+++ b/src/containers/sound-library.jsx
@@ -141,6 +141,7 @@ class SoundLibrary extends React.PureComponent {
return (