refactor: move onboarding app to react
This commit is contained in:
parent
06145abfa4
commit
15f7534995
|
@ -35,6 +35,7 @@
|
||||||
"p-defer": "^4.0.0",
|
"p-defer": "^4.0.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router-dom": "^6.14.2",
|
||||||
"webextension-polyfill": "^0.10.0"
|
"webextension-polyfill": "^0.10.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -3109,6 +3110,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
|
||||||
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
|
"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": {
|
"node_modules/@rollup/plugin-inject": {
|
||||||
"version": "5.0.3",
|
"version": "5.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-5.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-5.0.3.tgz",
|
||||||
|
@ -18425,6 +18434,36 @@
|
||||||
"node": ">=0.10.0"
|
"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": {
|
"node_modules/read-cache": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
"p-defer": "^4.0.0",
|
"p-defer": "^4.0.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router-dom": "^6.14.2",
|
||||||
"webextension-polyfill": "^0.10.0"
|
"webextension-polyfill": "^0.10.0"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 we’re doing to
|
||||||
|
provide accessible access to the open web for everyone.
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
import Onboarding from './components/onboarding/Onboarding.svelte'
|
import { createRoot } from "react-dom";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
const app = new Onboarding({
|
import App from "./apps/onboarding/App.tsx";
|
||||||
target: document.getElementById('app'),
|
|
||||||
})
|
|
||||||
|
|
||||||
export default app
|
const root = createRoot(document.getElementById("app"));
|
||||||
|
|
||||||
|
root.render(React.createElement(App));
|
||||||
|
|
Reference in New Issue