# LanguageSwitcher Component

A multilingual navigation component that displays the current page language and provides a slide-out drawer interface for selecting available language variants. Integrates with HubSpot's multi-language content system to enable seamless language switching across translated pages.

## Import path
```tsx
import LanguageSwitcher from '@hubspot/cms-component-library/LanguageSwitcher';
```

## Purpose

The LanguageSwitcher component provides an accessible interface for users to view and switch between available language variants of the current page. It displays a text-link trigger showing the current language (with an optional globe icon), and opens a slide-out drawer panel listing all available translations. The component automatically fetches language variants from HubSpot's CMS using the `useLanguageVariants` hook. Visual styling (text color, background color) is inherited from the section the component lives in via `--hs-section-color` and `--hs-section-backgroundColor` CSS custom properties — no manual color configuration is needed.

## Component Structure

```
LanguageSwitcher/
├── index.tsx                                 # Main component (wrapper that delegates to Island)
├── types.ts                                  # TypeScript type definitions
├── ContentFields.tsx                         # HubSpot field definitions for content
├── LanguageOptions.tsx                       # Language option list component
├── LanguageOptions.module.scss               # CSS module for language options
├── utils.tsx                                 # Utility functions for language display
├── _dummyData.tsx                            # Dummy translation data for development
├── index.module.scss                         # CSS module with design tokens
├── assets/
│   └── Globe.tsx                             # Globe SVG icon component
├── islands/
│   ├── LanguageSwitcherIsland.tsx            # Client-side island with interactive UI
│   └── LanguageSwitcherDrawer.tsx            # Portaled drawer (mobile full-screen, desktop side panel)
└── stories/
    ├── LanguageSwitcher.stories.tsx          # Component usage examples
    ├── LanguageSwitcherDecorator.tsx         # Storybook decorator
    └── LanguageSwitcherDecorator.module.css  # Decorator styles
```

## Components

### LanguageSwitcher (Main Component)

**Purpose:** Renders a text-link trigger displaying the current page language that opens a drawer panel with all available language options. Colors are inherited from the surrounding section.

**Props:**
```tsx
{
  translations?: LanguageVariant[];             // Language variants (if not provided, uses useLanguageVariants hook)
  className?: string;                           // Additional CSS classes
  style?: React.CSSProperties;                  // Inline styles
  showGlobeIcon?: boolean;                      // Show/hide globe icon (default: true)
  display?: 'fullName' | 'countryCode';         // How to display the current language (default: 'fullName')
  dropdownPosition?: 'left' | 'right';          // Which side the drawer slides in from on desktop (default: 'right')
  languageSwitcherSelectText?: string;          // Header text in drawer (default: 'Select a language')
}
```

**Mobile behavior:**
On mobile viewports (≤767px), the drawer slides in from the right as a full-screen panel (matching the NavigationMenu mobile slideout), positioned below the header section. The trigger button shows only the globe icon (no language text) on mobile. `dropdownPosition` only applies on desktop. Mobile detection uses `ResizeObserver` on the nearest `<section>` element so it works correctly inside the HubSpot editor's preview canvas. The LanguageSwitcher and NavigationMenu coordinate via `useMobileDrawerGroup` — opening one automatically closes the other.

**Portal behavior:**
The drawer is portaled into the nearest `<section>` ancestor of the trigger element. This means section CSS custom properties (`--hs-section-backgroundColor`, `--hs-section-color`) cascade naturally into the drawer without any JavaScript color bridging. The component returns `null` until the section is located (after first mount), which is safe since the drawer starts closed.

## Usage Examples

### Basic Usage

The LanguageSwitcher component automatically handles Island-ification internally. Simply import and use it:

```tsx
import LanguageSwitcher from '@hubspot/cms-component-library/LanguageSwitcher';

export default function MyComponent() {
  return <LanguageSwitcher />;
}
```

When used without a `translations` prop, it automatically calls `useLanguageVariants()` to fetch language data.

### With Custom Header Text

```tsx
<LanguageSwitcher languageSwitcherSelectText="Choose your language" />
```

### With Country Code Display

```tsx
<LanguageSwitcher display="countryCode" />
```

### With Custom Translations

```tsx
<LanguageSwitcher translations={customLanguageVariants} />
```

### In Header Navigation

```tsx
<header style={{ display: 'flex', justifyContent: 'space-between', padding: '16px' }}>
  <div>
    <h1>My Website</h1>
  </div>
  <nav style={{ display: 'flex', gap: '24px', alignItems: 'center' }}>
    <a href="/about">About</a>
    <a href="/contact">Contact</a>
    <LanguageSwitcher />
  </nav>
</header>
```

## HubSpot CMS Integration

### Field Definitions

The LanguageSwitcher component provides field definitions for easy integration with HubSpot CMS modules.

#### ContentFields

Configurable props for content and behavior:

```tsx
<LanguageSwitcher.ContentFields />
```

**Fields:**
- `showGlobeIcon`: Toggle to show/hide the globe icon
- `display`: Pill toggle between `'fullName'` and `'countryCode'`
- `dropdownPosition`: Pill toggle between `'left'` and `'right'` drawer direction

### Module Usage Example

```tsx
import LanguageSwitcher from '@hubspot/cms-component-library/LanguageSwitcher';

export default function HeaderModule({ fieldValues }) {
  return (
    <header>
      <nav>
        {/* Other navigation items */}
        <LanguageSwitcher
          showGlobeIcon={fieldValues.showGlobeIcon}
          display={fieldValues.display}
          dropdownPosition={fieldValues.dropdownPosition}
          languageSwitcherSelectText={fieldValues.languageSwitcherSelectText}
        />
      </nav>
    </header>
  );
}
```

## Styling

Colors are **not configurable via props**. Instead, the component inherits colors from the section it lives in via CSS custom properties:

- `--hs-section-color` — controls text color for the trigger, drawer title, close button, and language links
- `--hs-section-backgroundColor` — controls background color for the drawer panel and sticky drawer header

These variables are set by the section module wrapping the component. No additional color configuration is needed on the LanguageSwitcher itself.

**Trigger Styles:**
- Plain text-link appearance (no background, no border)
- Padding: 8px 12px with 8px gap between icon and text
- Globe icon size: 20px height
- Font size: 18px
- Focus: `outline: 2px solid AccentColor; outline-offset: 2px` on `:focus-visible`

**Drawer Styles:**
- Desktop: drawer width 400px, slides in from `dropdownPosition` side
- Mobile (≤767px): full-screen right-slide panel (100vw), positioned below the header section, matching NavigationMenu
- Header padding: 24px (sticky-positioned)
- Header font size: 24px, font weight 600
- Options container padding: 24px

**Language Options Styles:**
- Link font size: 18px
- Link padding: 12px 16px
- Active language item has a subtle background highlight

## Accessibility

The LanguageSwitcher component follows accessibility best practices:

- **Semantic HTML**: Uses native `<button>` elements and a drawer with `role="dialog"`
- **Keyboard Navigation**:
  - Trigger activates with Space or Enter keys
  - ESC key closes the drawer
  - Tab navigation works through language options
- **ARIA Attributes**:
  - `aria-expanded` on trigger indicates drawer state
  - `aria-label="Language selector"` on drawer provides context
  - `aria-label="Close language selector"` on close button
- **Focus Indicators**: `:focus-visible` outline on both trigger and close button using the browser's `AccentColor`
- **Screen Reader Support**:
  - Current language is announced on trigger
  - Language options are properly labeled with native names

## Best Practices

- **Island-ification is handled internally**: The LanguageSwitcher component automatically handles Island-ification for interactive state
- **Colors come from the section**: Place the component inside a section that sets `--hs-section-color` and `--hs-section-backgroundColor` — the component will inherit them automatically
- **Position prominently**: Place in global navigation (header or footer) where users expect language controls
- **Use native language names**: The component automatically displays language names in their native script (e.g., "Español" for Spanish, "Français" for French)
- **Customize header text**: Set `languageSwitcherSelectText` to match your site's primary language for consistency
- **Responsive design**: On mobile (≤767px) the drawer slides in from the right as a full-screen panel below the header, matching the NavigationMenu. The trigger shows only the globe icon. `dropdownPosition` only applies on desktop. Opening the LanguageSwitcher automatically closes the NavigationMenu and vice versa.
- **Test with real translations**: Pass real HubSpot language variants via the `translations` prop, or rely on the default `useLanguageVariants()` hook for production

## Common Patterns

### Header Navigation Integration

```tsx
import LanguageSwitcher from '@hubspot/cms-component-library/LanguageSwitcher';

export default function SiteHeader({ fieldValues }) {
  return (
    <header style={{
      display: 'flex',
      justifyContent: 'space-between',
      padding: '16px 24px',
      alignItems: 'center'
    }}>
      <div>
        <h1>Website Name</h1>
      </div>
      <nav style={{ display: 'flex', gap: '24px', alignItems: 'center' }}>
        <a href="/about">About</a>
        <a href="/services">Services</a>
        <a href="/contact">Contact</a>
        <LanguageSwitcher
          showGlobeIcon={fieldValues.showGlobeIcon}
          display={fieldValues.display}
          languageSwitcherSelectText={fieldValues.languageSwitcherSelectText}
        />
      </nav>
    </header>
  );
}
```

### Footer Placement

```tsx
import LanguageSwitcher from '@hubspot/cms-component-library/LanguageSwitcher';

export default function SiteFooter({ fieldValues }) {
  return (
    <footer style={{ padding: '48px 24px', textAlign: 'center' }}>
      <div style={{ marginBottom: '24px' }}>
        <LanguageSwitcher
          languageSwitcherSelectText={fieldValues.languageSwitcherSelectText}
        />
      </div>
      <p>© 2024 Company Name. All rights reserved.</p>
    </footer>
  );
}
```

### Mobile-First Navigation

```tsx
import LanguageSwitcher from '@hubspot/cms-component-library/LanguageSwitcher';

export default function MobileNav({ fieldValues }) {
  return (
    <nav style={{
      display: 'flex',
      flexDirection: 'column',
      gap: '16px',
      padding: '16px'
    }}>
      <a href="/">Home</a>
      <a href="/about">About</a>
      <a href="/contact">Contact</a>
      <div style={{ borderTop: '1px solid #eee', paddingTop: '16px' }}>
        <LanguageSwitcher dropdownPosition="left" />
      </div>
    </nav>
  );
}
```

## Related Components

- **Drawer**: Used internally for the language selection panel. The LanguageSwitcher uses Drawer with a configurable direction and handles open/close state.
- **Divider**: Used to separate the drawer header from language options.
