Skip to content

Commit

Permalink
feat: Add WalletAdvanced classnames overrides (#1912)
Browse files Browse the repository at this point in the history
  • Loading branch information
brendan-defi authored Feb 4, 2025
1 parent 9b032e8 commit 26643de
Show file tree
Hide file tree
Showing 17 changed files with 607 additions and 78 deletions.
3 changes: 2 additions & 1 deletion playground/nextjs-app-router/onchainkit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"repository": "https://github.com/coinbase/onchainkit.git",
"license": "MIT",
"scripts": {
"build": "packemon build --addEngines --addFiles --loadConfigs --declaration && npx packemon validate --no-license --no-people --no-repo && tailwindcss -i ./src/styles/index.css -o ./src/tailwind.css --minify && tailwindcss -i ./src/styles/index-with-tailwind.css -o ./src/styles.css --minify",
"build": "packemon build --addEngines --addFiles --loadConfigs --declaration && tscpaths -p tsconfig.esm.json -s ./src -o ./esm && npx packemon validate --no-license --no-people --no-repo && tailwindcss -i ./src/styles/index.css -o ./src/tailwind.css --minify && tailwindcss -i ./src/styles/index-with-tailwind.css -o ./src/styles.css --minify",
"check": "biome check --write .",
"check:unsafe": "biome check . --fix --unsafe",
"ci:check": "biome ci --formatter-enabled=false --linter-enabled=false",
Expand Down Expand Up @@ -77,6 +77,7 @@
"rimraf": "^5.0.5",
"storybook": "^8.2.9",
"tailwindcss": "^3.4.3",
"tscpaths": "^0.0.9",
"tsup": "^8.3.5",
"typescript": "~5.3.3",
"vite": "^5.3.3",
Expand Down
13 changes: 11 additions & 2 deletions src/wallet/components/WalletAdvanced.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,19 @@ import type { WalletAdvancedReact } from '../types';
import { WalletAdvancedContent } from './WalletAdvancedContent';
import { WalletAdvancedProvider } from './WalletAdvancedProvider';

export function WalletAdvanced({ children }: WalletAdvancedReact) {
export function WalletAdvanced({
children,
classNames,
swappableTokens,
}: WalletAdvancedReact) {
return (
<WalletAdvancedProvider>
<WalletAdvancedContent>{children}</WalletAdvancedContent>
<WalletAdvancedContent
classNames={classNames}
swappableTokens={swappableTokens}
>
{children}
</WalletAdvancedContent>
</WalletAdvancedProvider>
);
}
35 changes: 35 additions & 0 deletions src/wallet/components/WalletAdvancedAddressDetails.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -202,4 +202,39 @@ describe('WalletAdvancedAddressDetails', () => {
screen.getByTestId('ockWalletAdvanced_AddressBalance'),
).toHaveTextContent('$1,234.57');
});

it('applies custom classNames to components', () => {
mockUseWalletContext.mockReturnValue({
isClosing: false,
address: '0x1234567890',
chain: { id: 8453 },
});

mockUseWalletAdvancedContext.mockReturnValue({
portfolioFiatValue: 1000,
animations: {
content: '',
},
});

const customClassNames = {
container: 'custom-container',
avatar: 'custom-avatar',
nameButton: 'custom-name',
fiatBalance: 'custom-balance',
};

render(<WalletAdvancedAddressDetails classNames={customClassNames} />);

expect(screen.getByTestId('ockWalletAdvanced_AddressDetails')).toHaveClass(
'custom-container',
);
expect(screen.getByTestId('ockAvatar_ImageContainer')).toHaveClass(
'custom-avatar',
);
expect(screen.getByTestId('ockIdentity_Text')).toHaveClass('custom-name');
expect(screen.getByTestId('ockWalletAdvanced_AddressBalance')).toHaveClass(
'custom-balance',
);
});
});
38 changes: 28 additions & 10 deletions src/wallet/components/WalletAdvancedAddressDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,18 @@ import { useCallback, useState } from 'react';
import { useWalletAdvancedContext } from './WalletAdvancedProvider';
import { useWalletContext } from './WalletProvider';

export function WalletAdvancedAddressDetails() {
type WalletAdvancedAddressDetailsProps = {
classNames?: {
container?: string;
avatar?: string;
nameButton?: string;
fiatBalance?: string;
};
};

export function WalletAdvancedAddressDetails({
classNames,
}: WalletAdvancedAddressDetailsProps) {
const { address, chain, isSubComponentClosing } = useWalletContext();
const { animations } = useWalletAdvancedContext();
const [copyText, setCopyText] = useState('Copy');
Expand All @@ -30,18 +41,22 @@ export function WalletAdvancedAddressDetails() {

return (
<div
data-testid="ockWalletAdvanced_AddressDetails"
className={cn(
'mt-2 flex flex-col items-center justify-center',
color.foreground,
text.body,
animations.content,
classNames?.container,
)}
>
<div className="h-10 w-10">
<Avatar address={address} chain={chain} className="pointer-events-none">
<Badge />
</Avatar>
</div>
<Avatar
address={address}
chain={chain}
className={cn('pointer-events-none h-10 w-10', classNames?.avatar)}
>
<Badge />
</Avatar>
<div className="group relative mt-2 text-base">
<button
type="button"
Expand All @@ -51,7 +66,10 @@ export function WalletAdvancedAddressDetails() {
<Name
address={address}
chain={chain}
className="hover:text-[var(--ock-text-foreground-muted)] active:text-[var(--ock-text-primary)]"
className={cn(
'hover:text-[var(--ock-text-foreground-muted)] active:text-[var(--ock-text-primary)]',
classNames?.nameButton,
)}
/>
</button>
<button
Expand All @@ -71,12 +89,12 @@ export function WalletAdvancedAddressDetails() {
{copyText}
</button>
</div>
<AddressBalanceInFiat />
<AddressBalanceInFiat className={classNames?.fiatBalance} />
</div>
);
}

function AddressBalanceInFiat() {
function AddressBalanceInFiat({ className }: { className?: string }) {
const { portfolioFiatValue, isFetchingPortfolioData } =
useWalletAdvancedContext();

Expand All @@ -99,7 +117,7 @@ function AddressBalanceInFiat() {

return (
<div
className={cn(text.title1, 'mt-1 font-normal')}
className={cn(text.title1, 'mt-1 font-normal', className)}
data-testid="ockWalletAdvanced_AddressBalance"
>
{formattedValueInFiat}
Expand Down
59 changes: 55 additions & 4 deletions src/wallet/components/WalletAdvancedContent.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type { SwapDefaultReact } from '@/swap/types';
import { fireEvent, render, screen } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import type {
WalletAdvancedQrReceiveProps,
WalletAdvancedSwapProps,
} from '../types';
import { WalletAdvancedContent } from './WalletAdvancedContent';
import { useWalletAdvancedContext } from './WalletAdvancedProvider';
import { useWalletContext } from './WalletProvider';
Expand All @@ -17,16 +20,22 @@ vi.mock('./WalletAdvancedProvider', () => ({
}));

vi.mock('./WalletAdvancedQrReceive', () => ({
WalletAdvancedQrReceive: () => (
<div data-testid="ockWalletAdvancedQrReceive">WalletAdvancedQrReceive</div>
WalletAdvancedQrReceive: ({ classNames }: WalletAdvancedQrReceiveProps) => (
<div
data-testid="ockWalletAdvancedQrReceive"
className={classNames?.container}
>
WalletAdvancedQrReceive
</div>
),
}));

vi.mock('./WalletAdvancedSwap', () => ({
WalletAdvancedSwap: ({ from, to }: SwapDefaultReact) => (
WalletAdvancedSwap: ({ from, to, classNames }: WalletAdvancedSwapProps) => (
<div
data-testid="ockWalletAdvancedSwap"
data-props={JSON.stringify({ from, to })}
className={classNames?.container}
>
WalletAdvancedSwap
</div>
Expand Down Expand Up @@ -314,4 +323,46 @@ describe('WalletAdvancedContent', () => {
})),
);
});

it('applies custom classNames to components', () => {
mockUseWalletContext.mockReturnValue({
isSubComponentClosing: false,
showSubComponentAbove: false,
});

mockUseWalletAdvancedContext.mockReturnValue({
...defaultMockUseWalletAdvancedContext,
showQr: true,
showSwap: true,
});

const customClassNames = {
container: 'custom-container',
qr: {
container: 'custom-qr-container',
},
swap: {
container: 'custom-swap-container',
},
};

render(
<WalletAdvancedContent classNames={customClassNames}>
<div>Content</div>
</WalletAdvancedContent>,
);

expect(screen.getByTestId('ockWalletAdvancedContent')).toHaveClass(
'custom-container',
);

// Verify both rendered state and passed props
const qrComponent = screen.getByTestId('ockWalletAdvancedQrReceive');
expect(qrComponent).toHaveClass('custom-qr-container');
expect(qrComponent).toHaveProperty('className', 'custom-qr-container');

const swapComponent = screen.getByTestId('ockWalletAdvancedSwap');
expect(swapComponent).toHaveClass('custom-swap-container');
expect(swapComponent).toHaveProperty('className', 'custom-swap-container');
});
});
6 changes: 4 additions & 2 deletions src/wallet/components/WalletAdvancedContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useWalletContext } from './WalletProvider';
export function WalletAdvancedContent({
children,
swappableTokens,
classNames,
}: WalletAdvancedReact) {
const {
isSubComponentClosing,
Expand All @@ -28,6 +29,7 @@ export function WalletAdvancedContent({
'my-1.5 h-auto w-88',
'flex items-center justify-center',
animations.container,
classNames?.container,
)}
onAnimationEnd={() => {
if (isSubComponentClosing) {
Expand All @@ -43,7 +45,7 @@ export function WalletAdvancedContent({
showQr ? '' : 'hidden',
)}
>
<WalletAdvancedQrReceive />
<WalletAdvancedQrReceive classNames={classNames?.qr} />
</div>
<div
className={cn(
Expand All @@ -69,7 +71,7 @@ export function WalletAdvancedContent({
name: token.name,
})) ?? []
}
className="w-full px-4 pt-3 pb-4"
classNames={classNames?.swap}
/>
</div>
<div
Expand Down
29 changes: 29 additions & 0 deletions src/wallet/components/WalletAdvancedQrReceive.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -326,4 +326,33 @@ describe('WalletAdvancedQrReceive', () => {

expect(mockClipboard.writeText).toHaveBeenCalledWith('');
});

it('applies custom classNames to components', () => {
mockUseWalletContext.mockReturnValue({
isSubComponentClosing: false,
address: '0x1234567890',
});

const customClassNames = {
container: 'custom-container',
header: 'custom-header',
copyButton: 'custom-copy-button',
};

render(<WalletAdvancedQrReceive classNames={customClassNames} />);

expect(screen.getByTestId('ockWalletAdvancedQrReceive')).toHaveClass(
'custom-container',
);
expect(
screen
.getByTestId('ockWalletAdvancedQrReceive')
.querySelector('[class*="custom-header"]'),
).toBeInTheDocument();
expect(
screen.getByRole('button', {
name: 'Copy your address by clicking the button',
}),
).toHaveClass('custom-copy-button');
});
});
21 changes: 18 additions & 3 deletions src/wallet/components/WalletAdvancedQrReceive.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ import { copySvg } from '@/internal/svg/copySvg';
import { zIndex } from '@/styles/constants';
import { border, cn, color, pressable, text } from '@/styles/theme';
import { useCallback, useState } from 'react';
import type { WalletAdvancedQrReceiveProps } from '../types';
import { useWalletAdvancedContext } from './WalletAdvancedProvider';
import { useWalletContext } from './WalletProvider';

export function WalletAdvancedQrReceive() {
export function WalletAdvancedQrReceive({
classNames,
}: WalletAdvancedQrReceiveProps) {
const { address, isSubComponentClosing } = useWalletContext();
const { setShowQr, isQrClosing, setIsQrClosing } = useWalletAdvancedContext();
const [copyText, setCopyText] = useState('Copy');
Expand Down Expand Up @@ -63,6 +66,7 @@ export function WalletAdvancedQrReceive() {
<div
data-testid="ockWalletAdvancedQrReceive"
className={cn(
border.radius,
color.foreground,
text.headline,
'flex flex-col items-center justify-between',
Expand All @@ -71,10 +75,16 @@ export function WalletAdvancedQrReceive() {
isQrClosing
? 'fade-out slide-out-to-left-5 animate-out fill-mode-forwards ease-in-out'
: 'fade-in slide-in-from-left-5 linear animate-in duration-150',
classNames?.container,
)}
onAnimationEnd={handleAnimationEnd}
>
<div className="flex h-[34px] w-full flex-row items-center justify-between">
<div
className={cn(
'flex h-[34px] w-full flex-row items-center justify-between',
classNames?.header,
)}
>
<PressableIcon ariaLabel="Back button" onClick={handleCloseQr}>
<div className="p-2">{backArrowSvg}</div>
</PressableIcon>
Expand Down Expand Up @@ -115,7 +125,12 @@ export function WalletAdvancedQrReceive() {
<CopyButton
copyValue={address ?? ''}
label={copyButtonText}
className={cn(border.radius, pressable.alternate, 'w-full p-3')}
className={cn(
border.radius,
pressable.alternate,
'w-full p-3',
classNames?.copyButton,
)}
onSuccess={handleCopyButtonSuccess}
onError={handleCopyButtonError}
aria-label="Copy your address by clicking the button"
Expand Down
Loading

0 comments on commit 26643de

Please sign in to comment.