diff --git a/packages/smart-routing-address-react-ui/src/components/AddressDisplay/index.tsx b/packages/smart-routing-address-react-ui/src/components/AddressDisplay/index.tsx index d434ed2d..5748139d 100644 --- a/packages/smart-routing-address-react-ui/src/components/AddressDisplay/index.tsx +++ b/packages/smart-routing-address-react-ui/src/components/AddressDisplay/index.tsx @@ -1,12 +1,13 @@ import { cn, Icon, Text, Wrapper } from '@zerodev/react-ui' +import { LoadingCard } from '../LoadingCard' /** * The card that renders the deposit address in the SRA "Deposit funds" screen. * * Two visual states, each mapped 1:1 to a Figma node: - * - Loading (Figma 17634:104343, "Smart Funding" card): 16px radius, 20% - * white surface, centered loading icon + `loadingText`. Rendered when - * `address` is omitted. + * - Loading (Figma 17634:104343, "Smart Funding" card): delegates to + * `LoadingCard`, which is the shared spinner+text pill used elsewhere in + * the SRA flow (e.g., SmartFunding's "Watching for deposit" state). * - Ready (Figma 17762:78875, address+QR row): 14px radius, 40% offWhite * surface, left-aligned address text + a 52×52 white QR button on the * right. Rendered when `address` is supplied. @@ -35,23 +36,11 @@ export function AddressDisplay({ }: AddressDisplayProps) { if (address === undefined) { return ( - - - - {loadingText} - - + /> ) } diff --git a/packages/smart-routing-address-react-ui/src/components/LoadingCard/LoadingCard.stories.tsx b/packages/smart-routing-address-react-ui/src/components/LoadingCard/LoadingCard.stories.tsx new file mode 100644 index 00000000..7fc88522 --- /dev/null +++ b/packages/smart-routing-address-react-ui/src/components/LoadingCard/LoadingCard.stories.tsx @@ -0,0 +1,34 @@ +import type { Meta, StoryObj } from '@storybook/react-vite' +import { LoadingCard } from './index' + +const meta: Meta = { + title: 'SmartRoutingAddress/LoadingCard', + component: LoadingCard, + parameters: { layout: 'centered' }, + decorators: [ + (Story) => ( +
+ +
+ ), + ], +} + +export default meta +type Story = StoryObj + +/** Used inside `AddressDisplay`'s loading variant while the SRA server + * is generating the deposit address. */ +export const GeneratingAddress: Story = { + args: { + text: 'Generating deposit address…', + }, +} + +/** Used inside `SmartFunding` while the app is watching for an incoming + * deposit at the generated address. */ +export const WatchingForDeposit: Story = { + args: { + text: 'Watching for your deposit on Base…', + }, +} diff --git a/packages/smart-routing-address-react-ui/src/components/LoadingCard/LoadingCard.test.tsx b/packages/smart-routing-address-react-ui/src/components/LoadingCard/LoadingCard.test.tsx new file mode 100644 index 00000000..bdb43d9d --- /dev/null +++ b/packages/smart-routing-address-react-ui/src/components/LoadingCard/LoadingCard.test.tsx @@ -0,0 +1,35 @@ +/** + * @vitest-environment happy-dom + */ +import { cleanup, render, screen } from '@testing-library/react' +import { afterEach, describe, expect, it } from 'vitest' +import { LoadingCard } from './index' + +afterEach(cleanup) + +describe('LoadingCard', () => { + it('renders the status text', () => { + render() + expect(screen.getByText('Watching for your deposit on Base…')).toBeDefined() + }) + + it('renders the spinner icon', () => { + render() + expect(screen.getByTestId('loading-card-icon')).toBeDefined() + }) + + it('forwards extra HTML attributes (e.g., data-testid) to the root', () => { + render() + expect(screen.getByTestId('custom-root')).toBeDefined() + }) + + it('merges custom className with defaults', () => { + const { container } = render( + , + ) + const root = container.firstChild as HTMLElement + expect(root.className).toContain('custom-class') + // Sanity: the default height class is still applied + expect(root.className).toContain('zd:h-[68px]') + }) +}) diff --git a/packages/smart-routing-address-react-ui/src/components/LoadingCard/index.tsx b/packages/smart-routing-address-react-ui/src/components/LoadingCard/index.tsx new file mode 100644 index 00000000..411ab223 --- /dev/null +++ b/packages/smart-routing-address-react-ui/src/components/LoadingCard/index.tsx @@ -0,0 +1,27 @@ +import { cn, Icon, Text, Wrapper } from '@zerodev/react-ui' +import type { HTMLAttributes } from 'react' + +export interface LoadingCardProps extends HTMLAttributes { + text: string +} + +export function LoadingCard({ text, className, ...rest }: LoadingCardProps) { + return ( + + + {text} + + ) +}