# Perfetto UI Development for AI Agents

Perfetto UI is a Single Page Web Application written in TypeScript using the Mithril framework. It lives in `ui/` and powers ui.perfetto.dev. The UI embeds TraceProcessor via WebAssembly.

## General Principles

- **Don't over-engineer** - Solve the problem at hand, not hypothetical future problems.
- **Prefer simpler approaches** - If there's a simple solution and a complex one, choose simple.
- **Search before creating** - Always search for existing utilities before writing new ones.
- **Be consistent** - Follow the patterns established in the surrounding code.
- **Prefer interfaces with immutable readonly members** - We like immutability, makes the code easier to debug.

## Directory Structure

The UI codebase is organized as follows:

```text
ui/src/
├── base/           # Core utilities (time, color, arrays, logging, disposables)
├── widgets/        # Reusable UI components (Button, Menu, Modal, Popup, etc.)
├── components/     # Higher-level components (aggregation panels, query tables)
├── core/           # Core application logic and managers
├── public/         # Public API surface for plugins
├── plugins/        # Optional third-party/external plugins
├── core_plugins/   # Essential core plugins (cannot be disabled)
├── frontend/       # Main frontend rendering code
├── trace_processor/# Engine communication layer (query results, SQL utilities)
├── test/           # Playwright integration tests
└── assets/         # SCSS stylesheets and static assets
```

When possible (if the API surface allows) feature functionality should be encapsulated in a plugin in src/plugins.
- `core_plugins/` (e.g., `dev.perfetto.CoreCommands`, `dev.perfetto.Notes`) contain essential functionality. They cannot be disabled by users and are always active.
- `plugins/` (e.g., `dev.perfetto.Sched`, `com.android.AndroidStartup`) are optional. Users can enable/disable them via feature flags. These are organized by reverse-DNS naming (e.g., `com.android.*`, `dev.perfetto.*`, `org.chromium.*`).
- This distinction is mostly historical. These days in 90% of cases things can (and should) go only inside plugins/
- Look at /docs/contributing/ui-plugins.md as it has extra useful content for plugin authors.

## Building and Running the UI

To build and serve the UI for development:

```sh
# From the repository root
ui/build    # Builds the UI.
ui/build --typecheck # Run tsc --noEmit, doesn't bundle (faster).
ui/run-dev-server    # Starts the development server with live reload.
```

The UI uses:

- **TypeScript** for type safety
- **Mithril** as the UI framework
- **Rollup** for bundling
- **pnpm** for package management
- **ESLint** for linting (based on Google style)
- **Playwright** for integration tests

## Type checking when a build is already running

Each build claims a lockfile as it works, unless --no-build option is passed. If
you try to run a build but encounter a failure due to one of those lockfiles
being present, you can try just checking types using the following command 
without interfering with the current build.

```sh
ui/build --typecheck --no-build
```

## Plugin Architecture

Plugins are the primary extension mechanism for the UI. They follow this structure:

```typescript
import {PerfettoPlugin} from '../../public/plugin';
import {Trace} from '../../public/trace';
import {App} from '../../public/app';

export default class MyPlugin implements PerfettoPlugin {
  // Unique reverse-DNS identifier
  static readonly id = 'com.example.MyPlugin';

  // Optional: Human-readable description
  static readonly description = 'Does something useful';

  // Optional: Declare dependencies on other plugins
  static readonly dependencies = [OtherPlugin];

  // Called when the plugin is activated (before trace load)
  static onActivate(app: App): void {
    // Register commands, sidebar items, pages that don't need a trace
  }

  // Called when a trace is loaded
  async onTraceLoad(trace: Trace): Promise<void> {
    // Register tracks, tabs, commands that need trace data
    // Query the trace processor, add tracks to the workspace
  }
}
```

**Plugin Lifecycle:**

1. `onActivate()` - Called when the plugin is enabled, before any trace is loaded. Use for registering global commands, pages, and sidebar items.
2. `onTraceLoad()` - Called when a trace is loaded. Use for registering tracks, tabs, and commands that depend on trace data.
3. `trace.onTraceReady` event - Fired after all plugins have finished `onTraceLoad()`. Use for automations that need all tracks to be available.

**Key APIs available to plugins:**

- `trace.engine` - Run SQL queries against TraceProcessor
- `trace.tracks` - Register and find tracks
- `trace.selection` - Manage selection state
- `trace.commands` - Register commands
- `trace.tabs` - Register tabs in the details panel
- `trace.timeline` - Access timeline state
- `trace.workspace` - Manage the track tree structure

## Mithril Patterns and Best Practices

The UI uses Mithril.js. Follow these patterns:

**Component Structure:**
```typescript
import m from 'mithril';

interface MyComponentAttrs {
  readonly value: string;
  readonly onChange: (newValue: string) => void;
}

export class MyComponent implements m.ClassComponent<MyComponentAttrs> {
  // Local state
  private expanded = false;

  view({attrs}: m.CVnode<MyComponentAttrs>): m.Children {
    return m('.my-component',
      m(Button, {label: attrs.value, onclick: () => this.expanded = !this.expanded}),
      this.expanded && m('.details', 'Expanded content'),
    );
  }
}
```

**Mithril Rules:**

- No need to call`m.redraw()` most of the times. We automatically schedules redraws: (1) in Mithril's DOM event handlers; (2) after trace processor queries complete. But NOT after manually registered JS event handlers.
- Use `constructor` for initialization if no DOM access is needed, or `onCreate` if DOM is needed.
- Prefer using the existing widget library (`ui/src/widgets/`) over creating new components.
- Use `readonly` for attrs properties to prevent accidental mutation. We like things to be immutable.

**Conditional Rendering with State Preservation:**
Use the `Gate` component when you need to conditionally show/hide content while preserving component state:
```typescript
import {Gate} from '../base/mithril_utils';

m(Gate, {open: this.isVisible}, m(ExpensiveComponent));
```

### Widget Library

The `ui/src/widgets/` directory contains reusable components. Always check here before creating new UI elements:

- `Button`, `ButtonBar`, `ButtonGroup` - Various button styles
- `PopupMenu`, `Menu`, `MenuItem`, `MenuDivider` - Dropdown menus
- `Popup` - Floating popup containers
- `Modal` - Modal dialogs
- `TextInput`, `Select`, `Checkbox`, `Switch` - Form controls
- `Tree` - Tree view component
- `DataGrid` - Tabular data grid component
- `Tabs` - Tabbed interface
- `Spinner` - Loading indicator
- `EmptyState` - Empty state placeholder

**Using Widgets:**

```typescript
import {Button, ButtonVariant} from '../widgets/button';
import {Popup} from '../widgets/popup';

m(Button, {
  label: 'Click me',
  icon: 'search',
  variant: ButtonVariant.Filled,
  onclick: () => { /* handle click */ },
});
```

## TypeScript Code Style

Follow these guidelines for TypeScript code:

- **Avoid `any` as much as you can**: Use `@typescript-eslint/no-explicit-any` rule if you really need it. In most cases it's enough to use `unknown` and type guards instead.
- **Unused variables**: Prefix with underscore (`_unused`) to satisfy `@typescript-eslint/no-unused-vars`.
- **Strict boolean expressions**: Don't use numbers or strings in boolean contexts implicitly.
- **Readonly by default**: Use `readonly` for interface properties and function parameters.
- **Use existing utilities**: Check `ui/src/base/` for utilities before writing your own:
  - `time.ts`, `duration.ts` - Time handling
  - `logging.ts` - `assertTrue()`, `assertExists()`, `assertFalse()`
  - `disposable_stack.ts` - Resource cleanup
  - `deferred.ts` - Promise utilities
  - `string_utils.ts` - String manipulation
  - `array_utils.ts` - Array helpers

## Working with TraceProcessor

Plugins query data using SQL through the TraceProcessor engine:

```typescript
async onTraceLoad(trace: Trace): Promise<void> {
  const result = await trace.engine.query(`
    SELECT ts, dur, name
    FROM slice
    WHERE name LIKE '%mySlice%'
    LIMIT 100
  `);

  // Use typed iteration
  const iter = result.iter({
    ts: LONG,      // bigint
    dur: LONG,     // bigint
    name: STR,     // string
  });

  for (; iter.valid(); iter.next()) {
    console.log(iter.ts, iter.dur, iter.name);
  }
}
```

## Track creation

Rarely you need to create a new Track from scratch.
In most cases you can use higher level components in ui/src/components/tracks/, especially DatasetSliceTrack (examples in /docs/contributing/ui-plugins.md).
Look at those examples first and keep creating a track via trace.tracks.registerTrack as a last-resort.

## CSS/SCSS Conventions

Stylesheets live in `ui/src/assets/` and component-specific `.scss` files alongside components.

- Use the `pf-` prefix for all CSS classes (Perfetto namespace)
- Follow BEM-like naming: `.pf-component`, `.pf-component__element`, `.pf-component--modifier`
- Use CSS custom properties (variables) defined in `theme_provider.scss` for colors
- Support both light and dark themes using semantic color variables

## Common Pitfalls to Avoid

1. **Don't create new widgets without checking existing ones** - The widget library is comprehensive.
2. **Try to use the Trace object as much as possible** - Plumb the Trace object through the hierarchy wherever needed.

## Code Review Pet Peeves and Style Preferences

The following patterns are consistently enforced during code review. Adhering to these will significantly speed up the review process.

### TypeScript/JavaScript Style

**Prefer `undefined` over `null`:**
```typescript
// Bad
function getValue(): string | null { return null; }

// Good
function getValue(): string | undefined { return undefined; }
```

**Use `ReadonlyArray<T>` for arrays that shouldn't be modified:**
```typescript
// Bad
function process(items: string[]): void { ... }

// Good
function process(items: ReadonlyArray<string>): void { ... }
```

**Use `classNames()` utility for building CSS class strings:**
```typescript
import {classNames} from '../base/classnames';

// Bad
const cls = 'pf-row' + (isSelected ? ' pf-row--selected' : '') + (isDisabled ? ' pf-row--disabled' : '');

// Good
const cls = classNames('pf-row', isSelected && 'pf-row--selected', isDisabled && 'pf-row--disabled');
```

**Use `assertUnreachable()` in switch default cases:**
```typescript
import {assertUnreachable} from '../base/logging';

switch (value) {
  case 'a': return handleA();
  case 'b': return handleB();
  default:
    assertUnreachable(value); // TypeScript will error if cases aren't exhaustive
}
```

**Variables should be camelCase:**
```typescript
// Bad
const trace_processor_id = 123;

// Good
const traceProcessorId = 123;
```

### CSS/SCSS Style

**Never use inline styles - use stylesheets:**
```typescript
// Bad
m('div', {style: {color: 'red', padding: '10px'}}, 'content')

// Good
m('.pf-my-component', 'content') // with styles in .scss file
```

**All CSS classes must have the `pf-` prefix:**
```scss
// Bad
.my-component { ... }
.row { ... }

// Good
.pf-my-component { ... }
.pf-my-component__row { ... }
```

**Never hard-code colors - use theme variables:**
```scss
// Bad
.pf-my-component {
  color: #333;
  background: white;
}

// Good
.pf-my-component {
  color: var(--pf-color-foreground);
  background: var(--pf-color-background);
}
```

### Mithril-Specific Rules

**Don't use `oncreate`/lifecycle hooks for things that can be done in `view()`:**
```typescript
// Bad - splitting code across lifecycle methods hurts readability.
oncreate() {
  this.computedValue = inexpensiveComputation();
}

// Good - compute in view. If expensive initialize in the constructor.
view() {
  const computedValue = inexpensiveComputation();
  return m('div', computedValue);
}
```

### Widget Usage

**Use the `Anchor` widget for links:**
```typescript
import {Anchor} from '../widgets/anchor';
import {Icons} from '../widgets/icons';

// Bad
m('a', {href: 'https://example.com', target: '_blank'}, 'Link')

// Good
m(Anchor, {href: 'https://example.com', icon: Icons.ExternalLink}, 'Link')
```

### Naming Conventions

**Settings/flags should use reverse-DNS format:**
```typescript
// Bad
const settingId = 'trackHeightMinPx';

// Good
const settingId = 'dev.perfetto.TrackHeightMinPx';
```

**Command IDs should be descriptive but omit redundant plugin name:**
```typescript
// Bad (if plugin is com.android.OrganizeNestedTracks)
const commandId = 'com.android.OrganizeNestedTracks#organizeNestedTracks';

// Good
const commandId = 'com.android.OrganizeNestedTracks';
```

**Copyright years should be current when creating new files:**
But don't touch years when editing existing files.
```typescript
// Bad (if current year is 2025)
// Copyright (C) 2024 The Android Open Source Project

// Good
// Copyright (C) 2025 The Android Open Source Project
```

## Testing

**Use Zod for parsing objects of unknown types:**
```typescript
import {z} from 'zod';

// Bad - unsafe type assertion
const config = JSON.parse(data) as MyConfig;

// Good - validated parsing
const ConfigSchema = z.object({
  name: z.string(),
  value: z.number(),
});
const config = ConfigSchema.parse(JSON.parse(data));
```


### UI Unit Tests

Unit tests are run with:
```sh
$ui/run-unittests
```

TypeScript unit tests follow the pattern `*_unittest.ts` and use Jest.

### UI Integration Tests

Integration tests use Playwright:
```sh
ui/run-integrationtests
```
