import React, { useEffect, useReducer, type ComponentPropsWithoutRef, type FC } from 'react'; import styled from '@emotion/styled'; import { clsx } from 'clsx'; // noinspection CssUnresolvedCustomProperty const Container = styled.div` /*========== Colors ==========*/ --hue-color: 240; --first-color: hsl(var(--hue-color), 53%, 49%); --title-color: hsl(var(--hue-color), 53%, 15%); --text-color: hsl(var(--hue-color), 12%, 35%); --text-color-light: hsl(var(--hue-color), 12%, 65%); --white-color: #fff; --body-color: hsl(var(--hue-color), 24%, 94%); /*========== Font and typography ==========*/ --body-font: 'Poppins', sans-serif; --biggest-font-size: 3rem; --small-font-size: 0.813rem; --smaller-font-size: 0.75rem; --tiny-font-size: 0.625rem; /*========== Font weight ==========*/ --font-medium: 500; /*========== Margenes Bottom ==========*/ --mb-0-25: 0.25rem; --mb-1: 1rem; --mb-1-5: 1.5rem; --mb-2-5: 2.5rem; /*========== z index ==========*/ --z-normal: 1; --z-tooltip: 10; /*========== Button Dark/Light ==========*/ .clock__theme { position: absolute; top: -1rem; right: -1rem; display: flex; padding: 0.25rem; border-radius: 50%; box-shadow: inset -1px -1px 1px hsla(var(--hue-color), 0%, 100%, 1), inset 1px 1px 1px hsla(var(--hue-color), 30%, 86%, 1); color: var(--first-color); cursor: pointer; transition: 0.4s; // For dark mode animation } /*========== Box shadow Dark theme ==========*/ .dark-theme .clock__circle { box-shadow: 6px 6px 16px hsla(var(--hue-color), 8%, 12%, 1), -6px -6px 16px hsla(var(--hue-color), 8%, 20%, 1), inset -6px -6px 16px hsla(var(--hue-color), 8%, 20%, 1), inset 6px 6px 12px hsla(var(--hue-color), 8%, 12%, 1); } .dark-theme .clock__theme { box-shadow: inset -1px -1px 1px hsla(var(--hue-color), 8%, 20%, 1), inset 1px 1px 1px hsla(var(--hue-color), 8%, 12%, 1); } /*=============== REUSABLE CSS CLASSES ===============*/ .container { max-width: 968px; margin-left: var(--mb-1); margin-right: var(--mb-1); } .grid { display: grid; } /*=============== CLOCK ===============*/ .clock__container { grid-template-rows: 1fr max-content; } .clock__circle { position: relative; width: 200px; height: 200px; box-shadow: -6px -6px 16px var(--white-color), 6px 6px 16px hsla(var(--hue-color), 30%, 86%, 1), inset 6px 6px 16px hsla(var(--hue-color), 30%, 86%, 1), inset -6px -6px 16px var(--white-color); border-radius: 50%; justify-self: center; display: flex; justify-content: center; align-items: center; transition: 0.4s; // For dark mode animation } .clock__content { align-self: center; row-gap: 3.5rem; } .clock__twelve, .clock__three, .clock__six, .clock__nine { position: absolute; width: 1rem; height: 1px; background-color: var(--text-color-light); } .clock__twelve, .clock__six { transform: translateX(-50%) rotate(90deg); } .clock__twelve { top: 1.25rem; left: 50%; } .clock__three { top: 50%; right: 0.75rem; } .clock__six { bottom: 1.25rem; left: 50%; } .clock__nine { left: 0.75rem; top: 50%; } .clock__rounder { width: 0.75rem; height: 0.75rem; background-color: var(--first-color); border-radius: 50%; border: 2px solid var(--body-color); z-index: var(--z-tooltip); } .clock__hour, .clock__minutes, .clock__seconds { position: absolute; display: flex; justify-content: center; } .clock__hour { width: 105px; height: 105px; } .clock__hour::before { content: ''; position: absolute; background-color: var(--text-color); width: 0.25rem; height: 3rem; border-radius: 0.75rem; z-index: var(--z-normal); } .clock__minutes { width: 136px; height: 136px; } .clock__minutes::before { content: ''; position: absolute; background-color: var(--text-color); width: 0.25rem; height: 4rem; border-radius: 0.75rem; z-index: var(--z-normal); } .clock__seconds { width: 130px; height: 130px; } .clock__seconds::before { content: ''; position: absolute; background-color: var(--first-color); width: 0.125rem; height: 5rem; border-radius: 0.75rem; z-index: var(--z-normal); } .clock__logo { width: max-content; justify-self: center; margin-bottom: var(--mb-2-5); font-size: var(--smaller-font-size); font-weight: var(--font-medium); color: var(--text-color-light); transition: 0.3s; } .clock__logo:hover { color: var(--first-color); } .clock__text { display: flex; justify-content: center; } .clock__text-hour, .clock__text-minutes { font-size: var(--biggest-font-size); font-weight: var(--font-medium); color: var(--title-color); } .clock__text-ampm { font-size: var(--tiny-font-size); color: var(--title-color); font-weight: var(--font-medium); margin-left: var(--mb-0-25); } .clock__date { font-size: var(--small-font-size); font-weight: var(--font-medium); } `; export const Clock: FC> = ({ className, children, ...props }) => { // src https://www.cssscript.com/modern-clock-ui/ let date = new Date(); let h = date.getHours(); let m = date.getMinutes(); let s = date.getSeconds(); let mAng = m * 6; let sAng = s * 6; let hAng = h * 30 + mAng / 12; let textHour: string | number = '', textMinutes: string | number = '', textAmPm: string | number = ''; const clockText = () => { let hh: string | number = h, ampm, mm: string | number = m; // We change the hours from 24 to 12 hours and establish whether it is AM or PM if (hh >= 12) { hh = hh - 12; ampm = 'PM'; } else { ampm = 'AM'; } // We detect when it's 0 AM and transform to 12 AM if (hh == 0) { hh = 12; } // Show a zero before hours if (hh < 10) { hh = `0${hh}`; } // Show time textHour = `${hh}:`; // Show a zero before the minutes if (mm < 10) { mm = `0${mm}`; } // Show minutes textMinutes = mm; // Show am or pm textAmPm = ampm; }; clockText(); const [, forceRender] = useReducer((s: number) => s + 1, 0); useEffect(() => { let timer: ReturnType | undefined; let next = () => { timer = setTimeout( () => { forceRender(); next(); }, 1000 - (Date.now() % 1000), ); }; next(); return () => clearTimeout(timer); }, []); return (
{textHour}
{textMinutes}
{textAmPm}
{date.toLocaleDateString('default')}
); };