← Components/Data Display

ComparisonSlider

comparisonslider-1779379671626.tsx
'use client'
import { useState, useRef, useCallback, useEffect } from 'react'

export default function ComparisonSlider() {
  const [position, setPosition] = useState(50)
  const [dragging, setDragging] = useState(false)
  const containerRef = useRef<HTMLDivElement>(null)

  const handleMove = useCallback((clientX: number) => {
    if (!containerRef.current) return
    const rect = containerRef.current.getBoundingClientRect()
    const pct = ((clientX - rect.left) / rect.width) * 100
    setPosition(Math.max(0, Math.min(100, pct)))
  }, [])

  useEffect(() => {
    if (!dragging) return
    const onMove = (e: MouseEvent | TouchEvent) => {
      const x = 'touches' in e ? e.touches[0].clientX : e.clientX
      handleMove(x)
    }
    const onUp = () => setDragging(false)
    window.addEventListener('mousemove', onMove)
    window.addEventListener('touchmove', onMove)
    window.addEventListener('mouseup', onUp)
    window.addEventListener('touchend', onUp)
    return () => {
      window.removeEventListener('mousemove', onMove)
      window.removeEventListener('touchmove', onMove)
      window.removeEventListener('mouseup', onUp)
      window.removeEventListener('touchend', onUp)
    }
  }, [dragging, handleMove])

  useEffect(() => {
    const handler = (e: KeyboardEvent) => {
      if (e.key === 'ArrowLeft') setPosition(p => Math.max(0, p - 5))
      if (e.key === 'ArrowRight') setPosition(p => Math.min(100, p + 5))
    }
    document.addEventListener('keydown', handler)
    return () => document.removeEventListener('keydown', handler)
  }, [])

  return (
    <div style={{ padding: 32, background: '#0A0A0A', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 20 }}>
      <div style={{ color: '#F5F5F0', fontSize: 16, fontWeight: 700 }}>Before / After</div>

      <div ref={containerRef} onMouseDown={e => { setDragging(true); handleMove(e.clientX) }}
        onTouchStart={e => { setDragging(true); handleMove(e.touches[0].clientX) }}
        style={{ position: 'relative', width: 480, height: 280, borderRadius: 16, overflow: 'hidden', cursor: 'col-resize', userSelect: 'none', border: '1px solid rgba(255,255,255,0.08)' }}>

        {/* "Before" side — dark code editor */}
        <div style={{ position: 'absolute', inset: 0, background: '#111', display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', gap: 8 }}>
          <div style={{ background: '#1a1a1a', border: '1px solid rgba(255,255,255,0.1)', borderRadius: 12, padding: 20, width: 200, fontFamily: 'monospace', fontSize: 11 }}>
            {['<Button>', '  style={{', '    padding: 8,', '    color: 'white'', '  }}', '>Click</Button>'].map((l, i) => (
              <div key={i} style={{ color: i === 0 || i === 5 ? '#C9A84C' : 'rgba(255,255,255,0.5)', marginBottom: 2 }}>{l}</div>
            ))}
          </div>
          <div style={{ color: 'rgba(255,255,255,0.3)', fontSize: 12 }}>Writing from scratch</div>
        </div>

        {/* "After" side — Empire UI */}
        <div style={{ position: 'absolute', inset: 0, clipPath: `inset(0 ${100 - position}% 0 0)`, background: 'linear-gradient(135deg, #0A0A0A, #0d0817)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', gap: 8 }}>
          <div style={{ background: 'rgba(201,168,76,0.08)', border: '1px solid rgba(201,168,76,0.2)', borderRadius: 12, padding: 20, width: 200, display: 'flex', flexDirection: 'column', gap: 10 }}>
            <div style={{ display: 'flex', gap: 6 }}>
              {['⬡', '⊞', '◎'].map((i, idx) => (
                <div key={idx} style={{ flex: 1, height: 28, background: 'rgba(201,168,76,0.1)', border: '1px solid rgba(201,168,76,0.2)', borderRadius: 6, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 14 }}>{i}</div>
              ))}
            </div>
            <div style={{ height: 8, background: 'rgba(255,255,255,0.06)', borderRadius: 4 }} />
            <div style={{ height: 8, width: '70%', background: 'rgba(255,255,255,0.04)', borderRadius: 4 }} />
            <div style={{ background: '#C9A84C', borderRadius: 6, padding: '6px', textAlign: 'center', color: '#0A0A0A', fontWeight: 700, fontSize: 12 }}>GlowButton</div>
          </div>
          <div style={{ color: 'rgba(201,168,76,0.7)', fontSize: 12 }}>Using Empire UI MCP</div>
        </div>

        {/* Labels */}
        <div style={{ position: 'absolute', top: 12, left: 12, background: 'rgba(0,0,0,0.7)', color: 'rgba(255,255,255,0.6)', padding: '3px 8px', borderRadius: 4, fontSize: 11, fontWeight: 600 }}>BEFORE</div>
        <div style={{ position: 'absolute', top: 12, right: 12, background: 'rgba(201,168,76,0.2)', color: '#C9A84C', padding: '3px 8px', borderRadius: 4, fontSize: 11, fontWeight: 600 }}>AFTER</div>

        {/* Handle */}
        <div style={{ position: 'absolute', top: 0, bottom: 0, left: `${position}%`, width: 2, background: '#C9A84C', transform: 'translateX(-50%)' }}>
          <div style={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%,-50%)', width: 36, height: 36, background: '#C9A84C', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: '0 0 16px rgba(201,168,76,0.5)' }}>
            <span style={{ color: '#0A0A0A', fontSize: 14 }}>⇔</span>
          </div>
        </div>

        {/* Percent overlay */}
        <div style={{ position: 'absolute', bottom: 12, left: '50%', transform: 'translateX(-50%)', background: 'rgba(0,0,0,0.7)', color: '#F5F5F0', padding: '3px 10px', borderRadius: 20, fontSize: 11 }}>
          {Math.round(position)}% · drag or use arrow keys
        </div>
      </div>
    </div>
  )
}

Component info

CategoryData Display
Frameworkreact
TierFREE
Views0
Copies0

About

Before/after image comparison slider with drag handle, percentage overlay, and keyboard support

More from Data Display

'use client'
import { useState } from 'react'

const WEEKS = 26
const DAYS = 7

function randomActivity(): number {
  const r = Math.random()
  if (r < 0.3) return 0
  if (r < 0.55) return 1
  if (r < 0.75) return 2
  if (r < 0.9) return 3
  return 4
HeatmapCalendar
Data Display
'use client'
import { useState } from 'react'

const events = [
  { id: 1, icon: '🚀', title: 'Wave 7 generation complete', desc: '57 new components published across 14 categories', time: '14:32', type: 'success', day: 'Today' },
  { id: 2, icon: '👥
TimelineActivity
Data Display