1
0

feat: display a list of disc with tooltips

This commit is contained in:
Rokas Puzonas 2022-04-09 01:16:55 +00:00
parent 8c3963f18d
commit 6b22bf8431
28 changed files with 290 additions and 66 deletions

View File

@ -1,8 +1,9 @@
{
"name": "music-datapack-creator",
"name": "music-resource-pack-creator",
"version": "0.1.0",
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^1.8.1",
"@testing-library/jest-dom": "^5.16.3",
"@testing-library/react": "^12.1.4",
"@testing-library/user-event": "^13.5.0",
@ -10,8 +11,10 @@
"@types/node": "^16.11.26",
"@types/react": "^17.0.43",
"@types/react-dom": "^17.0.14",
"@types/react-redux": "^7.1.23",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-redux": "^7.2.8",
"react-scripts": "5.0.0",
"typescript": "^4.6.3",
"web-vitals": "^2.1.4"

View File

@ -4,11 +4,7 @@
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/water.css">
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
@ -24,7 +20,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>Music Resource Pack Creator</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

View File

@ -1,38 +1,14 @@
.App {
text-align: center;
main {
/* text-align: center; */
/* min-height: 100vh; */
/* display: flex; */
/* flex-direction: column; */
/* align-items: center; */
/* justify-content: center; */
/* font-size: calc(10px + 2vmin); */
/* color: white; */
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
footer {
margin-top: 1rem;
}

View File

@ -1,24 +1,22 @@
import React from 'react';
import logo from './logo.svg';
import './App.css';
import DiscRow from './components/DiscRow';
import { selectDiscs, useAppSelector } from './store';
function App() {
const discs = useAppSelector(selectDiscs)
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
<div className="app">
<header>
<button>Generate resource pack</button>
</header>
<main>
{ discs.discs.map((disc, idx) => { return <DiscRow key={idx} discId={idx} /> }) }
</main>
<footer>
Made By Rokas Puzonas
</footer>
</div>
);
}

View File

@ -0,0 +1,16 @@
.disc-row {
display: flex;
align-items: center;
}
.disc-row__icon {
width: 2.5em;
height: 2.5em;
/* IE, only works on <img> tags */
-ms-interpolation-mode: nearest-neighbor;
/* Firefox */
image-rendering: crisp-edges;
/* Chromium + Safari */
image-rendering: pixelated;
}

View File

@ -0,0 +1,21 @@
import DiscTooltip from "./DiscTooltip"
import { selectDiscs, useAppSelector } from '../store';
import "./DiscRow.css"
interface DiscRowProps {
discId: number
}
function DiscRow({ discId }: DiscRowProps) {
const discs = useAppSelector(selectDiscs)
const disc = discs.discs[discId]
return (
<div className="disc-row">
<img className="disc-row__icon" src={disc.icon} />
<DiscTooltip title={disc.title} description={disc.description} />
</div>
)
}
export default DiscRow

View File

@ -0,0 +1,60 @@
/* css ripped from https://minecraft.fandom.com/wiki/Music_Disc */
@font-face {
font-family: Minecraft;
src: url("../fonts/minecraft.woff") format('embedded-opentype'),url(https://minecraft.fandom.com/media/hydra/fonts/minecraft.woff) format('woff'),url(https://minecraft.fandom.com/media/hydra/fonts/minecraft.ttf) format('truetype')
}
.disc-tooltip {
color: #FFF;
text-shadow: 0.125em 0.125em 0 #3F3F3F
}
.disc-tooltip {
position: relative;
display: inline-block;
background-color: rgba(16,0,16,0.94);
padding: 0.375em;
font-family: Minecraft,sans-serif;
font-size: 16px;
word-spacing: 4px;
white-space: nowrap;
line-height: 1.25em;
margin: 0.125em 0.25em;
}
.disc-tooltip::before {
content: "";
position: absolute;
top: 0.125em;
right: -0.125em;
bottom: 0.125em;
left: -0.125em;
border: 0.125em solid #100010;
border-style: none solid;
border-color: rgba(16,0,16,0.94)
}
.disc-tooltip::after {
content: "";
position: absolute;
top: 0.125em;
right: 0;
bottom: 0.125em;
left: 0;
border: 0.125em solid #2D0A63;
border-image: -webkit-linear-gradient(rgba(80,0,255,0.31),rgba(40,0,127,0.31)) 1;
border-image: linear-gradient(rgba(80,0,255,0.31),rgba(40,0,127,0.31)) 1
}
.disc-tooltip > .disc-tooltip__description {
display: block;
margin-top: 0.25em;
color: #AAA;
text-shadow: 0.125em 0.125em 0 #2A2A2A
}
.disc-tooltip > .disc-tooltip__title {
color: #5FF;
text-shadow: 0.125em 0.125em 0 #153F3F
}

View File

@ -0,0 +1,21 @@
import './DiscTooltip.css';
interface DiscTooltip {
title: string
description: string
}
function DiscTooltip({ title, description }: DiscTooltip) {
return (
<div className="disc-tooltip">
<span className="disc-tooltip__title">
{ title }
</span>
<span className="disc-tooltip__description">
{ description }
</span>
</div>
)
}
export default DiscTooltip

BIN
src/fonts/minecraft.woff Normal file

Binary file not shown.

View File

@ -1,5 +1,4 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
@ -8,6 +7,5 @@ body {
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
}

View File

@ -2,12 +2,16 @@ import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import store from './store'
import { Provider } from 'react-redux'
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
<Provider store={store}>
<React.StrictMode>
<App />
</React.StrictMode>
</Provider>,
document.getElementById('root')
);

38
src/store/discs.ts Normal file
View File

@ -0,0 +1,38 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
export interface Disc {
title: string
description: string
icon: string
}
interface DiscsState {
discs: 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" },
]
}
export const discsSlice = createSlice({
name: "discs",
initialState,
reducers: {
updateTitle: (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 }>) => {
const { id, description } = action.payload;
state.discs[id].description = description
}
}
})
export const { updateTitle, updateDescription } = discsSlice.actions
export default discsSlice.reducer

22
src/store/index.ts Normal file
View File

@ -0,0 +1,22 @@
import { configureStore } from '@reduxjs/toolkit'
import discsReducer from './discs'
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
const store = configureStore({
reducer: {
discs: discsReducer
}
})
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch
export const useAppDispatch = () => useDispatch<AppDispatch>()
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
// Other code such as selectors can use the imported `RootState` type
export const selectDiscs = (state: RootState) => state.discs
export default store

View File

@ -1031,6 +1031,13 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.15.4":
version "7.17.9"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.9.tgz#d19fbf802d01a8cb6cf053a64e472d42c434ba72"
integrity sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/template@^7.16.7", "@babel/template@^7.3.3":
version "7.16.7"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155"
@ -1401,6 +1408,16 @@
schema-utils "^3.0.0"
source-map "^0.7.3"
"@reduxjs/toolkit@^1.8.1":
version "1.8.1"
resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.8.1.tgz#94ee1981b8cf9227cda40163a04704a9544c9a9f"
integrity sha512-Q6mzbTpO9nOYRnkwpDlFOAbQnd3g7zj7CtHAZWz5SzE5lcV97Tf8f3SzOO8BoPOMYBFgfZaqTUZqgGu+a0+Fng==
dependencies:
immer "^9.0.7"
redux "^4.1.2"
redux-thunk "^2.4.1"
reselect "^4.1.5"
"@rollup/plugin-babel@^5.2.0":
version "5.3.1"
resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283"
@ -1745,6 +1762,14 @@
dependencies:
"@types/node" "*"
"@types/hoist-non-react-statics@^3.3.0":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
dependencies:
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
"@types/html-minifier-terser@^6.0.0":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35"
@ -1841,6 +1866,16 @@
dependencies:
"@types/react" "*"
"@types/react-redux@^7.1.20", "@types/react-redux@^7.1.23":
version "7.1.23"
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.23.tgz#3c2bb1bcc698ae69d70735f33c5a8e95f41ac528"
integrity sha512-D02o3FPfqQlfu2WeEYwh3x2otYd2Dk1o8wAfsA0B1C2AJEFxE663Ozu7JzuWbznGgW248NaOF6wsqCGNq9d3qw==
dependencies:
"@types/hoist-non-react-statics" "^3.3.0"
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
redux "^4.0.0"
"@types/react@*", "@types/react@^17.0.43":
version "17.0.43"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.43.tgz#4adc142887dd4a2601ce730bc56c3436fdb07a55"
@ -4483,6 +4518,13 @@ he@^1.2.0:
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
dependencies:
react-is "^16.7.0"
hoopy@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d"
@ -6883,7 +6925,7 @@ prompts@^2.0.1, prompts@^2.4.2:
kleur "^3.0.3"
sisteransi "^1.0.5"
prop-types@^15.8.1:
prop-types@^15.7.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@ -7014,16 +7056,28 @@ react-error-overlay@^6.0.10:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.10.tgz#0fe26db4fa85d9dbb8624729580e90e7159a59a6"
integrity sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA==
react-is@^16.13.1:
react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-is@^17.0.1:
react-is@^17.0.1, react-is@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
react-redux@^7.2.8:
version "7.2.8"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.8.tgz#a894068315e65de5b1b68899f9c6ee0923dd28de"
integrity sha512-6+uDjhs3PSIclqoCk0kd6iX74gzrGc3W5zcAjbrFgEdIjRSQObdIwfx80unTkVUYvbQ95Y8Av3OvFHq1w5EOUw==
dependencies:
"@babel/runtime" "^7.15.4"
"@types/react-redux" "^7.1.20"
hoist-non-react-statics "^3.3.2"
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-is "^17.0.2"
react-refresh@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
@ -7135,6 +7189,18 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.0"
redux-thunk@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.1.tgz#0dd8042cf47868f4b29699941de03c9301a75714"
integrity sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==
redux@^4.0.0, redux@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.2.tgz#140f35426d99bb4729af760afcf79eaaac407104"
integrity sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==
dependencies:
"@babel/runtime" "^7.9.2"
regenerate-unicode-properties@^10.0.1:
version "10.0.1"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56"
@ -7232,6 +7298,11 @@ requires-port@^1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
reselect@^4.1.5:
version "4.1.5"
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.5.tgz#852c361247198da6756d07d9296c2b51eddb79f6"
integrity sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==
resolve-cwd@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"