# EasyStream Design System - Integration Snippets

Quick copy-paste snippets to integrate the new design system into EasyStream templates.

## Table of Contents
1. [HTML Head Updates](#html-head-updates)
2. [Skip Links](#skip-links)
3. [Theme Switcher UI](#theme-switcher-ui)
4. [Accessibility Improvements](#accessibility-improvements)
5. [Responsive Components](#responsive-components)

---

## HTML Head Updates

### Add to Smarty Template Headers

**For frontend templates** ([f_templates/tpl_frontend/tpl_head_min.tpl](f_templates/tpl_frontend/tpl_head_min.tpl)):

```smarty
{* Add after existing CSS includes *}

<!-- Design System v2.0 -->
<link rel="stylesheet" href="{$main_url}/f_scripts/shared/design-system.css">
<link rel="stylesheet" href="{$main_url}/f_scripts/shared/accessibility.css">
<link rel="stylesheet" href="{$main_url}/f_scripts/shared/responsive.css">

<!-- Meta tags for PWA -->
<meta name="theme-color" content="#06a2cb">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="EasyStream">

<!-- Manifest -->
<link rel="manifest" href="{$main_url}/manifest.json">

<!-- Preload critical fonts -->
<link rel="preload" as="font" type="font/woff2" crossorigin>
```

### Add to Footer Scripts

**For frontend templates** ([f_templates/tpl_frontend/tpl_footerjs_min.tpl](f_templates/tpl_frontend/tpl_footerjs_min.tpl)):

```smarty
{* Add before closing body tag *}

<!-- Theme Switcher -->
<script src="{$main_url}/f_scripts/shared/theme-switcher.js"></script>

<!-- Service Worker Registration (already in index.js but ensure it's loaded) -->
<script>
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js?v=2')
    .then(reg => console.log('[SW] Registered'))
    .catch(err => console.error('[SW] Registration failed:', err));
}
</script>
```

---

## Skip Links

### Add to Body Start

**Add to** ([f_templates/tpl_frontend/tpl_body.tpl](f_templates/tpl_frontend/tpl_body.tpl:1)) at the very beginning:

```smarty
<body class="fe media-width-768 is-fw{if $is_mobile eq 1} is-mobile{/if}" data-theme="{$theme_name|default:'blue'}">

  {* Skip links for accessibility *}
  <div class="skip-links" role="navigation" aria-label="Skip links">
    <a href="#main-content" class="skip-to-content">Skip to main content</a>
    <a href="#navigation" class="skip-to-content">Skip to navigation</a>
    <a href="#search" class="skip-to-content">Skip to search</a>
  </div>

  {* Rest of body content *}
```

### Add Main Content ID

**Update main wrapper** in [f_templates/tpl_frontend/tpl_body_main.tpl](f_templates/tpl_frontend/tpl_body_main.tpl):

```smarty
<main id="main-content" role="main" class="container">
  {* Your main content *}
</main>
```

---

## Theme Switcher UI

### Option 1: Add to Header Navigation

**Add to** [f_templates/tpl_frontend/tpl_header/tpl_headernav_yt.tpl](f_templates/tpl_frontend/tpl_header/tpl_headernav_yt.tpl):

```smarty
{* Add to header navigation area *}
<div class="header-controls">
  {* Theme toggle button *}
  <button
    id="theme-toggle"
    class="btn btn-secondary touch-target"
    aria-label="Toggle dark mode"
    title="Toggle dark mode">
    <i class="icon-moon"></i>
    <span class="sr-only">Toggle theme</span>
  </button>

  {* Existing notification bell, user menu, etc. *}
</div>
```

### Option 2: Full Theme Picker Modal

Create new template: `f_templates/tpl_frontend/tpl_theme_picker.tpl`

```smarty
{* Theme Picker Modal *}
<div id="theme-picker-modal" class="modal" role="dialog" aria-labelledby="theme-modal-title" aria-hidden="true">
  <div class="modal-backdrop" data-dismiss="modal"></div>
  <div class="modal-content card">
    <div class="modal-header">
      <h2 id="theme-modal-title" class="text-xl font-semibold">Appearance Settings</h2>
      <button class="modal-close" data-dismiss="modal" aria-label="Close">
        <i class="icon-close"></i>
      </button>
    </div>

    <div class="modal-body p-lg">
      {* Theme mode toggle *}
      <div class="theme-setting">
        <label class="theme-label flex justify-between items-center">
          <span class="font-medium">Theme Mode</span>
          <button id="theme-toggle" class="btn btn-secondary touch-target" aria-label="Toggle theme mode">
            <i class="icon-moon"></i>
          </button>
        </label>
      </div>

      <div class="hr m-y-md"></div>

      {* Color picker *}
      <div class="theme-setting">
        <span class="theme-label font-medium block m-b-sm">Color Theme</span>
        <div class="color-options flex gap-sm flex-wrap" role="group" aria-label="Color themes">
          <button class="color-btn color-blue touch-target" data-color-theme="blue" aria-label="Blue theme" title="Blue">
            <span class="sr-only">Blue</span>
          </button>
          <button class="color-btn color-red touch-target" data-color-theme="red" aria-label="Red theme" title="Red">
            <span class="sr-only">Red</span>
          </button>
          <button class="color-btn color-cyan touch-target" data-color-theme="cyan" aria-label="Cyan theme" title="Cyan">
            <span class="sr-only">Cyan</span>
          </button>
          <button class="color-btn color-green touch-target" data-color-theme="green" aria-label="Green theme" title="Green">
            <span class="sr-only">Green</span>
          </button>
          <button class="color-btn color-orange touch-target" data-color-theme="orange" aria-label="Orange theme" title="Orange">
            <span class="sr-only">Orange</span>
          </button>
          <button class="color-btn color-pink touch-target" data-color-theme="pink" aria-label="Pink theme" title="Pink">
            <span class="sr-only">Pink</span>
          </button>
          <button class="color-btn color-purple touch-target" data-color-theme="purple" aria-label="Purple theme" title="Purple">
            <span class="sr-only">Purple</span>
          </button>
        </div>
      </div>
    </div>
  </div>
</div>

<style>
.color-btn {
  width: 44px;
  height: 44px;
  border-radius: var(--border-radius-full);
  border: 3px solid transparent;
  cursor: pointer;
  transition: all var(--transition-base);
  position: relative;
}

.color-btn:hover {
  transform: scale(1.1);
  box-shadow: var(--shadow-md);
}

.color-btn.active {
  border-color: var(--color-text-primary);
  box-shadow: var(--shadow-lg);
}

.color-btn.active::after {
  content: '✓';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: white;
  font-weight: bold;
  font-size: 1.25rem;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}

.color-blue { background: #06a2cb; }
.color-red { background: #dd1e2f; }
.color-cyan { background: #00997a; }
.color-green { background: #199900; }
.color-orange { background: #f28410; }
.color-pink { background: #ec7ab9; }
.color-purple { background: #b25c8b; }
</style>
```

---

## Accessibility Improvements

### Form Labels

**Before:**
```html
<input type="text" name="username" placeholder="Username">
```

**After:**
```html
<label for="username" class="font-medium m-b-xs">
  Username
  <span class="required" aria-label="required">*</span>
</label>
<input
  type="text"
  id="username"
  name="username"
  class="input"
  aria-required="true"
  aria-describedby="username-error">
<div id="username-error" class="error-message" role="alert" style="display: none;">
  Please enter a username
</div>
```

### Image Alt Text

**Before:**
```smarty
<img src="{$video.thumbnail}">
```

**After:**
```smarty
<img
  src="{$video.thumbnail}"
  alt="{$video.title|escape} - Thumbnail"
  loading="lazy"
  width="320"
  height="180">
```

### Button Accessibility

**Before:**
```html
<button onclick="likeVideo()">
  <i class="icon-like"></i>
</button>
```

**After:**
```html
<button
  onclick="likeVideo()"
  class="btn btn-secondary touch-target"
  aria-label="Like this video"
  aria-pressed="false">
  <i class="icon-like" aria-hidden="true"></i>
  <span class="sr-only">Like</span>
</button>
```

### Heading Hierarchy

**Before:**
```html
<div class="title">Featured Videos</div>
<div class="video-title">My Video</div>
```

**After:**
```html
<h2 class="content-title text-2xl font-semibold">Featured Videos</h2>
<h3 class="video-title text-lg">My Video</h3>
```

### ARIA Landmarks

**Add to templates:**

```smarty
<header role="banner">
  {* Header content *}
</header>

<nav role="navigation" aria-label="Main navigation">
  {* Navigation menu *}
</nav>

<main role="main" id="main-content">
  {* Main content *}
</main>

<aside role="complementary" aria-label="Sidebar">
  {* Sidebar content *}
</aside>

<footer role="contentinfo">
  {* Footer content *}
</footer>
```

---

## Responsive Components

### Video Grid

**Before:**
```smarty
<div class="thumbs-wrapper">
  {foreach from=$videos item=video}
    <div class="vs-column">
      {* Video thumbnail *}
    </div>
  {/foreach}
</div>
```

**After:**
```smarty
<div class="video-grid">
  {foreach from=$videos item=video}
    <article class="video-card">
      <a href="{$video.url}" class="video-link">
        <div class="aspect-video">
          <img
            src="{$video.thumbnail}"
            alt="{$video.title|escape} - Thumbnail"
            loading="lazy"
            class="video-thumbnail">
        </div>
        <div class="video-info p-sm">
          <h3 class="video-title text-md font-medium">{$video.title}</h3>
          <p class="video-meta text-sm text-secondary">
            <span>{$video.views} views</span>
            <span aria-hidden="true">•</span>
            <span>{$video.date}</span>
          </p>
        </div>
      </a>
    </article>
  {/foreach}
</div>
```

### Responsive Container

**Before:**
```html
<div class="inner-block">
  {* Content *}
</div>
```

**After:**
```html
<div class="container">
  {* Content auto-sizes with padding *}
</div>
```

### Flex Layout

**Before:**
```html
<div style="display: flex; justify-content: space-between; align-items: center;">
  <div>{$title}</div>
  <div>{$actions}</div>
</div>
```

**After:**
```html
<div class="flex justify-between items-center gap-md">
  <div>{$title}</div>
  <div>{$actions}</div>
</div>
```

### Responsive Text

**Before:**
```html
<h1 style="font-size: 36px;">{$title}</h1>
```

**After:**
```html
<h1 class="text-responsive-xl font-bold">{$title}</h1>
```

### Responsive Spacing

**Before:**
```html
<div style="padding: 16px; margin-bottom: 24px;">
  {* Content *}
</div>
```

**After:**
```html
<div class="p-responsive m-b-lg">
  {* Content *}
</div>
```

### Card Component

**New pattern:**
```html
<div class="card shadow-md">
  <div class="card-header p-md">
    <h2 class="text-lg font-semibold">Card Title</h2>
  </div>
  <div class="card-body p-lg">
    {* Card content *}
  </div>
  <div class="card-footer p-md">
    <button class="btn btn-primary">Action</button>
  </div>
</div>
```

### Alert Messages

**Before:**
```smarty
{if $error_message}
  <div class="error-message-text">{$error_message}</div>
{/if}
```

**After:**
```smarty
{if $error_message}
  <div class="alert alert-error" role="alert">
    <i class="icon-warning" aria-hidden="true"></i>
    <span>{$error_message}</span>
  </div>
{/if}

{if $success_message}
  <div class="alert alert-success" role="alert">
    <i class="icon-check" aria-hidden="true"></i>
    <span>{$success_message}</span>
  </div>
{/if}
```

---

## JavaScript Enhancements

### Theme Switcher Events

```javascript
// Listen for theme changes
document.addEventListener('easystream:theme-change', (e) => {
  console.log('Theme changed:', e.detail);
  // Update other components if needed
});

// Programmatically change theme
window.themeSwitcher.toggleMode(); // Toggle light/dark
window.themeSwitcher.setColor('red'); // Change color

// Get current theme
const theme = window.themeSwitcher.getCurrentTheme();
console.log(theme); // { mode: 'dark', color: 'blue', ... }
```

### Service Worker Updates

```javascript
// Update service worker
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js?v=2')
    .then(reg => {
      // Check for updates
      reg.update();

      // Listen for updates
      reg.addEventListener('updatefound', () => {
        const newWorker = reg.installing;
        newWorker.addEventListener('statechange', () => {
          if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
            // New version available
            if (confirm('New version available! Reload to update?')) {
              window.location.reload();
            }
          }
        });
      });
    });
}
```

### Offline Detection

```javascript
// Detect online/offline
window.addEventListener('online', () => {
  console.log('Back online!');
  // Show success message
  showNotification('You are back online', 'success');
});

window.addEventListener('offline', () => {
  console.log('Gone offline');
  // Show warning message
  showNotification('You are offline. Some features may be unavailable.', 'warning');
});

function showNotification(message, type) {
  const alert = document.createElement('div');
  alert.className = `alert alert-${type}`;
  alert.textContent = message;
  alert.role = 'alert';
  document.body.appendChild(alert);

  setTimeout(() => alert.remove(), 5000);
}
```

---

## Testing Snippets

### Check Accessibility

```javascript
// Check for images without alt text
const imagesWithoutAlt = document.querySelectorAll('img:not([alt])');
console.log('Images missing alt text:', imagesWithoutAlt.length);

// Check for buttons without labels
const buttonsWithoutLabel = document.querySelectorAll('button:not([aria-label]):not(:has(.sr-only))');
console.log('Buttons missing labels:', buttonsWithoutLabel.length);

// Check heading hierarchy
const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
headings.forEach(h => console.log(h.tagName, h.textContent.substring(0, 50)));
```

### Check Contrast Ratios

```javascript
// Check text contrast (simplified)
function checkContrast(element) {
  const style = getComputedStyle(element);
  const color = style.color;
  const bgColor = style.backgroundColor;
  console.log(`Element: ${element.tagName}`, { color, bgColor });
}

// Check all text elements
document.querySelectorAll('p, h1, h2, h3, h4, h5, h6, a, button, span').forEach(checkContrast);
```

### Test Keyboard Navigation

```javascript
// Highlight focusable elements
document.querySelectorAll('a, button, input, select, textarea, [tabindex]').forEach(el => {
  el.style.outline = '2px solid red';
});

// Tab order test
let tabIndex = 0;
document.addEventListener('focus', (e) => {
  console.log(`Tab ${++tabIndex}:`, e.target);
}, true);
```

---

## Common Patterns

### Modal Dialog

```html
<div id="my-modal" class="modal" role="dialog" aria-labelledby="modal-title" aria-hidden="true">
  <div class="modal-backdrop" data-dismiss="modal"></div>
  <div class="modal-content card shadow-xl">
    <div class="modal-header p-md flex justify-between items-center">
      <h2 id="modal-title" class="text-xl font-semibold">Modal Title</h2>
      <button class="modal-close btn btn-secondary" data-dismiss="modal" aria-label="Close">
        <i class="icon-close"></i>
      </button>
    </div>
    <div class="modal-body p-lg">
      {* Modal content *}
    </div>
    <div class="modal-footer p-md flex justify-end gap-sm">
      <button class="btn btn-secondary" data-dismiss="modal">Cancel</button>
      <button class="btn btn-primary">Confirm</button>
    </div>
  </div>
</div>
```

### Dropdown Menu

```html
<div class="dropdown">
  <button
    class="btn btn-secondary dropdown-toggle touch-target"
    aria-haspopup="true"
    aria-expanded="false"
    id="dropdown-menu-btn">
    Menu <i class="icon-chevron-down"></i>
  </button>
  <ul
    class="dropdown-menu"
    role="menu"
    aria-labelledby="dropdown-menu-btn"
    hidden>
    <li role="none">
      <a href="#" role="menuitem" class="dropdown-item">Option 1</a>
    </li>
    <li role="none">
      <a href="#" role="menuitem" class="dropdown-item">Option 2</a>
    </li>
  </ul>
</div>
```

### Loading Spinner

```html
<div class="loading-spinner" role="status" aria-live="polite">
  <i class="icon-spinner spinner"></i>
  <span class="sr-only">Loading...</span>
</div>
```

### Breadcrumbs

```html
<nav aria-label="Breadcrumb">
  <ol class="breadcrumb flex gap-xs items-center">
    <li><a href="/">Home</a></li>
    <li aria-hidden="true">/</li>
    <li><a href="/videos">Videos</a></li>
    <li aria-hidden="true">/</li>
    <li aria-current="page">Current Page</li>
  </ol>
</nav>
```

---

## Quick Reference

### Class Names Cheat Sheet

**Spacing:**
- `m-xs`, `m-sm`, `m-md`, `m-lg` - Margins
- `p-xs`, `p-sm`, `p-md`, `p-lg` - Padding

**Typography:**
- `text-xs`, `text-sm`, `text-md`, `text-lg`, `text-xl` - Font sizes
- `font-light`, `font-normal`, `font-medium`, `font-bold` - Font weights

**Layout:**
- `flex`, `flex-col`, `flex-wrap` - Flexbox
- `grid`, `grid-cols-{n}` - Grid
- `container` - Responsive container

**Display:**
- `hidden`, `block`, `flex` - Display
- `xs:hidden`, `md:block` - Responsive display

**Colors:**
- `text-primary`, `text-secondary` - Text colors
- `bg-primary`, `bg-secondary` - Background colors

**Borders:**
- `rounded-sm`, `rounded-md`, `rounded-lg`, `rounded-full` - Border radius

**Shadows:**
- `shadow-sm`, `shadow-md`, `shadow-lg` - Box shadows

**Accessibility:**
- `sr-only` - Screen reader only
- `touch-target` - Minimum touch size
- `focus-visible` - Focus indicator

---

## Migration Checklist

- [ ] Include new CSS files in templates
- [ ] Include theme-switcher.js
- [ ] Add skip links to body
- [ ] Add main content ID
- [ ] Update navigation with theme toggle
- [ ] Replace inline styles with utility classes
- [ ] Add alt text to all images
- [ ] Add ARIA labels to buttons
- [ ] Add labels to form inputs
- [ ] Fix heading hierarchy
- [ ] Add ARIA landmarks
- [ ] Test keyboard navigation
- [ ] Test with screen reader
- [ ] Test on mobile devices
- [ ] Test all theme combinations
- [ ] Run Lighthouse audit

---

**Next Steps:** See [DESIGN_SYSTEM_GUIDE.md](DESIGN_SYSTEM_GUIDE.md) for complete documentation.
