Tabs and loadings

This commit is contained in:
Hamcha 2020-06-16 17:08:44 +02:00
parent 9ab5c6816b
commit 33affe9b8b
Signed by: hamcha
GPG key ID: 41467804B19A3315
6 changed files with 195 additions and 35 deletions

56
assets/images/speen.svg Normal file
View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
width="100vmin"
height="100vmin
"
viewBox="0 0 340 340"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:space="preserve"
xmlns:serif="http://www.serif.com/"
style="
fill-rule: evenodd;
clip-rule: evenodd;
stroke-linejoin: round;
stroke-miterlimit: 2;
"
>
<style>
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
#circleboi {
transform-origin: 50% 50%;
animation-name: rotate;
animation-duration: 6s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
</style>
<path
id="text"
d="M104.26,279.309L104.26,92.146L71.496,92.146L71.496,66.804L159.14,66.804L159.14,92.144L126.376,92.146L126.376,279.309M205.817,279.309C195.943,279.309 188.452,276.504 183.552,270.972C178.469,265.237 175.892,256.426 175.892,244.783L175.892,101.33C175.892,89.687 178.469,80.876 183.552,75.14C188.45,69.61 195.942,66.806 205.816,66.806L238.58,66.806C258.435,66.806 268.504,78.42 268.504,101.33L268.504,129.131L247.379,129.131L247.379,109.174C247.379,98.671 241.346,92.147 231.631,92.147L213.759,92.147C203.899,92.147 198.009,98.512 198.009,109.174L198.009,236.938C198.009,247.601 203.899,253.966 213.759,253.966L231.629,253.966C241.491,253.966 247.379,247.601 247.379,236.939L247.379,193.575L230.499,193.575L230.499,168.23L268.503,168.23L268.503,244.785C268.503,267.695 258.435,279.309 238.579,279.309L205.815,279.309L205.817,279.309Z"
style="fill-rule: nonzero;" fill="#a4b4c596"
/>
<g mask="url(#textmask)" fill="#a4b4c596">
<path
id="circleboi"
d="M52.637,76.985L18.344,100.266L21.88,141.563L2.335,178.114L24.655,213.037L24.334,254.481L60.327,275.033L79.305,311.88L120.727,313.353L154.653,337.161L192.017,319.211L233.12,324.528L257.861,291.272L296.727,276.871L303.177,235.932L330.903,205.122L317.587,165.871L327.817,125.706L297.788,97.137L288.18,56.819L248.314,45.477L221.07,14.243L180.501,22.728L141.862,7.731L109.881,34.098L68.701,38.776L52.636,76.985L52.637,76.985ZM216.761,280.742L233.774,257.052L261.937,246.736L266.17,217.095L286.412,194.913L276.395,166.806L284.078,137.84L262.106,117.706L255.471,88.592L226.577,81.044L207.143,58.451L177.947,65.218L150.167,54.321L127.357,73.853L97.594,77.15L86.396,104.972L61.469,121.707L64.448,151.446L50.067,177.785L66.541,202.627L66.007,232.209L78.356,239.26L92.195,246.791L105.376,272.936L118.069,273.388L118.261,273.589L135.534,273.821L159.847,291.067L186.628,277.524L216.245,281.435L216.761,280.742Z"
/>
</g>
<mask id="textmask">
<rect x="0" y="0" width="340" height="340" style="fill: white;" />
<path
d="M274.325,244.784C274.325,271.12 261.665,285.129 238.581,285.129L205.817,285.129C197.487,285.129 190.939,282.647 185.081,279.839C170.502,272.852 169.064,241.181 169.064,241.181L132.196,241.181L132.196,280.645C132.196,283.725 130.956,285.127 128.224,285.127L102.413,285.127C99.931,285.127 98.441,283.727 98.441,280.645L98.441,249.868L98.131,249.373L98.655,97.966L69.646,97.966C67.164,97.966 65.674,96.284 65.674,93.483L65.674,65.464C65.674,62.664 67.164,60.984 69.647,60.984L131.251,60.984L158.546,60.923C163.315,60.54 164.919,62.86 164.619,66.804L164.619,91.422L170.619,91.422C172.787,71.547 185.831,60.108 208.749,60.983L238.581,60.983C261.666,60.983 274.325,74.991 274.325,101.328L274.325,118.878L274.326,202.76L274.326,244.782L274.325,244.784Z"
style="fill-rule: nonzero;"
fill="black"
/>
</mask>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -1,15 +1,21 @@
import * as React from "react";
import TabItem from "./components/TabItem";
import WikiPage from "./components/WikiPage";
import TabList, { TabListItem } from "./components/TabList";
import { useState } from "react";
export default function App() {
const [tabs, setTabs] = useState<TabListItem[]>([
{ page: "Guide_to_medicine" },
// { page: "Guide_to_chemistry" },
]);
const [activeTab, setActiveTab] = useState(0);
return (
<React.Fragment>
<nav id="tablist">
<TabItem name="test" />
</nav>
<TabList tabs={tabs} active={activeTab} />
<section id="tabs">
<WikiPage page="Guide_to_medicine" />
{tabs.map((tab, i) => (
<WikiPage page={tab.page} visible={activeTab == i} />
))}
</section>
</React.Fragment>
);

View file

@ -1,5 +0,0 @@
import * as React from "react";
export default function TabItem({ name }) {
return <p>{name}</p>;
}

View file

@ -0,0 +1,28 @@
import * as React from "react";
export interface TabListItem {
page: string;
}
export interface TabListProps {
tabs: TabListItem[];
active: number;
}
function TabItem({ name, active }) {
return (
<div className={active ? "tab active" : "tab"}>
{name.replace(/_/gi, " ")}
</div>
);
}
export default function TabList({ tabs, active }: TabListProps) {
return (
<nav className="tab-list">
{tabs.map((tab, i) => (
<TabItem name={tab.page} active={i == active} />
))}
</nav>
);
}

View file

@ -3,6 +3,7 @@ import { darken, ColorFmt, lighten } from "../darkmode";
import * as React from "react";
import { useState, useEffect, useRef } from "react";
import userscript from "../userscript";
import speen from "~/assets/images/speen.svg";
function fixup(html: string): string {
// Convert relative links to absolute
@ -27,19 +28,12 @@ function fixup(html: string): string {
td.setAttribute("bgcolor", darken(bgcolor, ColorFmt.HEX).slice(1));
});
node.querySelectorAll("*[style]").forEach((td: HTMLElement) => {
const inlineCSS = td.getAttribute("style");
let bgcolor = null;
if (inlineCSS.includes("background-color:")) {
bgcolor = td.style.backgroundColor;
} else if (inlineCSS.includes("background:")) {
bgcolor = td.style.background;
} else {
return;
if (td.style.backgroundColor != "") {
td.style.backgroundColor = darken(td.style.backgroundColor, ColorFmt.RGB);
}
if (td.style.background != "") {
td.style.backgroundColor = darken(td.style.background, ColorFmt.RGB);
}
td.setAttribute(
"style",
inlineCSS + ";background-color:" + darken(bgcolor, ColorFmt.RGB)
);
});
// Lighten fgcolors
@ -53,13 +47,13 @@ function fixup(html: string): string {
// Remove fixed widths
node.querySelectorAll("table[width]").forEach((td) => {
const width = td.getAttribute("width");
if (width.includes("%")) {
// Leave it alone
return;
}
td.setAttribute("width", "100%");
});
node.querySelectorAll("table[style]").forEach((td: HTMLTableElement) => {
if (td.style.width != "") {
td.style.width = "100%";
}
});
// Group headers and content so stickies don't overlap
node.querySelectorAll("h3,h2").forEach((h3) => {
@ -92,7 +86,7 @@ function fixup(html: string): string {
return node.innerHTML;
}
export default function WikiPage({ page }) {
export default function WikiPage({ page, visible }) {
const [data, setData] = useState({ loaded: false, html: "" });
const containerRef = useRef(null);
@ -108,18 +102,33 @@ export default function WikiPage({ page }) {
// Page fetched, instance userscript
useEffect(() => {
if (data.loaded) {
console.log("Injecting userscript!");
userscript(containerRef.current, page);
}
}, [data]);
if (!data.loaded) {
return <p>You start skimming through the manual...</p>;
return (
<div className="page waiting">
<p
style={{
display: visible ? "block" : "none",
}}
>
You start skimming through the manual...
</p>
<div className="speen">
<img src={speen} />
</div>
</div>
);
} else {
return (
<div
ref={containerRef}
className="page"
style={{
display: visible ? "block" : "none",
}}
dangerouslySetInnerHTML={{ __html: data.html }}
></div>
);

View file

@ -1,3 +1,5 @@
$nanotrasen: #384e68;
html,
body {
margin: 0;
@ -21,8 +23,6 @@ body {
}
}
$nanotrasen: #384e68;
#app {
height: 100%;
display: grid;
@ -40,12 +40,62 @@ $nanotrasen: #384e68;
grid-template-rows: 40px 1fr;
}
::-webkit-scrollbar {
width: 14pt;
}
::-webkit-scrollbar-track {
background: linear-gradient(
to bottom,
darken($nanotrasen, 0%),
darken($nanotrasen, 10%),
darken($nanotrasen, 0%)
);
border: 1px solid lighten($nanotrasen, 10%);
}
::-webkit-scrollbar-thumb {
border-radius: 2px;
background: linear-gradient(
to bottom,
lighten($nanotrasen, 20%),
lighten($nanotrasen, 30%),
lighten($nanotrasen, 20%)
);
border: 1px solid lighten($nanotrasen, 10%);
}
#tabs {
grid-row: 2;
padding: 10pt;
overflow-y: scroll;
z-index: 1;
padding-top: 10pt;
.page {
&.waiting {
display: flex;
flex-direction: column;
height: 100%;
.speen {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
img {
flex: 1;
width: 50%;
height: 50%;
opacity: 0.9;
}
}
}
p,
h2,
h3,
h4 {
padding-left: 10pt;
padding-right: 10pt;
}
a[href] {
color: white;
}
@ -56,7 +106,7 @@ $nanotrasen: #384e68;
position: sticky;
top: -10pt;
background: $nanotrasen;
padding: 5px 10px;
padding: 10px;
z-index: 999;
}
#toctitle h2 {
@ -69,6 +119,22 @@ $nanotrasen: #384e68;
}
}
#tablist {
$tab-active: lighten($nanotrasen, 10%);
.tab-list {
grid-row: 1;
display: flex;
border-bottom: 2px solid $tab-active;
.tab {
max-width: 200px;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
&.active {
background-color: $tab-active;
}
}
}