More of a spotify-esque design

This commit is contained in:
James Barnsley
2017-02-07 20:07:04 +13:00
parent 48ccb69690
commit 20e6d903c6
9 changed files with 132 additions and 250 deletions

View File

@ -31,7 +31,7 @@ class FollowButton extends React.Component{
render(){
if( !this.props.spotify_authorized || !this.props.uri ) return false
var className = 'tertiary'
var className = ''
if (this.props.className) className += ' '+this.props.className
if( this.props.is_following === true ){

View File

@ -97,37 +97,36 @@ class Album extends React.Component{
return (
<div className="view album-view">
<SidebarToggleButton />
<div className="intro">
<Thumbnail size="large" canZoom images={ this.props.album.images } />
<ArtistGrid artists={artists} />
<div className="actions">
<button className="large primary" onClick={ e => this.play() }>Play</button>
{ helpers.uriSource(this.props.params.uri) == 'spotify' ? <FollowButton uri={this.props.params.uri} addText="Add to library" removeText="Remove from library" is_following={this.props.album.is_following} /> : null }
<Thumbnail size="large" canZoom images={ this.props.album.images } />
<div className="title">
<div className="source grey-text">
<FontAwesome name={helpers.sourceIcon( this.props.params.uri )} /> {helpers.uriSource( this.props.params.uri )} album
</div>
<h1>{ this.props.album.name }</h1>
<ul className="details">
{ artists.length > 0 ? <li><ArtistSentence artists={artists} /></li> : null }
{ this.props.album.release_date ? <li><Dater type="date" data={ this.props.album.release_date } /></li> : null }
<li>
{ this.props.album.tracks_total } tracks,&nbsp;
{ this.props.album.tracks ? <Dater type="total-time" data={this.props.album.tracks} /> : null }
{ this.props.album.tracks_total ? this.props.album.tracks_total : '0' } tracks,&nbsp;
{ this.props.album.tracks ? <Dater type="total-time" data={this.props.album.tracks} /> : '0 mins' }
</li>
{ this.props.album.release_date ? <li>Released <Dater type="date" data={ this.props.album.release_date } /></li> : null }
<li><FontAwesome name={helpers.sourceIcon( this.props.params.uri )} /> {helpers.uriSource( this.props.params.uri )} playlist</li>
</ul>
</div>
<div className="main">
<div className="title">
<h1>{ this.props.album.name }</h1>
<h3><ArtistSentence artists={artists} /></h3>
</div>
<section className="list-wrapper">
{ this.props.album.tracks ? <TrackList tracks={ this.props.album.tracks } /> : null }
<LazyLoadListener enabled={this.props.album.tracks_more} loadMore={ () => this.loadMore() }/>
</section>
<div className="actions">
<button className="rounded primary" onClick={e => this.play()}>Play</button>
{ helpers.uriSource(this.props.params.uri) == 'spotify' ? <FollowButton className="outline rounded" uri={this.props.params.uri} addText="Add to library" removeText="Remove from library" is_following={this.props.album.is_following} /> : null }
</div>
<section className="list-wrapper">
{ this.props.album.tracks ? <TrackList tracks={ this.props.album.tracks } /> : null }
<LazyLoadListener enabled={this.props.album.tracks_more} loadMore={ () => this.loadMore() }/>
</section>
</div>
);
}

View File

@ -47,7 +47,7 @@ class Artist extends React.Component{
}
componentWillUpdate( nextProps, nextState ){
if( nextState.sub_view != this.state.sub_view && nextState.sub_view == 'biography' ){
if( nextState.sub_view != this.state.sub_view && nextState.sub_view == 'about' ){
if( this.props.artist && !this.props.artist.bio ){
this.props.lastfmActions.getArtist( this.props.params.uri, this.props.artist.name.replace('&','and') )
}
@ -91,8 +91,8 @@ class Artist extends React.Component{
Overview
</span>
{this.props.artist.related_artists_uris ? <span className={'option '+( this.state.sub_view == 'related_artists' ? 'active' : null)} onClick={() => this.setState({ sub_view: 'related_artists' })}>Related artists</span> : null}
<span className={'option '+( this.state.sub_view == 'biography' ? 'active' : null)} onClick={() => this.setState({ sub_view: 'biography' })}>
Biography
<span className={'option '+( this.state.sub_view == 'about' ? 'active' : null)} onClick={() => this.setState({ sub_view: 'about' })}>
About
</span>
</div>
)
@ -130,9 +130,9 @@ class Artist extends React.Component{
</section>
</div>
)
}else if( this.state.sub_view == 'biography' ){
}else if( this.state.sub_view == 'about' ){
return (
<div className="body biography">
<div className="body about">
<h4 className="left-padding">Biography</h4>
<ul className="details">
@ -195,8 +195,8 @@ class Artist extends React.Component{
<div className="liner">
<h1>{ this.props.artist.name }</h1>
<div className="actions">
<button className="primary rounded" onClick={e => this.props.pusherActions.startRadio([this.props.artist.uri])}>Start radio</button>
{ scheme == 'spotify' ? <FollowButton className="rounded" uri={this.props.params.uri} removeText="Unfollow" addText="Follow" is_following={this.props.artist.is_following} /> : null }
{ scheme == 'spotify' ? <button className="primary rounded" onClick={e => this.props.pusherActions.startRadio([this.props.artist.uri])}>Start radio</button> : null }
{ scheme == 'spotify' ? <FollowButton className="outline rounded white" uri={this.props.params.uri} removeText="Unfollow" addText="Follow" is_following={this.props.artist.is_following} /> : null }
</div>
{ this.renderSubViewMenu() }
</div>

View File

@ -95,8 +95,8 @@ class Playlist extends React.Component{
case 'm3u':
return (
<span>
<button className="large tertiary" onClick={ e => this.props.uiActions.openModal('edit_playlist', { uri: this.props.playlist.uri, name: this.props.playlist.name }) }>Edit</button>
<ConfirmationButton className="large tertiary" content="Delete" confirmingContent="Are you sure?" onConfirm={ e => this.delete() } />
<button className="rounded outline" onClick={ e => this.props.uiActions.openModal('edit_playlist', { uri: this.props.playlist.uri, name: this.props.playlist.name }) }>Edit</button>
<ConfirmationButton className="rounded destructive" content="Delete" confirmingContent="Are you sure?" onConfirm={ e => this.delete() } />
</span>
)
@ -104,12 +104,12 @@ class Playlist extends React.Component{
if( this.props.playlist.can_edit ){
return (
<span>
<button className="large tertiary" onClick={ e => this.props.uiActions.openModal('edit_playlist', { uri: this.props.playlist.uri, name: this.props.playlist.name, is_public: this.props.playlist.public }) }>Edit</button>
<ConfirmationButton className="large tertiary" content="Delete" confirmingContent="Are you sure?" onConfirm={ e => this.unfollow() } />
<button className="outline rounded" onClick={ e => this.props.uiActions.openModal('edit_playlist', { uri: this.props.playlist.uri, name: this.props.playlist.name, is_public: this.props.playlist.public }) }>Edit</button>
<ConfirmationButton className="rounded destructive" content="Delete" confirmingContent="Are you sure?" onConfirm={ e => this.unfollow() } />
</span>
)
}
return <FollowButton uri={this.props.playlist.uri} addText="Add to library" removeText="Remove from library" is_following={this.props.playlist.is_following} />
return <FollowButton className="rounded outline" uri={this.props.playlist.uri} addText="Add to library" removeText="Remove from library" is_following={this.props.playlist.is_following} />
}
}
@ -126,41 +126,38 @@ class Playlist extends React.Component{
<SidebarToggleButton />
<div className="intro">
<Thumbnail size="large" canZoom images={ this.props.playlist.images } />
<Thumbnail size="large" canZoom images={ this.props.playlist.images } />
<div className="actions">
<button className="large primary" onClick={ e => this.play() }>Play</button>
{ this.renderExtraButtons() }
<div className="title">
<div className="source grey-text">
<FontAwesome name={helpers.sourceIcon( this.props.params.uri )} /> {helpers.uriSource( this.props.params.uri )} playlist
</div>
<h1>{ this.props.playlist.name }</h1>
{ this.props.playlist.description ? <div className="description grey-text" dangerouslySetInnerHTML={{__html: this.props.playlist.description}}></div> : null }
<ul className="details">
<li>
{ this.props.playlist.tracks_total } tracks,&nbsp;
{ this.props.playlist.tracks ? <Dater type="total-time" data={this.props.playlist.tracks} /> : null }
</li>
{ this.props.playlist.last_modified ? <li>Updated <Dater type="ago" data={this.props.playlist.last_modified} /> ago</li> : null }
{ this.props.playlist.owner ? <li><Link to={'/user/'+this.props.playlist.owner.uri}>{this.props.playlist.owner.id}</Link></li> : null }
{ this.props.playlist.followers ? <li>{this.props.playlist.followers.total.toLocaleString()} followers</li> : null }
{ scheme == 'spotify' && this.props.playlist.owner ? <li>By <Link to={'/user/'+this.props.playlist.owner.uri}>{this.props.playlist.owner.id}</Link> &nbsp;{ !this.props.playlist.public ? <FontAwesome name="lock" /> : null }</li> : null }
{ scheme == 'spotify' ? <li><FontAwesome name="spotify" /> Spotify playlist</li> : null }
{ scheme == 'm3u' ? <li><FontAwesome name="folder" /> Local playlist</li> : null }
{ this.props.playlist.last_modified ? <li><Dater type="ago" data={this.props.playlist.last_modified} /></li> : null }
<li>
{ this.props.playlist.tracks_total ? this.props.playlist.tracks_total : '0'} tracks,&nbsp;
{ this.props.playlist.tracks ? <Dater type="total-time" data={this.props.playlist.tracks} /> : '0 mins' }
</li>
</ul>
</div>
<div className="main">
<div className="title">
<h1>{ this.props.playlist.name }</h1>
{ this.props.playlist.description ? <h3 className="grey-text" dangerouslySetInnerHTML={{__html: this.props.playlist.description}}></h3> : null }
</div>
<section className="list-wrapper">
{ this.props.playlist.tracks ? <TrackList tracklist_uri={this.props.params.uri} context={context} tracks={this.props.playlist.tracks} removeTracks={ tracks_indexes => this.removeTracks(tracks_indexes) } reorderTracks={ (indexes, index) => this.reorderTracks(indexes, index) } /> : null }
<LazyLoadListener enabled={this.props.playlist.tracks_more} loadMore={ () => this.loadMore() }/>
</section>
<div className="actions">
<button className="rounded primary" onClick={ e => this.play() }>Play</button>
{ this.renderExtraButtons() }
</div>
<section className="list-wrapper">
{ this.props.playlist.tracks ? <TrackList tracklist_uri={this.props.params.uri} context={context} tracks={this.props.playlist.tracks} removeTracks={ tracks_indexes => this.removeTracks(tracks_indexes) } reorderTracks={ (indexes, index) => this.reorderTracks(indexes, index) } /> : null }
<LazyLoadListener enabled={this.props.playlist.tracks_more} loadMore={ () => this.loadMore() }/>
</section>
</div>
)
}

View File

@ -181,10 +181,20 @@ footer {
.details {
list-style-type: none;
color: $mid_grey;
text-transform: uppercase;
li {
padding-bottom: 4px;
display: inline-block;
&:not(:first-child){
padding-left: 14px;
&::before {
display: inline-block;
content: '•';
margin-left: -8px;
padding-right: 6px;
}
}
}
}

View File

@ -62,6 +62,29 @@ input[type="submit"] {
border-radius: 20px;
}
&.outline {
color: #FFFFFF;
padding: 9px 19px;
border: 1px solid $darkest_grey;
background: transparent;
color: $darkest_grey;
&.white {
border-color: #FFFFFF;
color: #FFFFFF;
background: rgba(0,0,0,0.2);
&:hover {
background: rgba(0,0,0,0.4);
border-color: inherit;
}
}
&:hover {
border-color: $turquoise;
}
}
&.primary {
background: $turquoise;
color: #FFFFFF;

View File

@ -1,105 +1,29 @@
.album-view {
.main {
padding-left: 300px;
.title {
padding: 30px 40px;
.title {
padding: 30px 40px;
h3 {
color: $mid_grey;
a:hover {
color: darken($mid_grey, 20%);
}
h3 {
color: $mid_grey;
a:hover {
color: darken($mid_grey, 20%);
}
}
}
.intro {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 300px;
background: $faint_grey;
.thumbnail {
float: none;
margin: 0 auto;
max-width: none;
}
.details {
padding: 30px;
}
.artist-grid {
padding: 0;
margin: 0;
.grid-item {
margin: 0;
width: 50%;
position: relative;
background: #000000;
.name {
@include animate();
position: absolute;
top: 40%;
left: 0;
right: 0;
text-align: center;
color: #FFFFFF;
opacity: 0;
z-index: 2;
font-weight: bold;;
font-size: 14px;
}
.secondary {
display: none;
}
&:hover {
.thumbnail {
opacity: 0.3;
}
.name {
opacity: 1;
}
}
}
}
.source {
text-transform: uppercase;
padding-bottom: 15px;
}
@include responsive( $bp_medium ){
.actions {
@include clearfix();
}
.main {
padding-left: 0;
.title {
padding: 20px;
}
}
.intro {
position: static;
width: auto;
.artist-grid {
display: none;
}
.details {
padding: 20px;
li {
display: inline-block;
padding-right: 15px;
}
}
}
.thumbnail {
float: left;
max-width: 230px;
margin: 0 30px 30px 0;
}
}

View File

@ -18,7 +18,7 @@
.liner {
position: relative;
z-index: 1;
padding: 15vh 40px 20px 40px;
padding: 20vh 40px 0 40px;
h1 {
color: #FFFFFF;
@ -26,21 +26,20 @@
}
.actions {
.button {
margin-right: 30px;
padding-bottom: 15px;
button {
margin-right: 20px;
}
}
.sub-views {
color: #FFFFFF;
position: absolute;
bottom: 0;
right: 30px;
.option {
display: inline-block;
padding: 8px 0;
margin: 0 10px;
margin: 0 25px 0 0;
font-size: 18px;
font-weight: 400;
border-bottom: 4px solid transparent;

View File

@ -1,103 +1,33 @@
.playlist-view {
.main {
padding-left: 300px;
.title {
padding: 30px 40px;
.title {
padding: 30px 40px;
h3 {
color: $mid_grey;
a:hover {
color: darken($mid_grey, 20%);
}
h3 {
color: $mid_grey;
a:hover {
color: darken($mid_grey, 20%);
}
}
}
.intro {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 300px;
background: $faint_grey;
> .thumbnail {
float: none;
margin: 0 auto;
max-width: none;
}
.details {
padding: 30px;
}
.artist-grid {
padding: 0;
margin: 0;
.grid-item {
margin: 0;
width: 50%;
position: relative;
.thumbnail .image {
background-color: $secondary_grey;
}
.name {
@include animate();
position: absolute;
top: 35%;
left: 0;
right: 0;
text-align: center;
color: #FFFFFF;
opacity: 0;
z-index: 2;
font-weight: bold;
}
.secondary {
display: none;
}
&:hover {
.name {
opacity: 1;
}
}
}
}
.owner {
padding: 30px;
}
.source {
text-transform: uppercase;
padding-bottom: 15px;
}
@include responsive( $bp_medium ){
.actions {
@include clearfix();
}
.main {
padding-left: 0px;
.description {
padding-bottom: 5px;
}
.title {
padding: 20px;
}
}
.intro {
width: auto;
position: static;
.details {
padding: 20px;
li {
display: inline-block;
padding-right: 15px;
}
}
}
.thumbnail {
float: left;
max-width: 230px;
margin: 0 30px 30px 0;
}
}