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

Connect wallet button [interchain UI part 2] #1014

Merged
merged 4 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions apps/minifront/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
"@bufbuild/protobuf": "^1.9.0",
"@cosmjs/proto-signing": "^0.32.3",
"@cosmjs/stargate": "^0.32.3",
"@cosmos-kit/react": "^2.11.0",
"@interchain-ui/react": "^1.23.3",
"@cosmos-kit/core": "^2.9.2",
"@cosmos-kit/react": "^2.11.2",
"@interchain-ui/react": "^1.23.10",
"@penumbra-labs/registry": "^5.1.0",
"@penumbra-zone/bech32m": "workspace:*",
"@penumbra-zone/client": "workspace:*",
Expand All @@ -36,14 +37,14 @@
"@tanstack/react-query": "^5.28.9",
"bech32": "^2.0.0",
"bignumber.js": "^9.1.2",
"chain-registry": "^1.41.9",
"cosmos-kit": "^2.10.0",
"chain-registry": "^1.45.5",
"cosmos-kit": "^2.10.2",
"date-fns": "^3.6.0",
"framer-motion": "^11.0.22",
"immer": "^10.0.4",
"lodash": "^4.17.21",
"match-sorter": "^6.3.4",
"osmo-query": "^16.11.0",
"lucide-react": "^0.363.0",
"osmo-query": "^16.12.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-helmet": "^6.1.0",
Expand All @@ -55,7 +56,7 @@
"zustand": "^4.5.2"
},
"devDependencies": {
"@chain-registry/types": "^0.25.7",
"@chain-registry/types": "^0.28.4",
"@penumbra-zone/polyfills": "workspace:*",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.2",
Expand Down
165 changes: 69 additions & 96 deletions apps/minifront/src/components/ibc/ibc-in/chain-dropdown.tsx
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Component completely broken after interchain deps update. Went ahead and swapped it out for https://ui.shadcn.com/docs/components/combobox

Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import * as React from 'react';
import { useMemo } from 'react';
import { Avatar, Box, Combobox, Skeleton, Stack, Text } from '@interchain-ui/react';
import { matchSorter } from 'match-sorter';
import { useManager } from '@cosmos-kit/react';

interface Option {
label: string;
value: string;
}
import { Popover, PopoverContent, PopoverTrigger } from '@penumbra-zone/ui/components/ui/popover';
import { ChevronsUpDown } from 'lucide-react';
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
} from '@penumbra-zone/ui/components/ui/command';
import { Button } from '@penumbra-zone/ui/components/ui/button';
import { ibcInSelector } from '../../../state/ibc-in';
import { useStore } from '../../../state';
import { Avatar, AvatarImage } from '@penumbra-zone/ui/components/ui/avatar';
import { Identicon } from '@penumbra-zone/ui/components/ui/identicon';

export interface ChainInfo {
chainName: string;
Expand All @@ -16,26 +23,6 @@ export interface ChainInfo {
icon?: string;
}

export interface ChooseChainProps {
onChange: (selectedItem: Option) => void;
}

const ChainOption = ({ chainInfo: { label, icon } }: { chainInfo: ChainInfo }) => {
return (
<Stack aria-label={`Chain option: ${label}`}>
<Avatar
name={label}
className='mr-2'
getInitials={name => name[0]!}
size='xs'
src={icon}
fallbackMode='bg'
/>
<Text>{label}</Text>
</Stack>
);
};

const useChainInfos = (): ChainInfo[] => {
const { chainRecords, getChainLogo } = useManager();
return useMemo(
Expand All @@ -54,80 +41,66 @@ const useChainInfos = (): ChainInfo[] => {

// Note the console will display aria-label warnings (despite them being present).
// The cosmology team has been notified of the issue.
export const ChainDropdown = ({ onChange }: ChooseChainProps) => {
export const ChainDropdown = () => {
const chainInfos = useChainInfos();
const { setSelectedChain } = useStore(ibcInSelector);

const [selectedKey, setSelectedKey] = React.useState<string>();
const [filterValue, setFilterValue] = React.useState<string>('');

const filteredItems = React.useMemo(() => {
return matchSorter(chainInfos, filterValue, {
keys: ['label', 'value'],
});
}, [chainInfos, filterValue]);
const [open, setOpen] = React.useState(false);
const [value, setValue] = React.useState('');

const avatarUrl = filteredItems.find(i => i.value === selectedKey)?.icon ?? undefined;
const selected = chainInfos.find(c => c.value === value);

return (
<Box className='flex flex-col items-center justify-center'>
<div className='font-bold text-stone-700'>Select chain</div>
<Combobox
aria-label='Select a chain'
items={filteredItems}
inputValue={filterValue}
openOnFocus
onInputChange={value => {
setFilterValue(value);
if (!value) {
setSelectedKey(undefined);
}
}}
selectedKey={selectedKey}
onSelectionChange={item => {
if (item) {
setSelectedKey(item as string);

const found = chainInfos.find(options => options.value === item) ?? null;

if (found) {
onChange(found);
setFilterValue(found.label);
}
}
}}
inputAddonStart={
selectedKey && avatarUrl ? (
<Avatar
name={selectedKey.toString()}
getInitials={name => name[0]!}
size='xs'
src={avatarUrl}
fallbackMode='bg'
className='px-2'
/>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button variant='onLight' role='combobox' aria-expanded={open} className='w-[300px]'>
{value ? (
<div className='flex gap-2'>
<Avatar className='size-6'>
<AvatarImage src={selected?.icon} />
<Identicon uniqueIdentifier={selected?.label ?? ''} type='gradient' size={22} />
</Avatar>
<span className='mt-0.5'>{selected?.label}</span>
</div>
) : (
<Box className='flex items-center justify-center px-2'>
<Skeleton width='24px' height='24px' className='rounded-full' />
</Box>
)
}
styleProps={{
width: {
mobile: '100%',
mdMobile: '350px',
},
}}
>
{filteredItems.map(info => (
<Combobox.Item
key={info.value}
textValue={info.label}
aria-label={`Select ${info.label}`}
>
<ChainOption chainInfo={info} />
</Combobox.Item>
))}
</Combobox>
</Box>
'Select a chain'
)}
<ChevronsUpDown className='ml-2 size-4 shrink-0 opacity-50' />
</Button>
</PopoverTrigger>
<PopoverContent className='w-[300px] p-0'>
<Command>
<CommandInput placeholder='Search chains...' />
<CommandEmpty>No framework found.</CommandEmpty>
<CommandGroup>
{chainInfos.map(chain => (
<CommandItem
key={chain.value}
value={chain.value}
onSelect={currentValue => {
setOpen(false);

if (currentValue === value) {
setValue('');
setSelectedChain(undefined);
} else {
setValue(currentValue);
const match = chainInfos.find(options => options.value === currentValue);
setSelectedChain(match);
}
}}
className='flex gap-2'
>
<Avatar className='size-6'>
<AvatarImage src={chain.icon} />
<Identicon uniqueIdentifier={chain.label} type='gradient' size={22} />
</Avatar>
{chain.label}
</CommandItem>
))}
</CommandGroup>
</Command>
</PopoverContent>
</Popover>
);
};
13 changes: 0 additions & 13 deletions apps/minifront/src/components/ibc/ibc-in/chain-picker.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export const IbcChainProvider = ({ registry, children }: IbcProviderProps) => {
},
}}
signerOptions={signerOptions}
modalTheme={{ defaultTheme: 'light' }}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the default changed to dark. Forcing the light theme here.

>
{children}
</ChainProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useStore } from '../../../state';
import { ibcInSelector } from '../../../state/ibc-in';
import { useChain, useManager } from '@cosmos-kit/react';
import { WalletStatus } from '@cosmos-kit/core';
import { WalletAddrCard } from './wallet-addr-card';
import { ConnectWalletButton } from './wallet-connect-button';

export const useChainConnector = () => {
const { selectedChain } = useStore(ibcInSelector);
const { chainRecords } = useManager();
const defaultChain = chainRecords[0]!.name;
return useChain(selectedChain?.chainName ?? defaultChain);
};

export const CosmosWalletConnector = () => {
const { selectedChain } = useStore(ibcInSelector);
const { username, address, status, message } = useChainConnector();

return (
<div className='flex flex-col items-center justify-center gap-4'>
{address && selectedChain && <WalletAddrCard username={username} address={address} />}
<div className='w-52'>
<ConnectWalletButton />
</div>
{(status === WalletStatus.Rejected || status === WalletStatus.Error) && (
<div className='text-purple-500'>{message}</div>
)}
</div>
);
};
2 changes: 1 addition & 1 deletion apps/minifront/src/components/ibc/ibc-in/ibc-in-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const IbcInForm = () => {
}}
>
<InterchainUi />
<Button type='submit' variant='onLight'>
<Button type='submit' variant='onLight' disabled>
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disabling until we get to the end of building this flow

<div className='flex items-center gap-2'>
<LockClosedIcon />
<span className='-mb-1'>Shield Assets</span>
Expand Down
9 changes: 5 additions & 4 deletions apps/minifront/src/components/ibc/ibc-in/interchain-ui.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { IbcChainProvider } from './chain-provider';
import { useRegistry } from '../../../fetchers/registry';
import { ChainPicker } from './chain-picker';
import { ChainDropdown } from './chain-dropdown';
import { CosmosWalletConnector } from './cosmos-wallet-connector';

export const InterchainUi = () => {
const { data, isLoading, error } = useRegistry();
Expand All @@ -12,10 +13,10 @@ export const InterchainUi = () => {
return (
<IbcChainProvider registry={data}>
{/* negative margin offsets div inserted by provider */}
<div className='-mt-4'>
<ChainPicker />
<div className='-mt-4 flex justify-center'>
<ChainDropdown />
</div>
{/* WalletSection to go here */}
<CosmosWalletConnector />
</IbcChainProvider>
);
};
16 changes: 16 additions & 0 deletions apps/minifront/src/components/ibc/ibc-in/wallet-addr-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Identicon } from '@penumbra-zone/ui/components/ui/identicon';

interface UserInfoProps {
address: string;
username?: string;
}

export const WalletAddrCard = ({ address, username }: UserInfoProps) => {
return (
<div className='flex flex-col items-center gap-2 space-y-1 rounded-lg bg-white p-6'>
<Identicon uniqueIdentifier={address} type='gradient' size={42} />
<div className='flex items-center justify-center gap-4 text-gray-500'>{address}</div>
<span className='text-sm font-semibold text-stone-700 sm:text-xl'>{username}</span>
</div>
);
};
Loading
Loading