Pomodoro z pierścieniem czasu
NarzędziaPodgląd
Ładowanie podglądu…
Minutnik z trybem pracy i przerwy, pauzą oraz resetem.
Kod źródłowy
Licencja MIT — także do użytku komercyjnego. Zachowaj informacje o autorze i licencji.
HTML
<main class="timer"><header><h1>Minutnik</h1><p>Wybierz pracę lub przerwę.</p></header><div class="timer-layout"><div class="clock"><svg viewBox="0 0 230 230" aria-hidden="true"><circle class="track" cx="115" cy="115" r="102"/><circle id="arc" cx="115" cy="115" r="102"/></svg><output id="time" aria-label="Pozostały czas">25:00</output></div><section><fieldset><legend>Tryb</legend><div class="row"><button id="focus-mode" type="button" class="secondary" aria-pressed="true">Skupienie 25 min</button><button id="break-mode" type="button" class="secondary" aria-pressed="false">Przerwa 5 min</button></div></fieldset><div class="row commands"><button id="run" type="button">Start</button><button id="reset" type="button" class="secondary">Reset</button></div><p id="timer-status" class="status" role="status">Gotowy do rozpoczęcia.</p><p class="note">Zmiana trybu rozpoczyna nową sesję.</p></section></div></main>
CSS
*{box-sizing:border-box}body{margin:0;min-height:100vh;padding:24px;font:16px/1.45 system-ui,sans-serif;display:grid;align-content:center;color:#17212e;background:#f5f7fb}main{width:min(100%,850px);margin:auto}h1,h2,p{margin:0 0 16px}h1{font-size:clamp(26px,4vw,42px);line-height:1.1}h2{font-size:21px}label{display:block;font-weight:600;margin-bottom:6px}input,select,textarea,button{font:inherit;max-width:100%}input:not([type=radio]):not([type=checkbox]):not([type=range]):not([type=color]),select,textarea{width:100%;padding:10px 12px;background:#fff;color:#17212e;border:1px solid #748091;min-height:44px;border-radius:0}textarea{resize:vertical}button{min-height:44px;padding:10px 18px;border:1px solid currentColor;background:#17212e;color:white;cursor:pointer;border-radius:0}button:hover{filter:brightness(1.15)}button:disabled{cursor:default;opacity:.55}button.secondary{background:transparent;color:inherit}input[type=radio],input[type=checkbox]{width:20px;height:20px;vertical-align:middle;accent-color:var(--accent,#3155c7)}input[type=range]{width:100%;accent-color:var(--accent,#3155c7);min-height:32px}input[type=color]{width:100%;min-height:52px;cursor:pointer;background:transparent;border:1px solid currentColor}fieldset{border:0;padding:0;margin:0}legend{font-weight:600;margin-bottom:12px}output{display:block}small,.note{font-size:13px}p.note{margin:10px 0 0}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible{outline:3px solid var(--accent,#3155c7);outline-offset:3px}[hidden]{display:none!important}.field{margin-bottom:16px}.row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.status{min-height:24px;margin-top:14px;font-weight:600;overflow-wrap:anywhere}.muted{color:#4b5868}.two{display:grid;grid-template-columns:1fr 1fr;gap:20px}@media(max-width:560px){body{padding:18px}.two{grid-template-columns:1fr}h1{font-size:29px}}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation:none!important;transition:none!important;scroll-behavior:auto!important}}body{background:#f1eaf0;color:#52344f;--accent:#8c486e}.timer{max-width:780px}.timer h1{font-family:Georgia,serif;font-weight:400}.timer header{text-align:center;margin-bottom:28px}.timer-layout{display:grid;grid-template-columns:260px 1fr;gap:35px;align-items:center}.clock{position:relative;aspect-ratio:1}.clock svg{width:100%;transform:rotate(-90deg)}.clock circle{fill:none;stroke-width:8}.track{stroke:#d5c6d0}#arc{stroke:#8c486e;stroke-dasharray:640.885;stroke-dashoffset:0}.clock output{position:absolute;inset:0;display:grid;place-items:center;font:48px ui-monospace,monospace}.timer button{background:#8c486e}.timer button.secondary{background:transparent;color:#52344f}.timer button[aria-pressed=true]{border-width:3px}.commands{margin-top:25px}#run{min-width:110px}@media(max-width:560px){.timer-layout{grid-template-columns:1fr;gap:15px}.clock{width:200px;margin:auto}.timer header{margin-bottom:15px}}
JavaScript
(()=>{const q=s=>document.querySelector(s);const all=s=>[...document.querySelectorAll(s)];let total=1500,remaining=total,running=false,end=0;const draw=()=>{q('#time').textContent=String(Math.floor(remaining/60)).padStart(2,'0')+':'+String(remaining%60).padStart(2,'0');q('#arc').style.strokeDashoffset=640.885*(1-remaining/total);q('#run').textContent=running?'Pauza':'Start'};const pause=()=>{if(running)remaining=Math.max(0,Math.ceil((end-Date.now())/1000));running=false;draw()};const mode=(seconds,button)=>{pause();total=seconds;remaining=seconds;all('[aria-pressed]').forEach(e=>e.setAttribute('aria-pressed',String(e.id===button)));q('#timer-status').textContent='Nowa sesja gotowa.';draw()};q('#focus-mode').onclick=()=>mode(1500,'focus-mode');q('#break-mode').onclick=()=>mode(300,'break-mode');q('#run').onclick=()=>{if(running){pause();q('#timer-status').textContent='Sesja wstrzymana.'}else{if(!remaining)remaining=total;end=Date.now()+remaining*1000;running=true;q('#timer-status').textContent='Sesja trwa.';draw()}};q('#reset').onclick=()=>{pause();remaining=total;q('#timer-status').textContent='Czas zresetowany.';draw()};setInterval(()=>{if(!running)return;remaining=Math.max(0,Math.ceil((end-Date.now())/1000));if(!remaining){running=false;q('#timer-status').textContent='Sesja zakończona. Zrób przerwę.'}draw()},250);draw();})();
Edytuj swój pen
Podaj adres e-mail użyty przy zapisie. Wyślemy link do edycji.