Skip to content

Commit

Permalink
Chore | Unify <Tabs /> component (#612)
Browse files Browse the repository at this point in the history
* Add wallet icon

* Add page for fund wallet

* Implement styling for fundwallet page

* Finish content for fund wallet page

* Add cards and icons

* Adjust zenlink icon

* Add mexc icon

* Tune cards

* Remove 'Buy PEN' item from sidebar

* Adjust font style for Amplitude

* Hide fund wallet page on Foucoco

* use .svg instead of react component for svg img

* change alchempaypay from .tsx to .svg

* change stellaswap from component to .svg

* change zenlink from component to .svg

* change mexc from component to .svg

* implement inline svg when custom fill is needed

* add zenlink for amplitude theme

* reduce code complexity

* add Banxa

* add slide tab animation

* extract FundWalletTabs into separate component

* extract FundWalletTabsContent into separate component

* implement Tabs reusable component

* create reusable CardExternalLink component

* refactor FundWalletContent

* create useResolvedUrl hook

* redirect to faucet for foucoco

* update yarn.lock

* change foucoco fund wallet button text

* dont show fund wallet tabs for foucoco

* Change button color back to primary

* move Banxa from exchange to buy for Pendulum

* replace wallet icon

* Change declaration of Chain logos, add SpacewalkTabs component

* unify Tabs component for Fund and Spacewalk

* fix SpacewalkTabs property bug

* use ChainLogo for SpacewalkTabs

* improve code readability

---------

Co-authored-by: Marcel Ebert <[email protected]>
  • Loading branch information
Sharqiewicz and ebma authored Oct 31, 2024
1 parent 0763590 commit 9fb80d9
Show file tree
Hide file tree
Showing 13 changed files with 102 additions and 79 deletions.
4 changes: 1 addition & 3 deletions src/assets/AmplitudeLogo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ interface Props extends HTMLAttributes<SVGSVGElement> {
className?: string;
}

const AmplitudeLogo = ({ className, ...rest }: Props) => (
export const AmplitudeLogo = ({ className, ...rest }: Props) => (
<svg fill="#4EE59A" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" className={className} {...rest}>
<path d="M3.8606 9.50286C3.8606 9.50286 4.34281 10.9582 4.61302 11.6738C4.88323 12.3895 5.03867 12.8273 5.71325 12.8259C5.99852 12.8252 6.29641 12.4543 6.62941 11.6738C7.01913 10.6583 7.4623 9.50286 7.4623 9.50286H3.8606Z" />
<path d="M7.46228 9.50286C7.46228 9.50286 6.98006 8.04752 6.70985 7.33188C6.43964 6.61625 6.28354 6.17847 5.60953 6.18002C5.32426 6.18067 5.02638 6.55167 4.69338 7.33205C4.30366 8.34748 3.86057 9.50286 3.86057 9.50286H7.46228Z" />
Expand All @@ -15,5 +15,3 @@ const AmplitudeLogo = ({ className, ...rest }: Props) => (
<path d="M3.90198 9.51406H7.43313" />
</svg>
);

export default AmplitudeLogo;
8 changes: 3 additions & 5 deletions src/assets/ChainLogo.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { HTMLAttributes } from 'preact/compat';
import { useGlobalState } from '../GlobalStateProvider';
import { TenantName } from '../models/Tenant';
import AmplitudeLogo from './AmplitudeLogo';
import PendulumLogo from './PendulumLogo';
import { AmplitudeLogo } from './AmplitudeLogo';
import { PendulumLogo } from './PendulumLogo';

interface Props extends HTMLAttributes<SVGSVGElement> {
className?: string;
}

const ChainLogo = (props: Props) => {
export const ChainLogo = (props: Props) => {
const { tenantName } = useGlobalState();
if (tenantName === TenantName.Pendulum) {
return <PendulumLogo {...props} />;
} else {
return <AmplitudeLogo {...props} />;
}
};

export default ChainLogo;
4 changes: 1 addition & 3 deletions src/assets/PendulumLogo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ interface Props {
light?: boolean;
}

const PendulumLogo = ({ className, light }: Props) =>
export const PendulumLogo = ({ className, light }: Props) =>
light ? (
<svg width="18" height="25" viewBox="0 0 18 25" xmlns="http://www.w3.org/2000/svg" className={className}>
<path
Expand All @@ -28,5 +28,3 @@ const PendulumLogo = ({ className, light }: Props) =>
<path d="M2.88557 24.002C4.4776 24.002 5.7682 22.6588 5.7682 21.0019C5.7682 19.345 4.4776 18.0018 2.88557 18.0018C1.29353 18.0018 0.00292969 19.345 0.00292969 21.0019C0.00292969 22.6588 1.29353 24.002 2.88557 24.002Z" />
</svg>
);

export default PendulumLogo;
2 changes: 1 addition & 1 deletion src/components/AccountCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { WalletAccount } from '@talismn/connect-wallets';
import { trimAddress } from '../../helpers/addressFormatter';
import { useGlobalState } from '../../GlobalStateProvider';
import ChainLogo from '../../assets/ChainLogo';
import { ChainLogo } from '../../assets/ChainLogo';

interface AccountProps {
account: WalletAccount;
Expand Down
4 changes: 2 additions & 2 deletions src/components/ChainSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ChevronDownIcon } from '@heroicons/react/20/solid';
import AmplitudeLogo from '../assets/AmplitudeLogo';
import PendulumLogo from '../assets/PendulumLogo';
import { AmplitudeLogo } from '../assets/AmplitudeLogo';
import { PendulumLogo } from '../assets/PendulumLogo';
import { toTitle } from '../helpers/string';
import useSwitchChain from '../hooks/useSwitchChain';
import { TenantName } from '../models/Tenant';
Expand Down
22 changes: 12 additions & 10 deletions src/components/Tabs/Tab/index.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import { motion } from 'framer-motion';

interface TabItemProps<T> {
export interface TabProps<T> {
index: T;
label: string;
children: JSX.Element;
activeTab: T;
setActiveTab: (index: T) => void;
className?: string;
activeClassName?: string;
}

export function Tab<T>({ index, label, activeTab, setActiveTab }: TabItemProps<T>) {
export function Tab<T>({ index, children, activeTab, setActiveTab, className, activeClassName }: TabProps<T>) {
const getTabProps = (tabIndex: T) => ({
'data-active': activeTab === tabIndex,
onClick: () => setActiveTab(tabIndex),
});

const defaultClassName = 'group tab relative w-full h-full p-2 ';

const stylingClassName = className || 'h-full text-lg font-bold text-primary py-5';

return (
<a
role="tab"
className="sm:text-md group tab relative h-full w-full py-5 text-lg font-bold text-primary"
{...getTabProps(index)}
>
<p className="z-20 group-data-[active=true]:text-white">{label}</p>
<a role="tab" className={defaultClassName + stylingClassName} {...getTabProps(index)}>
{children}
{activeTab === index && (
<motion.div
layoutId="bubble"
// @ts-expect-error Caused by Preact, remove this comment once migrated to React
className="absolute inset-0 z-10 rounded-lg bg-primary"
className={`absolute inset-0 z-10 h-full rounded-lg ${activeClassName || 'bg-primary'}`}
transition={{ type: 'spring', bounce: 0.2, duration: 0.6 }}
/>
)}
Expand Down
23 changes: 12 additions & 11 deletions src/components/Tabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@ import { Tab } from './Tab';
interface TabsProps<T> {
activeTab: T;
setActiveTab: (index: T) => void;
tabItems: { index: T; label: string }[];
tabItems: { index: T; children: JSX.Element; className?: string }[];
className?: string;
}

export function Tabs<T>({ activeTab, setActiveTab, tabItems }: TabsProps<T>) {
export function Tabs<T>({ activeTab, setActiveTab, tabItems, className }: TabsProps<T>) {
return (
<div className="mt-5 flex justify-between">
<div
role="tablist"
className="tabs-boxed tabs flex flex-grow justify-center border border-neutral-500 bg-base-100 p-0 sm:w-5/6"
>
{tabItems.map((tab) => (
<Tab key={tab.label} index={tab.index} label={tab.label} activeTab={activeTab} setActiveTab={setActiveTab} />
))}
</div>
<div
role="tablist"
className={`tabs-boxed tabs flex flex-grow justify-center ${className || 'border border-neutral-500 bg-base-100 p-0'}`}
>
{tabItems.map((tab) => (
<Tab key={tab.index} activeTab={activeTab} setActiveTab={setActiveTab} {...tab}>
{tab.children}
</Tab>
))}
</div>
);
}
7 changes: 4 additions & 3 deletions src/pages/fund-wallet/FundWalletTabs/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Tabs } from '../../../components/Tabs';
import { TabProps } from '../../../components/Tabs/Tab';
import { FundWalletTab } from '..';

interface FundWalletTabsProps {
Expand All @@ -7,9 +8,9 @@ interface FundWalletTabsProps {
}

export function FundWalletTabs({ activeTab, setActiveTab }: FundWalletTabsProps) {
const tabItems = [
{ index: FundWalletTab.Buy, label: 'Buy' },
{ index: FundWalletTab.Exchange, label: 'Exchange' },
const tabItems: Omit<TabProps<FundWalletTab>, 'setActiveTab' | 'activeTab'>[] = [
{ index: FundWalletTab.Buy, children: <p className="z-20 group-data-[active=true]:text-white">Buy</p> },
{ index: FundWalletTab.Exchange, children: <p className="z-20 group-data-[active=true]:text-white">Exchange</p> },
];

return <Tabs<FundWalletTab> activeTab={activeTab} setActiveTab={setActiveTab} tabItems={tabItems} />;
Expand Down
2 changes: 1 addition & 1 deletion src/pages/fund-wallet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function FundWallet() {
return (
<div className="mt-4 flex justify-center">
<Card bordered className="tab-card shadow-0 w-full max-w-xl bg-base-200 px-8 py-6">
<Card.Title tag="h2" className="text-3xl font-normal">
<Card.Title tag="h2" className="mb-5 text-3xl font-normal">
Fund Wallet
</Card.Title>
<CardContent />
Expand Down
53 changes: 53 additions & 0 deletions src/pages/spacewalk/bridge/SpacewalkTabs/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useNodeInfoState } from '../../../../NodeInfoProvider';
import { TabProps } from '../../../../components/Tabs/Tab';
import { Tabs } from '../../../../components/Tabs';
import { ChainLogo } from '../../../../assets/ChainLogo';
import StellarLogo from '../../../../assets/StellarLogo';
import { BridgeTabs } from '..';

interface SpacewalkTabsProps {
activeTab: BridgeTabs;
setActiveTab: (index: BridgeTabs) => void;
}

export function SpacewalkTabs({ activeTab, setActiveTab }: SpacewalkTabsProps) {
const { chain } = useNodeInfoState().state;

const cs = 'z-20 flex items-center justify-center p-2 text-xs sm:text-sm ';

const ToPendulum = () =>
chain ? (
<>
<ChainLogo className="z-20 mr-1 h-6 w-6" />
<p className="z-20 text-gray-500 group-data-[active=true]:text-black dark:text-white">To {chain}</p>
</>
) : (
<></>
);

const ToStellar = () => (
<>
<StellarLogo className="z-20 mr-1 h-6 w-6" />
<p className="z-20 text-gray-500 group-data-[active=true]:text-black dark:text-white">To Stellar</p>
</>
);

const tabItems: Omit<TabProps<BridgeTabs>, 'setActiveTab' | 'activeTab'>[] = [
{
index: BridgeTabs.Issue,
children: <ToPendulum />,
className: cs,
activeClassName: 'bg-[#f7f7f7] dark:bg-primary',
},
{
index: BridgeTabs.Redeem,
children: <ToStellar />,
className: cs,
activeClassName: 'bg-[#f7f7f7] dark:bg-primary',
},
];

return (
<Tabs<BridgeTabs> activeTab={activeTab} setActiveTab={setActiveTab} tabItems={tabItems} className="border-0" />
);
}
34 changes: 7 additions & 27 deletions src/pages/spacewalk/bridge/index.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import { createContext } from 'preact/compat';
import { StateUpdater, Dispatch, useMemo, useState, useContext } from 'preact/hooks';
import { Button, Card, Tabs } from 'react-daisyui';
import { Button, Card } from 'react-daisyui';
import { Asset } from '@stellar/stellar-sdk';
import AmplitudeLogo from '../../../assets/AmplitudeLogo';
import PendulumLogo from '../../../assets/PendulumLogo';
import SettingsIcon from '../../../assets/SettingsIcon';
import StellarLogo from '../../../assets/StellarLogo';
import { SpacewalkConstants } from '../../../helpers/spacewalk';
import { ExtendedRegistryVault } from '../../../hooks/spacewalk/useVaultRegistryPallet';
import { useNodeInfoState } from '../../../NodeInfoProvider';
import { TenantName } from '../../../models/Tenant';
import SettingsDialog from './Issue/SettingsDialog';
import Issue from './Issue';
import Redeem from './Redeem';
import '../styles.css';
import { SpacewalkTabs } from './SpacewalkTabs';

enum BridgeTabs {
export enum BridgeTabs {
Issue = 0,
Redeem = 1,
}
Expand Down Expand Up @@ -73,11 +70,6 @@ function Bridge() {
}
}, [chain, tokenSymbol, tabValue, wrappedCurrencySuffix]);

const getTabProps = (index: number) => ({
active: tabValue === index,
onClick: () => setTabValue(index),
});

const bridgeDirection = tabValue === BridgeTabs.Issue ? BridgeDirection.Issue : BridgeDirection.Redeem;

return chain ? (
Expand All @@ -94,30 +86,18 @@ function Bridge() {
setExtendedVaults,
}}
>
<div className="flex items-center justify-center h-full mt-4">
<div className="mt-4 flex items-center justify-center">
<SettingsDialog
visible={settingsVisible}
onClose={() => setSettingsVisible(false)}
bridgeDirection={bridgeDirection}
/>
<Card className="bridge-card min-h-500 w-full max-w-[520px] rounded-lg bg-base-200">
<div className="flex justify-between px-5 mt-5">
<Tabs className="flex justify-center flex-grow tabs-boxed sm:w-5/6">
<Tabs.Tab className="w-1/2 h-full p-2 text-xs sm:w-2/5 sm:text-sm" {...getTabProps(0)}>
{chain.toLowerCase() === TenantName.Pendulum && <PendulumLogo className="w-6 h-6 mr-1" />}
{(chain.toLowerCase() === TenantName.Amplitude || chain.toLowerCase() === TenantName.Foucoco) && (
<AmplitudeLogo className="w-6 h-6 mr-1" />
)}
To {chain}
</Tabs.Tab>
<Tabs.Tab className="w-1/2 h-full p-2 text-xs sm:w-2/5 sm:text-sm" {...getTabProps(1)}>
<StellarLogo className="w-6 h-6 mr-1" />
To Stellar
</Tabs.Tab>
</Tabs>
<div className="mt-5 flex justify-between px-5">
<SpacewalkTabs activeTab={tabValue} setActiveTab={setTabValue} />
<Button
color="ghost"
className="min-h-0 p-1 m-auto settings h-fit"
className="settings m-auto h-fit min-h-0 p-1"
onClick={() => setSettingsVisible(true)}
>
<SettingsIcon />
Expand Down
16 changes: 4 additions & 12 deletions src/pages/spacewalk/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,10 @@
}

[data-theme='pendulum'] {
.bridge-card .tabs-boxed :not(.tab-active) > svg {
.bridge-card .tabs-boxed :not([data-active='true']) > svg {
fill: var(--gray-3, #828282);
}

.bridge-card .tabs-boxed :not(.tab-active) {
color: var(--gray-3, #828282);
}

.bridge-card .tabs-boxed .tab-active:not(.tab-disabled):not([disabled]) {
background-color: #f7f7f7;
}
Expand Down Expand Up @@ -110,16 +106,12 @@
}

[data-theme='amplitude'] {
.bridge-card .tabs-boxed :not(.tab-active) > svg {
.bridge-card .tabs-boxed :not([data-active='true']) > svg {
fill: var(--primary);
}

.bridge-card .tabs-boxed :not(.tab-active) {
color: #fff;
}

.bridge-card .tabs-boxed .tab-active:not(.tab-disabled):not([disabled]) {
background-color: var(--primary);
.bridge-card .tabs-boxed [data-active='true'] > svg {
fill: black;
}

.bridge-card .disclaimer svg {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/staking/dialogs/DelegateToCollatorDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { yupResolver } from '@hookform/resolvers/yup';
import { useMemo, useState } from 'preact/hooks';
import { Button } from 'react-daisyui';
import { useForm } from 'react-hook-form';
import ChainLogo from '../../../assets/ChainLogo';
import { ChainLogo } from '../../../assets/ChainLogo';
import Amount from '../../../components/Form/Amount';
import { PublicKey } from '../../../components/PublicKey';
import { Dialog } from '../../../components/Dialog';
Expand Down

0 comments on commit 9fb80d9

Please sign in to comment.