Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New theme #72

Draft
wants to merge 15 commits into
base: master
Choose a base branch
from
12 changes: 12 additions & 0 deletions packages/frontend/PAGES.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const pages = [
{ label: "Dashboard", id: "dashboard", path: "/" },
{ label: "Automate", id: "automate", path: "/automate" },
{ label: "Swap Tokens", id: "swap-tokens", path: "/swap-tokens" },
{
label: "Import Positions",
id: "import-positions",
path: "/import-positions",
},
{ label: "Exit Positions", id: "exit-positions", path: "/exit-positions" },
{ label: "Info", id: "info", path: "/info" },
];
120 changes: 120 additions & 0 deletions packages/frontend/features/layout/Appbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import Router from "next/router";
import styled from "styled-components";
import { useState } from "react";
import { pages } from "../../PAGES";

const Container = styled.div`
color: white;
background: var(--bg);
height: 72px;
box-shadow: 0 6px 6px 0px rgba(0, 0, 0, 0.3);
z-index: 1;
position: relative;
`;

const LogoText = styled.div`
color: var(--highlight);
text-shadow: 0px 0px 12px rgba(254, 146, 31, 0.4);

font-family: IBM Plex Sans, Roboto, Sans-Serif;
font-size: 32px;
font-weight: 200;
text-transform: uppercase;
letter-spacing: 4px;

position: absolute;
left: 50%;
top: 50%;
transform: translate(calc(-50% + 4px), -50%);
`;

const MenuButton = styled.div`
color: #aaa;
font-size: 24px;
padding: 12px;
position: absolute;
right: 0;
top: 50%;
transform: translate(-12px, -50%);
cursor: pointer;
`;

const Menu = styled.div`
width: 90%;
height: 100vh;
background: var(--dark-bg);
position: fixed;
z-index: 1;
left: ${(p) => (p.isOpen ? `0` : `-100%`)};
transition: left 200ms ease-in-out;

display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
`;

const Overlay = styled.div`
pointer-events: ${(p) => (p.show ? `unset` : `none`)};
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.5);
position: fixed;
z-index: 1;
opacity: ${(p) => (p.show ? `1` : `0`)};
transition: opacity 200ms ease-in-out;
`;

const CloseButton = styled.div`
color: white;
font-size: 24px;
padding: 12px 16px;
position: absolute;
right: 12px;
top: 12px;
cursor: pointer;
`;

const MenuItem = styled.div`
font-family: IBM Plex Sans;
text-transform: uppercase;
font-weight: 200;
letter-spacing: 4px;
color: ${(p) => (p.active ? `var(--highlight)` : `#999`)};
text-align: center;
margin-bottom: 3rem;
font-size: 18px;
cursor: pointer;
`;

const Appbar = ({ activePage }) => {
const [isOpen, setIsOpen] = useState(false);
const openMenu = () => setIsOpen(true);
const closeMenu = () => setIsOpen(false);
return (
<>
<Container>
<LogoText>Dedge</LogoText>
<MenuButton onClick={openMenu}>☰</MenuButton>
</Container>
<Overlay show={isOpen} onClick={closeMenu} />
<Menu isOpen={isOpen}>
<CloseButton onClick={closeMenu}>✕</CloseButton>
{pages.map((page) => (
<MenuItem
key={page.id}
active={page.path === activePage}
onClick={() => {
closeMenu()
Router.push(page.path)
}}
>
{page.label}
</MenuItem>
))}
</Menu>
</>
);
};

export default Appbar;
28 changes: 28 additions & 0 deletions packages/frontend/features/layout/AppbarLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import styled from "styled-components";
import Appbar from "./Appbar";
import StatusBar from "../status-bar/StatusBar";

const Container = styled.div`
width: 100%;
height: 100vh;
background: var(--dark-bg);
display: flex;
flex-direction: column;
`;

const Content = styled.div`
overflow: auto;
flex: 1;
`;

const AppbarLayout = ({ children, activePage }) => {
return (
<Container>
<Appbar activePage={activePage} />
<StatusBar />
<Content>{children}</Content>
</Container>
);
};

export default AppbarLayout;
14 changes: 14 additions & 0 deletions packages/frontend/features/layout/Layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react";
import useScreenSize from "./useScreenSize";
import AppbarLayout from "./AppbarLayout";
import SidebarLayout from "./SidebarLayout";

const Layout = ({ children, activePage }) => {
const { isMobile } = useScreenSize();
if (isMobile) {
return <AppbarLayout activePage={activePage}>{children}</AppbarLayout>;
}
return <SidebarLayout activePage={activePage}>{children}</SidebarLayout>;
};

export default Layout;
61 changes: 61 additions & 0 deletions packages/frontend/features/layout/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import Router from "next/router";
import styled from "styled-components";
import useScreenSize from "./useScreenSize";
import { pages } from "../../PAGES";

const Container = styled.div`
background: var(--bg);
width: ${(p) => p.width};
height: 100%;

text-align: right;
padding: 24px;
display: flex;
flex-direction: column;
justify-content: center;
`;

const LogoText = styled.div`
font-family: IBM Plex Sans, sans-serif;
font-size: 24px;
font-weight: 300;
color: var(--highlight);
text-transform: uppercase;
letter-spacing: 4px;
margin-right: -6px;
text-shadow: 0px 0px 12px rgba(254, 146, 31, 0.4);

margin-top: 1rem;
margin-bottom: 2rem;
`;

const NavItem = styled.div`
cursor: pointer;
color: ${(p) => (p.active ? `white` : `#666`)};
margin-bottom: 2rem;

&:hover {
color: var(--highlight);
}
`;

const Sidebar = ({ activePage }) => {
const { isTablet } = useScreenSize();
return (
<Container width={isTablet ? `180px` : `256px`}>
<LogoText>Dedge</LogoText>

{pages.map((page) => (
<NavItem
key={page.id}
active={activePage === page.path}
onClick={() => Router.push(page.path)}
>
{page.label}
</NavItem>
))}
</Container>
);
};

export default Sidebar;
37 changes: 37 additions & 0 deletions packages/frontend/features/layout/SidebarLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import styled from "styled-components";
import Sidebar from "./Sidebar";
import StatusBar from "../status-bar/StatusBar";

const Container = styled.div`
width: 100%;
height: 100vh;
background: var(--dark-bg);
display: flex;
`;

const Main = styled.div`
height: 100%;
flex: 1;
overflow: auto;
display: flex;
flex-direction: column;
`;

const Content = styled.div`
flex: 1;
overflow: auto;
`;

const SidebarLayout = ({ children, activePage }) => {
return (
<Container>
<Sidebar activePage={activePage} />
<Main>
<StatusBar />
<Content>{children}</Content>
</Main>
</Container>
);
};

export default SidebarLayout;
11 changes: 11 additions & 0 deletions packages/frontend/features/layout/useScreenSize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { useMedia } from "use-media";

const useScreenSize = () => {
const isDesktop = useMedia({ minWidth: "1200px" });
const isTablet = useMedia({ minWidth: "600px" }) && !isDesktop;
const isMobile = !isDesktop && !isTablet;

return { isDesktop, isTablet, isMobile };
};

export default useScreenSize;
98 changes: 98 additions & 0 deletions packages/frontend/features/status-bar/MobileStatusBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import styled from "styled-components";
import { useState } from "react";

const Container = styled.div`
width: 100%;
height: 72px;
background: black;
position: relative;
`;

const Content = styled.div`
background black;
display: grid;
grid-template-columns: 1fr 1fr;
height: ${(p) => (p.isOpen ? `216px` : `72px`)};
overflow: hidden;
transition: height 200ms ease-in-out;
position: relative;
`;

const StatusItem = styled.div`
height: 72px;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
`;
const Value = styled.div`
color: white;
`;
const Label = styled.div`
color: var(--highlight);
font-size: 12px;
`;

const TriangleIndicator = styled.div`
position: absolute;
bottom: 4px;
left: 50%;
color: rgba(255, 255, 255, 0.15);
font-size: 24px;
transform: ${(p) =>
p.invert ? "rotate(-180deg) translateX(50%)" : "translateX(-50%)"};
`;

const Status = ({ label, value, percent = false }) => {
const valueStr = percent
? `${parseFloat(value).toFixed(2)}%`
: `$${parseFloat(value).toFixed(2)}`;
return (
<StatusItem>
<Value>{valueStr}</Value>
<Label>{label}</Label>
</StatusItem>
);
};

const LastUpdate = ({ lastUpdated }) => {
const valueStr = "23 seconds ago";
return (
<StatusItem>
<Value>{valueStr}</Value>
<Label>Last Updated</Label>
</StatusItem>
);
};

const MobileStatusBar = ({ statusData }) => {
const [isOpen, setIsOpen] = useState(false);
const toggleOpen = () => setIsOpen(!isOpen);

const {
supplyBalance,
borrowBalance,
borrowPercent,
liquidationPrice,
ethPrice,
lastUpdated,
} = statusData;
return (
<Container>
<Content isOpen={isOpen} onClick={toggleOpen}>
<Status label="Supply Balance" value={supplyBalance} />
<Status label="Borrow Balance" value={borrowBalance} />

<Status label="Borrow Percent" value={borrowPercent} percent />
<Status label="Liquidation Price" value={liquidationPrice} />

<Status label="ETH Price" value={ethPrice} />
<LastUpdate lastUpdated={lastUpdated} />

<TriangleIndicator invert={isOpen}>▾</TriangleIndicator>
</Content>
</Container>
);
};

export default MobileStatusBar;
Loading