Skip to content

Commit

Permalink
feat: update styles to the latest design (#94)
Browse files Browse the repository at this point in the history
  • Loading branch information
krzysu authored Jan 14, 2025
1 parent 0f4e226 commit c04cdc5
Show file tree
Hide file tree
Showing 41 changed files with 856 additions and 240 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build-demo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ jobs:
- run: yarn install
- run: yarn workspace circle-demo-webapp lint
- run: yarn workspace circle-demo-webapp build
- run: yarn workspace circle-demo-webapp build-storybook
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import type { Meta, StoryObj } from '@storybook/react';

import { Blockchain } from '~/lib/constants';

import { ChainIcon } from './ChainIcon';

const meta = {
title: 'ChainIcon',
component: ChainIcon,
tags: ['autodocs'],
} satisfies Meta<typeof ChainIcon>;

export default meta;

type Story = StoryObj<typeof meta>;

export const EthSepolia: Story = {
args: {
blockchain: Blockchain.EthSepolia,
},
};

export const EthMainnet: Story = {
args: {
blockchain: Blockchain.Eth,
},
};

export const ArbSepolia: Story = {
args: {
blockchain: Blockchain.ArbSepolia,
},
};

export const ArbMainnet: Story = {
args: {
blockchain: Blockchain.Arb,
},
};

export const AvaxFuji: Story = {
args: {
blockchain: Blockchain.AvaxFuji,
},
};

export const AvaxMainnet: Story = {
args: {
blockchain: Blockchain.Avax,
},
};

export const PolygonAmoy: Story = {
args: {
blockchain: Blockchain.MaticAmoy,
},
};

export const PolygonMainnet: Story = {
args: {
blockchain: Blockchain.Matic,
},
};

export const SolanaDevnet: Story = {
args: {
blockchain: Blockchain.SolDevnet,
},
};

export const SolanaMainnet: Story = {
args: {
blockchain: Blockchain.Sol,
},
};

export const NearTestnet: Story = {
args: {
blockchain: Blockchain.NearTestnet,
},
};

export const NearMainnet: Story = {
args: {
blockchain: Blockchain.Near,
},
};
38 changes: 38 additions & 0 deletions packages/circle-demo-webapp/app/components/ChainIcon/ChainIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { NetworkIcon } from '@web3icons/react';

import { Blockchain } from '~/lib/constants';

export interface ChainIconProps {
/** The blockchain network */
blockchain: string;
}

const BLOCKCHAIN_TO_ICON_MAP: Record<string, string> = {
[Blockchain.ArbSepolia]: 'arbitrum',
[Blockchain.Arb]: 'arbitrum',
[Blockchain.AvaxFuji]: 'avalanche',
[Blockchain.Avax]: 'avalanche',
[Blockchain.EthSepolia]: 'ethereum',
[Blockchain.Eth]: 'ethereum',
[Blockchain.EvmTestnet]: '',
[Blockchain.Evm]: '',
[Blockchain.MaticAmoy]: 'polygon',
[Blockchain.Matic]: 'polygon',
[Blockchain.NearTestnet]: 'near-protocol',
[Blockchain.Near]: 'near-protocol',
[Blockchain.SolDevnet]: 'solana',
[Blockchain.Sol]: 'solana',
};

/** A label with an icon and text to identify a blockchain network */
export function ChainIcon({ blockchain }: ChainIconProps) {
const network = BLOCKCHAIN_TO_ICON_MAP[blockchain];

const icon = <NetworkIcon network={network} size={20} variant="branded" />;

return network === 'arbitrum' ? (
<span className="rounded-full bg-[#2D3649]">{icon}</span>
) : (
icon
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ChainIcon';
Original file line number Diff line number Diff line change
@@ -1,29 +1,11 @@
import { NetworkIcon } from '@web3icons/react';

import { ChainIcon } from '~/components/ChainIcon';
import { Blockchain } from '~/lib/constants';

export interface ChainSelectProps {
/** The blockchain network */
blockchain: string;
}

const BLOCKCHAIN_TO_ICON_MAP: Record<string, string> = {
[Blockchain.ArbSepolia]: 'arbitrum',
[Blockchain.Arb]: 'arbitrum',
[Blockchain.AvaxFuji]: 'avalanche',
[Blockchain.Avax]: 'avalanche',
[Blockchain.EthSepolia]: 'ethereum',
[Blockchain.Eth]: 'ethereum',
[Blockchain.EvmTestnet]: '',
[Blockchain.Evm]: '',
[Blockchain.MaticAmoy]: 'polygon',
[Blockchain.Matic]: 'polygon',
[Blockchain.NearTestnet]: 'near-protocol',
[Blockchain.Near]: 'near-protocol',
[Blockchain.SolDevnet]: 'solana',
[Blockchain.Sol]: 'solana',
};

const BLOCKCHAIN_LABELS: Record<string, string> = {
[Blockchain.ArbSepolia]: 'Arbitrum Sepolia',
[Blockchain.Arb]: 'Arbitrum',
Expand All @@ -45,11 +27,8 @@ const BLOCKCHAIN_LABELS: Record<string, string> = {
export function ChainLabel({ blockchain }: ChainSelectProps) {
return (
<p className="text-sm text-muted-foreground flex items-center space-x-2">
<NetworkIcon
network={BLOCKCHAIN_TO_ICON_MAP[blockchain]}
size={20}
variant="branded"
/>
<ChainIcon blockchain={blockchain} />

<span>{BLOCKCHAIN_LABELS[blockchain]}</span>
</p>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { SelectProps } from '@radix-ui/react-select';
import { NetworkIcon } from '@web3icons/react';

import { ChainIcon } from '~/components/ChainIcon';
import {
Select,
SelectContent,
Expand All @@ -10,15 +10,6 @@ import {
} from '~/components/ui/select';
import { Blockchain } from '~/lib/constants';

const BLOCKCHAIN_TO_ICON_MAP: Record<string, string> = {
[Blockchain.Arb]: 'arbitrum',
[Blockchain.Avax]: 'avalanche',
[Blockchain.Eth]: 'ethereum',
[Blockchain.Matic]: 'polygon',
[Blockchain.Near]: 'near-protocol',
[Blockchain.Sol]: 'solana',
};

const BLOCKCHAIN_LABELS: Record<string, string> = {
[Blockchain.Arb]: 'Arbitrum',
[Blockchain.Avax]: 'Avalanche',
Expand All @@ -32,7 +23,7 @@ export type ChainSelectProps = Omit<SelectProps, 'children'> & { placeholder?: s

/** A dropdown select menu to choose a mainnet blockchain network */
export function ChainSelect({ ...props }: ChainSelectProps) {
const { placeholder = 'Select Network', ...other } = props;
const { placeholder = 'Select network', ...other } = props;
return (
<Select {...other}>
<SelectTrigger className="w-full max-w-md">
Expand All @@ -42,11 +33,7 @@ export function ChainSelect({ ...props }: ChainSelectProps) {
{Object.keys(BLOCKCHAIN_LABELS).map((blockchain) => (
<SelectItem key={blockchain} value={blockchain}>
<div className="text-sm text-muted-foreground flex items-center space-x-2 pr-4">
<NetworkIcon
network={BLOCKCHAIN_TO_ICON_MAP[blockchain]}
size={20}
variant="branded"
/>
<ChainIcon blockchain={blockchain} />
<span>{BLOCKCHAIN_LABELS[blockchain]}</span>
</div>
</SelectItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
import { ComplianceEngineText } from './ComplianceEngineText';

const meta = {
title: 'FormErrorText',
title: 'ComplianceEngineText',
component: ComplianceEngineText,
tags: ['autodocs'],
} satisfies Meta<typeof ComplianceEngineText>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
export function ComplianceEngineText({ result }: { result: boolean }) {
return (
<div className="flex">
{result ? (
<p className="bg-teal-600/10 rounded-lg py-1 px-3 my-2 text-xs text-success">
Approved by Circle Compliance Engine ✓
</p>
) : (
<p className="bg-teal-600/10 rounded-lg py-1 px-3 my-2 text-xs text-error denied">
Denied by Circle Compliance Engine ✘
</p>
)}
</div>
import { Badge } from '~/components/ui/badge';

export interface ComplianceEngineTextProps {
result: boolean;
}

export function ComplianceEngineText({ result }: ComplianceEngineTextProps) {
return result ? (
<Badge variant="accent" className="font-normal text-green-600 dark:text-green-500">
Approved by Circle Compliance Engine ✓
</Badge>
) : (
<Badge variant="accent" className="font-normal text-red-500 dark:text-red-400">
Denied by Circle Compliance Engine ✘
</Badge>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export interface SidebarProps {

export function Sidebar({ walletSets = [] }: SidebarProps) {
return (
<aside className="bg-background w-64 h-full shadow-md flex flex-col overflow-y-auto">
<aside className="bg-background w-64 h-full flex flex-col overflow-y-auto">
<div className="p-6 max-w-[180px]">
<Link to="/">
<img src={circleLogo} alt="Circle Logo" className="block dark:hidden" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { SelectProps } from '@radix-ui/react-select';
import { NetworkIcon } from '@web3icons/react';

import { ChainIcon } from '~/components/ChainIcon';
import {
Select,
SelectContent,
Expand All @@ -10,15 +10,6 @@ import {
} from '~/components/ui/select';
import { Blockchain } from '~/lib/constants';

const BLOCKCHAIN_TO_ICON_MAP: Record<string, string> = {
[Blockchain.ArbSepolia]: 'arbitrum',
[Blockchain.AvaxFuji]: 'avalanche',
[Blockchain.EthSepolia]: 'ethereum',
[Blockchain.MaticAmoy]: 'polygon',
[Blockchain.NearTestnet]: 'near-protocol',
[Blockchain.SolDevnet]: 'solana',
};

const BLOCKCHAIN_LABELS: Record<string, string> = {
[Blockchain.ArbSepolia]: 'Arbitrum Sepolia',
[Blockchain.AvaxFuji]: 'Avalanche Fuji',
Expand All @@ -35,17 +26,13 @@ export function TestChainSelect({ ...props }: TestChainSelectProps) {
return (
<Select {...props}>
<SelectTrigger className="w-full max-w-md">
<SelectValue placeholder="Select Test Network" />
<SelectValue placeholder="Select test network" />
</SelectTrigger>
<SelectContent>
{Object.keys(BLOCKCHAIN_LABELS).map((blockchain) => (
<SelectItem key={blockchain} value={blockchain}>
<div className="text-sm text-muted-foreground flex items-center space-x-2 pr-4">
<NetworkIcon
network={BLOCKCHAIN_TO_ICON_MAP[blockchain]}
size={20}
variant="branded"
/>
<ChainIcon blockchain={blockchain} />
<span>{BLOCKCHAIN_LABELS[blockchain]}</span>
</div>
</SelectItem>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { AccountType } from '@circle-fin/developer-controlled-wallets';
import makeBlockie from 'ethereum-blockies-base64';
import { Copy } from 'lucide-react';
import { useMemo } from 'react';

import { ChainLabel } from '~/components/ChainLabel';
import { Badge } from '~/components/ui/badge';
import { Button } from '~/components/ui/button';
import { shortenAddress } from '~/lib/format';
import { Wallet } from '~/lib/types';

Expand All @@ -10,24 +14,49 @@ export interface WalletDetailsProps {
wallet: Wallet;
/** Child components to associate with the wallet */
children?: React.ReactNode;
/** Copy the wallet address to the clipboard */
onAddressCopy?: (address: string) => void;
}

const ACCOUNT_TYPE_TO_TEXT: Record<AccountType, string> = {
SCA: 'Smart Contract',
EOA: 'Externally Owned',
};

/** The details of an on-chain account */
export function WalletDetails({ wallet, children }: WalletDetailsProps) {
export function WalletDetails({ wallet, onAddressCopy, children }: WalletDetailsProps) {
const shortAddress = useMemo(() => shortenAddress(wallet.address), [wallet]);
const walletImage = useMemo(() => makeBlockie(wallet.address), [wallet]);

const copyToClipboard = () => {
void navigator.clipboard.writeText(wallet.address);
if (typeof onAddressCopy === 'function') {
onAddressCopy(wallet.address);
}
};

return (
<div className="flex items-center space-x-4">
<img src={walletImage} alt="Wallet Avatar" className="w-16 h-16 rounded-full" />

<div className="flex-1">
<p className="text-m font-medium text-foreground">
{wallet.name || 'Unnamed Wallet'}
</p>
<div className="flex items-center space-x-2">
<span className="text-m font-medium text-foreground">{wallet.name}</span>
{wallet.accountType === 'SCA' && (
<Badge variant="secondary">
{ACCOUNT_TYPE_TO_TEXT[wallet.accountType as AccountType]}
</Badge>
)}
</div>

<p className="flex items-center space-x-2 mb-1">
<span className="text-sm text-foreground" title={wallet.address}>
{shortAddress}
</span>

<p className="text-sm text-foreground mb-1" title={wallet.address}>
{shortAddress}
<Button onClick={copyToClipboard} variant="ghost" size="sm">
<Copy size={16} strokeWidth={1} />
</Button>
</p>

<ChainLabel blockchain={wallet.blockchain} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ export function WalletSend({
},
},
} as CreateTransactionInput);
if ((res as CircleError).error) {
setRequestError((res as CircleError).error.message);
if (res as CircleError) {
setRequestError((res as CircleError).message);
return;
}
const tx = res as Transaction;
Expand Down
Loading

0 comments on commit c04cdc5

Please sign in to comment.