aesthetic improvements

This commit is contained in:
Paul Miller
2023-04-12 12:30:28 -05:00
parent 4f346dad71
commit 3b92e34309
12 changed files with 164 additions and 109 deletions

View File

@@ -0,0 +1,3 @@
<svg width="36" height="36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M35.597 3.477a1.5 1.5 0 0 1 .278 1.622l-11.768 27a1.5 1.5 0 0 1-2.387.509L14.157 25.7l-3.036 4.578a1.5 1.5 0 0 1-2.73-.58L6.825 20.34.872 17.596a1.5 1.5 0 0 1 .125-2.775l33-11.734a1.5 1.5 0 0 1 1.6.39ZM9.827 20.1l.896 5.35 1.902-2.869a1.5 1.5 0 0 1 .236-.276l11.04-10.122L9.826 20.1Zm8.665-8.317-13.02 4.63 2.633 1.213 10.387-5.843Zm11.805-1.395-14.2 13.02 6.098 5.57 8.102-18.59Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 531 B

View File

@@ -1,5 +1,5 @@
import logo from '~/assets/icons/mutiny-logo.svg';
import { SafeArea } from "~/components/layout";
import { NodeManagerGuard, SafeArea } from "~/components/layout";
import BalanceBox from "~/components/BalanceBox";
import NavBar from "~/components/NavBar";
@@ -9,6 +9,7 @@ import KitchenSink from './KitchenSink';
export default function App() {
return (
<NodeManagerGuard>
<SafeArea>
<main class='flex flex-col gap-4 py-8 px-4 max-w-[800px] mx-auto'>
<header>
@@ -22,5 +23,6 @@ export default function App() {
</main>
<NavBar activeTab="home" />
</SafeArea>
</NodeManagerGuard>
);
}

View File

@@ -15,14 +15,10 @@ export default function BalanceBox() {
const [state, _] = useMegaStore();
const fetchBalance = async () => {
if (state.node_manager) {
console.log("Refetching balance");
await state.node_manager.sync();
const balance = await state.node_manager.get_balance();
await state.node_manager?.sync();
const balance = await state.node_manager?.get_balance();
return balance
} else {
return undefined
}
};
const [balance, { refetch: refetchBalance }] = createResource(fetchBalance);
@@ -63,7 +59,7 @@ export default function BalanceBox() {
</h1>
</div>
<div class="flex gap-2 py-4">
<ButtonLink href="/scanner" intent="green">Send</ButtonLink>
<ButtonLink href="/send" intent="green">Send</ButtonLink>
<ButtonLink href="/receive" intent="blue">Receive</ButtonLink>
</div>
</div>

View File

@@ -60,12 +60,12 @@ function ConnectPeer(props: { refetchPeers: RefetchPeersType }) {
};
return (
<form class="border border-white/20 rounded-xl p-2 flex flex-col gap-4" onSubmit={onSubmit} >
<form class="border border-white/20 rounded-xl p-4 flex flex-col gap-4" onSubmit={onSubmit} >
<TextField.Root
value={value()}
onValueChange={setValue}
validationState={(value() == "" || value().startsWith("mutiny:")) ? "valid" : "invalid"}
class="flex flex-col gap-2"
class="flex flex-col gap-4"
>
<TextField.Label class="text-sm font-semibold uppercase" >Connect Peer</TextField.Label>
<TextField.Input class="w-full p-2 rounded-lg text-black" placeholder="mutiny:028241..." />

View File

@@ -1,16 +1,17 @@
import mutiny_m from '~/assets/icons/m.svg';
import scan from '~/assets/icons/scan.svg';
import airplane from '~/assets/icons/airplane.svg';
import settings from '~/assets/icons/settings.svg';
import { A } from "solid-start";
type ActiveTab = 'home' | 'scan' | 'settings' | 'none';
type ActiveTab = 'home' | 'scan' | 'send' | 'settings' | 'none';
export default function NavBar(props: { activeTab: ActiveTab }) {
const activeStyle = 'h-full border-t-2 border-b-2 border-b-black flex flex-col justify-center md:border-t-0 md:border-b-0 md:p-2 md:bg-white/20 md:rounded-xl'
const activeStyle = 'h-full border-t-2 border-b-2 border-b-sidebar-gray flex flex-col justify-center md:border-t-0 md:border-b-0 md:p-2 md:bg-white/20 md:rounded-xl'
const inactiveStyle = "md:p-2 md:hover:bg-white/10 md:rounded-xl"
return (
<nav class='bg-black fixed bottom-0 shadow-lg z-40 w-full safe-bottom md:top-0 md:bottom-auto md:left-0 md:w-auto md:h-full'>
<nav class='bg-sidebar-gray fixed bottom-0 shadow-lg z-40 w-full safe-bottom md:top-0 md:bottom-auto md:left-0 md:w-auto md:h-full'>
<ul class='h-16 flex justify-between px-16 items-center md:flex-col md:justify-start md:gap-4 md:px-4 md:mt-4'>
<li class={props.activeTab === "home" ? activeStyle : inactiveStyle}>
<A href="/">
@@ -22,6 +23,11 @@ export default function NavBar(props: { activeTab: ActiveTab }) {
<img src={scan} alt="scan" />
</A>
</li>
<li class={props.activeTab === "send" ? activeStyle : inactiveStyle}>
<A href="/send">
<img src={airplane} alt="send" />
</A>
</li>
<li class={props.activeTab === "settings" ? activeStyle : inactiveStyle}>
<A href="/settings">
<img src={settings} alt="settings" />

View File

@@ -3,14 +3,14 @@ import { children, JSX, ParentComponent, splitProps } from "solid-js";
import { Dynamic } from "solid-js/web";
import { A } from "solid-start";
const button = cva(["p-4", "rounded-xl", "text-xl", "font-semibold"], {
const button = cva(["p-4", "rounded-xl", "text-xl", "font-semibold", "disabled:opacity-50", "transition"], {
variants: {
intent: {
active: "bg-white text-black",
inactive: "bg-black text-white border border-white disabled:opacity-50",
blue: "bg-[#3B6CCC] text-white",
red: "bg-[#F61D5B] text-white",
green: "bg-[#1EA67F] text-white",
inactive: "bg-black text-white border border-white hover:enabled:text-[#3B6CCC]",
blue: "bg-m-blue text-white shadow-inner-button hover:bg-m-blue-dark text-shadow-button",
red: "bg-m-red text-white shadow-inner-button hover:bg-m-red-dark text-shadow-button",
green: "bg-m-green text-white shadow-inner-button hover:bg-m-green-dark text-shadow-button",
},
layout: {
flex: "flex-1",

View File

@@ -1,7 +1,8 @@
import { ParentComponent, Show } from "solid-js"
import { ParentComponent, Show, Suspense } from "solid-js"
import Linkify from "./Linkify"
import { Button, ButtonLink } from "./Button"
import { Separator } from "@kobalte/core"
import { useMegaStore } from "~/state/megaStore"
const SmallHeader: ParentComponent = (props) => <header class='text-sm font-semibold uppercase'>{props.children}</header>
@@ -29,6 +30,25 @@ const SafeArea: ParentComponent<{ main?: boolean }> = (props) => {
)
}
function FullscreenLoader() {
return (
<div class="w-screen h-screen flex justify-center items-center">
<LoadingSpinner />
</div>
);
}
const NodeManagerGuard: ParentComponent = (props) => {
const [state, _] = useMegaStore();
return (
<Suspense fallback={<FullscreenLoader />}>
<Show when={state.node_manager}>
{props.children}
</Show>
</Suspense>
)
}
const LoadingSpinner = () => {
return (<div role="status" class="w-full h-full grid" >
<svg aria-hidden="true" class="w-8 h-8 mr-2 text-gray-200 animate-spin dark:text-gray-600 fill-m-red place-self-center" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -41,4 +61,4 @@ const LoadingSpinner = () => {
const Hr = () => <Separator.Root class="my-4 border-white/20" />
export { SmallHeader, Card, SafeArea, LoadingSpinner, Button, ButtonLink, Linkify, Hr }
export { SmallHeader, Card, SafeArea, LoadingSpinner, Button, ButtonLink, Linkify, Hr, NodeManagerGuard, FullscreenLoader }

View File

@@ -4,7 +4,7 @@
body {
@apply text-white bg-black;
@apply bg-fixed bg-no-repeat bg-gradient-to-b from-black to-[#0b215b];
@apply bg-fixed bg-no-repeat bg-richer-fade;
overscroll-behavior-y: none;
min-height: 100.3%;
}

View File

@@ -1,8 +1,8 @@
import { TextField } from "@kobalte/core";
import { createMemo, createResource, createSignal, Match, Show, Suspense, Switch } from "solid-js";
import { createMemo, createResource, createSignal, Match, Switch } from "solid-js";
import { QRCodeSVG } from "solid-qr-code";
import { AmountInput } from "~/components/AmountInput";
import { Button, Card, SafeArea, SmallHeader } from "~/components/layout";
import { Button, Card, NodeManagerGuard, SafeArea, SmallHeader } from "~/components/layout";
import NavBar from "~/components/NavBar";
import { useMegaStore } from "~/state/megaStore";
import { satsToUsd } from "~/utils/conversions";
@@ -91,11 +91,11 @@ export default function Receive() {
const amountInUsd = createMemo(() => satsToUsd(price(), parseInt(amount()) || 0, true))
return (
<NodeManagerGuard>
<SafeArea main>
<div class="w-full max-w-[400px] flex flex-col gap-4">
<Suspense fallback={"..."}>
{/* If I don't have this guard then the node manager only half-works */}
<Show when={state.node_manager}>
<h1 class="text-2xl font-semibold uppercase border-b-2 border-b-white">Receive Bitcoin</h1>
<Switch>
<Match when={!unified() || receiveState() === "edit"}>
<form class="border border-white/20 rounded-xl p-2 flex flex-col gap-4" onSubmit={onSubmit} >
@@ -139,11 +139,9 @@ export default function Receive() {
</Card>
</Match>
</Switch>
</Show>
</Suspense>
</div>
<NavBar activeTab="none" />
</SafeArea >
</NodeManagerGuard>
)
}

13
src/routes/Send.tsx Normal file
View File

@@ -0,0 +1,13 @@
import NavBar from "~/components/NavBar";
import { SafeArea } from "~/components/layout";
export default function Send() {
return (
<SafeArea main>
<div class="w-full max-w-[400px] flex flex-col gap-4">
<h1 class="text-2xl font-semibold uppercase border-b-2 border-b-white">Send Bitcoin</h1>
</div>
<NavBar activeTab="send" />
</SafeArea >
)
}

View File

@@ -1,18 +1,10 @@
import App from "~/components/App";
import { Switch, Match } from "solid-js";
import { Switch, Match, Suspense, Show } from "solid-js";
import { WaitlistAlreadyIn } from "~/components/waitlist/WaitlistAlreadyIn";
import WaitlistForm from "~/components/waitlist/WaitlistForm";
import { useMegaStore } from "~/state/megaStore";
import { LoadingSpinner } from "~/components/layout";
function FullscreenLoader() {
return (
<div class="w-screen h-screen flex justify-center items-center">
<LoadingSpinner />
</div>
);
}
import { FullscreenLoader, LoadingSpinner } from "~/components/layout";
export default function Home() {
const [state, _] = useMegaStore();
@@ -20,8 +12,8 @@ export default function Home() {
return (
<>
<Switch fallback={<FullscreenLoader />} >
{/* TODO: might need this state.node_manager guard on all wallet routes */}
<Match when={state.user_status === "approved" && state.node_manager}>
{/* TODO: can you put a suspense around a match? */}
<Match when={state.user_status === "approved"}>
<App />
</Match>
<Match when={state.user_status === "waitlisted"}>

View File

@@ -16,16 +16,30 @@ module.exports = {
colors: {
"half-black": "rgba(0, 0, 0, 0.5)",
"faint-white": "rgba(255, 255, 255, 0.1)",
"m-red": "#F61D5B",
"light-text": "rgba(250, 245, 234, 0.5)",
"m-green": "hsla(163, 70%, 38%, 1)",
"m-green-dark": "hsla(163, 70%, 28%, 1)",
"m-blue": "hsla(220, 59%, 52%, 1)",
"m-blue-dark": "hsla(220, 59%, 42%, 1)",
"m-red": "hsla(343, 92%, 54%, 1)",
"m-red-dark": "hsla(343, 92%, 44%, 1)",
"sidebar-gray": "hsla(222, 15%, 7%, 1)"
},
backgroundImage: {
'fade-to-blue': 'linear-gradient(1.63deg, #0B215B 32.05%, rgba(11, 33, 91, 0) 84.78%)'
'fade-to-blue': 'linear-gradient(1.63deg, #0B215B 32.05%, rgba(11, 33, 91, 0) 84.78%)',
'subtle-fade': 'linear-gradient(180deg, #060A13 0%, #131E39 100%)',
'richer-fade': 'linear-gradient(180deg, #050914 0%, #0A1329 100%)'
},
dropShadow: {
'blue-glow': '0px 0px 32px rgba(11, 33, 91, 0.5)'
}
'blue-glow': '0px 0px 32px rgba(11, 33, 91, 0.5)',
'inner-button': '2px 2px 4px rgba(0, 0, 0, 0.1), inset 2px 2px 4px rgba(255, 255, 255, 0.25), inset -2px -2px 6px rgba(0, 0, 0, 0.3);'
},
boxShadow: {
'inner-button': '2px 2px 4px rgba(0, 0, 0, 0.1), inset 2px 2px 4px rgba(255, 255, 255, 0.25), inset -2px -2px 6px rgba(0, 0, 0, 0.3);'
},
textShadow: {
'button': '1px 1px 0px rgba(0, 0, 0, 0.4);'
},
},
},
plugins: [
@@ -68,6 +82,17 @@ module.exports = {
}
addUtilities(newUtilities);
})
}),
// Text shadow!
plugin(function ({ matchUtilities, theme }) {
matchUtilities(
{
'text-shadow': (value) => ({
textShadow: value,
}),
},
{ values: theme('textShadow') }
)
}),
],
}