-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
feat: header with connection button
- Loading branch information
Showing
18 changed files
with
761 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { Button } from '@penumbra-zone/ui/Button'; | ||
import { useConnect } from '@/utils/penumbra/useConnect.ts'; | ||
import { ProviderPopover } from './provider-popover.tsx'; | ||
|
||
export const Connection = () => { | ||
const { connected, connect } = useConnect(); | ||
|
||
if (!connected) { | ||
return ( | ||
<Button actionType='accent' onClick={() => void connect()}>Connect</Button> | ||
); | ||
} | ||
|
||
return <ProviderPopover /> | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { useRouter } from 'next/navigation'; | ||
import { Tabs } from '@penumbra-zone/ui/Tabs'; | ||
import { Density } from '@penumbra-zone/ui/Density'; | ||
import { HEADER_LINKS } from './links.ts'; | ||
import { usePagePath } from '@/utils/routes/usePagePath.ts'; | ||
|
||
export const DesktopNav = () => { | ||
const pagePath = usePagePath(); | ||
const router = useRouter(); | ||
|
||
return ( | ||
<nav className='hidden rounded-full bg-v2-other-tonalFill5 px-4 py-1 backdrop-blur-xl lg:flex'> | ||
<Density compact> | ||
<Tabs | ||
value={pagePath} | ||
onChange={value => router.push(value)} | ||
options={HEADER_LINKS} | ||
actionType='accent' | ||
/> | ||
</Density> | ||
</nav> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { Density } from '@penumbra-zone/ui/Density'; | ||
import { HeaderLogo } from './logo.tsx'; | ||
// import { StatusPopover } from './status-popover.tsx'; | ||
import { MobileNav } from './mobile-nav.tsx'; | ||
import { DesktopNav } from './desktop-nav.tsx'; | ||
import { Connection } from './connection.tsx'; | ||
|
||
export const Header = () => { | ||
return ( | ||
<header className='flex items-center justify-between py-5'> | ||
<HeaderLogo /> | ||
|
||
<DesktopNav /> | ||
|
||
<Density compact> | ||
<div className='hidden gap-2 lg:flex'> | ||
{/* <StatusPopover />*/} | ||
<Connection /> | ||
</div> | ||
<div className='block lg:hidden'> | ||
<MobileNav /> | ||
</div> | ||
</Density> | ||
</header> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { MoonStar, ArrowUpFromDot, Coins } from 'lucide-react'; | ||
import { PagePath } from '@/utils/routes/pages.ts'; | ||
|
||
export const HEADER_LINKS = [ | ||
{ label: 'Trade', value: PagePath.Trade, icon: ArrowUpFromDot }, | ||
{ label: 'Explore', value: PagePath.Explore, icon: Coins }, | ||
{ label: 'Inspect', value: PagePath.Inspect, icon: MoonStar }, | ||
{ label: 'Portfolio', value: PagePath.Portfolio, icon: Coins }, | ||
]; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import Link from 'next/link' | ||
import { PagePath } from '@/utils/routes/pages.ts'; | ||
import PenumbraLogo from './logo.svg'; | ||
|
||
export const HeaderLogo = () => { | ||
return ( | ||
<Link className='flex h-8 items-center' href={PagePath.Explore}> | ||
<PenumbraLogo /> | ||
</Link> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { useState } from 'react'; | ||
import { useRouter } from 'next/navigation'; | ||
import { Menu, X } from 'lucide-react'; | ||
import { Button } from '@penumbra-zone/ui/Button'; | ||
import { Dialog } from '@penumbra-zone/ui/Dialog'; | ||
import { Display } from '@penumbra-zone/ui/Display'; | ||
import { MenuItem } from '@penumbra-zone/ui/MenuItem'; | ||
// import { StatusPopover } from './status-popover.tsx'; | ||
import { HeaderLogo } from './logo.tsx'; | ||
import { HEADER_LINKS } from './links.ts'; | ||
import { Connection } from './connection.tsx'; | ||
|
||
export const MobileNav = () => { | ||
const router = useRouter(); | ||
const [isOpen, setIsOpen] = useState(false); | ||
|
||
const onNavigate = (link: string) => { | ||
router.push(link); | ||
setIsOpen(false); | ||
}; | ||
|
||
return ( | ||
<Dialog isOpen={isOpen} onClose={() => setIsOpen(false)}> | ||
<Button iconOnly icon={Menu} onClick={() => setIsOpen(true)}> | ||
Menu | ||
</Button> | ||
<Dialog.EmptyContent> | ||
<div className='pointer-events-auto h-full overflow-hidden bg-black'> | ||
<Display> | ||
<nav className='flex items-center justify-between py-5'> | ||
<HeaderLogo /> | ||
|
||
<div className='flex gap-2'> | ||
{/* <StatusPopover />*/} | ||
<Connection /> | ||
<Button iconOnly icon={X} onClick={() => setIsOpen(false)}> | ||
Close | ||
</Button> | ||
</div> | ||
</nav> | ||
|
||
<div className='flex flex-col gap-4'> | ||
{HEADER_LINKS.map(link => ( | ||
<MenuItem | ||
key={link.value} | ||
label={link.label} | ||
icon={link.icon} | ||
onClick={() => onNavigate(link.value)} | ||
/> | ||
))} | ||
</div> | ||
</Display> | ||
</div> | ||
</Dialog.EmptyContent> | ||
</Dialog> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { useMemo } from 'react'; | ||
import { Link2Off } from 'lucide-react'; | ||
import Image from 'next/image'; | ||
import { Popover } from '@penumbra-zone/ui/Popover'; | ||
import { Button } from '@penumbra-zone/ui/Button'; | ||
import { Text } from '@penumbra-zone/ui/Text'; | ||
import { useConnect } from '@/utils/penumbra/useConnect.ts'; | ||
|
||
export const ProviderPopover = () => { | ||
const { disconnect, manifest } = useConnect(); | ||
|
||
const name = manifest?.['name'] as string; | ||
const version = manifest?.['version'] as string; | ||
const description = manifest?.['description'] as string; | ||
|
||
const icon = useMemo(() => { | ||
const icons = (manifest?.['icons'] ?? {}) as Record<string, Blob>; | ||
const blob = icons['32'] ?? icons['128']; | ||
const element = !blob ? null : ( | ||
<Image width={16} height={16} src={URL.createObjectURL(blob)} alt={name} className='size-4' /> | ||
); | ||
return () => element; | ||
}, [name, manifest]); | ||
|
||
return ( | ||
<Popover> | ||
<Popover.Trigger> | ||
<Button icon={icon} iconOnly> | ||
{name} | ||
</Button> | ||
</Popover.Trigger> | ||
<Popover.Content align='end' side='bottom'> | ||
{manifest ? ( | ||
<div className='flex flex-col gap-2'> | ||
<Text body> | ||
{name} v{version} | ||
</Text> | ||
<Text small>{description}</Text> | ||
</div> | ||
) : ( | ||
<Text body>Loading provider manifest...</Text> | ||
)} | ||
<div className='mt-4'> | ||
<Button icon={Link2Off} onClick={() => void disconnect()}> | ||
Disconnect | ||
</Button> | ||
</div> | ||
</Popover.Content> | ||
</Popover> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { createPenumbraClient } from '@penumbra-zone/client'; | ||
|
||
const PRAX_ID = 'lkpmkhpnhknhmibgnmmhdhgdilepfghe'; | ||
export const PRAX_ORIGIN = new URL(`chrome-extension://${PRAX_ID}`).origin; | ||
|
||
export const penumbra = createPenumbraClient(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import { useEffect, useState } from 'react'; | ||
import { penumbra, PRAX_ORIGIN } from '@/utils/penumbra/penumbra.ts'; | ||
import { PenumbraRequestFailure, PenumbraState, PenumbraManifest } from '@penumbra-zone/client'; | ||
|
||
export const useConnect = () => { | ||
const [manifest, setManifest] = useState<PenumbraManifest>(); | ||
const [connectionLoading, setConnectionLoading] = useState<boolean>(false); | ||
const [connected, setConnected] = useState<boolean>(false); | ||
|
||
const reconnect = async () => { | ||
await penumbra.attach(PRAX_ORIGIN); | ||
if (!penumbra.connected) { | ||
return; | ||
} | ||
|
||
try { | ||
await penumbra.connect(); | ||
setConnected(true); | ||
} catch (error) { | ||
/* no-op */ | ||
} | ||
}; | ||
|
||
const connect = async () => { | ||
try { | ||
setConnectionLoading(true); | ||
await penumbra.connect(); | ||
} catch (error) { | ||
if (error instanceof Error && error.cause) { | ||
if (error.cause === PenumbraRequestFailure.Denied) { | ||
// TODO: replace these alerts with toasts | ||
alert('Connection denied: you may need to un-ignore this site in your extension settings.'); | ||
} | ||
if (error.cause === PenumbraRequestFailure.NeedsLogin) { | ||
alert('Not logged in: please login into the extension and try again'); | ||
} | ||
} | ||
} finally { | ||
setConnectionLoading(false); | ||
} | ||
}; | ||
|
||
const disconnect = async () => { | ||
if (!penumbra.connected) { | ||
return; | ||
} | ||
|
||
try { | ||
await penumbra.disconnect(); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
}; | ||
|
||
// Monitors the connection | ||
useEffect(() => { | ||
setManifest(penumbra.manifest); | ||
|
||
// If Prax is connected on page load, reconnect to ensure the connection is still active | ||
void reconnect(); | ||
|
||
penumbra.onConnectionStateChange((event) => { | ||
setManifest(penumbra.manifest); | ||
if (event.state === PenumbraState.Connected) { | ||
setConnected(true); | ||
} else { | ||
setConnected(false); | ||
} | ||
}); | ||
}, []); | ||
|
||
return { | ||
manifest, | ||
connectionLoading, | ||
connected, | ||
connect, | ||
disconnect, | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export enum PagePath { | ||
Explore = '/v2', | ||
Trade = '/v2/trade', | ||
Inspect = '/v2/inspect', | ||
Portfolio = '/v2/portfolio', | ||
} |
Oops, something went wrong.