Skip to content

Commit 4b98969

Browse files
committed
feat: chain groups
1 parent 4742ea0 commit 4b98969

File tree

73 files changed

+373
-63
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+373
-63
lines changed

packages/rainbowkit/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@stakekit/rainbowkit",
3-
"version": "2.2.6",
3+
"version": "2.2.7",
44
"description": "The best way to connect a wallet",
55
"files": ["dist", "styles.css", "wallets"],
66
"type": "module",

packages/rainbowkit/src/components/ConnectOptions/DesktopOptions.tsx

Lines changed: 162 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,12 @@ import {
4444
sidebar,
4545
sidebarCompactMode,
4646
} from './DesktopOptions.css';
47+
import type { ChainGroup } from '../../wallets/Wallet';
48+
import { indexBy } from '../../utils/indexBy';
4749

4850
export enum WalletStep {
4951
None = 'NONE',
52+
SelectChainGroup = 'SELECT_CHAIN_GROUP',
5053
LearnCompact = 'LEARN_COMPACT',
5154
Get = 'GET',
5255
Connect = 'CONNECT',
@@ -88,7 +91,28 @@ export function DesktopOptions({ onClose }: { onClose: () => void }) {
8891
.sort((a, b) => a.groupIndex - b.groupIndex);
8992
const unfilteredWallets = useWalletConnectors();
9093

91-
const groupedWallets = groupBy(wallets, (wallet) => wallet.groupName);
94+
const chainGroups = indexBy(
95+
wallets.map((w) => w.chainGroup),
96+
(cg) => cg.id,
97+
);
98+
99+
const [selectedChainGroupId, setSelectedChainGroupId] = useState<
100+
ChainGroup['id'] | undefined
101+
>(Object.values(chainGroups).length > 1 ? undefined : 'ethereum');
102+
103+
const groupedByChainGroupWallets = groupBy(
104+
wallets,
105+
(wallet) => wallet.chainGroup.id,
106+
);
107+
108+
const walletsFromSelectedChainGroup = selectedChainGroupId
109+
? groupedByChainGroupWallets[selectedChainGroupId] || []
110+
: [];
111+
112+
const groupedByGroupNameWallets = groupBy(
113+
walletsFromSelectedChainGroup,
114+
(wallet) => wallet.groupName,
115+
);
92116

93117
const supportedI18nGroupNames = [
94118
'Recommended',
@@ -208,10 +232,13 @@ export function DesktopOptions({ onClose }: { onClose: () => void }) {
208232
}
209233
setWalletStep(newWalletStep);
210234
};
235+
211236
const [initialWalletStep, setInitialWalletStep] = useState<WalletStep>(
212-
WalletStep.None,
237+
Object.values(chainGroups).length > 1
238+
? WalletStep.SelectChainGroup
239+
: WalletStep.None,
213240
);
214-
const [walletStep, setWalletStep] = useState<WalletStep>(WalletStep.None);
241+
const [walletStep, setWalletStep] = useState<WalletStep>(initialWalletStep);
215242

216243
let walletContent = null;
217244
let headerLabel = null;
@@ -228,11 +255,24 @@ export function DesktopOptions({ onClose }: { onClose: () => void }) {
228255
hasExtension && selectedWallet?.mobileDownloadUrl
229256
);
230257

258+
const onChainGroupSelect = (chainGroupId: string) => {
259+
setSelectedChainGroupId(chainGroupId);
260+
changeWalletStep(WalletStep.None);
261+
};
262+
231263
switch (walletStep) {
264+
case WalletStep.SelectChainGroup:
265+
headerLabel = i18n.t('connect.select_chain_group.title');
266+
break;
232267
case WalletStep.None:
268+
headerLabel = i18n.t('connect.title');
233269
walletContent = (
234270
<ConnectModalIntro getWallet={() => changeWalletStep(WalletStep.Get)} />
235271
);
272+
headerBackButtonLink =
273+
compactModeEnabled && Object.values(chainGroups).length > 1
274+
? WalletStep.SelectChainGroup
275+
: null;
236276
break;
237277
case WalletStep.LearnCompact:
238278
walletContent = (
@@ -364,30 +404,74 @@ export function DesktopOptions({ onClose }: { onClose: () => void }) {
364404
default:
365405
break;
366406
}
407+
408+
const topContent = (() => {
409+
if (!compactModeEnabled) return null;
410+
411+
if (walletStep === WalletStep.None) {
412+
return (
413+
<Box marginLeft="16" width="28">
414+
{headerBackButtonLink && (
415+
<Box
416+
as="button"
417+
className={touchableStyles({
418+
active: 'shrinkSm',
419+
hover: 'growLg',
420+
})}
421+
color="accentColor"
422+
onClick={() => {
423+
headerBackButtonLink &&
424+
changeWalletStep(headerBackButtonLink, true);
425+
headerBackButtonCallback?.();
426+
}}
427+
paddingX="8"
428+
paddingY="4"
429+
style={{
430+
boxSizing: 'content-box',
431+
height: 17,
432+
willChange: 'transform',
433+
}}
434+
transition="default"
435+
type="button"
436+
>
437+
<BackIcon />
438+
</Box>
439+
)}
440+
</Box>
441+
);
442+
}
443+
444+
if (Disclaimer) {
445+
return (
446+
<Box marginLeft="16" width="28">
447+
<InfoButton
448+
onClick={() => changeWalletStep(WalletStep.LearnCompact)}
449+
/>
450+
</Box>
451+
);
452+
}
453+
454+
return <Box marginLeft="16" width="28" />;
455+
})();
456+
367457
return (
368458
<Box
369459
display="flex"
370460
flexDirection="row"
371-
style={{ maxHeight: compactModeEnabled ? 468 : 504 }}
461+
style={{ maxHeight: compactModeEnabled ? 468 : 504, height: '100%' }}
372462
>
373-
{(compactModeEnabled ? walletStep === WalletStep.None : true) && (
463+
{(compactModeEnabled
464+
? walletStep === WalletStep.None ||
465+
walletStep === WalletStep.SelectChainGroup
466+
: true) && (
374467
<Box
375468
className={compactModeEnabled ? sidebarCompactMode : sidebar}
376469
display="flex"
377470
flexDirection="column"
378471
marginTop="16"
379472
>
380473
<Box display="flex" justifyContent="space-between">
381-
{compactModeEnabled && Disclaimer && (
382-
<Box marginLeft="16" width="28">
383-
<InfoButton
384-
onClick={() => changeWalletStep(WalletStep.LearnCompact)}
385-
/>
386-
</Box>
387-
)}
388-
{compactModeEnabled && !Disclaimer && (
389-
<Box marginLeft="16" width="28" />
390-
)}
474+
{topContent}
391475
<Box
392476
marginLeft={compactModeEnabled ? '0' : '6'}
393477
paddingBottom="8"
@@ -402,7 +486,7 @@ export function DesktopOptions({ onClose }: { onClose: () => void }) {
402486
weight="heavy"
403487
testId={'connect-header-label'}
404488
>
405-
{i18n.t('connect.title')}
489+
{headerLabel}
406490
</Text>
407491
</Box>
408492
{compactModeEnabled && (
@@ -412,49 +496,65 @@ export function DesktopOptions({ onClose }: { onClose: () => void }) {
412496
)}
413497
</Box>
414498
<Box className={ScrollClassName} paddingBottom="18">
415-
{Object.entries(groupedWallets).map(
416-
([groupName, wallets], index) =>
417-
wallets.length > 0 && (
418-
<Fragment key={index}>
419-
{groupName ? (
420-
<Box marginBottom="8" marginTop="16" marginX="6">
421-
<Text
422-
color={
423-
groupName === 'Installed'
424-
? 'accentColor'
425-
: 'modalTextSecondary'
426-
}
427-
size="14"
428-
weight="bold"
429-
>
430-
{supportedI18nGroupNames.includes(groupName)
431-
? i18n.t(
432-
`connector_group.${groupName.toLowerCase()}`,
433-
)
434-
: groupName}
435-
</Text>
499+
{walletStep === WalletStep.SelectChainGroup ? (
500+
<Box display="flex" flexDirection="column" gap="4" marginTop="16">
501+
{Object.values(chainGroups).map((cg) => (
502+
<ModalSelection
503+
key={cg.id}
504+
currentlySelected={cg.id === selectedChainGroupId}
505+
iconUrl={cg.iconUrl}
506+
name={cg.title}
507+
onClick={() => onChainGroupSelect(cg.id)}
508+
/>
509+
))}
510+
</Box>
511+
) : (
512+
Object.entries(groupedByGroupNameWallets).map(
513+
([groupName, wallets], index) =>
514+
wallets.length > 0 && (
515+
<Fragment key={index}>
516+
{groupName ? (
517+
<Box marginBottom="8" marginTop="16" marginX="6">
518+
<Text
519+
color={
520+
groupName === 'Installed'
521+
? 'accentColor'
522+
: 'modalTextSecondary'
523+
}
524+
size="14"
525+
weight="bold"
526+
>
527+
{supportedI18nGroupNames.includes(groupName)
528+
? i18n.t(
529+
`connector_group.${groupName.toLowerCase()}`,
530+
)
531+
: groupName}
532+
</Text>
533+
</Box>
534+
) : null}
535+
<Box display="flex" flexDirection="column" gap="4">
536+
{wallets.map((wallet) => {
537+
return (
538+
<ModalSelection
539+
currentlySelected={wallet.id === selectedOptionId}
540+
iconBackground={wallet.iconBackground}
541+
iconUrl={wallet.iconUrl}
542+
key={wallet.id}
543+
name={wallet.name}
544+
onClick={() => selectWallet(wallet)}
545+
ready={wallet.ready}
546+
recent={wallet.recent}
547+
testId={`wallet-option-${wallet.id}`}
548+
isRainbowKitConnector={
549+
wallet.isRainbowKitConnector
550+
}
551+
/>
552+
);
553+
})}
436554
</Box>
437-
) : null}
438-
<Box display="flex" flexDirection="column" gap="4">
439-
{wallets.map((wallet) => {
440-
return (
441-
<ModalSelection
442-
currentlySelected={wallet.id === selectedOptionId}
443-
iconBackground={wallet.iconBackground}
444-
iconUrl={wallet.iconUrl}
445-
key={wallet.id}
446-
name={wallet.name}
447-
onClick={() => selectWallet(wallet)}
448-
ready={wallet.ready}
449-
recent={wallet.recent}
450-
testId={`wallet-option-${wallet.id}`}
451-
isRainbowKitConnector={wallet.isRainbowKitConnector}
452-
/>
453-
);
454-
})}
455-
</Box>
456-
</Fragment>
457-
),
555+
</Fragment>
556+
),
557+
)
458558
)}
459559
</Box>
460560
{compactModeEnabled && (
@@ -506,7 +606,10 @@ export function DesktopOptions({ onClose }: { onClose: () => void }) {
506606
)}
507607
</Box>
508608
)}
509-
{(compactModeEnabled ? walletStep !== WalletStep.None : true) && (
609+
{(compactModeEnabled
610+
? walletStep !== WalletStep.SelectChainGroup &&
611+
walletStep !== WalletStep.None
612+
: true) && (
510613
<>
511614
{!compactModeEnabled && (
512615
<Box background="generalBorder" minWidth="1" width="1" />

0 commit comments

Comments
 (0)