diff --git a/.changeset/curly-lions-drum.md b/.changeset/curly-lions-drum.md new file mode 100644 index 00000000..f413b24d --- /dev/null +++ b/.changeset/curly-lions-drum.md @@ -0,0 +1,5 @@ +--- +"@zerodev/react-ui": patch +--- + +feat: promote `ArrowCardPair` (and `ArrowView`) to `@zerodev/react-ui`. Previously local to wallet-react-ui's signing pages; now a shared primitive available to other consumers (e.g. smart-routing-address-react-ui's Deposit flow). diff --git a/packages/react-ui/src/components/ArrowCardPair/ArrowCardPair.stories.tsx b/packages/react-ui/src/components/ArrowCardPair/ArrowCardPair.stories.tsx new file mode 100644 index 00000000..dc6e49bd --- /dev/null +++ b/packages/react-ui/src/components/ArrowCardPair/ArrowCardPair.stories.tsx @@ -0,0 +1,44 @@ +import type { Meta, StoryObj } from '@storybook/react-vite' + +import { Text } from '../Text' +import { Wrapper } from '../Wrapper' +import { ArrowCardPair } from '.' + +const meta: Meta = { + title: 'Layout/ArrowCardPair', + component: ArrowCardPair, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], + decorators: [ + (Story) => ( +
+ +
+ ), + ], +} + +export default meta +type Story = StoryObj + +/** + * Two cards with a chevron-down arrow floating between them, and rounded + * notches clipped out of each card where the arrow sits. Used to visually + * connect a "from" and "to" side of a swap, transfer, or deposit flow. + */ +export const Default: Story = { + args: { + topCard: ( + + Top card + + ), + bottomCard: ( + + Bottom card + + ), + }, +} diff --git a/packages/wallet-react-ui/src/signing/components/ArrowCardPair/ArrowCardPair.test.tsx b/packages/react-ui/src/components/ArrowCardPair/ArrowCardPair.test.tsx similarity index 85% rename from packages/wallet-react-ui/src/signing/components/ArrowCardPair/ArrowCardPair.test.tsx rename to packages/react-ui/src/components/ArrowCardPair/ArrowCardPair.test.tsx index d1387735..57482df4 100644 --- a/packages/wallet-react-ui/src/signing/components/ArrowCardPair/ArrowCardPair.test.tsx +++ b/packages/react-ui/src/components/ArrowCardPair/ArrowCardPair.test.tsx @@ -1,8 +1,11 @@ import { cleanup, render, screen } from '@testing-library/react' import { afterEach, describe, expect, it, vi } from 'vitest' -vi.mock('@zerodev/react-ui', async (importOriginal) => { - const actual = await importOriginal() +// The real Icon component uses `import.meta.glob` to eagerly load SVGs from +// disk, which vitest can't resolve. Stub it with a minimal mock that emits +// `data-testid="icon-"` for query-by-testid. +vi.mock('../Icon', async (importOriginal) => { + const actual = await importOriginal() const React = await import('react') const MockIcon = ({ diff --git a/packages/wallet-react-ui/src/signing/components/ArrowCardPair/index.tsx b/packages/react-ui/src/components/ArrowCardPair/index.tsx similarity index 96% rename from packages/wallet-react-ui/src/signing/components/ArrowCardPair/index.tsx rename to packages/react-ui/src/components/ArrowCardPair/index.tsx index 0da2f1e4..bdccf1eb 100644 --- a/packages/wallet-react-ui/src/signing/components/ArrowCardPair/index.tsx +++ b/packages/react-ui/src/components/ArrowCardPair/index.tsx @@ -1,5 +1,7 @@ -import { cn, Icon, Wrapper } from '@zerodev/react-ui' import { type ReactNode, useEffect, useRef, useState } from 'react' +import { cn } from '../../utils/common' +import { Icon } from '../Icon' +import { Wrapper } from '../Wrapper' const ARROW_INNER = 44 const PADDING = 4 diff --git a/packages/react-ui/src/index.ts b/packages/react-ui/src/index.ts index 7a715964..3d5af3bc 100644 --- a/packages/react-ui/src/index.ts +++ b/packages/react-ui/src/index.ts @@ -3,6 +3,11 @@ * React UI primitives for ZeroDev */ +export { + ArrowCardPair, + type ArrowCardPairProps, + ArrowView, +} from './components/ArrowCardPair' export { Badge, type BadgeProps } from './components/Badge' export { Button, type ButtonProps } from './components/Button' export { Callout, type CalloutProps } from './components/Callout' diff --git a/packages/wallet-react-ui/src/signing/components/ArrowCardPair/ArrowCardPair.stories.tsx b/packages/wallet-react-ui/src/signing/components/ArrowCardPair/ArrowCardPair.stories.tsx deleted file mode 100644 index 35796db9..00000000 --- a/packages/wallet-react-ui/src/signing/components/ArrowCardPair/ArrowCardPair.stories.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react-vite' - -import { InfoCard } from '../InfoCard' -import { ArrowCardPair } from '.' - -const meta = { - title: 'Signing/ArrowCardPair', - component: ArrowCardPair, - parameters: { - layout: 'centered', - }, - tags: ['autodocs'], - decorators: [ - (Story) => ( -
- -
- ), - ], -} satisfies Meta - -export default meta -type Story = StoryObj - -export const Default: Story = { - args: { - topCard: ( - - ), - bottomCard: ( - - ), - }, -} diff --git a/packages/wallet-react-ui/src/signing/pages/CollectionApproval.tsx b/packages/wallet-react-ui/src/signing/pages/CollectionApproval.tsx index f39c93d3..2b78a19c 100644 --- a/packages/wallet-react-ui/src/signing/pages/CollectionApproval.tsx +++ b/packages/wallet-react-ui/src/signing/pages/CollectionApproval.tsx @@ -1,8 +1,13 @@ -import { DataRow, DataRowSkeleton, Icon, Text } from '@zerodev/react-ui' +import { + ArrowCardPair, + DataRow, + DataRowSkeleton, + Icon, + Text, +} from '@zerodev/react-ui' import type { Address, Hex } from 'viem' import { useReadContract } from 'wagmi' import { shortenHex } from '../../shared/utils/common' -import { ArrowCardPair } from '../components/ArrowCardPair' import { InfoCard } from '../components/InfoCard' import { Section } from '../components/Section' import { SigningLayout } from '../components/SigningLayout' diff --git a/packages/wallet-react-ui/src/signing/pages/Erc20Approval.tsx b/packages/wallet-react-ui/src/signing/pages/Erc20Approval.tsx index 1f702b52..7f26a73e 100644 --- a/packages/wallet-react-ui/src/signing/pages/Erc20Approval.tsx +++ b/packages/wallet-react-ui/src/signing/pages/Erc20Approval.tsx @@ -1,8 +1,13 @@ -import { DataRow, DataRowSkeleton, Icon, Text } from '@zerodev/react-ui' +import { + ArrowCardPair, + DataRow, + DataRowSkeleton, + Icon, + Text, +} from '@zerodev/react-ui' import { type Address, erc20Abi, formatUnits, type Hex, maxUint256 } from 'viem' import { useReadContract } from 'wagmi' import { shortenHex } from '../../shared/utils/common' -import { ArrowCardPair } from '../components/ArrowCardPair' import { InfoCard } from '../components/InfoCard' import { Section } from '../components/Section' import { SigningLayout } from '../components/SigningLayout' diff --git a/packages/wallet-react-ui/src/signing/pages/Erc20Transfer.tsx b/packages/wallet-react-ui/src/signing/pages/Erc20Transfer.tsx index 000b9790..14214465 100644 --- a/packages/wallet-react-ui/src/signing/pages/Erc20Transfer.tsx +++ b/packages/wallet-react-ui/src/signing/pages/Erc20Transfer.tsx @@ -1,8 +1,13 @@ -import { DataRow, DataRowSkeleton, Icon, Text } from '@zerodev/react-ui' +import { + ArrowCardPair, + DataRow, + DataRowSkeleton, + Icon, + Text, +} from '@zerodev/react-ui' import { type Address, erc20Abi, formatUnits, type Hex } from 'viem' import { useReadContract } from 'wagmi' import { shortenHex } from '../../shared/utils/common' -import { ArrowCardPair } from '../components/ArrowCardPair' import { InfoCard } from '../components/InfoCard' import { Section } from '../components/Section' import { SigningLayout } from '../components/SigningLayout' diff --git a/packages/wallet-react-ui/src/signing/pages/EthTransfer.tsx b/packages/wallet-react-ui/src/signing/pages/EthTransfer.tsx index 95f7bc69..db666636 100644 --- a/packages/wallet-react-ui/src/signing/pages/EthTransfer.tsx +++ b/packages/wallet-react-ui/src/signing/pages/EthTransfer.tsx @@ -1,7 +1,12 @@ -import { DataRow, DataRowSkeleton, Icon, Text } from '@zerodev/react-ui' +import { + ArrowCardPair, + DataRow, + DataRowSkeleton, + Icon, + Text, +} from '@zerodev/react-ui' import { type Address, formatEther, type Hex } from 'viem' import { shortenHex } from '../../shared/utils/common' -import { ArrowCardPair } from '../components/ArrowCardPair' import { InfoCard } from '../components/InfoCard' import { Section } from '../components/Section' import { SigningLayout } from '../components/SigningLayout'