diff --git a/music-player/client/src/components/NowPlaying.ts b/music-player/client/src/components/NowPlaying.ts
new file mode 100644
index 0000000..e256a2f
--- /dev/null
+++ b/music-player/client/src/components/NowPlaying.ts
@@ -0,0 +1,79 @@
+import { TextField } from "./TextField";
+
+export class NowPlaying extends HTMLElement {
+ nameContainer: TextField;
+ albumContainer: TextField;
+ artistContainer: TextField;
+
+ static get observedAttributes() {
+ return ["name", "album", "artist"];
+ }
+
+ constructor() {
+ super();
+
+ this.nameContainer = document.createElement("text-field");
+ this.nameContainer.classList.add("now-playing__name");
+
+ this.albumContainer = document.createElement("text-field");
+ this.albumContainer.classList.add("now-playing__album");
+
+ this.artistContainer = document.createElement("text-field");
+ this.artistContainer.classList.add("now-playing__artist");
+ }
+
+ get name(): string | null {
+ return this.getAttribute("name");
+ }
+
+ set name(name: string | null) {
+ if (name) {
+ this.setAttribute("name", name);
+ this.nameContainer.text = name;
+ } else {
+ this.removeAttribute("open");
+ this.nameContainer.text = null;
+ }
+ }
+
+ get artist(): string | null {
+ return this.getAttribute("artist");
+ }
+
+ set artist(artist: string | null) {
+ if (artist) {
+ this.setAttribute("artist", artist);
+ this.artistContainer.text = artist;
+ } else {
+ this.removeAttribute("open");
+ this.artistContainer.text = null;
+ }
+ }
+
+ get album(): string | null {
+ return this.getAttribute("album");
+ }
+
+ set album(album: string | null) {
+ if (album) {
+ this.setAttribute("album", album);
+ this.albumContainer.text = album;
+ } else {
+ this.removeAttribute("open");
+ this.albumContainer.text = null;
+ }
+ }
+
+ connectedCallback() {
+ const container = document.createElement("data-card");
+ container.classList.add("card");
+ container.classList.add("card--recessed");
+ container.classList.add("now-playing");
+
+ container.appendChild(this.nameContainer);
+ container.appendChild(this.albumContainer);
+ container.appendChild(this.artistContainer);
+
+ this.appendChild(container);
+ }
+}
diff --git a/music-player/client/src/components/TrackCard.ts b/music-player/client/src/components/TrackCard.ts
index f060305..241a9ce 100644
--- a/music-player/client/src/components/TrackCard.ts
+++ b/music-player/client/src/components/TrackCard.ts
@@ -1,5 +1,4 @@
import { TextField } from "./TextField";
-import { DataCard } from "./DataCard";
export class TrackCard extends HTMLElement {
trackNumberContainer: TextField;
diff --git a/music-player/client/src/main.ts b/music-player/client/src/main.ts
index ec8a90d..2b6b2a3 100644
--- a/music-player/client/src/main.ts
+++ b/music-player/client/src/main.ts
@@ -1,16 +1,19 @@
import * as _ from "lodash";
import { TrackInfo, getTracks } from "./client";
import { DataCard } from "./components/DataCard";
+import { NowPlaying } from "./components/NowPlaying";
import { TextField } from "./components/TextField";
import { TrackCard } from "./components/TrackCard";
window.customElements.define("data-card", DataCard);
+window.customElements.define("now-playing", NowPlaying);
window.customElements.define("text-field", TextField);
window.customElements.define("track-card", TrackCard);
declare global {
interface HTMLElementTagNameMap {
"data-card": DataCard;
+ "now-playing": NowPlaying;
"text-field": TextField;
"track-card": TrackCard;
}
@@ -38,7 +41,24 @@ const updateTrackList = (tracks: TrackInfo[]) => {
}
};
+const updateNowPlaying = (track: TrackInfo) => {
+ const track_list = document.querySelector("#now-playing");
+ if (track_list) {
+ let card: NowPlaying = document.createElement("now-playing");
+ card.name = track.name || null;
+ card.album = track.album || null;
+ card.artist = track.artist || null;
+ track_list.appendChild(card);
+ }
+};
+
const run = () => {
+ updateNowPlaying({
+ id: "example id",
+ name: "Underground",
+ album: "Artemis",
+ artist: "Lindsey Stirling",
+ });
getTracks().then((tracks) => updateTrackList(tracks));
};
diff --git a/music-player/client/styles.css b/music-player/client/styles.css
deleted file mode 100644
index 10f8ca3..0000000
--- a/music-player/client/styles.css
+++ /dev/null
@@ -1,68 +0,0 @@
-body {
- background-color: rgb(240, 230, 230);
-}
-
-.currently-playing {
- padding: 8px;
-}
-
-.controls {
- padding: 8px;
-}
-
-.track-list {
- border: 1px solid black;
- display: flex;
-}
-
-.track-list__grouping {
- padding: 8px;
- border-style: solid;
- border-width: 0px 5px 0px 0px;
-}
-
-.bulletless-list {
- list-style: none;
-}
-
-.track-list__row {
- margin-top: 32px;
-}
-
-.card {
- border: 1px solid black;
- border-radius: 5px;
- padding: 8px;
- width: 300px;
- height: 100px;
-}
-
-.track-card {
- display: grid;
- gap: 4px 4px;
-}
-
-.track-card__name {
- display: block;
- grid-column: 1 / span 1;
- grid-row: 1 / span 1;
-}
-
-.track-card__length {
- display: block;
- grid-column: 1 / span 1;
- grid-row: 2 / span 1;
-}
-
-.track-card__album {
- display: block;
- grid-column: 2 / span 1;
- grid-row: 1 / span 1;
-}
-
-.track-card__artist {
- display: block;
- grid-column: 2 / span 1;
- grid-row: 2 / span 1;
-}
-
diff --git a/music-player/client/styles.scss b/music-player/client/styles.scss
new file mode 100644
index 0000000..a3d8f05
--- /dev/null
+++ b/music-player/client/styles.scss
@@ -0,0 +1,248 @@
+$color-grey-900: hsl(240 5% 20%);
+$color-grey-800: hsl(240 5% 25%);
+$color-grey-700: hsl(240 5% 35%);
+$color-grey-600: hsl(240 5% 45%);
+$color-grey-500: hsl(240 5% 50%);
+$color-grey-400: hsl(240 5% 60%);
+$color-grey-300: hsl(240 5% 75%);
+$color-grey-200: hsl(240 5% 90%);
+$color-grey-100: hsl(240 10% 95%);
+
+$color-blue-900: hsl(240 100% 10%);
+$color-blue-800: hsl(240 100% 20%);
+$color-blue-700: hsl(240 100% 30%);
+$color-blue-600: hsl(240 100% 40%);
+$color-blue-500: hsl(235 100% 50%);
+$color-blue-400: hsl(230 100% 60%);
+$color-blue-300: hsl(225 100% 70%);
+$color-blue-200: hsl(220 100% 75%);
+$color-blue-100: hsl(220 100% 80%);
+
+$color-purple-900: hsl(280 100% 10%);
+$color-purple-800: hsl(280 100% 20%);
+$color-purple-700: hsl(280 100% 30%);
+$color-purple-600: hsl(280 100% 40%);
+$color-purple-500: hsl(280 100% 50%);
+$color-purple-400: hsl(280 100% 60%);
+$color-purple-300: hsl(280 100% 70%);
+$color-purple-200: hsl(280 100% 80%);
+$color-purple-100: hsl(280 100% 90%);
+
+$color-red-900: hsl(20 100% 10%);
+$color-red-800: hsl(20 100% 10%);
+$color-red-700: hsl(20 100% 10%);
+$color-red-600: hsl(20 100% 10%);
+$color-red-500: hsl(20 100% 50%);
+$color-red-400: hsl(20 100% 90%);
+$color-red-300: hsl(20 100% 90%);
+$color-red-200: hsl(20 100% 90%);
+$color-red-100: hsl(20 100% 90%);
+
+$shadow-900: rgba(0, 0, 0, .20);
+$shadow-500: rgba(0, 0, 0, .15);
+$shadow-100: rgba(0, 0, 0, .1);
+
+$colors: [
+ (grey-900, $color-grey-900),
+ (grey-800, $color-grey-800),
+ (grey-700, $color-grey-700),
+ (grey-600, $color-grey-600),
+ (grey-500, $color-grey-500),
+ (grey-400, $color-grey-400),
+ (grey-300, $color-grey-300),
+ (grey-200, $color-grey-200),
+ (grey-100, $color-grey-100),
+
+ (blue-900, $color-blue-900),
+ (blue-800, $color-blue-800),
+ (blue-700, $color-blue-700),
+ (blue-600, $color-blue-600),
+ (blue-500, $color-blue-500),
+ (blue-400, $color-blue-400),
+ (blue-300, $color-blue-300),
+ (blue-200, $color-blue-200),
+ (blue-100, $color-blue-100),
+
+ (purple-900, $color-purple-900),
+ (purple-800, $color-purple-800),
+ (purple-700, $color-purple-700),
+ (purple-600, $color-purple-600),
+ (purple-500, $color-purple-500),
+ (purple-400, $color-purple-400),
+ (purple-300, $color-purple-300),
+ (purple-200, $color-purple-200),
+ (purple-100, $color-purple-100),
+
+ (red-900, $color-red-900),
+ (red-500, $color-red-500),
+ (red-100, $color-red-100),
+];
+
+@each $name, $value in $colors {
+ .swatch-#{$name} {
+ background-color: #{$value};
+ }
+}
+
+$border-color: $color-grey-600;
+$border-shadow: $color-grey-800;
+$background-color-light: $color-grey-100;
+$background-color-medium: $color-grey-200;
+$background-color-dark: $color-grey-300;
+$primary-color-light: $color-blue-100;
+$primary-color-medium: $color-blue-500;
+$primary-color-dark: $color-blue-700;
+$accent-color-light: $color-purple-100;
+$accent-color-medium: $color-purple-500;
+$accent-color-dark: $color-purple-700;
+
+$elevation-recessed: inset 1px 2px 3px $shadow-500, inset 0 1px 2px $shadow-900;
+$elevation-low: 1px 2px 3px $shadow-500, 0 1px 2px $shadow-900;
+$elevation-medium: 2px 6px 5px $shadow-500, 0 1px 2px $shadow-900;
+$elevation-high: 3px 8px 6px $shadow-900, 0 0px 3px $shadow-900;
+
+body {
+ background-color: $background-color-medium;
+}
+
+.colorset {
+ display: flex;
+ gap: 4px;
+ margin: 16px 0px 16px 0px;
+}
+
+.swatch {
+ border: 1px solid black;
+ border-radius: 5px;
+ width: 100px;
+ height: 50px;
+}
+
+.flex {
+ display: flex;
+ gap: 8px;
+ margin: 16px 0px 16px 0px;
+}
+
+.controls {
+ padding: 8px;
+}
+
+.track-list {
+ border: 1px solid black;
+ display: flex;
+}
+
+.track-list__grouping {
+ padding: 8px;
+ border-style: solid;
+ border-width: 0px 5px 0px 0px;
+}
+
+.bulletless-list {
+ list-style: none;
+}
+
+.track-list__row {
+ margin-top: 32px;
+}
+
+.card {
+ display: block;
+ border-radius: 5px;
+ padding: 8px;
+ width: 500px;
+ height: 100px;
+}
+
+.card--recessed {
+ border: 1px solid $border-color;
+ box-shadow: $elevation-recessed;
+}
+
+.card--low {
+ border: 1px solid $border-color;
+ box-shadow: $elevation-low;
+}
+
+.card--medium {
+ border: 1px solid $border-color;
+ box-shadow: $elevation-medium;
+}
+
+.card--high {
+ border: 1px solid $border-color;
+ box-shadow: $elevation-high;
+}
+
+.now-playing {
+ display: grid;
+ background-color: $background-color-light;
+}
+
+.now-playing__name {
+ display: block;
+ grid-column: 1 / span 1;
+ grid-row: 1 / span 1;
+ color: $accent-color-dark;
+}
+
+.now-playing__length {
+ display: block;
+ grid-column: 2 / span 1;
+ grid-row: 1 / span 1;
+ text-align: right;
+ color: $color-blue-300;
+}
+
+.now-playing__album {
+ display: block;
+ grid-column: 1 / span 1;
+ grid-row: 2 / span 1;
+ color: $color-grey-800;
+}
+
+.now-playing__artist {
+ display: block;
+ grid-column: 2 / span 1;
+ grid-row: 2 / span 1;
+ color: $color-grey-800;
+}
+
+.track-card {
+ display: grid;
+ gap: 4px 4px;
+ border: 1px solid $border-color;
+ background-color: $background-color-light;
+ box-shadow: $elevation-low;
+}
+
+.track-card__name {
+ display: block;
+ grid-column: 1 / span 1;
+ grid-row: 1 / span 1;
+ color: $primary-color-dark;
+}
+
+.track-card__length {
+ display: block;
+ grid-column: 2 / span 1;
+ grid-row: 1 / span 1;
+ text-align: right;
+ color: $primary-color-light;
+}
+
+.track-card__album {
+ display: block;
+ grid-column: 1 / span 1;
+ grid-row: 2 / span 1;
+ color: $color-grey-800;
+}
+
+.track-card__artist {
+ display: block;
+ grid-column: 2 / span 1;
+ grid-row: 2 / span 1;
+ color: $color-grey-800;
+}
+
diff --git a/music-player/client/webpack.config.js b/music-player/client/webpack.config.js
index d26d868..a7f44ed 100644
--- a/music-player/client/webpack.config.js
+++ b/music-player/client/webpack.config.js
@@ -3,7 +3,7 @@ const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
mode: 'development',
- entry: './src/main.ts',
+ entry: ['./src/main.ts', './styles.scss'],
module: {
rules: [
{
@@ -16,8 +16,8 @@ module.exports = {
type: 'asset/resource',
},
{
- test: /\.css$/i,
- use: ['style-loader', 'css-loader'],
+ test: /\.s[ac]ss$/i,
+ use: ['style-loader', 'css-loader', 'sass-loader'],
},
],
},
@@ -28,7 +28,8 @@ module.exports = {
new CopyPlugin({
patterns: [
{ from: "index.html", to: "index.html" },
- { from: "styles.css", to: "styles.css" },
+ { from: "design.html", to: "design.html" },
+ // { from: "styles.css", to: "styles.css" },
],
}),
],