npm package: @ng-shangjc/tabs
Description: Tabs component source package for ng-shangjc angular components
Author: jc-develop
Latest version: 1.0.1-beta

<p align="center">
<a href="https://juliancallejas.github.io/ng-shangjc-docs">
  <img src="https://res.cloudinary.com/dphleqb5t/image/upload/v1772819746/shangjc/shangjc-64-bg-dark_kwzs81.svg" width="307" alt="Shangjc"  /> 
</a>
</p>

# Tabs Component

A set of layered sections of content—known as tab panels—that are displayed one at a time. Built with Angular signals for modern, reactive UI development with full accessibility support and flexible positioning options.

## Official Documentation

<a href="https://juliancallejas.github.io/ng-shangjc-docs/?path=/docs/components-tabs">
    ng-Shangjc docs
</a>

## Features

- 🚀 **Signal-based State**: Modern Angular signals for reactive updates and performance
- 🎨 **Flexible Layouts**: Support for both horizontal and vertical orientations with start/end positioning
- ⌨️ **Keyboard Navigation**: Full arrow key, tab, and keyboard navigation support
- ♿ **Accessibility**: Complete ARIA compliance with proper roles, labels, and focus management
- 🎯 **Type-Safe**: Full TypeScript support with proper interfaces and type definitions
- 🎨 **Customizable**: Easy theming with CSS variables and custom styling
- ⚡ **Performance**: Optimized rendering with computed classes and efficient updates
- 🔧 **Controlled/Uncontrolled**: Support for both controlled and uncontrolled usage patterns
- 🚫 **Disabled States**: Built-in support for disabled tabs with proper visual feedback

## Installation

### Step 1: Install the CLI

First, install the ng-shangjc CLI globally or use npx:

```bash
# Install globally
npm install -g @ng-shangjc/cli

# or with yarn
yarn global add @ng-shangjc/cli

# or with pnpm
pnpm install -g @ng-shangjc/cli

# Or use npx without installation
npx @ng-shangjc/cli <command>
```

### Step 2: Initialize your project

If you haven't already, initialize your Angular project for ng-shangjc components:

```bash
ng-shangjc init
```

This will create a `shangjc.config.json` file and set up your project for component installations.

### Step 3: Install the component

Install the tabs component into your project:

```bash
ng-shangjc install tabs
```

The component will be installed in the configured path (default: `src/ui/shangjc`). Adjust the import path in your components based on your project structure and the configured installation path.

## Import

After installation, import the components from your configured installation path. The examples below use the default path `src/ui/shangjc` - adjust the path according to your project structure and configuration.

### Standalone Components (Recommended)

Import and use the individual components directly in your standalone components:

```typescript
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { 
  TabsComponent,
  TabListComponent, 
  TabTriggerComponent, 
  TabContentComponent 
} from './ui/shangjc/tabs';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [
    CommonModule,
    TabsComponent,
    TabListComponent,
    TabTriggerComponent,
    TabContentComponent
  ],
  template: `
    <ng-shangjc-tabs defaultValue="account">
      <ng-shangjc-tab-list>
        <ng-shangjc-tab-trigger value="account">Account</ng-shangjc-tab-trigger>
        <ng-shangjc-tab-trigger value="password">Password</ng-shangjc-tab-trigger>
      </ng-shangjc-tab-list>
      <ng-shangjc-tab-content value="account">
        <p>Make changes to your account here. Click save when you're done.</p>
      </ng-shangjc-tab-content>
      <ng-shangjc-tab-content value="password">
        <p>Change your password here. After saving, you'll be logged out.</p>
      </ng-shangjc-tab-content>
    </ng-shangjc-tabs>
  `
})
export class ExampleComponent { }
```

### Using NgModule (Legacy)

If you're using NgModules, import the `TabsModule`:

```typescript
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TabsModule } from './ui/shangjc/tabs';

@NgModule({
  declarations: [YourComponent],
  imports: [
    CommonModule,
    TabsModule
  ]
})
export class YourModule { }
```

Then use the components in your templates:

```html
<ng-shangjc-tabs>
  <ng-shangjc-tab-list>
    <ng-shangjc-tab-trigger value="tab1">Tab 1</ng-shangjc-tab-trigger>
  </ng-shangjc-tab-list>
  <ng-shangjc-tab-content value="tab1">
    Content here
  </ng-shangjc-tab-content>
</ng-shangjc-tabs>
```

## Basic Usage

### Default Example

```typescript
import { Component } from '@angular/core';
import { 
  TabsComponent,
  TabListComponent, 
  TabTriggerComponent, 
  TabContentComponent 
} from './ui/shangjc/tabs';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [
    TabsComponent,
    TabListComponent,
    TabTriggerComponent,
    TabContentComponent
  ],
  template: `
    <ng-shangjc-tabs defaultValue="account">
      <ng-shangjc-tab-list>
        <ng-shangjc-tab-trigger value="account">Account</ng-shangjc-tab-trigger>
        <ng-shangjc-tab-trigger value="password">Password</ng-shangjc-tab-trigger>
        <ng-shangjc-tab-trigger value="notifications">Notifications</ng-shangjc-tab-trigger>
      </ng-shangjc-tab-list>
      <ng-shangjc-tab-content value="account">
        <div class="space-y-4">
          <h3 class="text-lg font-medium">Account Settings</h3>
          <p class="text-sm text-muted-foreground">
            Make changes to your account here. Click save when you're done.
          </p>
        </div>
      </ng-shangjc-tab-content>
      <ng-shangjc-tab-content value="password">
        <div class="space-y-4">
          <h3 class="text-lg font-medium">Password Settings</h3>
          <p class="text-sm text-muted-foreground">
            Change your password here. After saving, you'll be logged out.
          </p>
        </div>
      </ng-shangjc-tab-content>
      <ng-shangjc-tab-content value="notifications">
        <div class="space-y-4">
          <h3 class="text-lg font-medium">Notification Preferences</h3>
          <p class="text-sm text-muted-foreground">
            Manage how you receive notifications.
          </p>
        </div>
      </ng-shangjc-tab-content>
    </ng-shangjc-tabs>
  `,
})
export class ExampleComponent {}
```

### Vertical Tabs

```html
<ng-shangjc-tabs defaultValue="general" orientation="vertical" position="start">
  <ng-shangjc-tab-list>
    <ng-shangjc-tab-trigger value="general">General</ng-shangjc-tab-trigger>
    <ng-shangjc-tab-trigger value="security">Security</ng-shangjc-tab-trigger>
    <ng-shangjc-tab-trigger value="integrations">Integrations</ng-shangjc-tab-trigger>
    <ng-shangjc-tab-trigger value="support">Support</ng-shangjc-tab-trigger>
  </ng-shangjc-tab-list>
  <ng-shangjc-tab-content value="general">
    <h3 class="text-lg font-medium">General Settings</h3>
    <p class="text-sm text-muted-foreground">
      Make changes to your general account settings here.
    </p>
  </ng-shangjc-tab-content>
  <ng-shangjc-tab-content value="security">
    <h3 class="text-lg font-medium">Security Settings</h3>
    <p class="text-sm text-muted-foreground">
      Manage your account security and authentication preferences.
    </p>
  </ng-shangjc-tab-content>
  <ng-shangjc-tab-content value="integrations">
    <h3 class="text-lg font-medium">Integrations</h3>
    <p class="text-sm text-muted-foreground">
      Connect and manage your third-party integrations.
    </p>
  </ng-shangjc-tab-content>
  <ng-shangjc-tab-content value="support">
    <h3 class="text-lg font-medium">Support</h3>
    <p class="text-sm text-muted-foreground">
      Get help and support for your account.
    </p>
  </ng-shangjc-tab-content>
</ng-shangjc-tabs>
```

## Advanced Usage

### Controlled Component

```typescript
import { Component, signal } from '@angular/core';
import { 
  TabsComponent,
  TabListComponent, 
  TabTriggerComponent, 
  TabContentComponent 
} from './ui/shangjc/tabs';

@Component({
  selector: 'app-controlled-example',
  standalone: true,
  imports: [
    TabsComponent,
    TabListComponent,
    TabTriggerComponent,
    TabContentComponent
  ],
  template: `
    <ng-shangjc-tabs [value]="activeTab" (valueChange)="onTabChange($event)">
      <ng-shangjc-tab-list>
        <ng-shangjc-tab-trigger value="tab1">Tab 1</ng-shangjc-tab-trigger>
        <ng-shangjc-tab-trigger value="tab2">Tab 2</ng-shangjc-tab-trigger>
        <ng-shangjc-tab-trigger value="tab3">Tab 3</ng-shangjc-tab-trigger>
      </ng-shangjc-tab-list>
      <ng-shangjc-tab-content value="tab1">
        <div class="space-y-4">
          <h3 class="text-lg font-medium">Tab 1 Content</h3>
          <p class="text-sm text-muted-foreground">This is the content for tab 1.</p>
        </div>
      </ng-shangjc-tab-content>
      <ng-shangjc-tab-content value="tab2">
        <div class="space-y-4">
          <h3 class="text-lg font-medium">Tab 2 Content</h3>
          <p class="text-sm text-muted-foreground">This is the content for tab 2.</p>
        </div>
      </ng-shangjc-tab-content>
      <ng-shangjc-tab-content value="tab3">
        <div class="space-y-4">
          <h3 class="text-lg font-medium">Tab 3 Content</h3>
          <p class="text-sm text-muted-foreground">This is the content for tab 3.</p>
        </div>
      </ng-shangjc-tab-content>
    </ng-shangjc-tabs>
    
    <div class="mt-4 p-4 bg-muted rounded-lg">
      <p class="text-sm font-medium">Active tab: {{ activeTab() }}</p>
    </div>
  `
})
export class ControlledExampleComponent {
  activeTab = signal('tab1');

  onTabChange(value: string) {
    this.activeTab.set(value);
    console.log('Tab changed to:', value);
  }
}
```

### Disabled Tabs

```html
<ng-shangjc-tabs defaultValue="available">
  <ng-shangjc-tab-list>
    <ng-shangjc-tab-trigger value="available">Available</ng-shangjc-tab-trigger>
    <ng-shangjc-tab-trigger value="disabled" [disabled]="true">Disabled</ng-shangjc-tab-trigger>
    <ng-shangjc-tab-trigger value="premium">Premium</ng-shangjc-tab-trigger>
  </ng-shangjc-tab-list>
  <ng-shangjc-tab-content value="available">
    <div class="space-y-2">
      <h3 class="text-lg font-medium">Available Features</h3>
      <p class="text-sm text-muted-foreground">This content is available to all users.</p>
    </div>
  </ng-shangjc-tab-content>
  <ng-shangjc-tab-content value="disabled">
    <div class="space-y-2">
      <h3 class="text-lg font-medium">Disabled Features</h3>
      <p class="text-sm text-muted-foreground">This content is currently disabled.</p>
    </div>
  </ng-shangjc-tab-content>
  <ng-shangjc-tab-content value="premium">
    <div class="space-y-2">
      <h3 class="text-lg font-medium">Premium Features</h3>
      <p class="text-sm text-muted-foreground">This content is available to premium users.</p>
    </div>
  </ng-shangjc-tab-content>
</ng-shangjc-tabs>
```

### Tabs with Forms

```typescript
import { Component } from '@angular/core';
import { 
  TabsComponent,
  TabListComponent, 
  TabTriggerComponent, 
  TabContentComponent 
} from './ui/shangjc/tabs';

@Component({
  selector: 'app-tabs-with-forms',
  standalone: true,
  imports: [
    TabsComponent,
    TabListComponent,
    TabTriggerComponent,
    TabContentComponent
  ],
  template: `
    <ng-shangjc-tabs defaultValue="account">
      <ng-shangjc-tab-list>
        <ng-shangjc-tab-trigger value="account">Account</ng-shangjc-tab-trigger>
        <ng-shangjc-tab-trigger value="password">Password</ng-shangjc-tab-trigger>
      </ng-shangjc-tab-list>
      
      <ng-shangjc-tab-content value="account" class="space-y-4">
        <div class="space-y-4">
          <div class="space-y-2">
            <label class="text-sm font-medium">Name</label>
            <input 
              type="text" 
              [(ngModel)]="name" 
              placeholder="Your name"
              class="w-full p-2 border rounded-md"
            />
          </div>
          <div class="space-y-2">
            <label class="text-sm font-medium">Email</label>
            <input 
              type="email" 
              [(ngModel)]="email" 
              placeholder="Your email"
              class="w-full p-2 border rounded-md"
            />
          </div>
          <button 
            (click)="saveAccount()"
            class="px-4 py-2 bg-primary text-primary-foreground rounded-md"
          >
            Save changes
          </button>
        </div>
      </ng-shangjc-tab-content>
      
      <ng-shangjc-tab-content value="password" class="space-y-4">
        <div class="space-y-4">
          <div class="space-y-2">
            <label class="text-sm font-medium">Current password</label>
            <input 
              type="password" 
              [(ngModel)]="currentPassword"
              class="w-full p-2 border rounded-md"
            />
          </div>
          <div class="space-y-2">
            <label class="text-sm font-medium">New password</label>
            <input 
              type="password" 
              [(ngModel)]="newPassword"
              class="w-full p-2 border rounded-md"
            />
          </div>
          <button 
            (click)="changePassword()"
            class="px-4 py-2 bg-primary text-primary-foreground rounded-md"
          >
            Update password
          </button>
        </div>
      </ng-shangjc-tab-content>
    </ng-shangjc-tabs>
  `,
})
export class TabsWithFormsComponent {
  name = '';
  email = '';
  currentPassword = '';
  newPassword = '';

  saveAccount() {
    console.log('Saving account:', { name: this.name, email: this.email });
  }

  changePassword() {
    console.log('Changing password');
  }
}
```

## API Reference

### TabsComponent

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `value` | `string` | `''` | The controlled active tab value (use with two-way binding) |
| `defaultValue` | `string` | `''` | The default active tab value for uncontrolled usage |
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | The orientation of the tabs layout |
| `position` | `'start' \| 'end'` | `'end'` | The position of tab list relative to content (start/end) |
| `class` | `string` | `''` | Additional CSS classes for the tabs container |

#### Events

| Event | Type | Description |
|-------|------|-------------|
| `valueChange` | `EventEmitter<string>` | Emitted when the active tab changes |

### TabListComponent

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `class` | `string` | `''` | Additional CSS classes for the tab list container |

### TabTriggerComponent

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `value` | `string` | `''` | The unique value for this tab trigger |
| `disabled` | `boolean` | `false` | Whether the tab trigger is disabled |
| `class` | `string` | `''` | Additional CSS classes for the tab trigger |

### TabContentComponent

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `value` | `string` | `''` | The unique value for this tab content (must match trigger value) |
| `class` | `string` | `''` | Additional CSS classes for the tab content panel |

## Accessibility

- **Keyboard Navigation**: Full support for Tab, Shift+Tab, Enter, Space, and Arrow keys
- **ARIA Attributes**: Proper ARIA labels, roles, and states
- **Focus Management**: Visible focus indicators and proper focus handling
- **Screen Reader**: Compatible with screen readers
- **Semantic Structure**: Uses proper HTML semantic elements

### ARIA Features

- `role="tablist"` on tab list container
- `role="tab"` on tab triggers
- `role="tabpanel"` on tab content
- `aria-selected` indicates selected tab
- `aria-controls` links tabs to their panels
- `aria-labelledby` links panels to their tabs
- `aria-orientation` indicates tab list orientation
- `aria-disabled` indicates disabled tabs

### Keyboard Navigation

- **Tab**: Move focus to next focusable element
- **Shift + Tab**: Move focus to previous focusable element
- **Enter/Space**: Activate focused tab
- **Arrow Keys**: Navigate between tabs (when tab list is focused)
  - **Arrow Right/Down**: Move to next tab
  - **Arrow Left/Up**: Move to previous tab
  - Respects orientation (horizontal/vertical)

## Browser Support

- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+

## Contributing

See the main project [CONTRIBUTING.md](../../CONTRIBUTING.md) for guidelines.

---

**Part of ng-shangjc component library** • [Documentation](https://juliancallejas.github.io/ng-shangjc-docs/)

<p align="center">
<a href="https://github.com/JulianCallejas">
  <img src="https://res.cloudinary.com/dphleqb5t/image/upload/v1740784502/github-jc-develop/JC-LOGO-Horizontal-170-50-thin-github_uu3b5n.svg" width="170" alt="{ jc - develop }"  /> 
</a>
</p>