Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/curly-lions-drum.md
Original file line number Diff line number Diff line change
@@ -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).
Original file line number Diff line number Diff line change
@@ -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<typeof ArrowCardPair> = {
title: 'Layout/ArrowCardPair',
component: ArrowCardPair,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
decorators: [
(Story) => (
<div style={{ width: 360 }}>
<Story />
</div>
),
],
}

export default meta
type Story = StoryObj<typeof meta>

/**
* 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: (
<Wrapper variant="ghost" className="zd:rounded-2xl zd:p-4">
<Text className="zd:text-h3">Top card</Text>
</Wrapper>
),
bottomCard: (
<Wrapper variant="ghost" className="zd:rounded-2xl zd:p-4">
<Text className="zd:text-h3">Bottom card</Text>
</Wrapper>
),
},
}
Original file line number Diff line number Diff line change
@@ -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<typeof import('@zerodev/react-ui')>()
// 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-<name>"` for query-by-testid.
vi.mock('../Icon', async (importOriginal) => {
const actual = await importOriginal<typeof import('../Icon')>()
const React = await import('react')

const MockIcon = ({
Expand Down

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I never really liked the ArrowCardPair name, feels very verbose. How about ArrowStack or CardPair?

@OmarBasem OmarBasem Jul 15, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly I prefer ArrowCardPair over the other 2, but I can consider renaming it to something else. I was thinking maybe CardPairWithArrow although that's even longer, but more understandable I think.

Anyways I would prefer to rename it in a separate PR as that component touches several files that would cause many conflicts.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave it as is then, it's more of a nit.

Original file line number Diff line number Diff line change
@@ -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
Expand Down
5 changes: 5 additions & 0 deletions packages/react-ui/src/index.ts

@brtkx brtkx Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

react-ui needs changeset update since now we have automatic releases. It will be a patch change. wallet-react-ui doesn't need it because nothing changes on the consumer end.

Here's the full reference on how to do it. One note: we don't need to merge #316 - we can just keep on developing until we have a decent stack of changes or need an urgent release.

Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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'
Expand Down
9 changes: 7 additions & 2 deletions packages/wallet-react-ui/src/signing/pages/Erc20Approval.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand Down
9 changes: 7 additions & 2 deletions packages/wallet-react-ui/src/signing/pages/Erc20Transfer.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand Down
9 changes: 7 additions & 2 deletions packages/wallet-react-ui/src/signing/pages/EthTransfer.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand Down
Loading