Skip to content

Commit

Permalink
feat: ✨ Re-implemented track adding modal
Browse files Browse the repository at this point in the history
It is now possible to add multiple tracks at once. The general UX was improved although the design
is still not great.

#73
  • Loading branch information
EricLambrecht committed Oct 25, 2019
1 parent 1e59b4e commit e9dedeb
Show file tree
Hide file tree
Showing 8 changed files with 331 additions and 74 deletions.
2 changes: 2 additions & 0 deletions src/assets/css/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

/* Colors */
--spotify-green: #1db954;
--spotify-green-light: #b4e6c7;
--spotify-black: #191414;

--color-default: #343030;
Expand All @@ -26,6 +27,7 @@
--font-size-playlist-name: 36px;
--font-size-choose-playlist: 40px;
--font-size-add-track-button: 18px;
--font-size-big-input: 18px;

/* Dimensions */
--grid-max-width: 1000px;
Expand Down
71 changes: 64 additions & 7 deletions src/components/_base/TextInput.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
<template>
<b-labeled-element :label="label">
<input
:type="type"
:value="value"
v-bind="attrs"
@input="$emit('input', $event.target.value)"
v-on="listeners"
/>
<div class="container">
<input
:type="type"
:value="value"
v-bind="attrs"
:class="{ hasIcon, big }"
@input="$emit('input', $event.target.value)"
v-on="listeners"
/>
<div v-if="hasIcon" :class="{ 'icon-container': true, big }">
<slot name="icon" class="icon" />
</div>
</div>
</b-labeled-element>
</template>

Expand All @@ -27,6 +33,14 @@ export default {
default: 'text',
validator: value => ['text', 'password'].indexOf(value) !== -1,
},
icon: {
type: String,
default: null,
},
big: {
type: Boolean,
default: false,
},
},
computed: {
attrs() {
Expand All @@ -37,16 +51,59 @@ export default {
const { input, ...listeners } = this.$listeners
return listeners
},
hasIcon() {
return Boolean(this.$slots.icon)
},
},
}
</script>

<style lang="scss" scoped>
.container {
width: 100%;
position: relative;
cursor: text;
}
input {
width: 100%;
font-family: var(--font-family);
color: var(--color-default-light);
border-radius: 3px;
border: 1px solid #ccc;
padding: 6px 10px 6px;
box-sizing: border-box;
cursor: text;
&.hasIcon {
padding-right: 30px;
}
&.big {
padding: 10px 16px 10px;
font-size: var(--font-size-big-input);
&.hasIcon {
padding-right: 50px;
}
}
}
.icon-container {
position: absolute;
right: 10px;
top: 0;
height: 100%;
display: flex;
align-items: center;
color: var(--color-default-light);
&.big {
right: 20px;
}
.icon {
height: 50%;
}
}
</style>
21 changes: 16 additions & 5 deletions src/components/editor/AddTrackModal.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
<template>
<b-modal headline="Add track" :show="show">
<track-search class="adder" @select="addTrack" />
<track-search class="adder" @select="updateTracks" />
<div slot="footer">
<b-button @click="$emit('close')">
Close
</b-button>
<b-button :disabled="!uris" primary @click="addTracks">
Add
</b-button>
</div>
</b-modal>
</template>
Expand All @@ -22,10 +25,18 @@ export default {
required: true,
},
},
data() {
return {
uris: [],
}
},
methods: {
...mapActions('editor', ['appendTrackToPlaylist']),
addTrack(uri) {
this.appendTrackToPlaylist(uri)
...mapActions('editor', ['appendTracksToPlaylist']),
updateTracks(uris) {
this.uris = uris
},
addTracks() {
this.appendTracksToPlaylist(this.uris)
this.$emit('close')
},
},
Expand All @@ -35,7 +46,7 @@ export default {
<style lang="scss" scoped>
.adder {
width: 600px;
height: 290px;
height: 405px;
}
@media screen and (max-width: 768px) {
Expand Down
135 changes: 135 additions & 0 deletions src/components/editor/SearchPlaylistItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<template>
<b-list-item class="playlist-item" tabindex="0">
<b-square-image :url="track.image" :size="36" class="image" />
<b-text class="time duration">
{{ track.duration_ms | formatTime('mm:ss') }}
</b-text>
<div class="artist-song-pair">
<b-text class="song">
{{ track.name }}
</b-text>
<b-text class="artist">
{{ track.artist }}
</b-text>
</div>
</b-list-item>
</template>

<script>
import formatTime from '../../utils/formatTime'
export default {
name: 'SearchPlaylistItem',
filters: {
formatTime(milliseconds, format = '') {
return formatTime(milliseconds, format)
},
},
props: {
track: {
type: Object,
required: true,
},
},
}
</script>

<style lang="scss">
:root {
--small-track-item-height: 36px;
--small-track-item-song-font-size: 12px;
--small-track-item-song-line-height: 15px;
--small-track-item-artist-font-size: 9px;
--small-track-item-artist-line-height: 13px;
}
@media screen and (max-width: 1080px) {
:root {
--small-track-item-height: 36px;
--small-track-item-song-font-size: 12px;
--small-track-item-song-line-height: 15px;
--small-track-item-artist-font-size: 9px;
--small-track-item-artist-line-height: 13px;
}
}
</style>

<style lang="scss" scoped>
.playlist-item {
display: flex;
align-items: center;
width: 100%;
height: var(--small-track-item-height);
padding: 0;
border-radius: 3px;
background-color: var(--color-default-opposite);
transition: background-color 0.1s ease;
font-size: var(--small-track-item-song-font-size);
&:not(:first-child) {
margin-top: 5px;
}
&:focus {
outline: none;
}
&:hover {
background-color: white;
box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.3);
cursor: pointer;
.track-menu {
opacity: 0; /* TODO: enable */
pointer-events: initial;
}
}
> * {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
pointer-events: none;
}
}
.image {
min-width: var(--small-track-item-height);
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.time {
color: var(--color-default);
min-width: 20px;
text-align: right;
margin-left: 14px;
}
.artist-song-pair {
display: flex;
flex-direction: column;
width: 200px;
margin-left: 14px;
.song {
font-size: var(--small-track-item-song-font-size);
line-height: var(--small-track-item-song-line-height);
color: var(--color-default);
overflow: hidden;
text-overflow: ellipsis;
}
.artist {
font-size: var(--small-track-item-artist-font-size);
line-height: var(--small-track-item-artist-line-height);
color: var(--color-grey);
overflow: hidden;
text-overflow: ellipsis;
}
}
</style>
1 change: 0 additions & 1 deletion src/components/editor/SelectPlaylistModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export default {
}),
},
methods: {
...mapActions('editor', ['appendTrackToPlaylist']),
...mapActions('app', ['closeModal']),
},
}
Expand Down
Loading

0 comments on commit e9dedeb

Please sign in to comment.