# @isa/ui/toolbar

A flexible toolbar container component for Angular applications with configurable sizing and content projection.

## Overview

The Toolbar library provides a single component (`ui-toolbar`) that serves as a styled container for toolbar content. It supports two size variants (small and medium) and uses content projection to allow flexible composition of toolbar items such as buttons, inputs, and action controls.

## Table of Contents

- [Features](#features)
- [Quick Start](#quick-start)
- [Component API](#component-api)
- [Usage Examples](#usage-examples)
- [Styling and Customization](#styling-and-customization)
- [Architecture Notes](#architecture-notes)
- [Testing](#testing)
- [Dependencies](#dependencies)

## Features

- **Two size variants** - Small and medium toolbar heights
- **Content projection** - Full flexibility for toolbar content composition
- **ViewEncapsulation.None** - Allows external styling
- **OnPush change detection** - Optimized performance
- **Signal-based sizing** - Reactive size computation with `computed()`
- **Host class bindings** - Dynamic CSS class application
- **Standalone component** - Modern Angular architecture

## Quick Start

### 1. Import Component

```typescript
import { Component } from '@angular/core';
import { ToolbarComponent } from '@isa/ui/toolbar';

@Component({
  selector: 'app-page-header',
  imports: [ToolbarComponent],
  template: `...`
})
export class PageHeaderComponent {}
```

### 2. Basic Usage

```html
<ui-toolbar>
  <h1>Page Title</h1>
  <button>Action</button>
</ui-toolbar>
```

### 3. Size Variants

```html
<!-- Medium toolbar (default) -->
<ui-toolbar>
  <span>Default medium toolbar</span>
</ui-toolbar>

<!-- Small toolbar -->
<ui-toolbar [size]="'small'">
  <span>Compact toolbar</span>
</ui-toolbar>
```

## Component API

### ToolbarComponent

Container component for toolbar content with size variants.

#### Selector
```typescript
'ui-toolbar'
```

#### Inputs

| Input | Type | Default | Description |
|-------|------|---------|-------------|
| `size` | `ToolbarSize` | `'medium'` | Size variant of the toolbar |

#### Size Options

```typescript
export const ToolbarSize = {
  Small: 'small',
  Medium: 'medium',
} as const;

export type ToolbarSize = (typeof ToolbarSize)[keyof typeof ToolbarSize];
```

#### Computed Properties

| Property | Type | Description |
|----------|------|-------------|
| `sizeClass()` | `string` | Computed CSS class based on size (`ui-toolbar__small` or `ui-toolbar__medium`) |

#### Host Bindings
- `class`: `['ui-toolbar', sizeClass()]` - Base class and size-specific class

#### Template
```html
<ng-content></ng-content>
```

#### Encapsulation
- Uses `ViewEncapsulation.None` to allow external styling of toolbar content

## Usage Examples

### Page Header Toolbar

```typescript
import { Component } from '@angular/core';
import { ToolbarComponent } from '@isa/ui/toolbar';
import { ButtonComponent } from '@isa/ui/buttons';

@Component({
  selector: 'app-page-header',
  imports: [ToolbarComponent, ButtonComponent],
  template: `
    <ui-toolbar>
      <h1 class="page-title">Dashboard</h1>
      <div class="toolbar-actions">
        <ui-button (click)="refresh()">Refresh</ui-button>
        <ui-button appearance="accent" (click)="create()">Create</ui-button>
      </div>
    </ui-toolbar>
  `,
  styles: [`
    .page-title {
      flex: 1;
      margin: 0;
    }
    .toolbar-actions {
      display: flex;
      gap: 0.5rem;
    }
  `]
})
export class PageHeaderComponent {
  refresh() { /* ... */ }
  create() { /* ... */ }
}
```

### Search Toolbar

```typescript
import { Component } from '@angular/core';
import { ToolbarComponent, ToolbarSize } from '@isa/ui/toolbar';
import { TextFieldComponent, InputControlDirective } from '@isa/ui/input-controls';

@Component({
  selector: 'app-search-toolbar',
  imports: [ToolbarComponent, TextFieldComponent, InputControlDirective],
  template: `
    <ui-toolbar [size]="ToolbarSize.Small">
      <ui-text-field>
        <input uiInputControl type="text" placeholder="Search..." />
      </ui-text-field>
      <button (click)="search()">Search</button>
    </ui-toolbar>
  `
})
export class SearchToolbarComponent {
  readonly ToolbarSize = ToolbarSize;

  search() { /* ... */ }
}
```

### Filter Toolbar with Multiple Controls

```typescript
import { Component, signal } from '@angular/core';
import { ToolbarComponent } from '@isa/ui/toolbar';
import { DropdownButtonComponent, DropdownOptionComponent } from '@isa/ui/input-controls';

@Component({
  selector: 'app-filter-toolbar',
  imports: [ToolbarComponent, DropdownButtonComponent, DropdownOptionComponent],
  template: `
    <ui-toolbar>
      <span class="filter-label">Filters:</span>

      <ui-dropdown [(value)]="selectedStatus" label="Status">
        <ui-dropdown-option [value]="'all'">All</ui-dropdown-option>
        <ui-dropdown-option [value]="'active'">Active</ui-dropdown-option>
        <ui-dropdown-option [value]="'inactive'">Inactive</ui-dropdown-option>
      </ui-dropdown>

      <ui-dropdown [(value)]="selectedCategory" label="Category">
        <ui-dropdown-option [value]="'all'">All</ui-dropdown-option>
        <ui-dropdown-option [value]="'electronics'">Electronics</ui-dropdown-option>
        <ui-dropdown-option [value]="'books'">Books</ui-dropdown-option>
      </ui-dropdown>

      <button (click)="resetFilters()">Reset</button>
    </ui-toolbar>
  `,
  styles: [`
    .filter-label {
      font-weight: 600;
      margin-right: 0.5rem;
    }
  `]
})
export class FilterToolbarComponent {
  selectedStatus = signal('all');
  selectedCategory = signal('all');

  resetFilters() {
    this.selectedStatus.set('all');
    this.selectedCategory.set('all');
  }
}
```

### Dynamic Size Toolbar

```typescript
import { Component, signal } from '@angular/core';
import { ToolbarComponent, ToolbarSize } from '@isa/ui/toolbar';

@Component({
  selector: 'app-dynamic-toolbar',
  imports: [ToolbarComponent],
  template: `
    <ui-toolbar [size]="currentSize()">
      <span>Toolbar Content</span>
      <button (click)="toggleSize()">Toggle Size</button>
    </ui-toolbar>
  `
})
export class DynamicToolbarComponent {
  currentSize = signal<ToolbarSize>(ToolbarSize.Medium);

  toggleSize() {
    const newSize = this.currentSize() === ToolbarSize.Medium
      ? ToolbarSize.Small
      : ToolbarSize.Medium;
    this.currentSize.set(newSize);
  }
}
```

### Toolbar with Icons and Actions

```typescript
import { Component } from '@angular/core';
import { ToolbarComponent } from '@isa/ui/toolbar';
import { NgIcon } from '@ng-icons/core';
import { ButtonComponent } from '@isa/ui/buttons';

@Component({
  selector: 'app-actions-toolbar',
  imports: [ToolbarComponent, ButtonComponent, NgIcon],
  template: `
    <ui-toolbar>
      <div class="toolbar-section">
        <ng-icon name="isaActionMenu" size="1.5rem"></ng-icon>
        <span class="toolbar-title">Orders</span>
      </div>

      <div class="toolbar-section">
        <ui-button (click)="export()">
          <ng-icon name="isaActionDownload"></ng-icon>
          Export
        </ui-button>
        <ui-button appearance="accent" (click)="createOrder()">
          <ng-icon name="isaActionPlus"></ng-icon>
          New Order
        </ui-button>
      </div>
    </ui-toolbar>
  `,
  styles: [`
    .toolbar-section {
      display: flex;
      align-items: center;
      gap: 0.75rem;
    }
    .toolbar-title {
      font-size: 1.25rem;
      font-weight: 600;
    }
  `]
})
export class ActionsToolbarComponent {
  export() { /* ... */ }
  createOrder() { /* ... */ }
}
```

### Responsive Toolbar with Breakpoints

```typescript
import { Component, computed } from '@angular/core';
import { ToolbarComponent, ToolbarSize } from '@isa/ui/toolbar';
import { breakpoint, Breakpoint } from '@isa/ui/layout';

@Component({
  selector: 'app-responsive-toolbar',
  imports: [ToolbarComponent],
  template: `
    <ui-toolbar [size]="toolbarSize()">
      @if (isDesktop()) {
        <h1>Full Desktop Title</h1>
        <div class="actions">
          <button>Action 1</button>
          <button>Action 2</button>
          <button>Action 3</button>
        </div>
      } @else {
        <h1>Mobile</h1>
        <button>Menu</button>
      }
    </ui-toolbar>
  `
})
export class ResponsiveToolbarComponent {
  isDesktop = breakpoint([Breakpoint.Desktop, Breakpoint.DekstopL, Breakpoint.DekstopXL]);

  toolbarSize = computed(() =>
    this.isDesktop() ? ToolbarSize.Medium : ToolbarSize.Small
  );
}
```

## Styling and Customization

### CSS Classes

The component exposes the following CSS classes for styling:

```css
/* Base toolbar class */
.ui-toolbar {
  /* Base toolbar styles */
}

/* Medium toolbar (default) */
.ui-toolbar__medium {
  /* Medium size styles */
}

/* Small toolbar */
.ui-toolbar__small {
  /* Small size styles */
}
```

### Example Styling

```scss
// Base toolbar styling
.ui-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 1rem;
  background-color: var(--isa-surface-100);
  border-bottom: 1px solid var(--isa-border-200);

  // Medium toolbar (default height)
  &.ui-toolbar__medium {
    height: 4rem;
    padding: 0 1.5rem;
  }

  // Small toolbar (compact height)
  &.ui-toolbar__small {
    height: 3rem;
    padding: 0 1rem;
    font-size: 0.875rem;
  }
}

// Toolbar sections and layouts
.ui-toolbar {
  .toolbar-section {
    display: flex;
    align-items: center;
    gap: 0.5rem;
  }

  .toolbar-title {
    font-weight: 600;
    font-size: 1.125rem;
  }

  .toolbar-actions {
    display: flex;
    gap: 0.5rem;
    margin-left: auto;
  }
}
```

### Dark Theme Example

```scss
// Dark mode toolbar
.dark-theme {
  .ui-toolbar {
    background-color: var(--isa-surface-900);
    border-bottom-color: var(--isa-border-700);
    color: var(--isa-text-inverse);
  }
}
```

## Architecture Notes

### Size Management

The component uses Angular signals for reactive size management:

```typescript
size = input<ToolbarSize>('medium');

sizeClass = computed(() => `ui-toolbar__${this.size()}`);
```

Benefits:
- **Automatic updates** - Size changes trigger class recomputation
- **Type safety** - ToolbarSize type ensures valid values
- **Performance** - OnPush detection with signals

### ViewEncapsulation.None

The component uses `ViewEncapsulation.None` to allow external styling:

```typescript
@Component({
  encapsulation: ViewEncapsulation.None
})
```

This enables:
- Parent components can style toolbar content
- Global styles can target toolbar elements
- Flexible theme integration

### Content Projection

The toolbar uses simple content projection for maximum flexibility:

```html
<ng-content></ng-content>
```

This allows any content structure:
- Buttons, inputs, dropdowns
- Custom components
- Icons and text
- Complex layouts

### Standalone Architecture

The component is fully standalone with no dependencies:

```typescript
@Component({
  standalone: true,
  imports: []
})
```

## Testing

The library uses **Jest** for testing.

### Running Tests

```bash
# Run tests for this library
npx nx test ui-toolbar --skip-nx-cache

# Run tests with coverage
npx nx test ui-toolbar --code-coverage --skip-nx-cache

# Run tests in watch mode
npx nx test ui-toolbar --watch
```

### Test Coverage

The library should include tests covering:

- **Component rendering** - Verifies toolbar renders correctly
- **Size variants** - Tests both small and medium sizes
- **Content projection** - Validates content appears correctly
- **Class bindings** - Tests dynamic class application
- **Signal reactivity** - Tests size changes update classes

### Example Test

```typescript
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ToolbarComponent, ToolbarSize } from './toolbar.component';

describe('ToolbarComponent', () => {
  let component: ToolbarComponent;
  let fixture: ComponentFixture<ToolbarComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [ToolbarComponent]
    });
    fixture = TestBed.createComponent(ToolbarComponent);
    component = fixture.componentInstance;
  });

  it('should apply medium size by default', () => {
    fixture.detectChanges();
    expect(component.sizeClass()).toBe('ui-toolbar__medium');
  });

  it('should apply small size when specified', () => {
    component.size = ToolbarSize.Small;
    fixture.detectChanges();
    expect(component.sizeClass()).toBe('ui-toolbar__small');
  });

  it('should project content correctly', () => {
    const compiled = fixture.nativeElement;
    compiled.innerHTML = '<span>Test Content</span>';
    fixture.detectChanges();
    expect(compiled.textContent).toContain('Test Content');
  });
});
```

## Dependencies

### Required Libraries

- `@angular/core` - Angular framework (v20.1.2)

### Path Alias

Import from: `@isa/ui/toolbar`

### No External Dependencies

This component has no external dependencies beyond Angular core, making it lightweight and easy to integrate.

## Best Practices

1. **Consistent Sizing** - Use the same toolbar size throughout similar contexts (e.g., all page headers use medium)
2. **Flexbox Layouts** - Structure toolbar content using flexbox for responsive behavior
3. **Semantic HTML** - Use appropriate HTML elements within the toolbar (headings, buttons, etc.)
4. **Accessibility** - Ensure toolbar controls are keyboard accessible and have proper ARIA labels
5. **Content Organization** - Group related toolbar items visually using spacing and dividers
6. **Responsive Design** - Consider using the breakpoint service to adapt toolbar content for different screen sizes

## Common Patterns

### Left-Right Layout

```html
<ui-toolbar>
  <div class="toolbar-left">
    <h1>Title</h1>
    <span>Subtitle</span>
  </div>
  <div class="toolbar-right">
    <button>Action 1</button>
    <button>Action 2</button>
  </div>
</ui-toolbar>

<style>
  .ui-toolbar {
    display: flex;
    justify-content: space-between;
  }
</style>
```

### Three-Section Layout

```html
<ui-toolbar>
  <div class="toolbar-left">Left content</div>
  <div class="toolbar-center">Center content</div>
  <div class="toolbar-right">Right content</div>
</ui-toolbar>

<style>
  .ui-toolbar {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: 1rem;
  }
  .toolbar-center {
    justify-self: center;
  }
  .toolbar-right {
    justify-self: end;
  }
</style>
```

## License

Internal ISA Frontend library - not for external distribution.
