# Keyboard Navigation Patterns

Common keyboard patterns for interactive components.

## Standard Keys

| Key | Action |
|-----|--------|
| Tab | Move to next focusable |
| Shift+Tab | Move to previous focusable |
| Enter | Activate button/link |
| Space | Activate button, toggle checkbox |
| Escape | Close modal/menu |
| Arrow keys | Navigate within component |

## Component Patterns

### Button
```typescript
handleKeydown(e: KeyboardEvent) {
  if (e.key === 'Enter' || e.key === ' ') {
    e.preventDefault();
    this.activate();
  }
}
```

### Menu
```typescript
handleKeydown(e: KeyboardEvent) {
  switch (e.key) {
    case 'ArrowDown':
      e.preventDefault();
      this.focusNext();
      break;
    case 'ArrowUp':
      e.preventDefault();
      this.focusPrevious();
      break;
    case 'Home':
      e.preventDefault();
      this.focusFirst();
      break;
    case 'End':
      e.preventDefault();
      this.focusLast();
      break;
    case 'Escape':
      this.close();
      break;
  }
}
```

### Modal / Dialog
```typescript
// Trap focus within modal
class Modal extends FASTElement {
  private focusableElements!: HTMLElement[];
  
  connectedCallback() {
    super.connectedCallback();
    this.focusableElements = this.getFocusableElements();
    this.addEventListener('keydown', this.handleKeydown);
    this.focusFirst();
  }
  
  handleKeydown(e: KeyboardEvent) {
    if (e.key === 'Escape') {
      this.close();
      return;
    }
    
    if (e.key === 'Tab') {
      this.trapFocus(e);
    }
  }
  
  trapFocus(e: KeyboardEvent) {
    const first = this.focusableElements[0];
    const last = this.focusableElements[this.focusableElements.length - 1];
    
    if (e.shiftKey && document.activeElement === first) {
      e.preventDefault();
      last.focus();
    } else if (!e.shiftKey && document.activeElement === last) {
      e.preventDefault();
      first.focus();
    }
  }
}
```

### Tabs
```typescript
handleKeydown(e: KeyboardEvent) {
  const tabs = this.getTabs();
  const currentIndex = tabs.indexOf(document.activeElement as HTMLElement);
  
  switch (e.key) {
    case 'ArrowLeft':
      e.preventDefault();
      const prev = currentIndex > 0 ? currentIndex - 1 : tabs.length - 1;
      tabs[prev].focus();
      this.selectTab(prev);
      break;
    case 'ArrowRight':
      e.preventDefault();
      const next = currentIndex < tabs.length - 1 ? currentIndex + 1 : 0;
      tabs[next].focus();
      this.selectTab(next);
      break;
  }
}
```

## Focus Management

```typescript
// Restore focus after action
const previousFocus = document.activeElement as HTMLElement;
this.doAction();
previousFocus?.focus();

// Set focus to element
this.myElement.focus();
this.myElement.scrollIntoView({ block: 'nearest' });
```
