diff --git a/README.md b/README.md index 3818713..a7ffb00 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,12 @@ npm install npm run dev ``` -3. Acesse no navegador: +3. Em outro terminal, acompanhe o Sass e gere o CSS automaticamente: +```bash +npm run watch:styles +``` + +4. Acesse no navegador: ``` http://localhost:1234 ``` diff --git a/asset/images/logo.svg b/asset/images/logo.svg new file mode 100644 index 0000000..8e73cb3 --- /dev/null +++ b/asset/images/logo.svg @@ -0,0 +1,15 @@ + diff --git a/asset/javascript/ThemeController.js b/asset/javascript/ThemeController.js new file mode 100644 index 0000000..0f118ef --- /dev/null +++ b/asset/javascript/ThemeController.js @@ -0,0 +1,45 @@ +export function ThemeController(reference) { + const body = reference; + + const themeMenuButton = body.querySelector('.js-theme-menu-button'); + const themeDropdown = body.querySelector('.js-theme-dropdown'); + + const defaultThemeButton = body.querySelector('.js-default-theme-button'); + const versusThemeButton = body.querySelector('.js-versus-theme-button'); + + function init() { + if (!themeMenuButton || !themeDropdown || !defaultThemeButton || !versusThemeButton) { + return; + } + + bindButtons(); + } + + function bindButtons() { + themeMenuButton.addEventListener('click', toggleThemeMenu); + defaultThemeButton.addEventListener('click', setDefaultTheme); + versusThemeButton.addEventListener('click', setVersusTheme); + } + + function toggleThemeMenu() { + themeDropdown.classList.toggle('hide'); + } + + function setDefaultTheme() { + body.classList.remove('versus-theme'); + body.classList.remove('inverted'); + closeThemeMenu(); + } + + function setVersusTheme() { + body.classList.add('versus-theme'); + body.classList.remove('inverted'); + closeThemeMenu(); + } + + function closeThemeMenu() { + themeDropdown.classList.add('hide'); + } + + init(); +} diff --git a/asset/javascript/TimeController.js b/asset/javascript/TimeController.js index 52acf4e..5a78148 100644 --- a/asset/javascript/TimeController.js +++ b/asset/javascript/TimeController.js @@ -10,11 +10,13 @@ import { secondsToHour, secondsToMinute, } from './TimeUtils.js'; +import { ThemeController } from './ThemeController.js'; function TimerController(reference) { const hourInput = reference.querySelector('.js-hour-input'); const minuteInput = reference.querySelector('.js-minute-input'); const secondInput = reference.querySelector('.js-seconds-input'); + const themeButton = reference.querySelector('.js-theme-menu-container'); const actionButtonsContainer = reference.querySelector('.js-stopwatch-action-buttons'); const enterFullscreenButton = actionButtonsContainer.querySelector('.js-enter-fullscreen-button'); @@ -55,6 +57,7 @@ function TimerController(reference) { bindButtons(); bindFullscreenEvents(); setInputValues(DEFAULT_SECONDS); + new ThemeController(reference); } var bindInputs = function () { @@ -197,7 +200,10 @@ function TimerController(reference) { lastTimerStatus = TimerStatus.COUNTDOWN; playCountdownSound(); - if (!preventOpenCountdown) executeCountdown(seconds); + if (!preventOpenCountdown) { + themeButton.hideElement(); + executeCountdown(seconds); + } } setInputValues(seconds); @@ -319,6 +325,7 @@ function TimerController(reference) { stopSound.pause(); stopSound.currentTime = 0; stopSound.volume = 0; + themeButton.showElement(); } function toggleButtonsContainer(isEditing) { diff --git a/asset/style/timer.css b/asset/style/timer.css index 436d4d3..b701ab5 100644 --- a/asset/style/timer.css +++ b/asset/style/timer.css @@ -1,158 +1,213 @@ -@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400..900&display=swap'); +@import url("https://fonts.googleapis.com/css2?family=Orbitron:wght@400..900&display=swap"); :root { - --primary-bg-color: #242424; - --primary-text-color: #46ffbe; - --secondary-bg-color: #46ffbe; - --secondary-text-color: #444444; + --primary-bg-color: #242424; + --primary-text-color: #46ffbe; + --secondary-bg-color: #46ffbe; + --secondary-text-color: #444444; + --button-background-color: transparent; + --button-icon-filter: inherit; + --button-border: 1px solid #fff; + --primary-dark-color: #1ea97a; +} + +.versus-theme { + --primary-bg-color: #ED5026; + --primary-text-color: #FFFFFF; + --secondary-bg-color: #000000; + --secondary-text-color: #444444; + --button-background-color: transparent; + --button-icon-filter: brightness(100); + --button-border: 1px solid #fff; +} +.versus-theme .timer-logo { + display: block; + width: 380px; } * { - font-family: 'Orbitron', sans-serif; - box-sizing: border-box; + font-family: "Orbitron", sans-serif; + box-sizing: border-box; } body, html { - background-color: var(--primary-bg-color); - color: var(--primary-text-color); - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 48px; - margin: 0; - height: 100dvh; - width: 100dvw; -} -body::-moz-selection, -html::-moz-selection { - background: var(--secondary-bg-color); - color: var(--secondary-text-color); + background-color: var(--primary-bg-color); + color: var(--primary-text-color); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 48px; + margin: 0; + height: 100dvh; + width: 100dvw; } body::selection, html::selection { - background: var(--secondary-bg-color); - color: var(--secondary-text-color); + background: var(--secondary-bg-color); + color: var(--secondary-text-color); } body ::-moz-selection, html ::-moz-selection { - background: var(--secondary-bg-color); - color: var(--secondary-text-color); + background: var(--secondary-bg-color); + color: var(--secondary-text-color); } body.inverted, html.inverted { - background-color: var(--primary-text-color); - color: var(--primary-bg-color); + background-color: var(--secondary-bg-color); + color: var(--primary-bg-color); } body.inverted .input-stopwatch-container input, html.inverted .input-stopwatch-container input { - color: var(--primary-bg-color); + color: var(--primary-bg-color); } .countdown-container { - width: 100%; - height: 100%; - position: absolute; - background: var(--primary-bg-color); - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - transition: all 0.5s ease; + width: 100%; + height: 100%; + position: absolute; + background: var(--primary-bg-color); + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + transition: all 0.5s ease; } .countdown-container .countdown-number { - font-size: 202px; - transition: all 0.5s ease; + font-size: 202px; + transition: all 0.5s ease; } .countdown-container.odd { - background: var(--secondary-bg-color); - color: var(--secondary-text-color); + background: var(--secondary-bg-color); + color: var(--secondary-text-color); } .countdown-container.even { - background: var(--primary-bg-color); - color: var(--primary-text-color); + background: var(--primary-bg-color); + color: var(--primary-text-color); } .countdown-container.inverted { - background: var(--primary-text-color); - color: var(--primary-bg-color); + background: var(--secondary-bg-color); + color: var(--primary-bg-color); } .countdown-container.inverted .action-button-container button { - border-color: var(--primary-bg-color); + border-color: var(--primary-bg-color); } .input-stopwatch-container { - width: 100%; - display: flex; - justify-content: center; - transition: all 0.5s ease; - font-size: 112px; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + transition: all 0.5s ease; + font-size: 112px; } @media screen and (max-width: 768px) { - .input-stopwatch-container { - font-size: 56px; - } + .input-stopwatch-container { + font-size: 56px; + } } .input-stopwatch-container input { - width: auto; - min-width: 1px; - max-width: 2ch; - margin: 0; - padding: 0; - color: var(--primary-text-color); - border: none; - background: none; - outline: none; - text-align: center; - font-size: inherit; - border-radius: 5px; -} -.input-stopwatch-container input::-webkit-outer-spin-button, -.input-stopwatch-container input::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; -} -.input-stopwatch-container input[type='number'] { - appearance: none; - -webkit-appearance: none; - -moz-appearance: textfield; + width: auto; + min-width: 1px; + max-width: 2ch; + margin: 0; + padding: 0; + color: var(--primary-text-color); + border: none; + background: none; + outline: none; + text-align: center; + font-size: inherit; + border-radius: 5px; +} +.input-stopwatch-container input::-webkit-outer-spin-button, .input-stopwatch-container input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} +.input-stopwatch-container input[type=number] { + appearance: none; + -webkit-appearance: none; + -moz-appearance: textfield; } .action-button-container { - display: flex; - flex-direction: row; - gap: 32px; -} -.action-button-container button { - display: flex; - align-items: center; - justify-content: center; - padding: 0; - height: 32px; - width: 32px; - background-color: transparent; - border: 1px solid white; - border-radius: 99px; - color: inherit; - cursor: pointer; - transition: all 0.5s ease; -} -.action-button-container button img { - max-width: 100%; - max-height: 100%; - display: block; -} -.action-button-container button:hover { - background-color: rgba(255, 255, 255, 0.15); -} -.action-button-container button:active, -.action-button-container button:focus, -.action-button-container button:focus-visible, -.action-button-container button:focus-within { - box-shadow: 0 0 10px var(--secondary-bg-color); - background-color: rgba(255, 255, 255, 0.15); - outline: none; + display: flex; + flex-direction: row; + gap: 32px; +} + +button.as-icon { + display: flex; + align-items: center; + justify-content: center; + padding: 0; + height: 32px; + width: 32px; + background-color: var(--button-background-color); + border: var(--button-border); + border-radius: 99px; + color: inherit; + cursor: pointer; + transition: all 0.5s ease; + font-size: 20px; +} +button.as-icon img { + max-width: 20px; + max-height: 20px; + display: block; + filter: var(--button-icon-filter); +} +button.as-icon:hover { + transform: scale(1.05); +} +button.as-icon:active, button.as-icon:focus, button.as-icon:focus-visible, button.as-icon:focus-within { + box-shadow: 0 0 10px var(--secondary-bg-color); + background-color: rgba(255, 255, 255, 0.15); + outline: none; } .hide { - display: none !important; -} /*# sourceMappingURL=timer.css.map */ + display: none !important; +} + +.timer-logo { + display: none; +} + +.theme-menu-container { + position: fixed; + bottom: 32px; + right: 32px; + z-index: 10; +} + +.theme-dropdown { + position: absolute; + bottom: 60px; + right: 0; + display: flex; + flex-direction: column; + gap: 8px; + padding: 12px; + background: rgba(255, 255, 255, 0.08); + backdrop-filter: blur(10px); + border-radius: 16px; + min-width: 180px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); +} +.theme-dropdown button { + border: none; + background: transparent; + padding: 12px; + border-radius: 8px; + cursor: pointer; + color: white; + font-size: 14px; + text-align: left; + transition: all 0.3s ease; +} +.theme-dropdown button:hover { + background: rgba(255, 255, 255, 0.1); +} + +/*# sourceMappingURL=timer.css.map */ diff --git a/asset/style/timer.css.map b/asset/style/timer.css.map index 0c5bc96..1b0ada7 100644 --- a/asset/style/timer.css.map +++ b/asset/style/timer.css.map @@ -1 +1 @@ -{"version":3,"sources":["timer.scss","timer.css"],"names":[],"mappings":"AAAQ,2FAAA;AAER;EACI,2BAAA;EACA,6BAAA;EACA,6BAAA;EACA,+BAAA;ACAJ;;ADGA;EACI,mCAAA;EACA,sBAAA;ACAJ;;ADGA;;EAEI,yCAAA;EACA,gCAAA;EACA,aAAA;EACA,sBAAA;EACA,uBAAA;EACA,mBAAA;EACA,SAAA;EACA,SAAA;EACA,cAAA;EACA,aAAA;ACAJ;ADEI;EACI,qCAAA;EACA,kCAAA;ACCR;ADHI;;EACI,qCAAA;EACA,kCAAA;ACCR;ADEI;;EACI,qCAAA;EACA,kCAAA;ACCR;;ADGA;EACI,WAAA;EACA,YAAA;EACA,kBAAA;EACA,mCAAA;EACA,aAAA;EACA,mBAAA;EACA,uBAAA;EACA,sBAAA;EACA,yBAAA;ACAJ;ADEI;EACI,gBAAA;EACA,yBAAA;ACAR;ADGI;EACI,qCAAA;EACA,kCAAA;ACDR;ADII;EACI,mCAAA;EACA,gCAAA;ACFR;;ADMA;EACI,WAAA;EACA,aAAA;EACA,uBAAA;EACA,yBAAA;EACA,gBAAA;ACHJ;ADKI;EAPJ;IAQQ,eAAA;ECFN;AACF;ADII;EACI,WAAA;EACA,cAAA;EACA,cAAA;EACA,SAAA;EACA,UAAA;EACA,gCAAA;EACA,YAAA;EACA,gBAAA;EACA,aAAA;EACA,kBAAA;EACA,kBAAA;EACA,kBAAA;ACFR;ADIQ;EAEI,wBAAA;EACA,SAAA;ACHZ;ADMQ;EACI,gBAAA;EACA,wBAAA;EACA,0BAAA;ACJZ;;ADSA;EACI,aAAA;EACA,mBAAA;EACA,SAAA;ACNJ;ADQI;EACI,aAAA;EACA,mBAAA;EACA,uBAAA;EACA,UAAA;EACA,YAAA;EACA,WAAA;EACA,6BAAA;EACA,uBAAA;EACA,mBAAA;EACA,cAAA;EACA,eAAA;EACA,yBAAA;ACNR;ADQQ;EACI,eAAA;EACA,gBAAA;EACA,cAAA;ACNZ;ADSQ;EACI,2CAAA;ACPZ;ADUQ;EAII,8CAAA;EACA,2CAAA;EACA,aAAA;ACXZ;;ADgBA;EACI,wBAAA;ACbJ","file":"timer.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["timer.scss"],"names":[],"mappings":"AAAQ;AAER;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;;AAIR;EACI;EACA;;;AAGJ;AAAA;EAEI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;AAAA;EACI;EACA;;AAGJ;AAAA;EACI;EACA;;AAGJ;AAAA;EACI;EACA;;AAEA;AAAA;EACI;;;AAKZ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;;AAEA;EACI;;;AAKZ;EACI;EACA;EACA;EACA;EACA;EACA;;AAEA;EARJ;IASQ;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEI;EACA;;AAGJ;EACI;EACA;EACA;;;AAKZ;EACI;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAGJ;EACI;;AAGJ;EAII;EACA;EACA;;;AAIR;EACI;;;AAGJ;EACI;;;AAGJ;EACI;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EAEA;EACA;EACA;EAEA;EAEA;EACA;EACA;EAEA;EAEA;;AAEA;EACI;EACA;EAEA;EACA;EAEA;EAEA;EACA;EACA;EAEA;;AAEA;EACI","file":"timer.css"} \ No newline at end of file diff --git a/asset/style/timer.scss b/asset/style/timer.scss index 560fdb7..986338f 100644 --- a/asset/style/timer.scss +++ b/asset/style/timer.scss @@ -5,6 +5,25 @@ --primary-text-color: #46ffbe; --secondary-bg-color: #46ffbe; --secondary-text-color: #444444; + --button-background-color: transparent; + --button-icon-filter: inherit; + --button-border: 1px solid #fff; + --primary-dark-color: #1ea97a; +} + +.versus-theme { + --primary-bg-color: #ED5026; + --primary-text-color: #FFFFFF; + --secondary-bg-color: #000000; + --secondary-text-color: #444444; + --button-background-color: transparent; + --button-icon-filter: brightness(100); + --button-border: 1px solid #fff; + + .timer-logo { + display: block; + width: 380px; + } } * { @@ -36,7 +55,7 @@ html { } &.inverted { - background-color: var(--primary-text-color); + background-color: var(--secondary-bg-color); color: var(--primary-bg-color); .input-stopwatch-container input { @@ -72,7 +91,7 @@ html { } &.inverted { - background: var(--primary-text-color); + background: var(--secondary-bg-color); color: var(--primary-bg-color); .action-button-container button { @@ -85,6 +104,7 @@ html { width: 100%; display: flex; justify-content: center; + align-items: center; transition: all 0.5s ease; font-size: 112px; @@ -124,42 +144,95 @@ html { display: flex; flex-direction: row; gap: 32px; +} - button { - display: flex; - align-items: center; - justify-content: center; - padding: 0; - height: 32px; - width: 32px; - background-color: transparent; - border: 1px solid white; - border-radius: 99px; - color: inherit; - cursor: pointer; - transition: all 0.5s ease; +button.as-icon { + display: flex; + align-items: center; + justify-content: center; + padding: 0; + height: 32px; + width: 32px; + background-color: var(--button-background-color); + border: var(--button-border); + border-radius: 99px; + color: inherit; + cursor: pointer; + transition: all 0.5s ease; + font-size: 20px; - img { - max-width: 100%; - max-height: 100%; - display: block; - } + img { + max-width: 20px; + max-height: 20px; + display: block; + filter: var(--button-icon-filter); + } - &:hover { - background-color: rgba(255, 255, 255, 0.15); - } + &:hover { + transform: scale(1.05); + } - &:active, - &:focus, - &:focus-visible, - &:focus-within { - box-shadow: 0 0 10px var(--secondary-bg-color); - background-color: rgba(255, 255, 255, 0.15); - outline: none; - } + &:active, + &:focus, + &:focus-visible, + &:focus-within { + box-shadow: 0 0 10px var(--secondary-bg-color); + background-color: rgba(255, 255, 255, 0.15); + outline: none; } } .hide { display: none !important; } + +.timer-logo { + display: none; +} + +.theme-menu-container { + position: fixed; + bottom: 32px; + right: 32px; + z-index: 10; +} + +.theme-dropdown { + position: absolute; + bottom: 60px; + right: 0; + + display: flex; + flex-direction: column; + gap: 8px; + + padding: 12px; + + background: rgba(255,255,255,0.08); + backdrop-filter: blur(10px); + border-radius: 16px; + + min-width: 180px; + + box-shadow: 0 10px 30px rgba(0,0,0,0.2); + + button { + border: none; + background: transparent; + + padding: 12px; + border-radius: 8px; + + cursor: pointer; + + color: white; + font-size: 14px; + text-align: left; + + transition: all 0.3s ease; + + &:hover { + background: rgba(255,255,255,0.1); + } + } +} diff --git a/index.html b/index.html index 38e315b..3bfa7ea 100644 --- a/index.html +++ b/index.html @@ -10,6 +10,12 @@
+