Skip to content

alfredoperez/ngx-dev-toolbar

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

178 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Angular Toolbar

npm version Downloads License Angular

A development toolbar for Angular 19+ applications that helps developers interact with the application more efficiently.

Toolbar Demo

Why ngx-dev-toolbar?

  • Toggle feature flags without backend changes
  • Simulate complete i18n environments (locale, timezone, currency, RTL)
  • Test product features and subscription tiers
  • Switch themes on the fly
  • Change user sessions effortlessly
  • Mock network requests in real-time
  • Test permission-based UI without backend changes

No more context switching or backend dependencies - everything you need is right in your browser!

Installation

npm install ngx-dev-toolbar

Quick Start

Add the toolbar to your app.config.ts alongside your other providers:

// app.config.ts
import { ApplicationConfig, isDevMode } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideToolbar } from 'ngx-dev-toolbar';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(appRoutes),
    provideToolbar({
      enabled: isDevMode(),
    }),
  ],
};
// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';

bootstrapApplication(AppComponent, appConfig);

That's it! No template changes needed. The toolbar automatically attaches to the DOM.

Available Tools

Tool Description
Feature Flags Toggle feature flags on/off during development
Permissions Test permission-based UI without backend changes
App Features Test product features and subscription tiers
i18n Advanced i18n simulation — locale, timezone, currency, pseudo-localization, RTL
Presets Save and restore tool configurations
Network Mocker Mock HTTP requests in real-time

Feature Flags

import { ToolbarFeatureFlagService } from 'ngx-dev-toolbar';

@Component({...})
export class AppComponent {
  private featureFlagsService = inject(ToolbarFeatureFlagService);

  constructor() {
    this.featureFlagsService.setAvailableOptions([
      { id: 'darkMode', name: 'Dark Mode', isEnabled: false },
      { id: 'betaFeatures', name: 'Beta Features', isEnabled: true },
    ]);
  }
}

Subscribe to forced values:

this.featureFlagsService.getForcedValues().subscribe((flags) => {
  // Apply forced flag states
});

Permissions

import { ToolbarPermissionsService } from 'ngx-dev-toolbar';

@Component({...})
export class AppComponent {
  private permissionsService = inject(ToolbarPermissionsService);

  constructor() {
    this.permissionsService.setAvailableOptions([
      { id: 'can-edit', name: 'Can Edit', isGranted: false },
      { id: 'is-admin', name: 'Admin Access', isGranted: false },
    ]);
  }
}

App Features

Test product-level feature availability like license tiers and subscription features:

import { ToolbarAppFeaturesService } from 'ngx-dev-toolbar';

@Component({...})
export class AppComponent {
  private appFeaturesService = inject(ToolbarAppFeaturesService);

  constructor() {
    this.appFeaturesService.setAvailableOptions([
      { id: 'analytics', name: 'Advanced Analytics', isEnabled: false },
      { id: 'multi-user', name: 'Multi-User Support', isEnabled: true },
    ]);
  }
}

i18n

Simulate complete internationalization environments — locale, timezone, currency, unit system, pseudo-localization, and RTL:

import { ToolbarI18nService } from 'ngx-dev-toolbar';

@Component({...})
export class AppComponent {
  private i18nService = inject(ToolbarI18nService);

  constructor() {
    // Set available locales
    this.i18nService.setAvailableOptions([
      { code: 'en', name: 'English' },
      { code: 'es', name: 'Spanish' },
      { code: 'ar', name: 'Arabic' },
    ]);

    // React to locale changes
    this.i18nService.getForcedValues().subscribe((locales) => {
      // Apply forced locale
    });

    // React to timezone, currency, and other i18n settings
    this.i18nService.getForcedTimezone().subscribe((tz) => { /* e.g. 'Asia/Tokyo' */ });
    this.i18nService.getForcedCurrency().subscribe((cur) => { /* e.g. 'JPY' */ });
  }
}

The i18n tool also supports pseudo-localization for spotting hardcoded strings and RTL simulation for layout testing. See the full docs for the complete API reference.

Creating Custom Tools

Build your own toolbar tools using the exported UI components. Here's a complete Notes tool:

import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';
import { Injectable } from '@angular/core';
import {
  ToolbarToolComponent,
  ToolbarWindowOptions,
  ToolbarButtonComponent,
  ToolbarInputComponent,
  ToolbarListComponent,
  ToolbarListItemComponent,
  ToolbarStepViewComponent,
  ToolbarStepDirective,
} from 'ngx-dev-toolbar';

// 1. Define your model
interface Note {
  id: string;
  title: string;
  content: string;
}

// 2. Create a service with signal-based state
@Injectable({ providedIn: 'root' })
class NotesService {
  private readonly _notes = signal<Note[]>([]);
  readonly notes = this._notes.asReadonly();

  add(title: string, content: string): void {
    this._notes.update(notes => [
      ...notes,
      { id: crypto.randomUUID(), title, content },
    ]);
  }

  remove(id: string): void {
    this._notes.update(notes => notes.filter(n => n.id !== id));
  }
}

// 3. Build the component
@Component({
  selector: 'app-notes-tool',
  standalone: true,
  imports: [
    ToolbarToolComponent,
    ToolbarButtonComponent,
    ToolbarInputComponent,
    ToolbarListComponent,
    ToolbarListItemComponent,
    ToolbarStepViewComponent,
    ToolbarStepDirective,
  ],
  template: `
    <ndt-toolbar-tool [options]="windowOptions" title="Notes" icon="edit">
      <ndt-step-view
        [currentStep]="viewMode()"
        defaultStep="list"
        (back)="viewMode.set('list')"
      >
        <!-- List view -->
        <ng-template ngtStep="list">
          <ndt-button (click)="viewMode.set('create')" icon="edit">
            Add Note
          </ndt-button>
          <ndt-list
            [hasItems]="notesService.notes().length > 0"
            emptyMessage="No notes yet"
            emptyHint="Click 'Add Note' to create one"
          >
            @for (note of notesService.notes(); track note.id) {
              <ndt-list-item [label]="note.title">
                <ndt-button
                  variant="icon"
                  icon="trash"
                  ariaLabel="Delete"
                  (click)="notesService.remove(note.id)"
                />
              </ndt-list-item>
            }
          </ndt-list>
        </ng-template>

        <!-- Create view -->
        <ng-template ngtStep="create" stepTitle="New Note">
          <ndt-input [(value)]="newTitle" placeholder="Title" ariaLabel="Note title" />
          <ndt-input [(value)]="newContent" placeholder="Content" ariaLabel="Note content" />
          <ndt-button (click)="onCreate()" label="Save" />
        </ng-template>
      </ndt-step-view>
    </ndt-toolbar-tool>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NotesToolComponent {
  protected readonly notesService = inject(NotesService);

  viewMode = signal<'list' | 'create'>('list');
  newTitle = signal('');
  newContent = signal('');

  readonly windowOptions: ToolbarWindowOptions = {
    id: 'notes',
    title: 'Notes',
    description: 'Quick development notes',
    size: 'medium',
  };

  onCreate(): void {
    if (this.newTitle()) {
      this.notesService.add(this.newTitle(), this.newContent());
      this.newTitle.set('');
      this.newContent.set('');
      this.viewMode.set('list');
    }
  }
}

Exported UI Components

Component Selector Purpose
ToolbarToolComponent ndt-toolbar-tool Window wrapper with positioning and animations
ToolbarButtonComponent ndt-button Buttons with optional icon
ToolbarInputComponent ndt-input Text inputs with two-way binding
ToolbarSelectComponent ndt-select Dropdown selection
ToolbarListComponent ndt-list List with empty/no-results states
ToolbarListItemComponent ndt-list-item List items with optional badge
ToolbarCardComponent ndt-card Content container
ToolbarClickableCardComponent ndt-clickable-card Interactive card with icon
ToolbarStepViewComponent ndt-step-view Multi-step view switcher
ToolbarIconComponent ndt-icon 30+ SVG icons
ToolbarLinkButtonComponent ndt-link-button External link button

For a complete guide, see: Create a Custom Tool

Configuration

Configure which tools are visible:

provideToolbar({
  enabled: isDevMode(),
  showI18nTool: true,
  showFeatureFlagsTool: true,
  showAppFeaturesTool: true,
  showPermissionsTool: true,
  showPresetsTool: true,
})

Keyboard Shortcuts

  • Ctrl+Shift+D: Toggle toolbar visibility

Features

  • Zero Bundle Impact: Dynamic imports exclude toolbar from production builds
  • Persistent State: Settings persist across page reloads
  • No Template Changes: Toolbar attaches automatically to the DOM
  • Extensible: Create custom tools to fit your workflow

Documentation

For full documentation, visit: https://alfredoperez.github.io/ngx-dev-toolbar/

Contributing

We welcome contributions! Please see our contributing guidelines for details.

Support

License

This project is licensed under the MIT License - see the LICENSE file for details.


LinkedIn Bluesky GitHub Stars

About

A powerful development toolbar for Angular applications to improve your developer productivity directly in the browser.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors