# Компонент ThemeToggle - Полная документация

## Назначение компонента

`ThemeToggle` - компонент для переключения между светлой и темной темами в приложении. Сохраняет выбор пользователя в localStorage, синхронизирует состояние между вкладками и обеспечивает плавные переходы между темами.

## git репозитарий
https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/src/master/vue/app/shared/ThemeToggle/

## Импорт и регистрация

```coffee
# В основном файле приложения (app/temp.coffee)
components:
    'themetoggle': require 'app/shared/ThemeToggle'
```

## Базовое использование

```pug
//- Минимальное использование
themetoggle

//- С кастомными классами
themetoggle(class="ml-4")

//- В навигационной панели
div(class="flex items-center space-x-4")
    language-switcher
    themetoggle
```

## Полный список props

### `size` (опциональный)
- **Тип:** `String`
- **По умолчанию:** `'md'`
- **Допустимые значения:** `'sm'`, `'md'`, `'lg'`
- **Описание:** Размер переключателя
- **Пример:**
  ```pug
  themetoggle(size="sm")
  themetoggle(size="lg")
  ```

### `variant` (опциональный)
- **Тип:** `String`
- **По умолчанию:** `'default'`
- **Допустимые значения:** `'default'`, `'minimal'`, `'icon-only'`
- **Описание:** Вариант отображения переключателя
- **Пример:**
  ```pug
  themetoggle(variant="minimal")
  themetoggle(variant="icon-only")
  ```

### `showLabels` (опциональный)
- **Тип:** `Boolean`
- **По умолчанию:** `true`
- **Описание:** Показывать текстовые метки
- **Пример:**
  ```pug
  themetoggle(:showLabels="false")
  ```

### `labels` (опциональный)
- **Тип:** `Object`
- **По умолчанию:** `{ light: 'Светлая', dark: 'Тёмная', system: 'Системная' }`
- **Описание:** Кастомные текстовые метки
- **Пример:**
  ```pug
  themetoggle(:labels="{ light: 'Light', dark: 'Dark', system: 'Auto' }")
  ```

### `storageKey` (опциональный)
- **Тип:** `String`
- **По умолчанию:** `'borbad-theme'`
- **Описание:** Ключ для сохранения в localStorage
- **Пример:**
  ```pug
  themetoggle(storageKey="my-app-theme")
  ```

### `class` (опциональный)
- **Тип:** `String | Object | Array`
- **По умолчанию:** `''`
- **Описание:** Дополнительные CSS классы
- **Пример:**
  ```pug
  themetoggle(class="border border-gray-300 rounded-lg")
  ```

## События (Events)

### `@change`
- **Описание:** Событие смены темы
- **Payload:** `{ theme: String, previousTheme: String }`
- **Пример:**
  ```pug
  themetoggle(@change="handleThemeChange")
  ```

### `@init`
- **Описание:** Событие инициализации темы
- **Payload:** `{ theme: String }`
- **Пример:**
  ```pug
  themetoggle(@init="handleThemeInit")
  ```

## Слоты (Slots)

### `[light-icon]`
- **Описание:** Иконка для светлой темы
- **Пример:**
  ```pug
  themetoggle
      template([light-icon])
          svig(class="w-4 h-4" ...) ...
  ```

### `[dark-icon]`
- **Описание:** Иконка для темной темы
- **Пример:**
  ```pug
  themetoggle
      template([dark-icon])
          svig(class="w-4 h-4" ...) ...
  ```

### `[system-icon]`
- **Описание:** Иконка для системной темы
- **Пример:**
  ```pug
  themetoggle
      template([system-icon])
          svig(class="w-4 h-4" ...) ...
  ```

## Доступные темы

### `light`
- Светлая тема
- Принудительно устанавливает светлый режим

### `dark`
- Темная тема
- Принудительно устанавливает темный режим

### `system`
- Системная тема
- Следует за настройками операционной системы
- Использует `prefers-color-scheme` media query

## Примеры использования

### 1. Базовые варианты
```pug
//- Стандартный переключатель
themetoggle

//- Только иконки
themetoggle(variant="icon-only")

//- Минималистичный вариант
themetoggle(variant="minimal")

//- Разные размеры
div(class="flex space-x-2")
    themetoggle(size="sm")
    themetoggle(size="md") 
    themetoggle(size="lg")
```

### 2. Кастомные иконки
```pug
themetoggle
    template([light-icon])
        div(class="w-4 h-4 bg-yellow-400 rounded-full")
    
    template([dark-icon])
        div(class="w-4 h-4 bg-purple-600 rounded-full")
    
    template([system-icon])
        div(class="w-4 h-4 bg-gray-500 rounded-full")
```

### 3. Кастомные метки
```pug
themetoggle(
    :labels="{ 
        light: '☀️ Светлая', 
        dark: '🌙 Тёмная', 
        system: '💻 Система' 
    }"
)
```

### 4. Интеграция с навигацией
```pug
header(class="bg-white dark:bg-gray-800 shadow-sm")
    div(class="container mx-auto px-4")
        div(class="flex justify-between items-center py-4")
            //- Логотип
            app-link(to="/" class="text-xl font-bold") Борбад
            
            //- Навигация
            nav(class="flex items-center space-x-6")
                app-link(to="/events") Мероприятия
                app-link(to="/blog") Блог
                
                //- Переключатель темы
                themetoggle(
                    variant="icon-only"
                    class="text-gray-600 dark:text-gray-300"
                )
```

### 5. В мобильном меню
```pug
div(class="mobile-menu bg-white dark:bg-gray-800 p-4")
    div(class="space-y-4")
        app-link(to="/" class="block") Главная
        app-link(to="/events" class="block") Мероприятия
        app-link(to="/blog" class="block") Блог
        
        //- Переключатель темы в мобильном меню
        div(class="pt-4 border-t dark:border-gray-700")
            themetoggle(
                variant="minimal"
                :showLabels="true"
                class="w-full"
            )
```

### 6. С обработкой событий
```pug
themetoggle(
    @change="onThemeChange"
    @init="onThemeInit"
)

//- В methods компонента
methods:
    onThemeChange: ({ theme, previousTheme }) ->
        debug.log "Тема изменена: "+previousTheme+" -> "+theme
        # Можно добавить аналитику
        analytics.track('theme_changed', { 
            new_theme: theme,
            previous_theme: previousTheme 
        })
    
    onThemeInit: ({ theme }) ->
        debug.log "Тема инициализирована: "+theme
```

## Программное взаимодействие

### Получение текущей темы
```coffee
# Через глобальный объект
currentTheme = _.appState?.currentTheme

# Через EventBus
EventBus.on 'theme_changed', (theme) ->
    debug.log "Текущая тема: "+theme
```

### Установка темы программно
```coffee
# Через глобальный объект
_.setTheme('dark')

# Через EventBus
EventBus.emit('set_theme', 'light')
```

### Подписка на изменения темы
```coffee
# В компоненте
beforeMount: ->
    EventBus.on 'theme_changed', @handleThemeChange

methods:
    handleThemeChange: (theme) ->
        # Обновляем стили компонента
        @updateComponentStyles(theme)
```

## Стили и кастомизация

### CSS-переменные
Компонент использует стандартные CSS-переменные Tailwind:
```css
:root {
  --color-bg-primary: #ffffff;
  --color-bg-secondary: #f7fafc;
  --color-text-primary: #2d3748;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-bg-primary: #1a202c;
    --color-bg-secondary: #2d3748;
    --color-text-primary: #f7fafc;
  }
}
```

### Кастомные стили
```styl
// Переопределение стандартных стилей
.theme-toggle--custom
    @apply bg-gradient-to-r from-blue-500 to-purple-600 text-white
    
    .theme-toggle__button
        @apply hover:from-blue-600 hover:to-purple-700
    
    .theme-toggle__button--active
        @apply from-blue-700 to-purple-800
```

### Анимации переходов
```styl
// Плавные переходы
.theme-transition
    transition: all 0.3s ease-in-out

// Анимация переключения
@keyframes theme-switch
    0%
        opacity: 0
        transform: scale(0.8)
    100%
        opacity: 1
        transform: scale(1)

.theme-toggle--animating
    animation: theme-switch 0.3s ease-in-out
```

## Интеграция с Tailwind CSS

### Конфигурация tailwind.config.js
```javascript
module.exports = {
  darkMode: 'class', // или 'media' для системной темы
  // ...
}
```

### Использование в компонентах
```pug
div(class="bg-white dark:bg-gray-800 text-gray-900 dark:text-white")
    h1(class="text-2xl font-bold") Заголовок
    p(class="text-gray-600 dark:text-gray-300") Текст
```

## Особенности работы

### Определение системной темы
```coffee
# Использует matchMedia для определения системных предпочтений
systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
```

### Синхронизация между вкладками
```coffee
# Слушает события storage для синхронизации
window.addEventListener('storage', (event) ->
    if event.key == @storageKey
        @applyTheme(event.newValue)
)
```

### Плавные переходы
```coffee
# Добавляет класс для анимации при переключении
document.documentElement.classList.add('theme-transition')
setTimeout(() ->
    document.documentElement.classList.remove('theme-transition')
, 300)
```

## Методы API

### `setTheme(theme)`
- **Описание:** Устанавливает указанную тему
- **Параметры:** `theme` - 'light', 'dark', или 'system'
- **Пример:**
  ```coffee
  @$refs.themeToggle.setTheme('dark')
  ```

### `getCurrentTheme()`
- **Описание:** Возвращает текущую активную тему
- **Возвращает:** `String`
- **Пример:**
  ```coffee
  currentTheme = @$refs.themeToggle.getCurrentTheme()
  ```

### `toggle()`
- **Описание:** Переключает между светлой и темной темами
- **Пример:**
  ```coffee
  @$refs.themeToggle.toggle()
  ```

## Обработка ошибок

### Валидация темы
```coffee
# Проверка допустимых значений
if !['light', 'dark', 'system'].includes(theme)
    throw new Error("Недопустимое значение темы: "+theme)
```

### Fallback для localStorage
```coffee
try
    localStorage.setItem(@storageKey, theme)
catch error
    # Используем cookie как fallback
    document.cookie = @storageKey+"="+theme+"; path=/; max-age=31536000"
```

## Примеры интеграции

### 1. С аналитикой
```coffee
methods:
    handleThemeChange: ({ theme, previousTheme }) ->
        # Отправка в аналитику
        gtag('event', 'theme_change', {
            event_category: 'ui',
            event_label: theme,
            value: theme == 'dark' ? 1 : 0
        })
```

### 2. С синхронизацией с сервером
```coffee
methods:
    handleThemeChange: ({ theme }) ->
        # Сохранение на сервере (если пользователь авторизован)
        if @user
            await @api.saveUserPreferences({ theme: theme })
```

### 3. С кастомной логикой
```coffee
methods:
    handleThemeChange: ({ theme }) ->
        # Изменение meta-тегов
        const themeColor = theme == 'dark' ? '#1a202c' : '#ffffff'
        document.querySelector('meta[name="theme-color"]').content = themeColor
        
        # Изменение favicon
        const favicon = theme == 'dark' ? '/favicon-dark.ico' : '/favicon-light.ico'
        document.querySelector('link[rel="icon"]').href = favicon
```

## Best Practices

### 1. Всегда предоставляйте все три варианта
```pug
//- Правильно
themetoggle

//- Неправильно (ограниченный выбор)
themetoggle(:themes="['light', 'dark']")
```

### 2. Используйте системную тему по умолчанию
```pug
//- Позволяет следовать системным настройкам
themetoggle
```

### 3. Сохраняйте состояние пользователя
```pug
//- Автоматически сохраняет в localStorage
themetoggle
```

### 4. Обеспечивайте доступность
```pug
//- Правильные ARIA-атрибуты
themetoggle(aria-label="Переключение темы")
```

### 5. Тестируйте все варианты
```coffee
# В тестах
describe('ThemeToggle', ->
    it('should switch between themes', ->
        toggle.setTheme('light')
        expect(toggle.getCurrentTheme()).toBe('light')
        
        toggle.setTheme('dark')
        expect(toggle.getCurrentTheme()).toBe('dark')
    )
)
```

Компонент ThemeToggle предоставляет полнофункциональное решение для управления темами в приложении с поддержкой доступности, сохранения состояния и плавных переходов.
