refactor: move onboarding app to react

This commit is contained in:
Derrick Hammer 2023-07-28 12:47:37 -04:00
parent 06145abfa4
commit 15f7534995
Signed by: pcfreak30
GPG Key ID: C997C339BE476FF2
6 changed files with 380 additions and 5 deletions

39
npm-shrinkwrap.json generated
View File

@ -35,6 +35,7 @@
"p-defer": "^4.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.14.2",
"webextension-polyfill": "^0.10.0"
},
"devDependencies": {
@ -3109,6 +3110,14 @@
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
},
"node_modules/@remix-run/router": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.7.2.tgz",
"integrity": "sha512-7Lcn7IqGMV+vizMPoEl5F0XDshcdDYtMI6uJLQdQz5CfZAwy3vvGKYSUk789qndt5dEC4HfSjviSYlSoHGL2+A==",
"engines": {
"node": ">=14"
}
},
"node_modules/@rollup/plugin-inject": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-5.0.3.tgz",
@ -18425,6 +18434,36 @@
"node": ">=0.10.0"
}
},
"node_modules/react-router": {
"version": "6.14.2",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.14.2.tgz",
"integrity": "sha512-09Zss2dE2z+T1D03IheqAFtK4UzQyX8nFPWx6jkwdYzGLXd5ie06A6ezS2fO6zJfEb/SpG6UocN2O1hfD+2urQ==",
"dependencies": {
"@remix-run/router": "1.7.2"
},
"engines": {
"node": ">=14"
},
"peerDependencies": {
"react": ">=16.8"
}
},
"node_modules/react-router-dom": {
"version": "6.14.2",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.14.2.tgz",
"integrity": "sha512-5pWX0jdKR48XFZBuJqHosX3AAHjRAzygouMTyimnBPOLdY3WjzUSKhus2FVMihUFWzeLebDgr4r8UeQFAct7Bg==",
"dependencies": {
"@remix-run/router": "1.7.2",
"react-router": "6.14.2"
},
"engines": {
"node": ">=14"
},
"peerDependencies": {
"react": ">=16.8",
"react-dom": ">=16.8"
}
},
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",

View File

@ -58,6 +58,7 @@
"p-defer": "^4.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.14.2",
"webextension-polyfill": "^0.10.0"
},
"overrides": {

136
ui/apps/onboarding/App.scss Normal file
View File

@ -0,0 +1,136 @@
@import "../../styles/global";
@import "../../styles/mixins";
@import "../../styles/vars";
main {
position: relative;
background: #080808;
}
.art,
.content {
position: absolute;
top: 0;
bottom: 0;
width: 50%;
}
.art {
transition: opacity 250ms ease;
opacity: 0;
&.art-1.visible, &.art-2.visible, &.art-3.visible, &.art-4.visible {
opacity: 1;
}
}
.art-1 {
left: 0;
background-image: url("../../assets/onboarding-1.jpg");
background-position: 50%;
background-size: cover;
border-right: 1px solid #363636;
}
.art-2 {
left: 50%;
background-image: url("../../assets/onboarding-2.jpg");
background-position: 50%;
background-size: cover;
border-left: 1px solid #363636;
}
.art-3 {
left: 50%;
background-image: url("../../assets/onboarding-3.jpg");
background-position: 50%;
background-size: cover;
border-left: 1px solid #363636;
}
.art-4 {
left: 50%;
background-image: url("../../assets/onboarding-4.jpg");
background-position: 50%;
background-size: cover;
border-left: 1px solid #363636;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
left: 50%;
padding: 5.5em 3.75%;
color: #fff;
background: #080808;
transition: left 250ms cubic-bezier(0.34, 1.56, 0.64, 1);
overflow: auto;
> div:first-child {
flex-grow: 1;
display: flex;
justify-content: center;
align-items: center;
max-width: 43.2em;
}
}
.page {
display: flex;
flex-direction: column;
justify-content: flex-end;
min-height: 42em;
}
h1 {
font-family: $font-family-jetbrains-mono;
@include fluid-font-size(3.125rem);
line-height: 110%;
}
p {
@include fluid-font-size(1.25rem);
margin-top: 1.4em;
line-height: 122%;
color: #808080;
}
.btn-wrapper {
margin-top: 5.5em;
a {
text-decoration: none;
color: inherit;
}
}
.grant-info {
@include fluid-font-size(1rem);
margin-top: 5em;
max-width: 27em;
line-height: 125%;
color: #808080;
a {
color: #fff;
}
}
.started {
.content {
left: 0;
}
}
@media screen and (max-width: 48rem) {
.art {
display: none;
}
.content {
left: 0;
width: 100%;
transition: none;
}
}

153
ui/apps/onboarding/App.tsx Normal file
View File

@ -0,0 +1,153 @@
import {
createHashRouter,
RouteObject,
RouterProvider,
useMatches,
} from "react-router-dom";
import Page from "./components/Page.js";
// @ts-ignore
import lumeLogo from "../../assets/lume-logo.png";
// @ts-ignore
import classNames from "classnames";
import "./App.scss";
// @ts-ignore
import browser from "webextension-polyfill";
const contentPages = [
{
heading: <>Thank you for supporting an open web.</>,
content: (
<>
We are an independent, pure organization. We have decided not to take
money from venture capitalists. Nor do we have a large treasury funding
our work.
</>
),
},
{
heading: <>Thank you for supporting an open web.</>,
content: (
<>
Easy Access to Web3. With native Handshake (HNS) and Ethereum (ENS)
support, you can forget eth.link and hns.is. This is your gateway.
</>
),
},
{
heading: <>Thank you for supporting an open web.</>,
content: (
<>
We are an independent, pure organization. We have decided not to take
money from venture capitalists. Nor do we have a large treasury funding
our work.
</>
),
},
{
heading: <>Thank you for supporting an open web.</>,
content: (
<>
Stop worrying about being vendor-locked. Remain flexible and reduce your
storage costs by 50% or more. Lume is affordable storage on-demand.
</>
),
},
] as {
heading: React.ReactElement;
content: React.ReactElement;
}[];
contentPages.map((page, index) => {
if (!index) {
return;
}
});
const childRoutes = contentPages.slice(1).map((item, index): RouteObject => {
return {
path: `page-${index + 1}`,
handle: {
page: index + 1,
},
};
});
const rootRoute = {
path: "/",
element: <Content />,
handle: {
page: 0,
},
};
const router = createHashRouter([{ ...rootRoute, children: childRoutes }]);
export default function App() {
return (
<>
<header>
<img src={lumeLogo} alt="Lume" />
</header>
<RouterProvider router={router} />
</>
);
}
function Content() {
const routeData = useMatches();
const accountUrl = browser.runtime.getURL("account.html");
const handle = routeData.pop().handle as { page: number };
const start = handle.page === 0 ? `page-1` : false;
const next =
!start && contentPages.length - 1 > handle.page
? `page-${handle.page + 1}`
: false;
const back = handle.page > 1 ? `page-${handle.page - 1}` : false;
const getStarted =
handle.page + 1 === contentPages.length ? accountUrl : false;
const skip = handle.page === 1 ? accountUrl : false;
return (
<main className={classNames({ started: handle.page > 0 })}>
{Array(contentPages.length)
.fill(0)
.map((_, index) => (
<div
className={classNames("art", `art-${index + 1}`, {
visible: handle.page === index,
})}
/>
))}
<div className="content">
<div>
<Page
heading={contentPages[handle.page].heading}
content={contentPages[handle.page].content}
start={start}
skip={skip}
back={back}
next={next}
getStarted={getStarted}
/>
</div>
<GrantInfo />
</div>
</main>
);
}
function GrantInfo() {
return (
<div className="grant-info">
Lume is a 503c Grant recipient,
<a href="https://lumeweb.com">learn more</a> about the work were doing to
provide accessible access to the open web for everyone.
</div>
);
}

View File

@ -0,0 +1,45 @@
import { Link } from "react-router-dom";
export default function Page({
heading,
content,
start,
skip,
next,
back,
getStarted,
}) {
return (
<div className="page">
<h1>{heading}</h1>
<p>{content}</p>
<div className="btn-wrapper">
{start && (
<Link to={start}>
<button className="btn-main">Begin</button>
</Link>
)}
{skip && (
<a href={skip} className="btn-main btn-black">
<button>Skip</button>
</a>
)}
{back && (
<Link to={back} className="btn-main btn-black">
<button>Back</button>
</Link>
)}
{next && (
<Link to={next} className="btn-main">
<button>Next</button>
</Link>
)}
{getStarted && (
<a href={getStarted} className="btn-main btn-green">
<button>Get started</button>
</a>
)}
</div>
</div>
);
}

View File

@ -1,7 +1,8 @@
import Onboarding from './components/onboarding/Onboarding.svelte'
import { createRoot } from "react-dom";
import React from "react";
const app = new Onboarding({
target: document.getElementById('app'),
})
import App from "./apps/onboarding/App.tsx";
export default app
const root = createRoot(document.getElementById("app"));
root.render(React.createElement(App));