@manufosela/animation-handclock

@manufosela/animation-handclock

SVG analog clock web component with animated hands built with Lit 3

Animation Handclock Demo

Interactive Clock

--:--:--

Minimal Style

Elegant Gold

Neon Glow

World Clocks

New York

London

Paris

Tokyo

Sydney

Dubai

Demo code (CodePen-ready HTML, CSS, JS)
HTML (html)
<div class="demo-container">
      <h1>Animation Handclock Demo</h1>

      <div class="controls">
        <div class="control-group">
          <label>Show Seconds</label>
          <input type="checkbox" id="secondsToggle" checked />
        </div>

        <div class="control-group">
          <label>Show Numbers</label>
          <input type="checkbox" id="numbersToggle" checked />
        </div>

        <div class="control-group">
          <label>Show Minute Markers</label>
          <input type="checkbox" id="markersToggle" checked />
        </div>

        <div class="control-group">
          <label>Theme</label>
          <select id="themeSelect">
            <option value="light">Light</option>
            <option value="dark">Dark</option>
          </select>
        </div>
      </div>

      <div class="clocks-grid">
        <div class="clock-card">
          <h3>Interactive Clock</h3>
          <div class="clock-wrapper">
            <animation-handclock id="mainClock"></animation-handclock>
          </div>
          <div class="digital-time" id="digitalTime">--:--:--</div>
        </div>

        <div class="clock-card">
          <h3>Minimal Style</h3>
          <div class="clock-wrapper">
            <animation-handclock class="minimal-clock" .showNumbers=${false}></animation-handclock>
          </div>
        </div>

        <div class="clock-card">
          <h3>Elegant Gold</h3>
          <div class="clock-wrapper">
            <animation-handclock class="elegant-clock"></animation-handclock>
          </div>
        </div>

        <div class="clock-card">
          <h3>Neon Glow</h3>
          <div class="clock-wrapper">
            <animation-handclock class="neon-clock"></animation-handclock>
          </div>
        </div>
      </div>

      <h2>World Clocks</h2>

      <div class="timezone-grid">
        <div class="timezone-card">
          <h4>New York</h4>
          <animation-handclock class="timezone-clock" timezone="America/New_York" .showSeconds=${false}></animation-handclock>
        </div>

        <div class="timezone-card">
          <h4>London</h4>
          <animation-handclock class="timezone-clock" timezone="Europe/London" .showSeconds=${false}></animation-handclock>
        </div>

        <div class="timezone-card">
          <h4>Paris</h4>
          <animation-handclock class="timezone-clock" timezone="Europe/Paris" .showSeconds=${false}></animation-handclock>
        </div>

        <div class="timezone-card">
          <h4>Tokyo</h4>
          <animation-handclock class="timezone-clock" timezone="Asia/Tokyo" .showSeconds=${false}></animation-handclock>
        </div>

        <div class="timezone-card">
          <h4>Sydney</h4>
          <animation-handclock class="timezone-clock" timezone="Australia/Sydney" .showSeconds=${false}></animation-handclock>
        </div>

        <div class="timezone-card">
          <h4>Dubai</h4>
          <animation-handclock class="timezone-clock" timezone="Asia/Dubai" .showSeconds=${false}></animation-handclock>
        </div>
      </div>
    </div>
CSS (css)
:root {
  --bg: #0c0f14;
  --bg-elevated: #141923;
  --bg-panel: #171d28;
  --border: #262f3f;
  --text: #f4f6fb;
  --text-muted: #a7b0c2;
  --text-dim: #7d879b;
  --accent: #ff8a3d;
  --accent-strong: #ff6a00;
  --accent-soft: rgba(255, 138, 61, 0.16);
  --shadow: 0 20px 50px rgba(5, 8, 14, 0.45);
  --radius-lg: 22px;
  --radius-md: 14px;
  --radius-sm: 10px;
  --max-width: 1160px;
}

<script type="module" src="../src/animation-handclock.js"></script>
    
      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }

      h1, h2 {
        text-align: center;
        color: var(--text);
        margin-bottom: 2rem;
        font-weight: 300;
        letter-spacing: 2px;
      }

      .demo-container {
        max-width: 1200px;
        margin: 0 auto;
      }

      .clocks-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
        gap: 2rem;
        margin-bottom: 3rem;
      }

      .clock-card {
        background: var(--bg-elevated);
        border-radius: 16px;
        padding: 2rem;
        text-align: center;
        box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
      }

      .clock-card h3 {
        margin-bottom: 1rem;
        font-weight: 500;
        color: var(--accent);
      }

      .clock-wrapper {
        display: flex;
        justify-content: center;
        margin-bottom: 1rem;
      }

      .digital-time {
        font-family: 'Courier New', monospace;
        font-size: 1.5rem;
        color: #667eea;
        font-weight: bold;
      }

      .controls {
        display: flex;
        flex-wrap: wrap;
        gap: 1rem;
        justify-content: center;
        margin-bottom: 2rem;
        padding: 1.5rem;
        background: rgba(255, 255, 255, 0.95);
        border-radius: 12px;
        box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
      }

      .control-group {
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
        align-items: center;
      }

      .control-group label {
        font-size: 0.875rem;
        color: var(--text-muted);
      }

      input[type='checkbox'] {
        width: 20px;
        height: 20px;
        accent-color: #667eea;
      }

      select {
        padding: 0.5rem 1rem;
        border: 2px solid #667eea;
        border-radius: 8px;
        font-size: 1rem;
        color: var(--accent);
        background: var(--bg-elevated);
        cursor: pointer;
      }

      /* Custom themed clocks */
      .minimal-clock {
        --handclock-size: 180px;
        --handclock-face-color: #f5f5f5;
        --handclock-border-color: #e0e0e0;
        --handclock-border-width: 2;
        --handclock-hour-hand-color: #424242;
        --handclock-minute-hand-color: #757575;
        --handclock-second-hand-color: #ff5722;
        --handclock-marker-color: #bdbdbd;
      }

      .elegant-clock {
        --handclock-size: 180px;
        --handclock-face-color: var(--bg-panel);
        --handclock-border-color: #c9a227;
        --handclock-border-width: 3;
        --handclock-hour-hand-color: #c9a227;
        --handclock-minute-hand-color: #c9a227;
        --handclock-second-hand-color: #ff6b6b;
        --handclock-marker-color: #c9a227;
        --handclock-number-color: #c9a227;
        --handclock-center-color: #c9a227;
      }

      .neon-clock {
        --handclock-size: 180px;
        --handclock-face-color: #0a0a0a;
        --handclock-border-color: #00ff88;
        --handclock-border-width: 2;
        --handclock-hour-hand-color: #00ff88;
        --handclock-minute-hand-color: #00ff88;
        --handclock-second-hand-color: #ff00ff;
        --handclock-marker-color: #00ff88;
        --handclock-number-color: #00ff88;
        --handclock-center-color: #00ff88;
      }

      .timezone-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
        gap: 1.5rem;
      }

      .timezone-card {
        background: var(--bg-elevated);
        border-radius: 12px;
        padding: 1.5rem;
        text-align: center;
        box-shadow: 0 5px 20px rgba(0, 0, 0, 0.15);
      }

      .timezone-card h4 {
        margin-bottom: 0.5rem;
        font-size: 0.9rem;
        color: var(--text-muted);
      }

      .timezone-clock {
        --handclock-size: 120px;
      }
JS (js)
const mainClock = document.getElementById('mainClock');
      const digitalTime = document.getElementById('digitalTime');
      const secondsToggle = document.getElementById('secondsToggle');
      const numbersToggle = document.getElementById('numbersToggle');
      const markersToggle = document.getElementById('markersToggle');
      const themeSelect = document.getElementById('themeSelect');

      mainClock.addEventListener('time-change', (e) => {
        const { hours, minutes, seconds } = e.detail;
        const h = hours.toString().padStart(2, '0');
        const m = minutes.toString().padStart(2, '0');
        const s = seconds.toString().padStart(2, '0');
        digitalTime.textContent = `${h}:${m}:${s}`;
      });

      secondsToggle.addEventListener('change', (e) => {
        mainClock.showSeconds = e.target.checked;
      });

      numbersToggle.addEventListener('change', (e) => {
        mainClock.showNumbers = e.target.checked;
      });

      markersToggle.addEventListener('change', (e) => {
        mainClock.showMinuteMarkers = e.target.checked;
      });

      themeSelect.addEventListener('change', (e) => {
        mainClock.theme = e.target.value;
      });