responsive

This commit is contained in:
Alex Bates 2021-03-04 12:18:14 +00:00
parent f6a1b3576d
commit ddc46a3d1c
No known key found for this signature in database
GPG Key ID: 7531C5E1D6B1CA9A
4 changed files with 108 additions and 62 deletions

View File

@ -1,10 +1,6 @@
import React, { useState, useEffect } from "react"
import React, { useState, useEffect, useMemo } from "react"
import { createPortal } from "react-dom"
import { Area, XAxis, YAxis, AreaChart, CartesianGrid, Tooltip, ResponsiveContainer } from "recharts"
import { scalePow } from "d3-scale"
const scale = scalePow()
.exponent(30)
const csvVersions = {
"1": {
@ -45,7 +41,7 @@ async function fetchData(version) {
const latest = rows[rows.length - 1]
for (const row of rows) {
row.percentBytes = (row.matchingBytes / latest.totalBytes) * 100
row.percentBytes = (row.matchingBytes / latest.totalBytes) * 100
}
return rows
@ -67,17 +63,6 @@ export default function ProgressPane({ captionPortal, nonce, color, version }) {
</div>
}
const monthDates = []
{
let date = new Date(2020, 3, 1)
while (date < Date.now()) {
monthDates.push(date / 1000)
date = new Date(date) // clone
date.setMonth(date.getMonth() + 1)
}
}
function DataView({ data, captionPortal, nonce, color }) {
const latest = data[data.length - 1]
const oldest = data[0]
@ -85,6 +70,10 @@ function DataView({ data, captionPortal, nonce, color }) {
const [selectedEntry, setSelectedEntry] = useState(latest)
if (!selectedEntry && latest) {
setSelectedEntry(latest)
}
function renderTooltip(tip) {
const entry = data.find(row => row.timestamp === tip.label)
@ -97,13 +86,31 @@ function DataView({ data, captionPortal, nonce, color }) {
const maxPercent = latest ? Math.ceil(latest.percentBytes / 25) * 25 : 25
const monthDates = useMemo(() => {
const monthDates = []
if (oldest) {
let date = new Date(oldest.timestamp * 1000)
date.setDate(0)
while (date < Date.now()) {
monthDates.push(date / 1000)
date = new Date(date) // clone
date.setMonth(date.getMonth() + 1)
}
return monthDates
}
}, [oldest && oldest.timestamp])
return <>
<div className="shadow-box flex-grow">
<div className="shadow-box-inner" style={{ paddingRight: ".7em", paddingTop: ".7em", "--text-outline": "transparent", background: "#e2e1d8" }}>
<div className="progress-chart">
<ResponsiveContainer>
<AreaChart data={data}>
<XAxis dataKey="timestamp" type="number" scale={scale} domain={["dataMin", Date.now()/1000]} ticks={monthDates} tickFormatter={formatTimestampMonth} interval={0}/>
<XAxis dataKey="timestamp" type="number" scale="linear" domain={["dataMin", Date.now()/1000]} ticks={monthDates} tickFormatter={formatTimestampMonth}/>
<YAxis type="number" unit="%" domain={[0, maxPercent]} tickCount={maxPercent / 5 + 1}/>
<CartesianGrid stroke="#d9d0c9"/>
@ -168,16 +175,11 @@ function EntryInfo({ entry, isLatest }) {
{entry.commit.substr(0, 8)}
</a>
{isLatest && " (latest)"}
<table>
<tbody>
<tr>
<td width="200">Matched</td>
<td className="thin align-right">
{Math.round(entry.percentBytes * 100) / 100}% bytes
({entry.matchingFuncs}/{entry.totalFuncs} functions)
</td>
</tr>
</tbody>
</table>
<br/>
<span className="thin">
Matched {Math.round(entry.percentBytes * 100) / 100}% bytes ({entry.matchingFuncs}/{entry.totalFuncs} functions)
</span>
</div>
}

View File

@ -7,7 +7,8 @@ html {
--dark: #313131;
--light: #d6d6ce;
font-size: 32px;
font-size: 21px;
font-size: clamp(21px, 1.5vw, 32px);
font-family: "Paper Mario Dialog Redesigned", sans-serif;
font-weight: 700;
line-height: 1.2;
@ -32,6 +33,13 @@ body {
background-repeat: repeat-x;
background-size: contain;
animation: clouds linear 30s infinite normal;
/* centre children */
display: flex;
align-items: center;
justify-content: center;
padding: 1vw 1vh;
}
@keyframes clouds {
@ -55,13 +63,13 @@ p {
margin: 0;
}
a:any-link {
a:any-link:not(.tab) {
color: #3796ff;
--text-outline: #d3e5f9;
text-decoration: none;
}
button {
button, .tab {
all: unset;
border-radius: 100em;
@ -80,9 +88,11 @@ button {
user-select: none;
text-align: center;
color: var(--light);
}
button.red {
button.red, .tab.red {
border-top-color: #f04e54;
border-left-color: #f04e54;
background: #b4313e;
@ -90,7 +100,7 @@ button.red {
border-right-color: #7f1729;
}
button.yellow {
button.yellow, .tab.yellow {
border-top-color: #f0c74e;
border-left-color: #f0c74e;
background: #b48b31;
@ -98,7 +108,7 @@ button.yellow {
border-right-color: #7f5617;
}
button.blurple {
button.blurple, .tab.blurple {
border-top-color: #98a9e2;
border-left-color: #98a9e2;
background: #7289da;
@ -106,7 +116,7 @@ button.blurple {
border-right-color: #4E5D94;
}
button.github {
button.github, .tab.github {
border-top-color: #554e4e;
border-left-color: #554e4e;
background: #322f2f;
@ -114,7 +124,7 @@ button.github {
border-right-color: #171515;
}
button.teal {
button.teal, .tab.teal {
border-top-color: #22eec9;
border-left-color: #22eec9;
background: #14a98e;
@ -122,7 +132,7 @@ button.teal {
border-right-color: #076d5a;
}
button.green {
button.green, .tab.green {
border-top-color: #68ff51;
border-left-color: #68ff51;
background: #47b836;
@ -130,11 +140,11 @@ button.green {
border-right-color: #2a791e;
}
button.inactive {
button.inactive, .tab.inactive {
filter: brightness(0.6);
}
button:hover {
button:hover, .tab:hover {
filter: brightness(1.0);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
@ -142,29 +152,40 @@ button:hover {
.tab {
margin-right: .25em;
cursor: pointer;
display: inline-block;
}
#container {
/* TODO: use flex on body */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
align-items: center;
width: 1600px;
max-width: 95%;
height: 1100px;
max-height: 950%;
width: 100%;
max-width: 1600px;
height: 100%;
max-height: 1100px;
}
@media (min-width: 2100px) {
#container {
max-width: 90%;
max-height: 90%;
width: max(80vw, calc(80vh * 16/11));
height: max(calc(80vw * 11/16), 80vh);
}
}
nav {
margin-bottom: -.6em;
z-index: 1;
width: 95%;
width: 100%;
}
@media (min-width: 600px) {
nav {
margin-left: 48px;
}
}
main {
@ -195,6 +216,14 @@ main {
box-shadow: 0 2px 16px rgba(0, 0, 0, 0.3);
}
@media (max-width: 800px) {
main {
padding-left: 0;
padding-right: 0;
padding-top: 0;
}
}
main > :last-child {
padding-bottom: 1.5em;
}
@ -251,6 +280,14 @@ main > * {
position: relative;
}
@media (max-width: 800px) {
.shadow-box {
padding: .5em;
margin: .3em;
margin-bottom: .5em;
}
}
.shadow-box-inner {
border-radius: 12px;
box-shadow: inset .4em .4em rgba(0, 0, 0, 0.15);
@ -275,7 +312,8 @@ button.shadow-box-title {
bottom: -1em;
transform: translateX(-50%);
width: 60%;
width: 90%;
max-width: 600px;
text-align: center;
@ -300,7 +338,7 @@ button.shadow-box-title {
border-radius: 1rem;
width: 85%;
height: 4rem;
min-height: 4rem;
padding: .5em 1em;
margin-top: -2em;
@ -312,7 +350,7 @@ button.shadow-box-title {
.progress-chart {
flex: 1;
font-size: 18px;
font-size: 14px;
overflow: hidden;
user-select: none;

View File

@ -2,6 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width"/>
<title>Paper Mario Decompilation</title>
<link rel="stylesheet" href="index.css"/>

View File

@ -77,22 +77,27 @@ function App() {
return <>
<nav>
{tabs.map((tab, index) => {
return <button
return <a
key={tab.name}
className={clsx("tab", tab.color, { "inactive": index !== tabIndex })}
onClick={() => {
switchToTab(index, true)
href={tab.slug}
onClick={evt => {
const q = window.matchMedia("(prefers-reduced-motion: reduce)")
if (!q.matches) {
switchToTab(index, true)
evt.preventDefault()
}
}}
>
{tab.name}
</button>
</a>
})}
<button className="tab blurple inactive" onClick={() => window.open("https://discord.gg/urUm3VG")}>
<a className="tab blurple inactive" href="https://discord.gg/urUm3VG">
Discord
</button>
<button className="tab github inactive" onClick={() => window.open("https://github.com/pmret/papermario")}>
</a>
<a className="tab github inactive" href="https://github.com/pmret/papermario">
GitHub
</button>
</a>
</nav>
<main id="main" ref={pane} className={clsx(tabs[paneIndex].color)} style={{
transform: `perspective(4000px) rotateX(${rotation}deg)`,