npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jpmorgan-payments/embedded-finance-components

v0.12.5

Published

Embedded Finance Components

Readme

Embedded UI Components

🚧 Pre-release Version Notice

Embedded UI Components and this guide is currently in draft form and under active development. Components are not ready for production use and may change significantly until version 1.x.x is released. Please consider this document as a work in progress.

ADA Compliance Disclaimer

While we strive to incorporate ADA (Americans with Disabilities Act) best practices, please note that developers are responsible for conducting their own comprehensive ADA testing to ensure full compliance with all applicable standards and regulations.

Overview

The Embedded UI Components library offers a seamless way to integrate sophisticated UI capabilities into your existing web applications, providing a plug-and-play solution for Embedded Finance features.

Important Usage Notes

All Embedded UI Components must be wrapped within the EBComponentsProvider. The EBComponentsProvider is specifically designed for these components and is not applicable to any other client components in your application.

Main Embedded UI Components Architecture Concepts

The library is built on several key architectural concepts:

Integration Scenarios and Use Cases

The Embedded UI Components are designed for flexible integration into parent web applications, offering several customization points:

graph LR
    subgraph "Parent Web Application"
        CMS["Content Management System"]
        Theme["Theming System"]
        RUM["Real User Monitoring"]
        Storage[("Client ID / Platform ID / User Identity")]

        subgraph "Embedded Components Integration"
            Provider["EBComponentsProvider"]
            Components["Embedded UI Components"]

            Provider --> Components
        end

        CMS -->|"Content Tokens"| Provider
        Theme -->|"Design Tokens"| Provider
        RUM -->|"User Event Handler"| Components
        Storage -->|"Client ID / Platform ID"| Components
    end

Integration Flexibility

  1. Runtime Customization

    • Inject design tokens to match parent app's theme or use the default ones
    • Override content tokens from parent app's CMS systems or any other source
    • Connect to parent app's monitoring via userEventsHandler (see User Journey Tracking section)
  2. Component Configuration

    • Configure API endpoints via provider
    • Customize component behavior through props
  3. Client ID / Platform ID (only for onboarding components)

    • Onboarding Embedded UI Components can be used in fully controlled (client ID is provided and managed by the parent app) or uncontrolled (client ID is created from scratch by the embedded component) mode
    • In uncontrolled mode the embedded component will create a new client and it is recommended to manage its lifecycle via the onPostClientSettled callback prop

Future Extensibility

  1. Field Configuration

    • Externalization of field mapping logic
    • Custom field validation rules
    • Dynamic form layout configuration
    • Validation rules can be overridden from the parent app
  2. Workflow Customization

    • Integration with Arazzo workflow definitions
    • Custom step sequencing
    • Conditional flow logic

Overall Logical Composition Diagram

Note: The following diagram illustrates the component architecture using the onboarding wizard as an example:

graph TB
    subgraph "Development Time"
        direction TB
        OAS[OpenAPI Specification] --> |Orval Generation| Types[TypeScript Types]
        OAS --> |Orval Generation| Hooks[React Query Hooks]

        AF[Arazzo Flows] --> |Future: Flow Generation| Flows[Operation Sequences]

        subgraph "Embedded UI Components"
            direction TB
            Types & Hooks & Flows --> Components

            subgraph "Opinionated Layer"
                direction LR
                V[Enhanced Client<br/>Validations]
                P[Smart Payload<br/>Formation]
                E[Error Mapping<br/>& Recovery]
                U[UX Optimizations]
            end

            V & P & E & U --> Components
        end
    end

    subgraph "Runtime"
        direction TB
        Components --> |API Calls| PSL[Platform Service Layer]
        PSL --> |Authentication| API[Backend APIs]
    end

Key Principles

  1. OpenAPI Specification (OAS) & Future Arazzo Flows

    • OAS defines API contracts and types
    • Serves as source of truth for API interfaces
    • Generates TypeScript types and React Query hooks
    • Future: Arazzo Flows will enable automated flow generation (not currently available)
  2. Automated Code Generation

    • Currently, Orval generates from OAS:
      • TypeScript interfaces
      • Type-safe React Query hooks
      • API client utilities
    • Ensures type consistency between API and UI
  3. Other utility functions

    Built using generated types and hooks with an opinionated layer providing:

    • Enhanced client validations based on API specifications
    • Smart payload formation
    • Error mapping & recovery
    • UX optimizations implemented based on best practices:
      • Smart field prepopulation
      • Cognitive load reduction
      • Intelligent navigation

Embedded UI Components

The library currently provides the following components:

| Component | Description | Status | | --------------------- | ------------------------------------------------------ | ------------------------------------- | | EBComponentsProvider | Provider wrapper for all embedded components | Stable | | OnboardingWizardBasic | Legacy onboarding wizard | Deprecated | | OnboardingFlow | Modern onboarding experience | Stable | | Accounts | Account management and display | In Testing | | ClientDetails | Detailed client information (identity, ownership, KYC) | In Testing | | LinkedAccountWidget | External bank account linking with microdeposits | Stable | | RecipientsWidget | Payment recipient management (NEW) | Stable | | MakePayment | Payment processing interface | In Testing | | TransactionsDisplay | Transaction history and display | In Testing | | Recipients | Legacy recipient management | Deprecated - Use RecipientsWidget |

EBComponentsProvider

The EBComponentsProvider is a crucial wrapper component that must be placed at the top level of your Embedded UI Components implementation. It handles authentication, applies theming, and provides necessary context to all child Embedded UI Components. It is using @tanstack/react-query for handling API calls and authentication as well as Orval generated types for the API requests and responses.

Key Props:

  • apiBaseUrl: The base URL for API calls (required)
  • theme: Customization options for the components' appearance (optional)
  • headers: Custom headers for API requests (optional)
  • queryParams: Custom query parameters for API requests (optional)
  • contentTokens: Custom content tokens for internationalization (optional)

Usage:

import { EBComponentsProvider } from '@jpmorgan-payments/embedded-finance-components';

const EmbeddedFinanceSection = () => {
  return (
    <EBComponentsProvider
      apiBaseUrl="https://your-api-base-url.com"
      theme={{
        colorScheme: 'light',
        variables: {
          primaryColor: '#007bff',
          fontFamily: 'Arial, sans-serif',
        },
      }}
      headers={{
        'Custom-Header': 'value',
      }}
      queryParams={{
        'custom-param': 'value',
      }}
      contentTokens={{
        name: 'enUS',
      }}
    >
      {/* Your Embedded UI Components go here */}
    </EBComponentsProvider>
  );
};

1. OnboardingWizardBasic

The OnboardingWizardBasic component implements the client onboarding process as described in the Embedded Payments API documentation.

Main Features:

  • Create a client profile
  • Incrementally update client's related parties
  • Complete due diligence questions
  • Handle client attestations
  • Manage requests for additional documentation
  • Check and display onboarding status

Props:

| Prop Name | Type | Required | Description | | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------- | | onSetClientId | (clientId: string) => Promise<void> | No | Callback function when client ID is set | | onGetClientSettled | (clientData: ClientResponse \| undefined, status: 'success' \| 'pending' \| 'error', error: ErrorType<SchemasApiError> \| null) => void | No | Callback function triggered when client data is fetched | | onPostClientSettled | (response?: ClientResponse, error?: ApiError) => void | No | Callback function for client creation response | | onPostPartySettled | (response?: PartyResponse, error?: ApiError) => void | No | Callback function for party creation response | | onPostClientVerificationsSettled | (response?: ClientVerificationResponse, error?: ApiError) => void | No | Callback function for client verification response | | availableProducts | Array<ClientProduct> | Yes | List of available products for onboarding | | availableJurisdictions | Array<Jurisdiction> | Yes | List of available jurisdictions for onboarding | | availableOrganizationTypes | Array<OrganizationType> | No | List of available organization types | | usePartyResource | boolean | No | Whether to use party resource for onboarding | | blockPostVerification | boolean | No | Whether to block post-verification steps | | showLinkedAccountPanel | boolean | No | Whether to show linked account panel | | initialStep | number | No | Initial step to start onboarding from | | variant | 'circle' \| 'circle-alt' \| 'line' | No | Visual variant of the stepper component | | onboardingContentTokens | DeepPartial<typeof defaultResources['enUS']['onboarding']> | No | Custom content tokens for onboarding | | alertOnExit | boolean | No | Whether to show alert when exiting onboarding | | userEventsHandler | (context: UserEventContext) => void \| number | No | Handler for user events with rich context | | userEventsLifecycle | UserEventLifecycle | No | Optional lifecycle handlers for RUM libraries |

Usage:

import {
  EBComponentsProvider,
  OnboardingWizardBasic,
} from '@jpmorgan-payments/embedded-finance-components';

const OnboardingSection = () => {
  const [clientId, setClientId] = useManageClientExternalState();

  const handlePostClientResponse = ({ response, error }) => {
    // Handle client creation response or error
    setClientId(response.id);
  };

  const handlePostClientVerificationsResponse = ({ clientId, error }) => {
    // Handle post client verifications response or error
  };

  return (
    <EBComponentsProvider
      apiBaseUrl="https://your-api-base-url.com"
      clientId={clientId}
    >
      <OnboardingWizardBasic
        title="Client Onboarding"
        onPostClientSettled={handlePostClientResponse}
        onPostClientVerificationSettled={handlePostClientVerificationsResponse}
        availableProducts={['EMBEDDED_PAYMENTS']}
        availableJurisdictions={['US']}
        variant="circle-alt"
        initialStep={0}
        showLinkedAccountPanel={true}
        userEventsHandler={(context) => {
          const { actionName, eventType, timestamp, metadata } = context;
          // Track user events with rich context
          console.log(`User journey: ${actionName}`, {
            eventType,
            timestamp,
            metadata,
          });
        }}
      />
    </EBComponentsProvider>
  );
};

2. OnboardingFlow

The OnboardingFlow component provides a modern, enhanced onboarding experience with improved UX and better flow management. It represents the next generation of the onboarding process with screen-based navigation and enhanced state management.

Main Features:

  • Screen-based navigation with flow control
  • Enhanced document upload with preview and drag-and-drop
  • Improved mobile responsiveness
  • Better error handling and recovery
  • Streamlined user experience with intelligent navigation
  • Support for document-only onboarding mode

Props:

| Prop Name | Type | Required | Description | | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------- | | onGetClientSettled | (clientData: ClientResponse \| undefined, status: 'success' \| 'pending' \| 'error', error: ErrorType<SchemasApiError> \| null) => void | No | Callback function triggered when client data is fetched | | onPostClientSettled | (response?: ClientResponse, error?: ApiError) => void | No | Callback function for client creation response | | onPostPartySettled | (response?: PartyResponse, error?: ApiError) => void | No | Callback function for party creation response | | onPostClientVerificationsSettled | (response?: ClientVerificationResponse, error?: ApiError) => void | No | Callback function for client verification response | | availableProducts | Array<ClientProduct> | Yes | List of available products for onboarding | | availableJurisdictions | Array<Jurisdiction> | Yes | List of available jurisdictions for onboarding | | availableOrganizationTypes | Array<OrganizationType> | No | List of available organization types | | usePartyResource | boolean | No | Whether to use party resource for onboarding | | blockPostVerification | boolean | No | Whether to block post-verification steps | | docUploadOnlyMode | boolean | No | Whether to show only document upload screens | | height | string | No | Minimum height for the component container | | onboardingContentTokens | DeepPartial<typeof defaultResources['enUS']['onboarding']> | No | Custom content tokens for onboarding | | alertOnExit | boolean | No | Whether to show alert when exiting onboarding | | userEventsHandler | (context: UserEventContext) => void \| number | No | Handler for user events with rich context | | userEventsLifecycle | UserEventLifecycle | No | Optional lifecycle handlers for RUM libraries |

Usage:

import {
  EBComponentsProvider,
  OnboardingFlow,
} from '@jpmorgan-payments/embedded-finance-components';

const OnboardingSection = () => {
  return (
    <EBComponentsProvider
      apiBaseUrl="https://your-api-base-url.com"
      clientId="your-client-id"
    >
      <OnboardingFlow
        availableProducts={['EMBEDDED_PAYMENTS']}
        availableJurisdictions={['US']}
        height="100vh"
        onPostClientSettled={(response, error) => {
          // Handle client creation
        }}
        docUploadOnlyMode={false}
        alertOnExit={true}
      />
    </EBComponentsProvider>
  );
};

3. Accounts

⚠️ In Testing: This component is currently in testing state and could be not fully integrated with the OpenAPI Specification (OAS) or missing some target state functional/non-functional capabilities. It could be subject to significant changes.

The Accounts component provides a read-only, responsive UI for displaying all accounts associated with a client, including their categories, states, routing information, and balances.

Main Features:

  • Display accounts with categories, states, and routing information
  • Show account balances (ITAV, ITBD) with human-friendly labels
  • Filter accounts by category via props
  • Responsive layout with mobile support
  • Loading states and error handling
  • Masked account numbers for security

Props:

| Prop Name | Type | Required | Description | | ------------------- | ---------- | -------- | --------------------------------------- | | allowedCategories | string[] | Yes | Array of account categories to display | | clientId | string | No | Client ID to filter accounts | | title | string | No | Optional title for the accounts section |

Usage:

import {
  Accounts,
  EBComponentsProvider,
} from '@jpmorgan-payments/embedded-finance-components';

const AccountsSection = () => {
  return (
    <EBComponentsProvider apiBaseUrl="https://your-api-base-url.com">
      <Accounts
        allowedCategories={['LIMITED_DDA', 'LIMITED_DDA_PAYMENTS']}
        clientId="your-client-id"
        title="My Accounts"
      />
    </EBComponentsProvider>
  );
};

4. Recipients (DEPRECATED)

⚠️ DEPRECATED: The Recipients component is deprecated and will be removed in a future release.

Please use the new RecipientsWidget component instead.

The RecipientsWidget provides a modern, streamlined API for managing payment recipients with better i18n support, improved UX, and shared architecture with LinkedAccountWidget.

The Recipients component provides comprehensive management of payment recipients, enabling users to create, view, edit, and delete recipient information. It now supports integration with the MakePayment component for seamless payment workflows.

Main Features:

  • Create, view, edit, and delete payment recipients
  • Support for multiple payment methods (ACH, WIRE, RTP)
  • Dynamic form validation based on selected payment methods
  • Search and filtering capabilities
  • Pagination for large recipient lists
  • Mobile-responsive design
  • NEW: Integration with MakePayment component for direct payment initiation
  • NEW: Widget mode for compact display in parent applications

Props:

| Prop Name | Type | Required | Description | | ------------------------ | ----------------- | -------- | ---------------------------------------------------------------------- | | clientId | string | No | Optional client ID filter | | initialRecipientType | string | No | Default recipient type (RECIPIENT, LINKED_ACCOUNT, SETTLEMENT_ACCOUNT) | | showCreateButton | boolean | No | Show/hide create functionality | | config | object | No | Configuration for payment methods and validation rules | | makePaymentComponent | React.ReactNode | No | MakePayment component to render in each recipient card/row | | onRecipientCreated | function | No | Callback when recipient is created | | onRecipientUpdated | function | No | Callback when recipient is updated | | onRecipientDeactivated | function | No | Callback when recipient is deactivated | | userEventsHandler | function | No | Handler for user events | | isWidget | boolean | No | Force widget layout with minimal columns and no filters |

Usage:

import {
  EBComponentsProvider,
  MakePayment,
  Recipients,
} from '@jpmorgan-payments/embedded-finance-components';

const RecipientsSection = () => {
  return (
    <EBComponentsProvider apiBaseUrl="https://your-api-base-url.com">
      <Recipients
        clientId="your-client-id"
        initialRecipientType="RECIPIENT"
        showCreateButton={true}
        makePaymentComponent={
          <MakePayment
            triggerButtonVariant="link"
            onTransactionSettled={(response, error) => {
              console.log('Payment completed:', response);
            }}
          />
        }
        onRecipientCreated={(recipient) => {
          console.log('Recipient created:', recipient);
        }}
      />
    </EBComponentsProvider>
  );
};

5. LinkedAccountWidget

The LinkedAccountWidget component facilitates the process of adding a client's linked account, as described in the Add Linked Account API documentation.

Main Features:

  • Add and manage external linked bank accounts for clients
  • Handle complex micro-deposits initiation logic
  • Support for multiple account types and verification methods
  • NEW: Integration with MakePayment component for direct payment initiation
  • NEW: Single account mode for focused workflows

Props:

| Prop Name | Type | Required | Description | | ------------------------ | --------------------------------------------------- | -------- | ------------------------------------------------------------------- | | variant | 'default' \| 'singleAccount' | No | Display variant for different use cases | | showCreateButton | boolean | No | Show/hide create functionality | | makePaymentComponent | React.ReactNode | No | MakePayment component to render in each linked account card | | onLinkedAccountSettled | (recipient?: Recipient, error?: ApiError) => void | No | Callback function for linked account creation/verification response |

Usage:

import {
  EBComponentsProvider,
  LinkedAccountWidget,
  MakePayment,
} from '@jpmorgan-payments/embedded-finance-components';

const LinkedAccountSection = () => {
  return (
    <EBComponentsProvider apiBaseUrl="https://your-api-base-url.com">
      <LinkedAccountWidget
        variant="default"
        makePaymentComponent={
          <MakePayment
            triggerButtonVariant="link"
            onTransactionSettled={(response, error) => {
              console.log('Payment completed:', response);
            }}
          />
        }
      />
    </EBComponentsProvider>
  );
};

6. RecipientsWidget

The RecipientsWidget component enables users to manage payment recipients within your application. Unlike LinkedAccountWidget, it provides a simpler flow without microdeposit verification, ideal for managing payees and beneficiaries.

Main Features:

  • 👤 Recipient Management: View, add, edit, and remove payment recipients
  • 🔍 Search & Filter: Quickly find recipients
  • 📱 Responsive Design: Works on all device sizes
  • 🌍 i18n Support: Full internationalization via recipients namespace
  • 🎨 Themeable: Follows design token system

Props:

| Prop Name | Type | Required | Description | | ------------------ | -------------------------------- | -------- | ------------------------------------------------------------- | | mode | 'list' \| 'single' | No | list: Show all recipients. single: Show one recipient | | recipientId | string | No | Recipient ID for single mode | | showCreateButton | boolean | No | Show/hide create functionality | | hideActions | boolean | No | Hide action buttons | | title | string | No | Custom widget title | | pageSize | number | No | Number of recipients per page | | onRecipientAdded | (recipient: Recipient) => void | No | Callback when a recipient is added | | onError | (error: Error) => void | No | Callback when an error occurs |

Usage:

import {
  EBComponentsProvider,
  RecipientsWidget,
} from '@jpmorgan-payments/embedded-finance-components';

const RecipientsSection = () => {
  return (
    <EBComponentsProvider apiBaseUrl="https://your-api-base-url.com">
      <RecipientsWidget
        mode="list"
        showCreateButton={true}
        pageSize={10}
        onRecipientAdded={(recipient) => {
          console.log('Recipient added:', recipient);
        }}
      />
    </EBComponentsProvider>
  );
};

7. MakePayment

⚠️ In Testing: This component is currently in testing state and could be not fully integrated with the OpenAPI Specification (OAS) or missing some target state functional/non-functional capabilities. It could be subject to significant changes.

The MakePayment component provides a comprehensive payment interface that allows users to initiate payments between accounts with various payment methods. It can be used standalone or integrated into other components like Recipients and LinkedAccountWidget.

Main Features:

  • Payment initiation with multiple payment methods (ACH, RTP, WIRE)
  • Fee calculation and display
  • Form validation and error handling
  • Success confirmation and repeat payment functionality
  • Customizable payment methods and fees
  • Auto-selection for single options
  • NEW: Integration with Recipients and LinkedAccountWidget components
  • NEW: Pre-selection of recipients based on account compatibility
  • NEW: Real-time account balance validation
  • NEW: Support for different trigger button variants

Props:

| Prop Name | Type | Required | Description | | ---------------------- | ----------------------------------------------------------------------------- | -------- | ------------------------------------------------ | | triggerButton | React.ReactNode | No | Custom trigger button for opening payment dialog | | triggerButtonVariant | 'default' \| 'destructive' \| 'outline' \| 'secondary' \| 'ghost' \| 'link' | No | Button variant for trigger button | | accounts | Array<{ id: string; name: string }> | No | List of available accounts to pay from | | recipients | Array<{ id: string; name: string; accountNumber: string }> | No | List of available recipients | | paymentMethods | Array<{ id: string; name: string; fee: number; description?: string }> | No | List of available payment methods with fees | | icon | string | No | Icon name from Lucide React icons | | recipientId | string | No | Optional recipient ID to pre-select | | onTransactionSettled | (response?: TransactionResponseV2, error?: ApiErrorV2) => void | No | Callback when transaction is completed |

Usage:

import {
  EBComponentsProvider,
  MakePayment,
} from '@jpmorgan-payments/embedded-finance-components';

const PaymentSection = () => {
  return (
    <EBComponentsProvider apiBaseUrl="https://your-api-base-url.com">
      <MakePayment
        triggerButtonVariant="link"
        accounts={[
          { id: 'account1', name: 'Main Account' },
          { id: 'account2', name: 'Savings Account' },
        ]}
        recipients={[
          {
            id: 'recipient1',
            name: 'John Doe',
            accountNumber: '****1234',
          },
        ]}
        paymentMethods={[
          { id: 'ACH', name: 'ACH Transfer', fee: 2.5 },
          { id: 'WIRE', name: 'Wire Transfer', fee: 25.0 },
        ]}
        icon="CirclePlus"
        onTransactionSettled={(response, error) => {
          if (response) {
            console.log('Payment successful:', response);
          } else {
            console.error('Payment failed:', error);
          }
        }}
      />
    </EBComponentsProvider>
  );
};

8. TransactionsDisplay

⚠️ In Testing: This component is currently in testing state and could be not fully integrated with the OpenAPI Specification (OAS) or missing some target state functional/non-functional capabilities. It could be subject to significant changes.

The TransactionsDisplay component provides a comprehensive view of transaction history with detailed information and filtering capabilities.

Main Features:

  • Transaction listing with sorting and filtering
  • Transaction details view with expandable information
  • Support for different transaction types (PAYIN/PAYOUT)
  • Currency formatting and localization
  • Pagination and search capabilities
  • Mobile-responsive design

Props:

| Prop Name | Type | Required | Description | | ----------- | -------- | -------- | ------------------------------------ | | accountId | string | Yes | Account ID to fetch transactions for |

Usage:

import {
  EBComponentsProvider,
  TransactionsDisplay,
} from '@jpmorgan-payments/embedded-finance-components';

const TransactionsSection = () => {
  return (
    <EBComponentsProvider apiBaseUrl="https://your-api-base-url.com">
      <TransactionsDisplay accountId="your-account-id" />
    </EBComponentsProvider>
  );
};

Theming

The library supports comprehensive theming through the EBComponentsProvider. Components can be styled to match your application's design system using semantic design tokens.

Design Token System

The design token naming follows the Salt Design System semantic nomenclature. Tokens are organized by characteristics that group tokens sharing the same purpose or intent.

Token Format

[characteristic][Specifier][Variant][Property][State]
  • Characteristic (required): Groups tokens by purpose (e.g., actionable, container, content)
  • Specifier: Subset within a characteristic (e.g., Primary, Secondary)
  • Variant: Variation within a set (e.g., Accent)
  • Property (required): UI attribute (e.g., Background, Foreground, BorderColor)
  • State: Element condition (e.g., Hover, Active)

Characteristics

| Characteristic | Purpose | | -------------- | ---------------------------------------------------- | | content | Typography and text properties | | container | Surfaces, backgrounds, and layout areas | | actionable | Interactive elements (buttons, links) | | editable | Form inputs and text fields | | overlayable | Popovers, dialogs, tooltips | | navigable | Sidebars and navigation elements | | separable | Borders and dividers | | focused | Focus ring indicators | | sentiment | Emotional states (negative, positive, caution) | | status | Informational states (info, error, success, warning) | | accent | Highlight and metric colors |

Theme Configuration

The EBComponentsProvider accepts a theme prop with these properties:

  • colorScheme: 'dark' | 'light' | 'system'
  • variables: Tokens applied to all color schemes
  • light: Light mode-specific tokens
  • dark: Dark mode-specific tokens
<EBComponentsProvider
  apiBaseUrl="https://api.example.com"
  theme={{
    colorScheme: 'light',
    variables: {
      contentFontFamily: 'Inter, system-ui, sans-serif',
      separableBorderRadius: '0.5rem',
    },
    light: {
      containerPrimaryBackground: '#ffffff',
      actionableAccentedBoldBackground: '#2563eb',
    },
    dark: {
      containerPrimaryBackground: '#1f2937',
      actionableAccentedBoldBackground: '#3b82f6',
    },
  }}
>
  {/* Components */}
</EBComponentsProvider>

Design Token Reference

Content Tokens (Typography)

| Token | Description | Default | | ----------------------- | -------------------------- | --------- | | contentFontFamily | Primary font for body text | "Geist" | | textHeadingFontFamily | Font for headings (h1-h6) | Inherits |

Container Tokens (Surfaces)

| Token | Description | Light Default | Dark Default | | ------------------------------ | ----------------------- | --------------------- | --------------------- | | containerPrimaryBackground | Base page background | hsl(0 0% 100%) | hsl(240 10% 3.9%) | | contentPrimaryForeground | Primary text color | hsl(240 10% 3.9%) | hsl(0 0% 98%) | | containerCardBackground | Card/panel background | hsl(0 0% 100%) | hsl(240 10% 3.9%) | | containerPrimaryForeground | Text on cards/panels | hsl(240 10% 3.9%) | hsl(0 0% 98%) | | containerSecondaryBackground | Muted/subtle background | hsl(240 4.8% 95.9%) | hsl(240 3.7% 15.9%) | | containerSecondaryForeground | Subtle text color | hsl(240 3.8% 46.1%) | hsl(240 5% 64.9%) |

Actionable Tokens (Buttons)

| Token | Description | Default | | ------------------------- | --------------------------- | ------------ | | actionableFontFamily | Button font family | Inherits | | actionableFontWeight | Button text weight | "500" | | actionableFontSize | Button text size | "0.875rem" | | actionableLineHeight | Button line height | "1.25rem" | | actionableTextTransform | Text transform | "none" | | actionableLetterSpacing | Letter spacing | "0em" | | actionableBorderRadius | Button corner radius | Inherits | | actionableShiftOnActive | Press animation (1px shift) | true |

Accented Bold Variant (Solid CTA with accent/brand color):

| Token | Description | Light Default | Dark Default | | ---------------------------------------- | ------------------------------- | --------------- | --------------- | | actionableAccentedBoldBackground | Accented bold button background | #155C93 | #155C93 | | actionableAccentedBoldBackgroundHover | Hover background | Auto (90%) | Auto (90%) | | actionableAccentedBoldBackgroundActive | Active background | - | - | | actionableAccentedBoldForeground | Accented bold button text | hsl(0 0% 98%) | hsl(0 0% 98%) | | actionableAccentedBoldBorderWidth | Border width | "0rem" | "0rem" | | actionableAccentedBoldFontWeight | Font weight override | Inherits | Inherits |

Subtle Variant (Transparent neutral - previous Secondary):

| Token | Description | Light Default | Dark Default | | --------------------------------- | ------------------------ | --------------------- | --------------------- | | actionableSubtleBackground | Subtle button background | hsl(240 4.8% 95.9%) | hsl(240 3.7% 15.9%) | | actionableSubtleBackgroundHover | Hover background | Auto (90%) | Auto (90%) | | actionableSubtleForeground | Subtle button text | hsl(240 5.9% 10%) | hsl(0 0% 98%) | | actionableSubtleBorderWidth | Border width | "0rem" | "0rem" |

Editable Tokens (Form Inputs)

| Token | Description | Light Default | Dark Default | | ------------------------- | ------------------- | ------------------- | --------------------- | | editableBackground | Input background | hsl(0 0% 100%) | hsl(240 3.7% 15.9%) | | editableBorderColor | Input border color | hsl(240 5.9% 90%) | hsl(240 3.7% 15.9%) | | editableBorderRadius | Input corner radius | Inherits | Inherits | | editableLabelFontSize | Label text size | "0.875rem" | "0.875rem" | | editableLabelLineHeight | Label line height | "1.25rem" | "1.25rem" | | editableLabelFontWeight | Label font weight | "500" | "500" | | editableLabelForeground | Label text color | hsl(240 10% 3.9%) | hsl(0 0% 98%) |

Overlayable Tokens (Dialogs, Popovers)

| Token | Description | Light Default | Dark Default | | ----------------------- | ------------------------- | ------------------- | ------------------- | | overlayableBackground | Dialog/popover background | hsl(0 0% 100%) | hsl(240 10% 3.9%) | | overlayableForeground | Dialog/popover text | hsl(240 10% 3.9%) | hsl(0 0% 98%) | | overlayableZIndex | Overlay stacking order | 100 | 100 |

Navigable Tokens (Sidebar, Navigation)

| Token | Description | Light Default | Dark Default | | --------------------------- | -------------------- | --------------------- | --------------------- | | navigableBackground | Sidebar background | hsl(0 0% 98%) | hsl(240 5.9% 10%) | | navigableForeground | Sidebar text | hsl(240 5.3% 26.1%) | hsl(240 4.8% 95.9%) | | navigableAccentBackground | Active nav item bg | hsl(240 4.8% 95.9%) | hsl(240 3.7% 15.9%) | | navigableAccentForeground | Active nav item text | hsl(240 5.9% 10%) | hsl(240 4.8% 95.9%) |

Separable Tokens (Borders)

| Token | Description | Light Default | Dark Default | | ----------------------- | --------------------- | ------------------- | --------------------- | | separableBorderColor | Default border color | hsl(240 5.9% 90%) | hsl(240 3.7% 15.9%) | | separableBorderRadius | Default corner radius | "0.375rem" | "0.375rem" |

Focused Tokens (Focus Indicators)

| Token | Description | Light Default | Dark Default | | ------------------ | ---------------- | ------------------- | --------------------- | | focusedRingColor | Focus ring color | hsl(240 10% 3.9%) | hsl(240 4.9% 83.9%) |

Actionable Negative Tokens (Destructive Actions)

Negative Bold Variant (Solid destructive):

| Token | Description | Light Default | Dark Default | | --------------------------------------- | ------------------------- | -------------------- | ---------------- | | actionableNegativeBoldBackground | Negative bold button bg | hsl(0 84.2% 60.2%) | hsl(0 74% 54%) | | actionableNegativeBoldBackgroundHover | Hover background | Auto (90%) | Auto (90%) | | actionableNegativeBoldForeground | Negative bold button text | hsl(0 0% 98%) | hsl(0 0% 98%) | | actionableNegativeBoldBorderWidth | Border width | "0rem" | "0rem" |

Sentiment Tokens (Emotional States - Non-Actionable)

Negative (Error alerts, messages):

| Token | Description | Default | | ----------------------------------- | ---------------------- | --------- | | sentimentNegativeAccentBackground | Error alert background | #FFECEA |

Positive (Success states):

| Token | Description | Default | | ----------------------------------- | ------------------------ | --------- | | sentimentPositiveForeground | Success indicator color | #00875D | | sentimentPositiveAccentBackground | Success alert background | #EAF5F2 |

Caution (Warning states):

| Token | Description | Default | | ---------------------------------- | ------------------------ | --------- | | sentimentCautionForeground | Warning indicator color | #C75300 | | sentimentCautionAccentBackground | Warning alert background | #FFECD9 |

Status Tokens (Informational States)

| Token | Description | Default | | ---------------------------- | --------------------- | --------- | | statusInfoForeground | Info indicator color | #0078CF | | statusInfoAccentBackground | Info alert background | #EAF6FF |

Accent Tokens (Highlights)

| Token | Description | Light Default | Dark Default | | ------------------------- | ------------------ | --------------------- | --------------------- | | accentBackground | Accent background | hsl(240 4.8% 95.9%) | hsl(240 3.7% 15.9%) | | contentAccentForeground | Accent text | hsl(240 5.9% 10%) | hsl(0 0% 98%) | | accentMetricBackground | Data visualization | - | - |

Layout Tokens

| Token | Description | Default | | ------------- | ----------------------- | ----------- | | spacingUnit | Base spacing multiplier | "0.25rem" |

Backward Compatibility

All legacy token names (e.g., primaryColor, backgroundColor, fontFamily) remain fully supported. The new semantic names are preferred for new implementations.

| Legacy Token | New Semantic Token | | ------------------------ | ---------------------------------- | | fontFamily | contentFontFamily | | backgroundColor | containerBackground | | foregroundColor | contentPrimaryForeground | | primaryColor | actionableAccentedBoldBackground | | primaryForegroundColor | actionableAccentedBoldForeground | | secondaryColor | actionableSubtleBackground | | destructiveColor | actionableNegativeBoldBackground | | successColor | sentimentPositiveForeground | | warningColor | sentimentCautionForeground | | informativeColor | statusInfoForeground | | cardColor | containerPrimaryBackground | | mutedColor | containerSecondaryBackground | | popoverColor | overlayableBackground | | borderColor | separableBorderColor | | borderRadius | separableBorderRadius | | inputColor | editableBackground | | inputBorderColor | editableBorderColor | | ringColor | focusedRingColor | | zIndexOverlay | overlayableZIndex | | buttonFontWeight | actionableFontWeight | | buttonFontSize | actionableFontSize | | formLabelFontSize | editableLabelFontSize |

Theme Inheritance

The theme system uses a layered inheritance approach:

  1. Base Layer: defaultTheme.variables (always applied)
  2. Global Override: theme.variables (overrides base for all modes)
  3. Mode-Specific: theme.light or theme.dark (overrides for specific color scheme)

Complete Theme Example

import { EBComponentsProvider } from '@jpmorgan-payments/embedded-finance-components';

function App() {
  return (
    <EBComponentsProvider
      apiBaseUrl="https://api.example.com"
      theme={{
        colorScheme: 'light',
        variables: {
          // Typography
          contentFontFamily: 'Inter, system-ui, sans-serif',

          // Layout
          separableBorderRadius: '0.5rem',
          spacingUnit: '0.25rem',

          // Buttons
          actionableFontWeight: '600',
          actionableShiftOnActive: true,
        },
        light: {
          // Surfaces
          containerPrimaryBackground: '#ffffff',
          contentPrimaryForeground: '#1f2937',
          containerCardBackground: '#f9fafb',

          // Primary actions (accented bold)
          actionableAccentedBoldBackground: '#2563eb',
          actionableAccentedBoldForeground: '#ffffff',

          // Destructive actions (negative bold)
          actionableNegativeBoldBackground: '#dc2626',

          // Sentiment colors (non-actionable)
          sentimentPositiveForeground: '#059669',
          sentimentCautionForeground: '#d97706',
          statusInfoForeground: '#0284c7',
        },
        dark: {
          containerPrimaryBackground: '#111827',
          contentPrimaryForeground: '#f9fafb',
          containerCardBackground: '#1f2937',
          actionableAccentedBoldBackground: '#3b82f6',
        },
      }}
    >
      {/* Components */}
    </EBComponentsProvider>
  );
}

User Journey Tracking

All components support automatic user journey tracking when userEventsHandler is provided. Each component defines its own opinionated list of user journeys that are automatically tracked.

How It Works

Components automatically track user journeys through:

  1. Data Attributes: DOM elements with data-user-event="journey-name" attributes are automatically tracked
  2. Programmatic Events: Components call trackUserEvent() for important state changes
  3. Event Delegation: Uses efficient event delegation for better performance

Basic Usage

<Recipients
  userEventsHandler={(context) => {
    const { actionName, eventType, timestamp, metadata } = context;
    console.log('User journey:', actionName);
    // Send to your analytics service
    analytics.track(actionName, { eventType, timestamp, ...metadata });
  }}
/>

Integration with Dynatrace

<Recipients
  userEventsHandler={(context) => {
    if (window.dtrum) {
      const actionId = window.dtrum.enterAction(context.actionName);
      setTimeout(() => {
        window.dtrum.leaveAction(actionId);
      }, 100);
    }
  }}
  userEventsLifecycle={{
    onEnter: (context) => {
      if (window.dtrum) {
        return window.dtrum.enterAction(context.actionName);
      }
    },
    onLeave: (context) => {
      if (window.dtrum && context.actionId) {
        window.dtrum.leaveAction(context.actionId);
      }
    },
  }}
/>

Integration with Datadog RUM

import { datadogRum } from '@datadog/browser-rum';

<Recipients
  userEventsHandler={(context) => {
    datadogRum.addAction(context.actionName, {
      eventType: context.eventType,
      timestamp: context.timestamp,
      ...context.metadata,
    });
  }}
/>;

Tracked Journeys by Component

Each component documents its tracked journeys in its README file. For example:

  • Recipients: recipient_details_viewed, recipient_created, recipient_updated, etc.
  • OnboardingFlow: onboarding_screen_navigation, onboarding_form_submit, etc.
  • LinkedAccountWidget: linked_account_viewed, linked_account_link_completed, etc.

See each component's README for the complete list of tracked journeys.

Event Context

Each tracked event includes:

  • actionName: The journey identifier (e.g., recipient_created)
  • eventType: DOM event type (click, blur, etc.) or programmatic
  • timestamp: Event timestamp (milliseconds since epoch)
  • element: The DOM element that triggered the event (if available)
  • metadata: Additional context (recipient ID, status, etc.)

Internationalization

The library supports internationalization with the following languages:

  • English (US) - en-US (default)
  • French (Canada) - fr-CA

Language Configuration

import { EBComponentsProvider } from '@jpmorgan-payments/embedded-finance-components';

const InternationalizedApp = () => {
  return (
    <EBComponentsProvider
      apiBaseUrl="https://api.example.com"
      contentTokens={{
        name: 'frCA', // Use French Canadian
      }}
    >
      {/* Your components */}
    </EBComponentsProvider>
  );
};

Installation

npm install @jpmorgan-payments/embedded-finance-components

or

yarn add @jpmorgan-payments/embedded-finance-components

Contributing

To contribute to the development of this library, please follow these guidelines:

Recommended VSCode plugins:

  • Prettier
  • Tailwind CSS Intellisense

Recommended VS Code Settings

files.associations

Use the files.associations setting to tell VS Code to always open .css files in Tailwind CSS mode:

"files.associations": {
  "*.css": "tailwindcss"
}

editor.quickSuggestions

By default VS Code will not trigger completions when editing "string" content, for example within JSX attribute values. Updating the editor.quickSuggestions setting may improve your experience:

"editor.quickSuggestions": {
  "strings": "on"
}

Guidelines

  1. Create a new component in ./src/core
  2. Export it in ./src/index.tsx (this is the main public API for React/npm consumers)
  3. Optionally add it to ./src/vanilla/componentRegistry.ts only if the component should be mountable by name via initEBComponentsManager() (e.g. for the HTML/vanilla JS demo)

Onboarding fieldMap.ts configuration

This configuration file is a mapping utility that connects form fields to API fields. It is designed to handle server errors and create request bodies for API interactions. The configuration is structured as a partyFieldMap object, which defines the mapping rules for various fields related to both organizations and individuals.

Key Components

  • Field Mapping: Each form field is mapped to a corresponding API field using a path. This path indicates where the data should be placed in the API request or where it can be found in the API response.

  • Base Rules: Each field has a baseRule that defines its default properties, such as visibility and required status. These rules determine whether a field is visible in the form and whether it is mandatory.

  • Conditional Rules: Some fields have conditionalRules that modify the base rules based on specific conditions, such as the product type or jurisdiction. These rules allow for dynamic adjustments to field properties.

  • Transformation Functions: Fields that require data transformation between the form and the API use fromResponseFn and toRequestFn functions. These functions handle the conversion of data formats, such as phone numbers.

npm scripts

Build and dev scripts

  • dev – start development server
  • build – build production version of the app
  • preview – locally preview production build

Testing scripts

  • typecheck – checks TypeScript types
  • lint – runs ESLint
  • prettier:check – checks files with Prettier
  • vitest – runs vitest tests
  • vitest:watch – starts vitest watch
  • test – runs vitest, prettier:check, lint and typecheck scripts

Other scripts

  • storybook – starts storybook dev server
  • storybook:build – build production storybook bundle to storybook-static
  • prettier:write – formats all files with Prettier
  • generate-api – generates API client from OpenAPI specifications using Orval