diff --git a/babel-plugin-macros.config.js b/babel-plugin-macros.config.js new file mode 100644 index 0000000..6867ea4 --- /dev/null +++ b/babel-plugin-macros.config.js @@ -0,0 +1,5 @@ +module.exports = { + 'fontawesome-svg-core': { + 'license': 'free' + } +} diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..e821e16 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,5 @@ +module.exports = function (api) { + return { + plugins: ['macros'], + } +} diff --git a/package.json b/package.json index 5d1adaa..bdea1b5 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,9 @@ "version": "0.1.0", "private": true, "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.1.1", + "@fortawesome/free-solid-svg-icons": "^6.1.1", + "@fortawesome/react-fontawesome": "^0.1.18", "@reduxjs/toolkit": "^1.8.1", "@testing-library/jest-dom": "^5.16.3", "@testing-library/react": "^12.1.4", @@ -12,10 +15,12 @@ "@types/react": "^17.0.43", "@types/react-dom": "^17.0.14", "@types/react-redux": "^7.1.23", + "babel-plugin-macros": "^3.1.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-redux": "^7.2.8", "react-scripts": "5.0.0", + "react-tooltip": "^4.2.21", "typescript": "^4.6.3", "web-vitals": "^2.1.4" }, diff --git a/src/App.css b/src/App.css index 30240ee..7667529 100644 --- a/src/App.css +++ b/src/App.css @@ -5,7 +5,7 @@ main { /* flex-direction: column; */ /* align-items: center; */ /* justify-content: center; */ - /* font-size: calc(10px + 2vmin); */ + font-size: calc(10px + 2vmin); /* color: white; */ } diff --git a/src/App.tsx b/src/App.tsx index 08cc15c..8530d96 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,8 @@ import React from 'react'; import './App.css'; import DiscRow from './components/DiscRow'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { solid } from '@fortawesome/fontawesome-svg-core/import.macro' import { selectDiscs, useAppSelector } from './store'; function App() { @@ -9,7 +11,10 @@ function App() { return (
- +
{ discs.discs.map((disc, idx) => { return }) } diff --git a/src/components/DiscRow.css b/src/components/DiscRow.css index 55964d3..fb03b35 100644 --- a/src/components/DiscRow.css +++ b/src/components/DiscRow.css @@ -1,11 +1,16 @@ .disc-row { display: flex; align-items: center; + margin-top: 1rem; +} + +.disc-row > button { + font-size: 1.25rem; } .disc-row__icon { - width: 2.5em; - height: 2.5em; + width: 1.5em; + height: 1.5em; /* IE, only works on tags */ -ms-interpolation-mode: nearest-neighbor; @@ -14,3 +19,9 @@ /* Chromium + Safari */ image-rendering: pixelated; } + +.disc-preview { + display: flex; + flex: 1 0 auto; + align-items: center; +} diff --git a/src/components/DiscRow.tsx b/src/components/DiscRow.tsx index cc82e5a..90eb881 100644 --- a/src/components/DiscRow.tsx +++ b/src/components/DiscRow.tsx @@ -1,6 +1,12 @@ import DiscTooltip from "./DiscTooltip" -import { selectDiscs, useAppSelector } from '../store'; +import { selectDiscs, useAppSelector } from "../store" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" +import { solid } from "@fortawesome/fontawesome-svg-core/import.macro" +import ReactTooltip from "react-tooltip" +import EditNameModal from "./EditNameModal" + import "./DiscRow.css" +import { useState } from "react" interface DiscRowProps { discId: number @@ -10,10 +16,32 @@ function DiscRow({ discId }: DiscRowProps) { const discs = useAppSelector(selectDiscs) const disc = discs.discs[discId] + const [showEditName, setShowEditName] = useState(false); + return (
- - + + + +
+ + +
+ + setShowEditName(false)} + discId={discId} + />
) } diff --git a/src/components/DiscTooltip.css b/src/components/DiscTooltip.css index 47d7cf6..2764395 100644 --- a/src/components/DiscTooltip.css +++ b/src/components/DiscTooltip.css @@ -7,7 +7,7 @@ .disc-tooltip { color: #FFF; - text-shadow: 0.125em 0.125em 0 #3F3F3F + text-shadow: 0.125em 0.125em 0 #3F3F3F; } .disc-tooltip { @@ -16,9 +16,9 @@ background-color: rgba(16,0,16,0.94); padding: 0.375em; font-family: Minecraft,sans-serif; - font-size: 16px; + font-size: 12px; word-spacing: 4px; - white-space: nowrap; + /* white-space: nowrap; */ line-height: 1.25em; margin: 0.125em 0.25em; } diff --git a/src/components/EditNameModal.tsx b/src/components/EditNameModal.tsx new file mode 100644 index 0000000..a9eb419 --- /dev/null +++ b/src/components/EditNameModal.tsx @@ -0,0 +1,40 @@ +import { selectDiscs, useAppDispatch, useAppSelector } from "../store" +import { setDescription, setTitle } from "../store/discs" + +import Modal from "./Modal" + +interface EditNameModalProps { + discId: number + show: boolean + onClose: { (): void } +} + + +function EditNameModal({ discId, show, onClose }: EditNameModalProps) { + const discs = useAppSelector(selectDiscs) + const disc = discs.discs[discId] + + const dispatch = useAppDispatch() + function setInputTitle(e: React.ChangeEvent) { + dispatch(setTitle({ + id: discId, + title: e.target.value + })) + } + + function setInputDescription(e: React.ChangeEvent) { + dispatch(setDescription({ + id: discId, + description: e.target.value + })) + } + + return + + + + + +} + +export default EditNameModal diff --git a/src/components/Modal.css b/src/components/Modal.css new file mode 100644 index 0000000..9623b4a --- /dev/null +++ b/src/components/Modal.css @@ -0,0 +1,25 @@ +.modal { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: var(--background-body); + padding: 2rem; + z-index: 900; + border-radius: 1rem; +} + +.modal__overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.7); + z-index: 900; +} + +.modal__close-btn { + margin-top: 1rem; + float: right; +} diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx new file mode 100644 index 0000000..26d040b --- /dev/null +++ b/src/components/Modal.tsx @@ -0,0 +1,41 @@ +import { useEffect } from "react" +import "./Modal.css" + +interface ModalProps { + show: boolean + onClose: { (): void } + children: React.ReactNode +} + +function Modal({ show, onClose, children }: ModalProps) { + + function onKeyUp(e: KeyboardEvent) { + if (show && e.key == "Escape") { + onClose() + } + } + + useEffect(() => { + document.addEventListener("keyup", onKeyUp) + return () => document.removeEventListener("keyup", onKeyUp) + }) + + if (!show) return null + + return ( + <> +
+
+
+ {children} +
+ +
+ + ) +} + +export default Modal diff --git a/src/index.css b/src/index.css index 568938b..127034f 100644 --- a/src/index.css +++ b/src/index.css @@ -9,3 +9,7 @@ body { code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } + +.margin-right-1 { + margin-right: 1rem; +} diff --git a/src/store/discs.ts b/src/store/discs.ts index ca9f973..c318faf 100644 --- a/src/store/discs.ts +++ b/src/store/discs.ts @@ -1,8 +1,10 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit' export interface Disc { - title: string - description: string + title?: string + description?: string + defaultTitle: string + defaultDescription: string icon: string } @@ -10,11 +12,66 @@ interface DiscsState { discs: Disc[] } +const defaultTitle = "Music Disc" + const initialState: DiscsState = { discs: [ - { title: "Music Disc", description: "C418 - 13", icon: "/sprites/music_disc_13.png" }, - { title: "Music Disc", description: "C418 - cat", icon: "/sprites/music_disc_cat.png" }, - { title: "Music Disc", description: "C418 - blocks", icon: "/sprites/music_disc_blocks.png" }, + { + defaultTitle, defaultDescription: "C418 - 13", + icon: "/sprites/music_disc_13.png" + }, + { + defaultTitle, defaultDescription: "C418 - cat", + icon: "/sprites/music_disc_cat.png" + }, + { + defaultTitle, defaultDescription: "C418 - blocks", + icon: "/sprites/music_disc_blocks.png" + }, + { + defaultTitle, defaultDescription: "C418 - chirp", + icon: "/sprites/music_disc_chirp.png" + }, + { + defaultTitle, defaultDescription: "C418 - far", + icon: "/sprites/music_disc_far.png" + }, + { + defaultTitle, defaultDescription: "C418 - mall", + icon: "/sprites/music_disc_mall.png" + }, + { + defaultTitle, defaultDescription: "C418 - mellohi", + icon: "/sprites/music_disc_mellohi.png" + }, + { + defaultTitle, defaultDescription: "C418 - stal", + icon: "/sprites/music_disc_stal.png" + }, + { + defaultTitle, defaultDescription: "C418 - strad", + icon: "/sprites/music_disc_strad.png" + }, + { + defaultTitle, defaultDescription: "C418 - ward", + icon: "/sprites/music_disc_ward.png" + }, + { + defaultTitle, defaultDescription: "C418 - 11", + icon: "/sprites/music_disc_11.png" + }, + { + defaultTitle, defaultDescription: "C418 - wait", + icon: "/sprites/music_disc_wait.png" + }, + { + defaultTitle, defaultDescription: "Lena Raine - otherside", + icon: "/sprites/music_disc_otherside.png" + }, + { + defaultTitle, defaultDescription: "Lena Raine - Pigstep", + icon: "/sprites/music_disc_pigstep.png" + }, ] } @@ -22,17 +79,17 @@ export const discsSlice = createSlice({ name: "discs", initialState, reducers: { - updateTitle: (state, action: PayloadAction<{ id: number, title: string }>) => { + setTitle: (state, action: PayloadAction<{ id: number, title: string }>) => { const { id, title } = action.payload; state.discs[id].title = title }, - updateDescription: (state, action: PayloadAction<{ id: number, description: string }>) => { + setDescription: (state, action: PayloadAction<{ id: number, description: string }>) => { const { id, description } = action.payload; state.discs[id].description = description } } }) -export const { updateTitle, updateDescription } = discsSlice.actions +export const { setTitle, setDescription } = discsSlice.actions export default discsSlice.reducer diff --git a/yarn.lock b/yarn.lock index d366854..9b2249e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1155,6 +1155,32 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@fortawesome/fontawesome-common-types@6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.1.tgz#7dc996042d21fc1ae850e3173b5c67b0549f9105" + integrity sha512-wVn5WJPirFTnzN6tR95abCx+ocH+3IFLXAgyavnf9hUmN0CfWoDjPT/BAWsUVwSlYYVBeCLJxaqi7ZGe4uSjBA== + +"@fortawesome/fontawesome-svg-core@^6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.1.1.tgz#3424ec6182515951816be9b11665d67efdce5b5f" + integrity sha512-NCg0w2YIp81f4V6cMGD9iomfsIj7GWrqmsa0ZsPh59G7PKiGN1KymZNxmF00ssuAlo/VZmpK6xazsGOwzKYUMg== + dependencies: + "@fortawesome/fontawesome-common-types" "6.1.1" + +"@fortawesome/free-solid-svg-icons@^6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.1.1.tgz#3369e673f8fe8be2fba30b1ec274d47490a830a6" + integrity sha512-0/5exxavOhI/D4Ovm2r3vxNojGZioPwmFrKg0ZUH69Q68uFhFPs6+dhAToh6VEQBntxPRYPuT5Cg1tpNa9JUPg== + dependencies: + "@fortawesome/fontawesome-common-types" "6.1.1" + +"@fortawesome/react-fontawesome@^0.1.18": + version "0.1.18" + resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.18.tgz#dae37f718a24e14d7a99a5496c873d69af3fbd73" + integrity sha512-RwLIB4TZw0M9gvy5u+TusAA0afbwM4JQIimNH/j3ygd6aIvYPQLqXMhC9ErY26J23rDPyDZldIfPq/HpTTJ/tQ== + dependencies: + prop-types "^15.8.1" + "@humanwhocodes/config-array@^0.9.2": version "0.9.5" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" @@ -7138,6 +7164,14 @@ react-scripts@5.0.0: optionalDependencies: fsevents "^2.3.2" +react-tooltip@^4.2.21: + version "4.2.21" + resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.2.21.tgz#840123ed86cf33d50ddde8ec8813b2960bfded7f" + integrity sha512-zSLprMymBDowknr0KVDiJ05IjZn9mQhhg4PRsqln0OZtURAJ1snt1xi5daZfagsh6vfsziZrc9pErPTDY1ACig== + dependencies: + prop-types "^15.7.2" + uuid "^7.0.3" + react@^18.0.0: version "18.0.0" resolved "https://registry.yarnpkg.com/react/-/react-18.0.0.tgz#b468736d1f4a5891f38585ba8e8fb29f91c3cb96" @@ -8291,6 +8325,11 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= +uuid@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" + integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== + uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"