From 5bcb9fd704335e514bd45075942f8619b5397caa Mon Sep 17 00:00:00 2001 From: hamdi Date: Mon, 18 Mar 2024 15:17:03 +0100 Subject: [PATCH 1/3] finnishing up --- .eslintrc.cjs | 46 +++++++++----- package.json | 3 +- src/App.jsx | 20 +++++- src/components/Album.jsx | 67 ++++++++++++++++++++ src/components/AlbumName.jsx | 19 ++++++ src/components/ArtistName.jsx | 18 ++++++ src/components/CoverImage.jsx | 7 +++ src/components/Header.jsx | 10 +++ src/components/Icon.jsx | 17 +++++ src/index.css | 114 ++++++++++++++++++++++++++++++++++ 10 files changed, 302 insertions(+), 19 deletions(-) create mode 100644 src/components/Album.jsx create mode 100644 src/components/AlbumName.jsx create mode 100644 src/components/ArtistName.jsx create mode 100644 src/components/CoverImage.jsx create mode 100644 src/components/Header.jsx create mode 100644 src/components/Icon.jsx diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 4dcb4390..80d96cbc 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,20 +1,32 @@ module.exports = { - root: true, - env: { browser: true, es2020: true }, - extends: [ - 'eslint:recommended', - 'plugin:react/recommended', - 'plugin:react/jsx-runtime', - 'plugin:react-hooks/recommended', - ], - ignorePatterns: ['dist', '.eslintrc.cjs'], - parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, - settings: { react: { version: '18.2' } }, - plugins: ['react-refresh'], - rules: { - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, + "env": { + "browser": true, + "es2021": true + }, + "extends": [ + "eslint:recommended", + "plugin:react/recommended" ], - }, + "overrides": [ + { + "env": { + "node": true + }, + "files": [ + ".eslintrc.{js,cjs}" + ], + "parserOptions": { + "sourceType": "script" + } + } + ], + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": [ + "react" + ], + "rules": { + } } diff --git a/package.json b/package.json index a3bd4ec3..86cdbbbf 100644 --- a/package.json +++ b/package.json @@ -14,11 +14,12 @@ "react-dom": "^18.2.0" }, "devDependencies": { + "@svgr/webpack": "^8.1.0", "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", "@vitejs/plugin-react": "^4.0.3", "eslint": "^8.45.0", - "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", "vite": "^4.4.5" diff --git a/src/App.jsx b/src/App.jsx index a13f8faf..7b549513 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,7 +1,25 @@ +/* eslint-disable react/react-in-jsx-scope */ +/* eslint-disable no-unreachable */ import data from "./data.json"; console.log(data); +import { Header } from "./components/Header"; +import Album from "./components/Album"; +import "./index.css"; + export const App = () => { - return
Find me in src/app.jsx!
; + const albumsData = data.albums.items; + console.log(albumsData); + + return ( + <> +
+
+ {albumsData.map((albumData) => ( + + ))} +
+ + ); }; diff --git a/src/components/Album.jsx b/src/components/Album.jsx new file mode 100644 index 00000000..17596461 --- /dev/null +++ b/src/components/Album.jsx @@ -0,0 +1,67 @@ +/* eslint-disable react/prop-types */ +import React, { useState } from "react"; +import AlbumName from "./AlbumName"; +import ArtistName from "./ArtistName"; +import CoverImage from "./CoverImage"; +//import { ReactComponent as PlayIcon } from "../assets/icons/play.svg"; +//import { ReactComponent as HeartIcon } from "../assets/icons/heart.svg"; +//import { ReactComponent as DotIcon } from "../assets/icons/dots.svg"; +import playIcon from "../assets/icons/play.svg"; +import heartIcon from "../assets/icons/heart.svg"; +import dotIcon from "../assets/icons/dots.svg"; + +const Album = ({ albumData }) => { + const [isHovered, setIsHovered] = useState(false); + + // Define event handlers for mouse enter and leave + const handleMouseEnter = () => { + setIsHovered(true); + }; + + const handleMouseLeave = () => { + setIsHovered(false); + }; + + return ( +
+
+
+ +
+
+ {isHovered && ( +
+ + + +
+ )} +
+
+ +
+
+ {albumData.artists.map((artist, index) => ( + + + {index < albumData.artists.length - 1 && ( +  & + )} + + ))} +
+
+
+ ); +}; + +export default Album; diff --git a/src/components/AlbumName.jsx b/src/components/AlbumName.jsx new file mode 100644 index 00000000..0effa8b5 --- /dev/null +++ b/src/components/AlbumName.jsx @@ -0,0 +1,19 @@ +/* eslint-disable react/prop-types */ +/* eslint-disable react/react-in-jsx-scope */ +const AlbumName = ({ name }) => { + console.log(name); + const openAlbumUrl = () => { + window.open(name[1]); + }; + + return ( +
+

{name[0]}

+
+ ); +}; + +export default AlbumName; diff --git a/src/components/ArtistName.jsx b/src/components/ArtistName.jsx new file mode 100644 index 00000000..dcd1e353 --- /dev/null +++ b/src/components/ArtistName.jsx @@ -0,0 +1,18 @@ +/* eslint-disable react/react-in-jsx-scope */ +// eslint-disable-next-line react/prop-types +const ArtistName = ({ name }) => { + const openArtistUrl = () => { + window.open(name[1]); + }; + + return ( +
+

{name[0]}

+
+ ); +}; + +export default ArtistName; diff --git a/src/components/CoverImage.jsx b/src/components/CoverImage.jsx new file mode 100644 index 00000000..f75e636f --- /dev/null +++ b/src/components/CoverImage.jsx @@ -0,0 +1,7 @@ +/* eslint-disable react/prop-types */ +/* eslint-disable react/react-in-jsx-scope */ +export const CoverImage = ({ imageUrl }) => { + return Album cover; +}; + +export default CoverImage; diff --git a/src/components/Header.jsx b/src/components/Header.jsx new file mode 100644 index 00000000..f30f9a0d --- /dev/null +++ b/src/components/Header.jsx @@ -0,0 +1,10 @@ +/* eslint-disable react/react-in-jsx-scope */ +export const Header = () => { + const headertext = "New albums & singels"; + + return ( +
+

{headertext}

+
+ ); +}; diff --git a/src/components/Icon.jsx b/src/components/Icon.jsx new file mode 100644 index 00000000..c3112147 --- /dev/null +++ b/src/components/Icon.jsx @@ -0,0 +1,17 @@ +/* eslint-disable react/react-in-jsx-scope */ +import playIcon from "../../public/icons/play.svg"; +import heartIcon from "../../public/icons/heart.svg"; +import dotIcon from "../../public/icons/dots.svg"; + +export const PlayIcon = () => { + // eslint-disable-next-line react/react-in-jsx-scope + return Play; +}; + +export const HeartIcon = () => { + return Heart; +}; + +export const DotIcon = () => { + return Dot; +}; diff --git a/src/index.css b/src/index.css index 4558f538..b9af9efb 100644 --- a/src/index.css +++ b/src/index.css @@ -11,3 +11,117 @@ code { font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } + +body { + background-color: black; +} + +.header { + color: #fff; + display: flex; + font-family: Helvetica, sans-serif; + font-size: 20px; + justify-content: center; + margin-bottom: 2em; +} + +/*-----wrapping all albums-----*/ +.album-wrapper { + display: grid; + grid-template-columns: 1fr; + grid-gap: 25px; +} + +/*----------wrapping every single album-----*/ +.album { + margin: 10px; + color: #fff; + font-size: 14px; +} + +.artists { + display: flex; + align-items: center; /* Vertically aligns children in the middle */ + flex-wrap: wrap; + gap: 5px; + color: #a0a0a0; +} + +.artistName, +.artists span { + display: inline-flex; /* Ensures inline display */ + align-items: center; /* Aligns text vertically */ +} + +/*--------- container to albim image and buttons-----*/ +.cover-image-container { + position: relative; + width: 100%; + z-index: 1; +} + +img { + width: 100%; + height: auto; + max-width: 600px; +} + +.buttons { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + display: flex; + justify-content: center; + align-items: center; + gap: 20px; + z-index: 2; +} + +button { + border: none; + padding: 0; + margin: 0; + background: none; + outline: none; + cursor: pointer; + fill: white; + filter: invert(1); + z-index: 2; + width: 40px; +} + +/* --------- Hover effects-----------*/ + +.cover-image-container:hover .cover-image img { + opacity: 0.3; +} + +.cover-image-container .play-icon:hover, +.cover-image-container .heart-icon:hover, +.cover-image-container .dot-icon:hover { + transform: scale(1.2); +} + +.album-name:hover { + text-decoration: underline; +} + +.artists:hover { + text-decoration: underline; + color: #a0a0a0; +} + +/*------ responsive design--------*/ + +@media (min-width: 667px) { + .album-wrapper { + grid-template-columns: 1fr 1fr; + } +} + +@media (min-width: 1025px) { + .album-wrapper { + grid-template-columns: 1fr 1fr 1fr 1fr; + } +} From 4bf065bb2f29ac5fbdb24529a9d06121e5b2db60 Mon Sep 17 00:00:00 2001 From: hamdi Date: Mon, 29 Apr 2024 10:51:43 +0200 Subject: [PATCH 2/3] corrected hover effect and replaced onclick with a regular anchor tag --- src/components/AlbumName.jsx | 28 ++++++++++++---------------- src/components/ArtistName.jsx | 27 ++++++++++++--------------- src/index.css | 9 +++++++++ 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/components/AlbumName.jsx b/src/components/AlbumName.jsx index 0effa8b5..054437ed 100644 --- a/src/components/AlbumName.jsx +++ b/src/components/AlbumName.jsx @@ -1,19 +1,15 @@ -/* eslint-disable react/prop-types */ -/* eslint-disable react/react-in-jsx-scope */ -const AlbumName = ({ name }) => { - console.log(name); - const openAlbumUrl = () => { - window.open(name[1]); - }; +import React from "react"; - return ( -
-

{name[0]}

-
- ); -}; +// eslint-disable-next-line react/prop-types +const AlbumName = ({ name }) => ( + +

{name[0]}

+
+); export default AlbumName; diff --git a/src/components/ArtistName.jsx b/src/components/ArtistName.jsx index dcd1e353..e935cdc1 100644 --- a/src/components/ArtistName.jsx +++ b/src/components/ArtistName.jsx @@ -1,18 +1,15 @@ -/* eslint-disable react/react-in-jsx-scope */ -// eslint-disable-next-line react/prop-types -const ArtistName = ({ name }) => { - const openArtistUrl = () => { - window.open(name[1]); - }; +/* eslint-disable react/prop-types */ +import React from "react"; - return ( -
-

{name[0]}

-
- ); -}; +const ArtistName = ({ name }) => ( + +

{name[0]}

+
+); export default ArtistName; diff --git a/src/index.css b/src/index.css index b9af9efb..437fecb1 100644 --- a/src/index.css +++ b/src/index.css @@ -103,6 +103,15 @@ button { transform: scale(1.2); } +.cover-image-container .cover-image img, +.buttons button { + transition: transform 0.3s ease, opacity 0.3s ease; +} + +.buttons button:hover { + transform: scale(1.2); +} + .album-name:hover { text-decoration: underline; } From b7398addcdf49e88f9ac2e2c77494d4416ea6abf Mon Sep 17 00:00:00 2001 From: hamdi Date: Mon, 29 Apr 2024 12:03:00 +0200 Subject: [PATCH 3/3] fixed play heart dot button on image hover effekt --- src/components/Album.jsx | 57 +++++++++++++++++----------------------- src/components/Icon.jsx | 6 ++--- src/index.css | 17 ++++++------ 3 files changed, 35 insertions(+), 45 deletions(-) diff --git a/src/components/Album.jsx b/src/components/Album.jsx index 17596461..cfebf12b 100644 --- a/src/components/Album.jsx +++ b/src/components/Album.jsx @@ -3,12 +3,7 @@ import React, { useState } from "react"; import AlbumName from "./AlbumName"; import ArtistName from "./ArtistName"; import CoverImage from "./CoverImage"; -//import { ReactComponent as PlayIcon } from "../assets/icons/play.svg"; -//import { ReactComponent as HeartIcon } from "../assets/icons/heart.svg"; -//import { ReactComponent as DotIcon } from "../assets/icons/dots.svg"; -import playIcon from "../assets/icons/play.svg"; -import heartIcon from "../assets/icons/heart.svg"; -import dotIcon from "../assets/icons/dots.svg"; +import { PlayIcon, HeartIcon, DotIcon } from "./Icon"; const Album = ({ albumData }) => { const [isHovered, setIsHovered] = useState(false); @@ -31,34 +26,30 @@ const Album = ({ albumData }) => {
+ {isHovered && ( +
+ + + +
+ )} - {isHovered && ( -
- - - -
- )} -
-
- -
-
- {albumData.artists.map((artist, index) => ( - - - {index < albumData.artists.length - 1 && ( -  & - )} - - ))} -
+
+ +
+
+ {albumData.artists.map((artist, index) => ( + + + {index < albumData.artists.length - 1 &&  & } + + ))}
); diff --git a/src/components/Icon.jsx b/src/components/Icon.jsx index c3112147..f34b9481 100644 --- a/src/components/Icon.jsx +++ b/src/components/Icon.jsx @@ -1,7 +1,7 @@ /* eslint-disable react/react-in-jsx-scope */ -import playIcon from "../../public/icons/play.svg"; -import heartIcon from "../../public/icons/heart.svg"; -import dotIcon from "../../public/icons/dots.svg"; +import playIcon from "../assets/icons/play.svg"; +import heartIcon from "../assets/icons/heart.svg"; +import dotIcon from "../assets/icons/dots.svg"; export const PlayIcon = () => { // eslint-disable-next-line react/react-in-jsx-scope diff --git a/src/index.css b/src/index.css index 437fecb1..b7c3f452 100644 --- a/src/index.css +++ b/src/index.css @@ -23,6 +23,7 @@ body { font-size: 20px; justify-content: center; margin-bottom: 2em; + /*border: 2px solid red;*/ } /*-----wrapping all albums-----*/ @@ -30,6 +31,7 @@ body { display: grid; grid-template-columns: 1fr; grid-gap: 25px; + /* border: 2px solid red;*/ } /*----------wrapping every single album-----*/ @@ -37,8 +39,13 @@ body { margin: 10px; color: #fff; font-size: 14px; + /*border: 2px solid red;*/ } +/* .artistName h3 { + color: #a0a0a0; +} */ + .artists { display: flex; align-items: center; /* Vertically aligns children in the middle */ @@ -58,6 +65,7 @@ body { position: relative; width: 100%; z-index: 1; + /*border: 4px solid green;*/ } img { @@ -103,15 +111,6 @@ button { transform: scale(1.2); } -.cover-image-container .cover-image img, -.buttons button { - transition: transform 0.3s ease, opacity 0.3s ease; -} - -.buttons button:hover { - transform: scale(1.2); -} - .album-name:hover { text-decoration: underline; }