# Brave's UI Components and React Component Patterns: A Deep Dive into the Browser's Frontend Architecture

> Explore the robust frontend architecture of Brave browser. Discover its custom UI components, React component patterns, and performance optimizations in this deep dive.

- Repository: [Brave Software/brave-browser](https://github.com/brave/brave-browser)
- Tags: deep-dive
- Published: 2026-02-16

---

**Brave's desktop browser UI is built entirely with functional React components using hooks, a custom `@brave/ui` design system, context-based state management, and code-splitting patterns to ensure performance and maintainability.**

The `brave/brave-browser` repository implements a modern React architecture for its desktop interface. Understanding Brave's UI components and React component patterns reveals how the browser maintains a consistent, themeable, and resilient user experience across features like the Wallet, Rewards, and Settings.

## Core Architectural Patterns in Brave's React UI

Brave's React implementation follows strict architectural conventions located primarily under `browser/ui/react_components`. These patterns ensure modularity, testability, and seamless integration with the Chromium backend.

### Functional Components with Hooks

All UI pieces in `browser/ui/react_components/*/*.tsx` are written as plain functions rather than class-based components. They leverage React hooks including `useState`, `useEffect`, and `useContext` for local state and side effects. This approach reduces boilerplate and improves tree-shaking compatibility.

### Design-System-Driven Styling via @brave/ui

Styling is centralized through the internal **Brave UI design system** (`@brave/ui`), which supplies themed primitives such as `Box`, `Text`, and `Button`. The `useTheme` hook, defined in `browser/ui/theme/*`, provides runtime access to dark/light mode values, ensuring consistent visual identity without inline CSS.

### Context-Based State Sharing

Global UI state—such as the active tab, wallet unlock status, or rewards eligibility—is exposed via React contexts including `UiContext`, `WalletContext`, and `RewardsContext` located in `browser/ui/context/*`. Components subscribe to these contexts using `useContext`, eliminating prop drilling across deeply nested trees.

### Error Boundaries and Resilience

Critical UI panels are wrapped in the `withErrorBoundary` higher-order component (HOC) found at [`browser/ui/hocs/withErrorBoundary.tsx`](https://github.com/brave/brave-browser/blob/main/browser/ui/hocs/withErrorBoundary.tsx). This pattern catches rendering errors and displays fallback UI, preventing a single component crash from bringing down the entire browser window.

### Performance Optimization via Code Splitting

Heavy feature panels such as the **Brave Wallet** or **Rewards** are code-split using `React.lazy` and `Suspense`. The [`WalletPanel.tsx`](https://github.com/brave/brave-browser/blob/main/WalletPanel.tsx) file in `browser/ui/react_components/Wallet/` demonstrates this pattern, ensuring the main window bundle remains lightweight while feature-specific code loads on demand.

### Cross-Layer Communication Patterns

UI components communicate with the Chromium C++ layer through the `BraveMessenger` utility located in [`browser/ui/messaging/BraveMessenger.ts`](https://github.com/brave/brave-browser/blob/main/browser/ui/messaging/BraveMessenger.ts). This module abstracts `chrome.runtime.sendMessage` into type-safe methods, standardizing how React code triggers native browser functionality.

## Directory Structure and Key Files

The following table maps the essential files that define Brave's UI component architecture:

| File | Role | Location |
|------|------|----------|
| [`README.md`](https://github.com/brave/brave-browser/blob/main/README.md) | Overview of the UI component hierarchy | [`browser/ui/react_components/README.md`](https://github.com/brave/brave-browser/blob/main/browser/ui/react_components/README.md) |
| [`UiContext.tsx`](https://github.com/brave/brave-browser/blob/main/UiContext.tsx) | Global UI-state provider (tabs, side-panel, theme) | [`browser/ui/context/UiContext.tsx`](https://github.com/brave/brave-browser/blob/main/browser/ui/context/UiContext.tsx) |
| [`ThemeProvider.tsx`](https://github.com/brave/brave-browser/blob/main/ThemeProvider.tsx) | Supplies `useTheme` hook and styled-components theme object | [`browser/ui/theme/ThemeProvider.tsx`](https://github.com/brave/brave-browser/blob/main/browser/ui/theme/ThemeProvider.tsx) |
| [`withErrorBoundary.tsx`](https://github.com/brave/brave-browser/blob/main/withErrorBoundary.tsx) | HOC that catches render errors for any UI panel | [`browser/ui/hocs/withErrorBoundary.tsx`](https://github.com/brave/brave-browser/blob/main/browser/ui/hocs/withErrorBoundary.tsx) |
| [`BraveMessenger.ts`](https://github.com/brave/brave-browser/blob/main/BraveMessenger.ts) | Wrapper around `chrome.runtime.sendMessage` for UI ↔︎ Chromium communication | [`browser/ui/messaging/BraveMessenger.ts`](https://github.com/brave/brave-browser/blob/main/browser/ui/messaging/BraveMessenger.ts) |
| [`WalletPanel.tsx`](https://github.com/brave/brave-browser/blob/main/WalletPanel.tsx) | Example of a heavy feature panel that uses lazy loading and context | [`browser/ui/react_components/Wallet/WalletPanel.tsx`](https://github.com/brave/brave-browser/blob/main/browser/ui/react_components/Wallet/WalletPanel.tsx) |
| [`Settings.tsx`](https://github.com/brave/brave-browser/blob/main/Settings.tsx) | Central settings UI demonstrating nested contexts and design-system usage | [`browser/ui/react_components/Settings/Settings.tsx`](https://github.com/brave/brave-browser/blob/main/browser/ui/react_components/Settings/Settings.tsx) |

## Practical Implementation Examples

### Building a Toggle Component with Context

The following example from [`browser/ui/react_components/AdblockToggle/AdblockToggle.tsx`](https://github.com/brave/brave-browser/blob/main/browser/ui/react_components/AdblockToggle/AdblockToggle.tsx) demonstrates how to combine the `@brave/ui` design system with the `UiContext` for stateful interactions:

```tsx
import React, { useContext } from 'react'
import { Box, Switch } from '@brave/ui'
import { UiContext } from '../../context/UiContext'

export const AdblockToggle = () => {
  const { adblockEnabled, setAdblockEnabled } = useContext(UiContext)

  const handleChange = () => setAdblockEnabled(!adblockEnabled)

  return (
    <Box display="flex" alignItems="center" gap={2}>
      <Box as="span">Ad‑Block</Box>
      <Switch checked={adblockEnabled} onChange={handleChange} />
    </Box>
  )
}

```

### Implementing Lazy Loading for Heavy Panels

To maintain startup performance, Brave code-splits heavy features like the Wallet. The [`browser/ui/react_components/Wallet/WalletLazy.tsx`](https://github.com/brave/brave-browser/blob/main/browser/ui/react_components/Wallet/WalletLazy.tsx) file illustrates the combination of `React.lazy`, `Suspense`, and the `withErrorBoundary` HOC:

```tsx
import React, { Suspense, lazy } from 'react'
import { withErrorBoundary } from '../../hocs/withErrorBoundary'
import { LoadingSpinner } from '@brave/ui'

const WalletPanel = lazy(() =>
  import('../Wallet/WalletPanel')
)

const LazyWallet = () => (
  <Suspense fallback={<LoadingSpinner size="large" />}>
    <WalletPanel />
  </Suspense>
)

export default withErrorBoundary(LazyWallet, { fallback: <div>Wallet error</div> })

```

### Triggering UI Actions via Context

Components deep in the tree can trigger global UI changes without prop drilling. The `OpenSidePanelButton` in [`browser/ui/react_components/SidePanel/OpenSidePanelButton.tsx`](https://github.com/brave/brave-browser/blob/main/browser/ui/react_components/SidePanel/OpenSidePanelButton.tsx) uses `UiContext` to control the side panel visibility:

```tsx
import React, { useContext } from 'react'
import { UiContext } from '../../context/UiContext'
import { Button } from '@brave/ui'

export const OpenSidePanelButton = () => {
  const { setSidePanelOpen } = useContext(UiContext)

  return (
    <Button onClick={() => setSidePanelOpen(true)}>
      Open Side Panel
    </Button>
  )
}

```

## Testing Patterns for Brave UI Components

All components in the `browser/ui/react_components` directory include unit tests located in `__tests__` subfolders. These tests use **React Testing Library** and render components inside a `UiProvider` test wrapper to inject necessary contexts and the theme object. This approach ensures that components behave correctly under different state configurations and theme modes without requiring the full Chromium runtime.

## Summary

- Brave's desktop UI is built entirely with **functional React components** using hooks, located under `browser/ui/react_components`.
- The **@brave/ui** design system provides themed primitives and the `useTheme` hook for consistent dark/light mode support.
- **React Contexts** (`UiContext`, `WalletContext`, etc.) enable global state sharing without prop drilling.
- **Error boundaries** implemented via the `withErrorBoundary` HOC prevent individual panel crashes from destabilizing the browser window.
- **Code splitting** with `React.lazy` and `Suspense` keeps the main bundle lightweight while heavy features like Wallet load on demand.
- **BraveMessenger** abstracts Chromium communication via `chrome.runtime.sendMessage` for type-safe UI-to-native messaging.

## Frequently Asked Questions

### What design system does Brave use for its UI components?

Brave uses an internal design system called **@brave/ui** that supplies themed React primitives such as `Box`, `Text`, `Button`, and the `useTheme` hook. This system is integrated through [`browser/ui/theme/ThemeProvider.tsx`](https://github.com/brave/brave-browser/blob/main/browser/ui/theme/ThemeProvider.tsx) and ensures consistent styling across dark and light modes without inline CSS.

### How does Brave handle state management between React components?

State management relies on **React Context** rather than external libraries like Redux. Brave exposes global state through specialized contexts such as `UiContext`, `WalletContext`, and `RewardsContext` located in `browser/ui/context/`. Components subscribe to these contexts using the `useContext` hook, enabling efficient state sharing across deeply nested trees without prop drilling.

### Why does Brave use React.lazy for certain panels?

Brave uses **`React.lazy` and `Suspense`** to code-split heavy feature panels such as the **Brave Wallet** and **Rewards**. This pattern, visible in files like [`browser/ui/react_components/Wallet/WalletLazy.tsx`](https://github.com/brave/brave-browser/blob/main/browser/ui/react_components/Wallet/WalletLazy.tsx), ensures that the main browser window bundle remains lightweight and fast to initialize, while feature-specific JavaScript loads only when the user accesses those panels.

### How are Brave UI components tested?

Components are tested using **React Testing Library** with a custom `UiProvider` wrapper that injects necessary contexts and theme objects. Test files reside in `__tests__` subdirectories within `browser/ui/react_components/`, allowing developers to verify component behavior under different state configurations without launching the full Chromium runtime.