UNPKG

pkg-components

Version:
148 lines (126 loc) 3.18 kB
/* ========================= ThemeToggle.module.css ========================= */ .toggle { position: relative; display: inline-block; border-radius: 999px; border: none; cursor: pointer; overflow: hidden; padding: 8px; background: linear-gradient(180deg, #111 0%, #0b0b0b 100%); transition: background-color 260ms ease, box-shadow 200ms ease, transform 120ms ease; -webkit-tap-highlight-color: transparent; } /* Focus */ .toggle:focus-visible { outline: 3px solid rgba(255, 255, 255, 0.14); outline-offset: 4px; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45), 0 0 0 6px rgba(255, 255, 255, 0.02); } /* States */ .light { background: linear-gradient(180deg, #f6f7f9 0%, #eef0f2 100%); } .dark { background: linear-gradient(180deg, #0b0b0b 0%, #060606 100%); } /* ========================= Knob ========================= */ .knob { position: absolute; top: 8px; left: 8px; width: calc(50% - 9px); height: calc(100% - 16px); border-radius: 999px; background: linear-gradient(180deg, #ffffff 0%, #f0f0f0 100%); box-shadow: 0 10px 30px rgba(2, 6, 23, 0.18), inset 0 -6px 12px rgba(0, 0, 0, 0.06); transform: translateX(0) scale(1); transition: transform 450ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 220ms ease; will-change: transform; } /* Press feedback */ .toggle:active { transform: scale(0.985); } .toggle:active .knob { transform: translateX(0) scale(0.985); transition-duration: 120ms; } /* Dark slide with overshoot */ .dark .knob { transform: translateX(calc(100% - 2px)); animation: knob-slide 450ms cubic-bezier(0.22, 1, 0.36, 1) both; } /* ========================= Icons ========================= */ .iconSun, .iconMoon { position: absolute; top: 50%; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; transform: translateY(-50%) scale(0.9); opacity: 0; pointer-events: none; transition: opacity 280ms ease, transform 450ms cubic-bezier(0.22, 1, 0.36, 1); } .iconSun { left: 20px; color: #ffb84d; } .iconMoon { right: 20px; color: #2b2f36; } /* Icon states */ .light .iconSun { opacity: 1; transform: translateY(-50%) scale(1) rotate(0deg); } .dark .iconSun { opacity: 0; transform: translateY(-50%) scale(0.7) rotate(-35deg); } .light .iconMoon { opacity: 0; transform: translateY(-50%) scale(0.7) rotate(35deg); } .dark .iconMoon { opacity: 1; transform: translateY(-50%) scale(1) rotate(0deg); } /* ========================= Animations ========================= */ @keyframes knob-slide { 0% { transform: translateX(0) scale(1); } 60% { transform: translateX(calc(100% + 6px)) scale(1.01); } 100% { transform: translateX(calc(100% - 2px)) scale(1); } } /* ========================= Accessibility ========================= */ @media (prefers-reduced-motion: reduce) { .toggle, .knob, .iconSun, .iconMoon { transition: none !important; animation: none !important; } }