From 0bf319eaec0dd9f11e7749394584624b03c63043 Mon Sep 17 00:00:00 2001 From: Jenny Date: Wed, 9 Oct 2024 09:58:58 +0200 Subject: [PATCH 1/4] added album component etc --- package.json | 3 +- src/Album.jsx | 64 +++++++++++++++++++ src/App.jsx | 32 +++++++++- src/index.css | 165 +++++++++++++++++++++++++++++++++++++++++++++++++ style.css | 14 +++++ vite.config.js | 15 +++-- 6 files changed, 285 insertions(+), 8 deletions(-) create mode 100644 src/Album.jsx create mode 100644 style.css diff --git a/package.json b/package.json index a3bd4ec3..0cf6c080 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", - "vite": "^4.4.5" + "vite": "^4.4.5", + "vite-plugin-svgr": "^4.2.0" } } diff --git a/src/Album.jsx b/src/Album.jsx new file mode 100644 index 00000000..07ba5850 --- /dev/null +++ b/src/Album.jsx @@ -0,0 +1,64 @@ +// src/Album.jsx + +// This line imports React and useState, which we need to create our component and manage hover state +import React, { useState } from 'react'; + +// Importing our icon SVGs +import heartIcon from './assets/icons/heart.svg'; +import playIcon from './assets/icons/play.svg'; +import dotsIcon from './assets/icons/dots.svg'; + +// This is the Album component. It's like a template for each album card. +// It takes 'album' as a prop, which is all the information about one album. +const Album = ({ album }) => { + // This line creates a state to track whether the album is being hovered + const [isHovered, setIsHovered] = useState(false); + + return ( + // This is the main container for our album card + // We've added onMouseEnter and onMouseLeave to handle hover state +
setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + > + {/* This is a container for our album image and the overlay with icons */} +
+ {/* This shows the album cover image */} + {album.name} + {/* If the album is being hovered, we show the overlay with icons */} + {isHovered && ( +
+ Like + Play + More +
+ )} +
+ {/* This shows the album name */} +

+ + {album.name} + +

+ {/* This shows all the artists, joined by commas */} +

+ {album.artists.map((artist, index) => ( + + {index > 0 && ", "} + + {artist.name} + + + ))} +

+
+ ); +}; + +// This line makes our Album component available to use in other files +export default Album; \ No newline at end of file diff --git a/src/App.jsx b/src/App.jsx index a13f8faf..6fc8414d 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,7 +1,35 @@ +// src/App.jsx + +// Importing React to create our component +import React from 'react'; + +// This imports all the Spotify data from the JSON file import data from "./data.json"; -console.log(data); +// This imports the Album component +import Album from './Album'; +//This is the main App compontent export const App = () => { - return
Find me in src/app.jsx!
; + return ( + // This is the main container for the whole app +
+
+

New Releases

+
+ {/* This div contains all album cards */} +
+ {/* Breakdown of this line: + 1. data.albums.items is an array of albums + 2. .map() goes through each album one by one + 3. For each album, an Album component is created + 4. Each Album component is given a unique 'key' + all the album data */} + {data.albums.items.map((album) => ( + + ))} +
+
+ ); }; + + diff --git a/src/index.css b/src/index.css index 4558f538..8513144b 100644 --- a/src/index.css +++ b/src/index.css @@ -5,9 +5,174 @@ sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + background-color: #010101; + color: white; } code { font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } + +.title-container { + max-width: 1400px; + margin: 0 auto; +} + +.album-grid { + display: grid; + grid-template-columns: repeat(1, 1fr); + max-width: 1400px; + margin: 0 auto; + gap: 20px; + padding: 15px; +} + +.album-card { + background-color: #000000; + padding: 13px; + border-radius: 8px; + position: relative; + transition: all 0.3s ease; +} + +.image-container { + position: relative; + overflow: hidden; +} + +.album-image { + width: 100%; + height: auto; + display: block; + transition: all 0.3s ease; +} + +/* Overlay styles for hover effect */ +.overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + opacity: 0; + transition: opacity 0.3s ease; +} + +.album-card:hover .overlay { + opacity: 1; +} + +/* Icon styles */ +.icon { + width: 46px; + height: 46px; + margin: 0 25px; + cursor: pointer; + filter: brightness(0) invert(1); +} + +.play-icon { + width: 80px; + height: 80px; + position: static; + transition: transform 0.2s ease; +} + +.play-icon:hover { + transform: scale(1.12); +} + +.heart-icon { + position: absolute; + left: 10px; + position: static; +} + +.dots-icon { + position: absolute; + right: 10px; + position: static; +} + +.icon-container { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + gap: 15px; +} + +/* Hover effect for album image */ +.album-card:hover .album-image { + transform: scale(1.03); +} + +/* Album title styles */ +.album-card h3 { + margin: 10px 0 5px; + font-size: 16px; + transition: all 0.3s ease; +} + +.album-card h3:hover { + text-decoration: underline; + cursor: pointer; +} + +a:link { + text-decoration: none; + color: white; +} +a:visited { + text-decoration: none; + color: white; +} +a:hover { + text-decoration: none; + color: white; +} +a:active { + text-decoration: none; + color: white; +} + +/* Artist name styles */ +.album-card p { + margin: 0; + font-size: 14px; + color: #a0a0a0; + transition: all 0.3s ease; +} + +.album-card p:hover { + text-decoration: underline; + cursor: pointer; +} + +h1 { + margin: 30px 5px 20px 30px; + font-size: 2rem; + +} + +@media (min-width: 667px) and (max-width: 1023px) { + .album-grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (min-width: 1024px) { + .album-grid { + grid-template-columns: repeat(4, 1fr); + } + + @media (min-width: 1400px) { + h1 { + margin: 30px 5px 20px 11px; + } +} \ No newline at end of file diff --git a/style.css b/style.css new file mode 100644 index 00000000..4c4f57c6 --- /dev/null +++ b/style.css @@ -0,0 +1,14 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; + } \ No newline at end of file diff --git a/vite.config.js b/vite.config.js index 5a33944a..955124b3 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,7 +1,12 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import svgr from 'vite-plugin-svgr'; -// https://vitejs.dev/config/ export default defineConfig({ - plugins: [react()], -}) + plugins: [react(), svgr()], + resolve: { + alias: { + '@': '/src', + }, + }, +}); \ No newline at end of file From 7e30957aba04268732b34f9fb3b0169844e8e7f2 Mon Sep 17 00:00:00 2001 From: Jenny Date: Thu, 10 Oct 2024 16:54:42 +0200 Subject: [PATCH 2/4] updates to components and css --- src/Album.jsx | 64 ----------------------------------- src/App.jsx | 2 +- src/components/Album.jsx | 21 ++++++++++++ src/components/AlbumCover.jsx | 39 +++++++++++++++++++++ src/components/AlbumName.jsx | 13 +++++++ src/components/ArtistName.jsx | 20 +++++++++++ src/index.css | 63 +++++++++++++++------------------- src/main.jsx | 2 ++ 8 files changed, 123 insertions(+), 101 deletions(-) delete mode 100644 src/Album.jsx create mode 100644 src/components/Album.jsx create mode 100644 src/components/AlbumCover.jsx create mode 100644 src/components/AlbumName.jsx create mode 100644 src/components/ArtistName.jsx diff --git a/src/Album.jsx b/src/Album.jsx deleted file mode 100644 index 07ba5850..00000000 --- a/src/Album.jsx +++ /dev/null @@ -1,64 +0,0 @@ -// src/Album.jsx - -// This line imports React and useState, which we need to create our component and manage hover state -import React, { useState } from 'react'; - -// Importing our icon SVGs -import heartIcon from './assets/icons/heart.svg'; -import playIcon from './assets/icons/play.svg'; -import dotsIcon from './assets/icons/dots.svg'; - -// This is the Album component. It's like a template for each album card. -// It takes 'album' as a prop, which is all the information about one album. -const Album = ({ album }) => { - // This line creates a state to track whether the album is being hovered - const [isHovered, setIsHovered] = useState(false); - - return ( - // This is the main container for our album card - // We've added onMouseEnter and onMouseLeave to handle hover state -
setIsHovered(true)} - onMouseLeave={() => setIsHovered(false)} - > - {/* This is a container for our album image and the overlay with icons */} -
- {/* This shows the album cover image */} - {album.name} - {/* If the album is being hovered, we show the overlay with icons */} - {isHovered && ( -
- Like - Play - More -
- )} -
- {/* This shows the album name */} -

- - {album.name} - -

- {/* This shows all the artists, joined by commas */} -

- {album.artists.map((artist, index) => ( - - {index > 0 && ", "} - - {artist.name} - - - ))} -

-
- ); -}; - -// This line makes our Album component available to use in other files -export default Album; \ No newline at end of file diff --git a/src/App.jsx b/src/App.jsx index 6fc8414d..7c75e306 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -7,7 +7,7 @@ import React from 'react'; import data from "./data.json"; // This imports the Album component -import Album from './Album'; +import { Album } from './components/Album'; //This is the main App compontent export const App = () => { diff --git a/src/components/Album.jsx b/src/components/Album.jsx new file mode 100644 index 00000000..d0e13ced --- /dev/null +++ b/src/components/Album.jsx @@ -0,0 +1,21 @@ +// src/components/Album.jsx + +// This line imports React and useState, which we need to create our component and manage hover state +import React, { useState } from 'react'; +import { AlbumCover } from './AlbumCover'; +import { AlbumName } from './AlbumName'; +import { ArtistName } from './ArtistName'; + +// This is the Album component. It's like a template for each album card. +// It takes 'album' as a prop, which is all the information about one album. +export const Album = ({ album }) => { + + return ( + // This is the main container for our album card +
+ + + +
+ ); +}; diff --git a/src/components/AlbumCover.jsx b/src/components/AlbumCover.jsx new file mode 100644 index 00000000..48daefb7 --- /dev/null +++ b/src/components/AlbumCover.jsx @@ -0,0 +1,39 @@ +// src/components/AlbumCover.jsx + +import React, { useState } from 'react'; +// Importing our icon SVGs +import heartIcon from '../assets/icons/heart.svg'; +import playIcon from '../assets/icons/play.svg'; +import dotsIcon from '../assets/icons/dots.svg'; + +export const AlbumCover = ({ album }) => { + + // This line creates a state to track whether the album is being hovered + const [isHovered, setIsHovered] = useState(false); + + + return ( +
setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + > + {/* This is a container for our album image and the overlay with icons */} +
+ + {/* This shows the album cover image */} + {album.name} + + {/* If the album is being hovered, we show the overlay with icons */} + {isHovered && ( +
+ Like + Play + More +
+ )} +
+
+ ) +} \ No newline at end of file diff --git a/src/components/AlbumName.jsx b/src/components/AlbumName.jsx new file mode 100644 index 00000000..126d29bc --- /dev/null +++ b/src/components/AlbumName.jsx @@ -0,0 +1,13 @@ +// src/components/AlbumName.jsx + +export const AlbumName = ({ album }) => { + return ( +

+ + {album.name} + +

+ ); +} \ No newline at end of file diff --git a/src/components/ArtistName.jsx b/src/components/ArtistName.jsx new file mode 100644 index 00000000..8df365b8 --- /dev/null +++ b/src/components/ArtistName.jsx @@ -0,0 +1,20 @@ +// src/components/AlbumName.jsx +import React from 'react'; + +export const ArtistName = ({ album }) => { + return ( +

+ {album.artists.map((artist, index) => ( + + {index > 0 && ", "} + + {artist.name} + + + ))} +

+ ); +} + diff --git a/src/index.css b/src/index.css index 8513144b..e0c06bf7 100644 --- a/src/index.css +++ b/src/index.css @@ -1,17 +1,9 @@ -:root { +/* src/index.css */ + +html { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + font-family: Helvetica; background-color: #010101; - color: white; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; } .title-container { @@ -115,49 +107,47 @@ code { /* Album title styles */ .album-card h3 { margin: 10px 0 5px; - font-size: 16px; + font-size: 14px; transition: all 0.3s ease; } -.album-card h3:hover { - text-decoration: underline; - cursor: pointer; -} - -a:link { - text-decoration: none; +.album-card h3 a { color: white; -} -a:visited { text-decoration: none; - color: white; -} -a:hover { - text-decoration: none; - color: white; -} -a:active { - text-decoration: none; + transition: all 0.3s ease; +} + +.album-card h3 a:hover, +.album-card h3 a:visited, +.album-card h3 a:active { color: white; + text-decoration: underline; } /* Artist name styles */ .album-card p { margin: 0; font-size: 14px; + transition: all 0.3s ease; +} + +.album-card p a { color: #a0a0a0; + text-decoration: none; transition: all 0.3s ease; } -.album-card p:hover { +.album-card p a:hover, +.album-card p a:visited, +.album-card p a:active { + color: #a0a0a0; text-decoration: underline; - cursor: pointer; } h1 { margin: 30px 5px 20px 30px; font-size: 2rem; - + color: #ffffff; } @media (min-width: 667px) and (max-width: 1023px) { @@ -170,9 +160,10 @@ h1 { .album-grid { grid-template-columns: repeat(4, 1fr); } +} - @media (min-width: 1400px) { - h1 { - margin: 30px 5px 20px 11px; +@media (min-width: 1400px) { + h1 { + margin: 30px 5px 20px 11px; } } \ No newline at end of file diff --git a/src/main.jsx b/src/main.jsx index 51294f39..8072be03 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -1,3 +1,5 @@ +// src/main.jsx + import React from "react"; import ReactDOM from "react-dom/client"; import { App } from "./App.jsx"; From 84faba632643378f5a3009240b79bd52ab8672d4 Mon Sep 17 00:00:00 2001 From: Jenny Date: Sun, 13 Oct 2024 21:01:30 +0200 Subject: [PATCH 3/4] final changes to comments --- README.md | 31 ++----------------------------- src/components/Album.jsx | 3 --- src/components/AlbumCover.jsx | 2 +- src/components/AlbumName.jsx | 6 ++++-- src/components/ArtistName.jsx | 15 ++++++++++++--- 5 files changed, 19 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 38807b33..f6c383eb 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,10 @@ -

- - Project Banner Image - -

# Music Releases -Replace this readme with your own information about your project. +A project to practice React and creating components that will use data from Spotify, which will then transfer to its children's components using props. -Start by briefly describing the assignment in a sentence or two. Keep it short and to the point. - -## Getting Started with the Project - -### Dependency Installation & Startup Development Server - -Once cloned, navigate to the project's root directory and this project uses npm (Node Package Manager) to manage its dependencies. - -The command below is a combination of installing dependencies, opening up the project on VS Code and it will run a development server on your terminal. - -```bash -npm i && code . && npm run dev -``` - -### The Problem - -Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next? +The project was to build a page that shows new albums and single releases. ### View it live Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about. - -## Instructions - - - See instructions of this project - diff --git a/src/components/Album.jsx b/src/components/Album.jsx index d0e13ced..3aa6a782 100644 --- a/src/components/Album.jsx +++ b/src/components/Album.jsx @@ -1,13 +1,10 @@ // src/components/Album.jsx -// This line imports React and useState, which we need to create our component and manage hover state import React, { useState } from 'react'; import { AlbumCover } from './AlbumCover'; import { AlbumName } from './AlbumName'; import { ArtistName } from './ArtistName'; -// This is the Album component. It's like a template for each album card. -// It takes 'album' as a prop, which is all the information about one album. export const Album = ({ album }) => { return ( diff --git a/src/components/AlbumCover.jsx b/src/components/AlbumCover.jsx index 48daefb7..8618a142 100644 --- a/src/components/AlbumCover.jsx +++ b/src/components/AlbumCover.jsx @@ -15,7 +15,7 @@ export const AlbumCover = ({ album }) => { return (
setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > diff --git a/src/components/AlbumName.jsx b/src/components/AlbumName.jsx index 126d29bc..9aa69fb2 100644 --- a/src/components/AlbumName.jsx +++ b/src/components/AlbumName.jsx @@ -3,9 +3,11 @@ export const AlbumName = ({ album }) => { return (

+ {/* Create a link to the album Spotify page */} + target="_blank"> + + {/* This displays the album name */} {album.name}

diff --git a/src/components/ArtistName.jsx b/src/components/ArtistName.jsx index 8df365b8..a096946f 100644 --- a/src/components/ArtistName.jsx +++ b/src/components/ArtistName.jsx @@ -1,15 +1,24 @@ -// src/components/AlbumName.jsx +// src/components/Artistame.jsx + import React from 'react'; export const ArtistName = ({ album }) => { return (

+ {/* Map to iterate over each artist in the album's artists array */} {album.artists.map((artist, index) => ( + + {/* If this isn't the first artist, add a comma and space before the name */} {index > 0 && ", "} + + {/* Create a link to the artist's Spotify page */} + + // target="_blank" opens the link in a new tab or window + target="_blank"> + + {/* This displays the artist name */} {artist.name} From 4886eb577fa8bd7629c61edb192a92257560c20b Mon Sep 17 00:00:00 2001 From: Jenny Date: Sun, 13 Oct 2024 21:04:43 +0200 Subject: [PATCH 4/4] updated link in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f6c383eb..35cb1431 100644 --- a/README.md +++ b/README.md @@ -7,4 +7,4 @@ The project was to build a page that shows new albums and single releases. ### View it live -Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about. +https://new-music-app-jenny.netlify.app/ \ No newline at end of file