Przejdź do treści
<code>pen.pl

Ustawienia treningu jak transmisja sportowa

Interfejs

Podgląd

Ładowanie podglądu…

Dynamiczny panel treningowy inspirowany grafiką telewizyjną z czasem, dyscypliną i intensywnością.

0,0 / 5 Brak ocen

Kod źródłowy

Licencja MIT — także do użytku komercyjnego. Zachowaj informacje o autorze i licencji.

HTML
<main class='broadcast' data-state='idle'>
  <header><div class='live'><i></i> TRENING / USTAWIENIA</div><div class='score'><span>SESJA</span><b id='sport-score'>00:00</b></div></header>
  <div class='broadcast-grid'>
    <section class='intro'><span class='round'>PLAN 10</span><h1>Ustaw<br>tempo</h1><p>Zbuduj krótką sesję i zapisz ją na tablicy treningowej.</p><div class='lane' aria-hidden='true'><i></i><i></i><i></i></div></section>
    <form id='sport-form' novalidate>
      <div class='two'>
        <div class='field'><label for='sport-athlete'>Imię zawodnika</label><input id='sport-athlete' name='athlete' required autocomplete='name' aria-describedby='sport-athlete-error'><span class='error' id='sport-athlete-error'></span></div>
        <div class='field'><label for='sport-duration'>Czas w minutach</label><input id='sport-duration' name='duration' type='number' required min='5' max='180' value='30' inputmode='numeric' aria-describedby='sport-duration-error'><span class='error' id='sport-duration-error'></span></div>
      </div>
      <div class='field'><label for='sport-discipline'>Dyscyplina</label><select id='sport-discipline' name='discipline' required aria-describedby='sport-discipline-error'><option value=''>Wybierz dyscyplinę</option><option value='run'>Bieg interwałowy</option><option value='cycle'>Rower</option><option value='strength'>Trening siłowy</option></select><span class='error' id='sport-discipline-error'></span></div>
      <fieldset aria-describedby='sport-level-error'><legend>Intensywność</legend><label><input type='radio' name='sport-level' value='easy'> Spokojna</label><label><input type='radio' name='sport-level' value='steady'> Równa</label><label><input id='sport-high' type='radio' name='sport-level' value='high'> Wysoka</label><span class='error' id='sport-level-error'></span></fieldset>
      <div class='actions'><button class='primary' id='sport-save' type='submit'>Zapisz trening</button><button type='reset'>Wyczyść tablicę</button><button type='button' disabled>Synchronizacja</button></div>
      <p class='status' id='sport-status' role='status' aria-live='polite'>Tablica czeka na plan.</p>
    </form>
  </div>
  <footer><strong id='sport-ticker'>GOTOWOŚĆ: 100%</strong><span>CODEPEN TRAINING NETWORK</span></footer>
</main>
CSS
*{box-sizing:border-box}html,body{margin:0;min-width:280px}body{min-height:100vh;padding:clamp(10px,3vw,25px);background:#061426;color:#f5f8fb;font:16px/1.4 Arial,sans-serif}.broadcast{width:min(100%,980px);margin:auto;border:2px solid #d7ff42;background:#0a1d34;box-shadow:9px 9px 0 #2cc9ff;overflow:hidden}.broadcast>header{display:flex;justify-content:space-between;align-items:stretch;border-bottom:2px solid #d7ff42}.live{display:flex;align-items:center;gap:9px;padding:11px 18px;font-weight:900;font-style:italic}.live i{display:block;width:13px;height:13px;background:#ff4d3f}.score{display:flex;align-items:center;background:#d7ff42;color:#061426;clip-path:polygon(20px 0,100% 0,100% 100%,0 100%);padding:7px 18px 7px 31px;gap:13px}.score span{font-size:11px;font-weight:900}.score b{font:900 26px/1 'Arial Narrow',Arial,sans-serif}.broadcast-grid{display:grid;grid-template-columns:minmax(230px,.72fr) minmax(0,1.3fr);gap:25px;padding:24px}.intro{position:relative;padding-right:18px;border-right:1px solid #50708e}.round{display:inline-block;background:#2cc9ff;color:#061426;padding:5px 9px;font-weight:900;transform:skewX(-10deg)}h1{margin:20px 0 16px;font:900 clamp(48px,8vw,86px)/.77 'Arial Narrow',Arial,sans-serif;text-transform:uppercase;letter-spacing:-.07em;font-style:italic}.intro p{max-width:26ch;color:#c4d1dc}.lane{margin-top:28px;display:grid;gap:6px;transform:skewX(-15deg)}.lane i{height:7px;background:#d7ff42}.lane i:nth-child(2){width:72%;background:#2cc9ff}.lane i:nth-child(3){width:42%;background:#ff4d3f}.two{display:grid;grid-template-columns:1fr 1fr;gap:12px}.field{margin-bottom:12px}label,legend{font-weight:800}label{display:block;margin-bottom:5px}input:not([type=radio]),select{width:100%;min-height:44px;border:1px solid #6c879e;border-radius:0;background:#eff5f8;color:#07192c;padding:8px 10px}button,input,select{font:inherit}button{min-height:44px;border:2px solid #d7ff42;border-radius:0;background:transparent;color:#f5f8fb;padding:8px 13px;font-weight:900;cursor:pointer;transform:skewX(-5deg)}button.primary{background:#d7ff42;color:#061426}button:disabled{cursor:not-allowed;border-color:#61758a;color:#8798a9}button:focus-visible,input:focus-visible,select:focus-visible{outline:4px solid #2cc9ff;outline-offset:3px}fieldset{margin:0 0 14px;padding:8px 11px;border:1px solid #6c879e}fieldset label{display:inline-flex;align-items:center;gap:7px;min-height:44px;margin:0 14px 2px 0}input[type=radio]{width:22px;height:22px;accent-color:#d7ff42}.error{display:block;min-height:17px;color:#ff9288;font-size:12px}[aria-invalid=true]{border-color:#ff4d3f!important}.actions{display:flex;gap:8px;flex-wrap:wrap}.status{min-height:24px;margin:11px 0 0;font-weight:800}.broadcast footer{display:flex;justify-content:space-between;gap:18px;background:#f5f8fb;color:#061426;padding:9px 18px;font-size:12px;font-weight:900}.broadcast footer strong{color:#a01e17}.broadcast[data-state=success] #sport-ticker{color:#176f2c;animation:ticker-in .35s ease-out}@keyframes ticker-in{from{transform:translateX(-18px);opacity:0}to{transform:none;opacity:1}}@media(max-width:650px){body{padding:7px}.broadcast-grid{grid-template-columns:1fr;padding:18px}.intro{border-right:0;border-bottom:1px solid #50708e;padding:0 0 16px}.intro h1{font-size:56px;margin:15px 0 11px}.intro p{max-width:42ch}.lane{display:none}.two{grid-template-columns:1fr}.actions button{flex:1 1 140px}.broadcast footer{flex-wrap:wrap}.live{font-size:13px}}@media(max-width:340px){.broadcast-grid{padding:12px}.broadcast>header{display:block}.score{clip-path:none;justify-content:space-between}.intro h1{font-size:49px}.actions{display:grid}.actions button{width:100%;transform:none}fieldset label{display:flex;margin-right:0}.broadcast footer{padding:9px 12px}}@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}}
JavaScript
(()=>{const form=$('#sport-form'),board=$('.broadcast'),status=$('#sport-status'),ticker=$('#sport-ticker');function mark(el,message){$(el).attr('aria-invalid','true');$('#'+el.id+'-error').text(message)}function clear(el){$(el).removeAttr('aria-invalid');if(el.id)$('#'+el.id+'-error').text('')}form.on('input change','input,select',function(){clear(this);if(this.name==='sport-level')$('#sport-level-error').text('')});$('#sport-duration').on('input',function(){const minutes=Math.max(0,Number(this.value||0));$('#sport-score').text(String(minutes).padStart(2,'0')+':00')});form.on('submit',function(event){event.preventDefault();form.find('[aria-invalid]').removeAttr('aria-invalid');form.find('.error').text('');let first=null,athlete=$('#sport-athlete')[0],duration=$('#sport-duration')[0],discipline=$('#sport-discipline')[0];if(!athlete.value.trim()){mark(athlete,'Wpisz imię zawodnika.');first=first||athlete}if(!duration.validity.valid){mark(duration,'Podaj czas od 5 do 180 minut.');first=first||duration}if(!discipline.value){mark(discipline,'Wybierz dyscyplinę.');first=first||discipline}const level=form.find('[name=sport-level]:checked');if(!level.length){$('#sport-level-error').text('Wybierz intensywność.');first=first||form.find('[name=sport-level]')[0]}if(first){board.attr('data-state','error');status.text('Plan wymaga uzupełnienia.');first.focus();return}board.attr('data-state','success');$('#sport-score').text(String(duration.value).padStart(2,'0')+':00');ticker.text(athlete.value.trim().toUpperCase()+' / '+discipline.options[discipline.selectedIndex].text.toUpperCase());status.text('Trening zapisany dla '+athlete.value.trim()+'.')});form.on('reset',()=>setTimeout(()=>{form.find('[aria-invalid]').removeAttr('aria-invalid');form.find('.error').text('');board.attr('data-state','idle');$('#sport-score').text('00:00');ticker.text('GOTOWOŚĆ: 100%');status.text('Wyczyszczono tablicę treningową.')},0));const activate=event=>{event.preventDefault();form.triggerHandler('submit')};$('#sport-save').on('click',activate);form.on('keydown','input:not([type=radio]):not([type=range])',event=>{if(event.key==='Enter')activate(event)})})();
Biblioteki

JavaScript

Edytuj swój pen

Podaj adres e-mail użyty przy zapisie. Wyślemy link do edycji.

Link jest ważny przez 30 minut.