Skip to main content

Custom Components

Custom components offer maximum flexibility and control over your brokerize integration. Unlike the main component, custom components allow you to build exactly the user interface you need by using individual brokerize components separately.

When to Choose Custom Components

Custom components are ideal if you need:

  • Custom layouts – Specific positioning and arrangement of UI elements
  • Selective functionality – Only certain brokerize features in your application
  • Advanced integration – Deep integration with existing UI frameworks or design systems
  • Custom user flows – Full control over the user journey and navigation
  • Granular control – Fine-tuning the behavior and styling of individual components

Prerequisites

Installation

npm install @brokerize/elements @brokerize/client

Set Up Brokerize Client

First, create a brokerize client instance:

import { Brokerize } from '@brokerize/client';

const brokerizeClient = new Brokerize({
basePath: 'https://api-preview.brokerize.com', // Use preview environment
clientId: '<YOUR-API-CLIENT-ID>',
fetch: globalThis.fetch.bind(globalThis),
createAbortController: () => new AbortController(),
createWebSocket: (url, protocol) => new WebSocket(url, protocol)
});

Create API Context

const user = await brokerizeClient.createGuestUser();
const apiCtx = brokerizeClient.createAuthorizedContext(user);

Available Custom Components

Broker List Component

Display a list of available brokers with custom handling:

import { createBrokerList } from '@brokerize/elements';

createBrokerList({
authorizedApiContext: apiCtx,
theme: theme,
addFrame: addFrame,
renderTo: document.getElementById('broker-list-container'),
onLogin({ brokerName }) {
// Custom login handling
// Show custom login UI or redirect to your login flow
showCustomLoginModal(brokerName);
},
openExternalLink: (url) => {
// Custom external link handling
window.open(url, '_blank');
}
});

Overview Component

Implement custom overview functionality:

import { createOverview } from '@brokerize/elements';

createOverview({
theme,
renderTo: resetRenderTo(),
authorizedApiContext: globalApiCtx,
onNavigate(portfolio) {
/* navigate to the selected portfolio view, e.g. by calling `createPortfolioView(...)` */
// showPortfolioView(portfolio.id);
},
onLogin({ brokerName }) {
/* open the broker login for the given brokerName. */
// createBrokerLoginForm(...) // function from @brokerize/elements
}
});

Broker Login Component

Implement broker login functionality:

import { createBrokerLoginForm } from '@brokerize/elements';

createBrokerLoginForm({
authorizedApiContext,
theme,
addFrame,
renderTo,
brokerName,
performOAuthRedirect({ url }) {
/*
if the broker login is implemented using OAuth redirects,
this callback will be called with the URL to redirect to.
After login, the client will redirect back to the configured application URL.
After that redirect, the client application must use `confirmOAuth` to confirm
the session.
*/
},
onExit: ({ loggedIn }) => {
/* application can handle a successful broker login (e.g. show a SessionsTable or PortfolioTable) */
},
openExternalLink
});

Custom Components Workflow

1. Component Initialization

Set up your brokerize client and API context as shown in the prerequisites section.

2. Create Individual Components

Use the respective factory functions to create only the components you need:

// Create multiple components for a custom layout
const brokerList = createBrokerList({ /* config */ });
const overview = createOverview({ /* config */ });
const brokerlogin = createBrokerLoginForm({ /* config */ });

3. Handle Component Interactions

Implement custom logic for component interactions through callbacks:

createBrokerList({
// ... other config
onLogin({ brokerName }) {
// Hide broker list, show login form
hideBrokerList();
showLoginForm(brokerName);
}
});

4. Manage Component Lifecycle

Control when components are created, updated, and destroyed:

class TradingApp {
private components = new Map();

showBrokerSelection() {
const brokerList = createBrokerList({
// ... config
onLogin: (data) => this.handleBrokerLogin(data)
});
this.components.set('brokerList', brokerList);
}

handleBrokerLogin(data) {
// Clean up broker list
this.components.get('brokerList')?.destroy();
this.components.delete('brokerList');

// Show portfolio
this.showPortfolio();
}
}

5. Implement Custom Routing

Handle navigation between different views:

class Router {
navigate(route, params = {}) {
switch(route) {
case 'brokers':
this.showBrokerList();
break;
case 'portfolio':
this.showOverview(params.brokerId);
break;
case 'trade':
this.showBrokerLoginForm(params.brokerId);
break;
}
}
}

Theming Custom Components

Custom components use the same theming system as the main component:

const theme = {
layout: 'columns',
logoStyle: 'light',
tokens: {
'zl-primary-color': '#3870db',
'zl-primary-bg-color': 'white',
'zl-secondary-bg-color': 'var(--zl-color-gray-lighter)',
'zl-outline-color': 'var(--zl-color-primary-light)',
'zl-default-text-color': 'var(--zl-color-gray-darkest)',
'zl-success-color': '#3db969',
'zl-error-color': '#ff3e3e',
// ... additional theme tokens
}
};

// Apply theme to all components
createBrokerList({ theme, /* ... */ });
createPortfolio({ theme, /* ... */ });

For more information, examples, and a live demo, see the theming article.

Advanced Integration Patterns

State Management

class BrokerizeStateManager {
private state = {
selectedBroker: null,
portfolio: null,
activeInstrument: null
};

private listeners = new Set();

setState(updates) {
this.state = { ...this.state, ...updates };
this.notifyListeners();
}

subscribe(listener) {
this.listeners.add(listener);
return () => this.listeners.delete(listener);
}

private notifyListeners() {
this.listeners.forEach(listener => listener(this.state));
}
}

Best Practices

  1. Component Lifecycle Management: Always clean up components when they're no longer needed to prevent memory leaks.

  2. Error Handling: Implement proper error handling for all component interactions:

  3. Loading States: Provide feedback such as custom loading spinners during component initialization:

  4. Responsive Design: Ensure components work well across different screen sizes by configuring appropriate themes and layouts.

  5. Accessibility: Maintain accessibility standards by properly handling focus management and keyboard navigation between custom components.

Custom components give you the power to create exactly the trading experience your users need, with complete control over every aspect of the interface and user flow.