diff --git a/client/src/modules/front_end_components/Confirmation.js b/client/src/modules/front_end_components/Confirmation.js index cc2d3b4..bd1c51c 100644 --- a/client/src/modules/front_end_components/Confirmation.js +++ b/client/src/modules/front_end_components/Confirmation.js @@ -6,6 +6,7 @@ export const Confirmation = (message, onYes = null, isDOMNode = false) => { let confirmation = document.createElement('div'); confirmation.setAttribute('id', 'confirmation'); + confirmation.setAttribute('tabindex', '-1'); confirmation.innerHTML = onYes ? `
@@ -73,4 +74,5 @@ export const Confirmation = (message, onYes = null, isDOMNode = false) => { document.body.appendChild(background); document.body.appendChild(confirmation); + confirmation.querySelector('#confirmation-yes-button').focus(); }; diff --git a/client/src/modules/front_end_components/HTMLFragments.js b/client/src/modules/front_end_components/HTMLFragments.js index 90cbedf..bceb814 100644 --- a/client/src/modules/front_end_components/HTMLFragments.js +++ b/client/src/modules/front_end_components/HTMLFragments.js @@ -26,7 +26,7 @@ export const HTMLFragments = {
-
+
`, ENTER_NAME_STEP: - `
-
+ `
@@ -44,8 +43,7 @@ export const HTMLFragments = { -
-
`, +
`, START_GAME_PROMPT: `
@@ -80,18 +78,18 @@ export const HTMLFragments = {
-
+

role

-
+

Double-click here to show your role

(Double-click here again to hide)

-
+
`, SPECTATOR_GAME_VIEW: @@ -121,7 +119,7 @@ export const HTMLFragments = {
-
+
`, TRANSFER_MOD_MODAL: @@ -155,7 +153,7 @@ export const HTMLFragments = {
-
+
@@ -166,7 +164,7 @@ export const HTMLFragments = {
-
+
@@ -206,18 +204,18 @@ export const HTMLFragments = {
-
+

role

-
+

Double-click here to show your role

(Double-click here again to hide)

-
+
`, @@ -280,7 +278,7 @@ export const HTMLFragments = {

Roles in this game:

`, END_OF_GAME_VIEW: @@ -339,7 +337,9 @@ export const HTMLFragments = {
`, DECK_SELECT_ROLE: - `
+ `
+ +
add one info diff --git a/client/src/modules/game_creation/DeckStateManager.js b/client/src/modules/game_creation/DeckStateManager.js index c48df14..20cf186 100644 --- a/client/src/modules/game_creation/DeckStateManager.js +++ b/client/src/modules/game_creation/DeckStateManager.js @@ -92,6 +92,7 @@ export class DeckStateManager { for (const templateName of Object.keys(this.templates)) { const templateOption = document.createElement('div'); templateOption.classList.add('template-option'); + templateOption.setAttribute('tabindex', '0'); templateOption.innerHTML = HTMLFragments.DECK_TEMPLATE; templateOption.querySelector('.template-option-name').innerText = templateName; for (let i = 0; i < Object.keys(this.templates[templateName]).length; i ++) { @@ -104,24 +105,28 @@ export class DeckStateManager { roleEl.classList.add(roleBox.defaultRoles.find((entry) => entry.role === role).team); templateOption.querySelector('.template-option-roles').appendChild(roleEl); } - templateOption.addEventListener('click', (e) => { - e.preventDefault(); - for (const card of this.deck) { - card.quantity = 0; - } - for (const role of Object.keys(this.templates[templateName])) { - const roleObj = roleBox.getDefaultRole(role); - if (!this.hasRole(roleObj.role)) { - this.addToDeck(roleObj); + const templateHandler = (e) => { + if (e.type === 'click' || e.code === 'Enter') { + e.preventDefault(); + for (const card of this.deck) { + card.quantity = 0; } - for (let i = roleObj.quantity; i < this.templates[templateName][role]; i ++) { - this.addCopyOfCard(roleObj.role); + for (const role of Object.keys(this.templates[templateName])) { + const roleObj = roleBox.getDefaultRole(role); + if (!this.hasRole(roleObj.role)) { + this.addToDeck(roleObj); + } + for (let i = roleObj.quantity; i < this.templates[templateName][role]; i ++) { + this.addCopyOfCard(roleObj.role); + } } + this.updateDeckStatus(); + ModalManager.dispelModal('deck-template-modal', 'modal-background'); + toast('Template loaded', 'success', true, true, 'short'); } - this.updateDeckStatus(); - ModalManager.dispelModal('deck-template-modal', 'modal-background'); - toast('Template loaded', 'success', true, true, 'short'); - }); + }; + templateOption.addEventListener('click', templateHandler); + templateOption.addEventListener('keyup', templateHandler); document.getElementById('deck-template-container').appendChild(templateOption); } } diff --git a/client/src/modules/game_state/states/InProgress.js b/client/src/modules/game_state/states/InProgress.js index 2d7d59f..8d8fccd 100644 --- a/client/src/modules/game_state/states/InProgress.js +++ b/client/src/modules/game_state/states/InProgress.js @@ -63,12 +63,16 @@ export class InProgress { } const spectatorCount = this.container.querySelector('#spectator-count'); + const spectatorHandler = (e) => { + if (e.type === 'click' || e.code === 'Enter') { + Confirmation(SharedStateUtil.buildSpectatorList(this.stateBucket.currentGameState.people + .filter(p => p.userType === globals.USER_TYPES.SPECTATOR)), null, true); + } + }; if (spectatorCount) { - spectatorCount?.addEventListener('click', () => { - Confirmation(SharedStateUtil.buildSpectatorList(this.stateBucket.currentGameState.people.filter(p => p.userType === globals.USER_TYPES.SPECTATOR)), null, true); - }); - + spectatorCount?.addEventListener('click', spectatorHandler); + spectatorCount?.addEventListener('keyup', spectatorHandler); SharedStateUtil.setNumberOfSpectators( this.stateBucket.currentGameState.people.filter(p => p.userType === globals.USER_TYPES.SPECTATOR).length, spectatorCount @@ -438,15 +442,25 @@ function renderPlayerRole (gameState) { document.querySelector('#role-description').innerText = gameState.client.gameRoleDescription; - document.getElementById('game-role-back').addEventListener('dblclick', () => { - document.getElementById('game-role').style.display = 'flex'; - document.getElementById('game-role-back').style.display = 'none'; - }); + const roleBackHandler = (e) => { + if (e.type === 'dblclick' || e.code === 'Enter') { + document.getElementById('game-role').style.display = 'flex'; + document.getElementById('game-role-back').style.display = 'none'; + } + }; - document.getElementById('game-role').addEventListener('dblclick', () => { - document.getElementById('game-role-back').style.display = 'flex'; - document.getElementById('game-role').style.display = 'none'; - }); + const roleFrontHandler = (e) => { + if (e.type === 'dblclick' || e.code === 'Enter') { + document.getElementById('game-role-back').style.display = 'flex'; + document.getElementById('game-role').style.display = 'none'; + } + }; + + document.getElementById('game-role-back').addEventListener('dblclick', roleBackHandler); + document.getElementById('game-role-back').addEventListener('keyup', roleBackHandler); + + document.getElementById('game-role').addEventListener('dblclick', roleFrontHandler); + document.getElementById('game-role').addEventListener('keyup', roleFrontHandler); } function removeExistingPlayerElements (killPlayerHandlers, revealRoleHandlers) { diff --git a/client/src/modules/timer/GameTimerManager.js b/client/src/modules/timer/GameTimerManager.js index 9b76f79..5b839ea 100644 --- a/client/src/modules/timer/GameTimerManager.js +++ b/client/src/modules/timer/GameTimerManager.js @@ -4,11 +4,15 @@ import { Confirmation } from '../front_end_components/Confirmation.js'; export class GameTimerManager { constructor (stateBucket, socket) { this.stateBucket = stateBucket; - this.playListener = () => { - socket.emit(globals.SOCKET_EVENTS.IN_GAME_MESSAGE, globals.EVENT_IDS.RESUME_TIMER, this.stateBucket.currentGameState.accessCode); + this.playListener = (e) => { + if (e.type === 'click' || e.code === 'Enter') { + socket.emit(globals.SOCKET_EVENTS.IN_GAME_MESSAGE, globals.EVENT_IDS.RESUME_TIMER, this.stateBucket.currentGameState.accessCode); + } }; - this.pauseListener = () => { - socket.emit(globals.SOCKET_EVENTS.IN_GAME_MESSAGE, globals.EVENT_IDS.PAUSE_TIMER, this.stateBucket.currentGameState.accessCode); + this.pauseListener = (e) => { + if (e.type === 'click' || e.code === 'Enter') { + socket.emit(globals.SOCKET_EVENTS.IN_GAME_MESSAGE, globals.EVENT_IDS.PAUSE_TIMER, this.stateBucket.currentGameState.accessCode); + } }; } @@ -94,7 +98,9 @@ export class GameTimerManager { const currentBtn = document.querySelector('#timer-container-moderator #play-pause img'); if (currentBtn) { currentBtn.removeEventListener('click', this.pauseListener); + currentBtn.removeEventListener('keyup', this.pauseListener); currentBtn.removeEventListener('click', this.playListener); + currentBtn.removeEventListener('keyup', this.playListener); currentBtn.classList.add('disabled'); currentBtn.setAttribute('src', '/images/play-pause-placeholder.svg'); } else { @@ -140,12 +146,15 @@ export class GameTimerManager { const currentBtn = document.querySelector('#play-pause img'); if (currentBtn) { currentBtn.removeEventListener('click', this.pauseListener); + currentBtn.removeEventListener('keyup', this.pauseListener); currentBtn.remove(); } const playBtn = document.createElement('img'); playBtn.setAttribute('src', '../images/play-button.svg'); + playBtn.setAttribute('tabindex', '0'); playBtn.addEventListener('click', this.playListener); + playBtn.addEventListener('keyup', this.playListener); document.querySelector('#play-pause-placeholder')?.remove(); document.getElementById('play-pause').appendChild(playBtn); } @@ -154,12 +163,15 @@ export class GameTimerManager { const currentBtn = document.querySelector('#play-pause img'); if (currentBtn) { currentBtn.removeEventListener('click', this.playListener); + currentBtn.removeEventListener('keyup', this.playListener); currentBtn.remove(); } const pauseBtn = document.createElement('img'); pauseBtn.setAttribute('src', '../images/pause-button.svg'); + pauseBtn.setAttribute('tabindex', '0'); pauseBtn.addEventListener('click', this.pauseListener); + pauseBtn.addEventListener('keyup', this.pauseListener); document.querySelector('#play-pause-placeholder')?.remove(); document.getElementById('play-pause').appendChild(pauseBtn); } diff --git a/client/src/styles/create.css b/client/src/styles/create.css index e8c4975..4c0a139 100644 --- a/client/src/styles/create.css +++ b/client/src/styles/create.css @@ -102,11 +102,11 @@ } .template-option { + background-color: #4645525c; + border: 2px solid #46455299; color: #d7d7d7; display: flex; justify-content: space-between; - background-color: #0f0f10; - border: 2px solid #3b3a4a; padding: 5px; border-radius: 5px; font-size: 16px; @@ -156,7 +156,7 @@ #custom-roles-container, #deck-status-container { color: #d7d7d7; margin: 1em 0.5em; - background-color: #191920; + background-color: #16141e; padding: 10px; border-radius: 5px; border: 2px solid #3b3a4a; @@ -314,6 +314,10 @@ option { margin: 0 auto; } +#step-4 > div { + width: 100%; +} + #step-4 div:nth-child(2) { margin-top: 25px; } @@ -370,9 +374,9 @@ select { #game-time { display: flex; flex-wrap: wrap; - background-color: #191920; - border: 2px solid #3b3a4a; border-radius: 5px; + background-color: #16141e; + border: 2px solid #3b3a4a; } .step { @@ -573,7 +577,6 @@ input[type="number"] { } #step-forward-button, #step-back-button { - background-color: #66666657 !important; padding: 0 !important; width: 50px; height: 44px; @@ -581,7 +584,8 @@ input[type="number"] { -ms-user-select: none; -webkit-user-select: none; -moz-user-select: none; - border: 2px solid #56565673; + background-color: #16141e; + border: 2px solid #3b3a4a; } #step-forward-button:hover, #step-back-button:hover { @@ -605,7 +609,7 @@ input[type="number"] { } #step-1 div { - background-color: #191920; + background-color: #16141e; color: #e7e7e7; padding: 1em; max-width: 20em; diff --git a/client/src/styles/game.css b/client/src/styles/game.css index d65b8aa..622bc58 100644 --- a/client/src/styles/game.css +++ b/client/src/styles/game.css @@ -20,7 +20,7 @@ .potential-moderator { margin: 0.5em auto; border: 2px solid #46455299; - background: #4645523b; + background: #4645525c; } #transfer-mod-modal h2 { @@ -224,7 +224,7 @@ h1 { #game-role-info-container > div { width: 95%; border: 1px solid #46455299; - background: #4645523b; + background: #4645525c; padding: 5px; border-radius: 5px; margin-bottom: 5px; @@ -272,7 +272,8 @@ h1 { display: none; position: relative; border: 5px solid transparent; - background-color: #e7e7e7; + background-color: #16141e; + color: #d7d7d7; flex-direction: column; cursor: pointer; justify-content: space-between; @@ -303,19 +304,19 @@ h1 { } .game-role-good { - border: 5px solid #5469c5 !important; + border: 3px solid #5469c5 !important; } .game-role-evil { - border: 5px solid #c55454 !important; + border: 3px solid #c55454 !important; } #game-role-back { display: flex; align-items: center; justify-content: center; - background-color: #171522; - border: 5px solid #61606a; + background-color: #16141e; + border: 3px solid #61606a; position: relative; flex-direction: column; cursor: pointer; @@ -351,7 +352,7 @@ h1 { #game-timer { padding: 10px; margin-top: 5px; - background-color: #262626; + background-color: #0f0f10; color: #e7e7e7; border-radius: 5px; font-size: 35px; @@ -434,9 +435,10 @@ h1 { flex-wrap: wrap; align-items: center; justify-content: space-between; - background-color: #3b3a4a; border-radius: 5px; min-width: 15em; + border: 1px solid #46455299; + background: #4645525c; } #client-name { @@ -450,7 +452,7 @@ h1 { color: #21ba45; font-family: 'signika-negative', sans-serif; font-size: 25px; - background-color: #171522; + background-color: black; border-radius: 5px; display: block; padding: 0 5px; @@ -616,7 +618,8 @@ label[for='moderator'] { margin-bottom: 1em; padding: 0.5em; border-radius: 5px; - background-color: #3b3a4a; + border: 1px solid #46455299; + background: #4645525c; } canvas { @@ -760,7 +763,8 @@ canvas { } #game-parameters { - background-color: #3b3a4a; + border: 1px solid #46455299; + background: #4645525c; border-radius: 5px; padding: 5px 20px; } @@ -808,7 +812,7 @@ canvas { border-radius: 5px; min-height: 25em; border: 1px solid #46455299; - background: #4645523b; + background: #4645525c; max-width: 35em; min-width: 19em; margin-top: 1em; diff --git a/client/src/styles/home.css b/client/src/styles/home.css index 353976c..56f672d 100644 --- a/client/src/styles/home.css +++ b/client/src/styles/home.css @@ -126,7 +126,7 @@ form > div { #join-container { max-width: 90%; border: 1px solid #46455299; - background: #4645523b; + background: #4645525c; padding: 0.5em; border-radius: 5px; margin: 20px diff --git a/client/src/styles/modal.css b/client/src/styles/modal.css index 3f8d646..fba45d8 100644 --- a/client/src/styles/modal.css +++ b/client/src/styles/modal.css @@ -68,11 +68,12 @@ #custom-role-info-modal-description { border-radius: 5px; - background-color: black; + background-color: #4645525c; max-height: 10em; overflow: auto; padding: 5px; margin-bottom: 2em; + border: 1px solid #46455299; } #custom-role-info-modal-name { @@ -86,7 +87,8 @@ #custom-role-info-modal-alignment { border-radius: 5px; - background-color: black; + background-color: #4645525c; + border: 1px solid #46455299; font-size: 18px; font-weight: bold; padding: 5px;