Back to catalog

code-quality-best-practices

Estándares de calidad de código, accesibilidad, manejo de errores y estados de carga. Usa esto para revisar código, implementar mejores prácticas, mejorar performance y asegurar accesibilidad.

  • Category: discovered
  • Tags: github, community
  • Version: 1.0.0
  • Author: walid
  • Downloads: 0
  • Updated: 2025-11-22

Download the latest version (v1.0.0) from this page.

SKILL.md

---
description: Estándares de calidad de código, accesibilidad, manejo de errores y estados de carga. Usa esto para revisar código, implementar mejores prácticas, mejorar performance y asegurar accesibilidad.
---

# Code Quality & Performance Standards 🚀

## Proactive Code Review

**ALWAYS** suggest improvements when you see opportunities to enhance:
- Code quality
- Performance
- Accessibility
- User experience
- Type safety
- Error handling

## Areas to Watch For

### 1. Code Simplification

Look for:
- Redundant code that can be simplified
- Repeated logic that should be extracted
- Overly complex conditionals
- Duplicate code across components

### 2. Performance Optimization

Identify:
- Unnecessary re-renders
- Heavy computations in templates
- Missing `trackBy` functions in `@for` loops
- Unsubscribed observables
- Large bundle sizes

```typescript
// ✅ Good - use trackBy for performance
@for (item of items(); track item.id) {
  <app-item [data]="item" />
}

// ❌ Bad - missing trackBy causes unnecessary re-renders
@for (item of items(); track $index) {
  <app-item [data]="item" />
}
```

### 3. Type Safety

Ensure:
- No `any` types
- Proper interface definitions
- Type guards where needed
- Correct generic usage

### 4. Signal Usage Patterns

Verify:
- Appropriate use of `signal()`, `computed()`, and `effect()`
- No unnecessary signal updates
- Proper read-only signals
- Correct signal composition

## Accessibility Standards ♿

### ARIA Labels

Always add proper ARIA labels to interactive elements:

```html
<!-- ✅ Good - has aria-label -->
<button 
  pButton 
  icon="pi pi-trash"
  aria-label="Delete user"
  (onClick)="delete()">
</button>

<!-- ❌ Bad - missing aria-label -->
<button 
  pButton 
  icon="pi pi-trash"
  (onClick)="delete()">
</button>
```

### Keyboard Navigation

Ensure all interactive elements are keyboard accessible:

```typescript
@Component({
  host: {
    '(keydown.enter)': 'onEnter()',
    '(keydown.space)': 'onSpace()',
    '[attr.tabindex]': '0',
    '[attr.role]': '"button"'
  }
})
```

### Semantic HTML

Use proper semantic elements:

```html
<!-- ✅ Good - semantic structure -->
<nav>
  <ul>
    <li><a href="/home">Home</a></li>
  </ul>
</nav>

<main>
  <article>
    <h1>Page Title</h1>
    <section>Content</section>
  </article>
</main>

<!-- ❌ Bad - div soup -->
<div class="nav">
  <div class="menu">
    <div><a href="/home">Home</a></div>
  </div>
</div>
```

### Alternative Text

Provide alt text for all images:

```html
<!-- ✅ Good -->
<img 
  ngSrc="logo.png"
  alt="Company logo"
  width="200"
  height="50">

<!-- ❌ Bad - missing alt -->
<img ngSrc="logo.png" width="200" height="50">
```

### Color Contrast

Ensure sufficient color contrast for text:
- Normal text: 4.5:1 minimum ratio
- Large text: 3:1 minimum ratio
- Use browser DevTools to check contrast

### Screen Reader Testing

Test with screen readers in mind:
- Logical reading order
- Descriptive labels
- Proper heading hierarchy
- Form field associations

## Error Handling 🛡️

### HTTP Errors

Always handle errors in services:

```typescript
getUsers(): Observable<User[]> {
  return this.http.get<User[]>(this.apiUrl).pipe(
    catchError(error => {
      console.error('Error fetching users:', error);
      
      this.messageService.add({
        severity: 'error',
        summary: 'Error',
        detail: 'Failed to load users'
      });
      
      return throwError(() => error);
    })
  );
}
```

### User-Friendly Messages

Show clear, actionable error messages:

```typescript
// ✅ Good - helpful message
this.messageService.add({
  severity: 'error',
  summary: 'Save Failed',
  detail: 'Unable to save changes. Please check your connection and try again.'
});

// ❌ Bad - cryptic message
this.messageService.add({
  severity: 'error',
  summary: 'Error',
  detail: error.message
});
```

### Form Validation Errors

Display validation errors clearly:

```html
<p-floatLabel>
  <input 
    pInputText 
    id="email" 
    formControlName="email" />
  <label for="email">Email</label>
</p-floatLabel>

@if (form.controls.email.invalid && form.controls.email.touched) {
  <small class="text-red-500">
    @if (form.controls.email.errors?.['required']) {
      Email is required
    }
    @if (form.controls.email.errors?.['email']) {
      Please enter a valid email
    }
  </small>
}
```

## Loading States ⏳

### Show Loading Indicators

Always indicate when operations are in progress:

```typescript
export class MyComponent {
  isLoading = signal(false);
  
  loadData() {
    this.isLoading.set(true);
    
    this.service.getData().subscribe({
      next: (data) => {
        this.items.set(data);
        this.isLoading.set(false);
      },
      error: (error) => {
        console.error(error);
        this.isLoading.set(false);
      }
    });
  }
}
```

### Loading UI Components

Use appropriate loading indicators:

```html
<!-- Spinner for full page loading -->
@if (isLoading()) {
  <p-progressSpinner />
}

<!-- Skeleton for better UX -->
@if (isLoading()) {
  <p-skeleton width="100%" height="4rem" />
  <p-skeleton width="100%" height="4rem" />
} @else {
  <app-content [data]="data()" />
}

<!-- Button loading state -->
<p-button 
  label="Save" 
  [loading]="isSaving()" 
  (onClick)="save()" />

<!-- Table loading state -->
<p-table 
  [value]="items()"
  [loading]="isLoading()">
</p-table>
```

## Empty States

Always handle empty data states:

```html
@if (items().length === 0 && !isLoading()) {
  <div class="empty-state">
    <i class="pi pi-inbox text-4xl text-gray-400"></i>
    <p class="text-gray-500 mt-3">No items found</p>
    <p-button 
      label="Create New" 
      icon="pi pi-plus"
      (onClick)="create()" />
  </div>
} @else {
  <p-table [value]="items()">
    <!-- table content -->
  </p-table>
}
```

## Performance Best Practices

### OnPush Change Detection

Always use OnPush strategy:

```typescript
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush
})
```

### Lazy Loading

Implement lazy loading for routes:

```typescript
const routes: Routes = [
  {
    path: 'users',
    loadComponent: () => import('./users/user-list.page').then(m => m.UserListPage)
  }
];
```

### Unsubscribe from Observables

Use `takeUntilDestroyed()` to prevent memory leaks:

```typescript
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

export class MyComponent {
  private destroyRef = inject(DestroyRef);
  
  ngOnInit() {
    this.service.getData()
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(data => {
        // handle data
      });
  }
}
```

## Code Review Checklist ✅

When reviewing or writing code, check:

- [ ] No `any` types used
- [ ] Proper error handling implemented
- [ ] Loading states shown
- [ ] Empty states handled
- [ ] ARIA labels added
- [ ] Keyboard navigation works
- [ ] Alt text for images
- [ ] Color contrast is sufficient
- [ ] OnPush change detection used
- [ ] Observables properly unsubscribed
- [ ] Forms have validation messages
- [ ] Code is DRY (Don't Repeat Yourself)
- [ ] Performance optimizations applied
- [ ] User-friendly error messages

## Summary

Always strive for:
- 🎯 Clean, maintainable code
- ⚡ Optimal performance
- ♿ Full accessibility
- 🛡️ Robust error handling
- ⏳ Clear loading states
- 💡 Proactive improvements