Add play buttons to sound library tiles for touch

Add prop to library items to show a play button. If a play button is present the ‘play on hover’ only applies over the icon rather than the full tile.
This commit is contained in:
Chris Garrity committed 2019-07-31 12:05:16 -04:00
1 parent a72a420bd3
commit f3d1a91533
6 files changed
+117 -7

No files matched your search

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="49px" height="52px" viewBox="-5 0 49 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>play</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M17.2214651,8.34499443 C19.7766419,4.08636653 23.9234057,4.09303946 26.4745787,8.34499443 L40.1520974,31.140859 C42.7072741,35.3994869 40.7489672,38.8517869 35.7726637,38.8517869 L7.92338006,38.8517869 C2.9495089,38.8517869 0.992773429,35.392814 3.54394641,31.140859 L17.2214651,8.34499443 Z" id="path-1"></path>
<filter x="-16.7%" y="-19.3%" width="133.5%" height="138.6%" filterUnits="objectBoundingBox" id="filter-2">
<feMorphology radius="2.5" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1"></feMorphology>
<feOffset dx="0" dy="0" in="shadowSpreadOuter1" result="shadowOffsetOuter1"></feOffset>
<feComposite in="shadowOffsetOuter1" in2="SourceAlpha" operator="out" result="shadowOffsetOuter1"></feComposite>
<feColorMatrix values="0 0 0 0 0.298039216 0 0 0 0 0.592156863 0 0 0 0 1 0 0 0 0.1 0" type="matrix" in="shadowOffsetOuter1"></feColorMatrix>
</filter>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Desktop---1280x720" transform="translate(-623.000000, -347.000000)">
<g id="Step-3---Altering-Suggested-Trim" transform="translate(0.000000, 42.000000)">
<g id="Play-/-Record-/-Stop" transform="translate(623.000000, 307.000000)">
<g id="play" transform="translate(21.849131, 22.002656) rotate(90.000000) translate(-21.849131, -22.002656) ">
<use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
<use stroke="#FFFFFF" stroke-width="1" fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-1"></use>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -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;
}
+33 -5
View File
@@ -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 */}
<Box className={styles.libraryItemImageContainerWrapper}>
<Box className={styles.libraryItemImageContainer}>
<Box
className={styles.libraryItemImageContainer}
onMouseEnter={this.props.showPlayButton ? this.props.onMouseEnter : null}
onMouseLeave={this.props.showPlayButton ? this.props.onMouseLeave : null}
>
<img
className={styles.libraryItemImage}
src={this.props.iconURL}
@@ -128,6 +137,22 @@ class LibraryItemComponent extends React.PureComponent {
</Box>
</Box>
<span className={styles.libraryItemName}>{this.props.name}</span>
{this.props.showPlayButton ? (
<div
aria-label="Play"
className={styles.playButton}
role="button"
tabIndex="0"
onClick={preventClick}
onMouseDown={this.props.onPlay}
>
<img
className={styles.playIcon}
draggable={false}
src={playIcon}
/>
</div>
) : null}
</Box>
);
}
@@ -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;
+4 -1
View File
@@ -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);
+9 -1
View File
@@ -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);
+1
View File
@@ -141,6 +141,7 @@ class SoundLibrary extends React.PureComponent {
return (
<LibraryComponent
showPlayButton
data={soundLibraryThumbnailData}
id="soundLibrary"
tags={soundTags}