Merge pull request #152 from AlecM33/accessibility

Accessibility updates
This commit is contained in:
Alec
2023-02-21 22:18:17 -05:00
committed by GitHub
9 changed files with 114 additions and 71 deletions

View File

@@ -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
? `<div id="confirmation-message"></div>
<div class="confirmation-buttons">
@@ -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();
};

View File

@@ -26,7 +26,7 @@ export const HTMLFragments = {
<div>
<div id='lobby-people-container'>
<label for='lobby-players'></label>
<div id="spectator-count"></div>
<div id="spectator-count" tabindex="0"></div>
<div id='lobby-players'></div>
</div>
<div id='lobby-footer'>
@@ -34,8 +34,7 @@ export const HTMLFragments = {
</div>
</div>`,
ENTER_NAME_STEP:
`<div id='step-4'>
<div>
`<div>
<input type="text" id="moderator-name" autocomplete='given-name' placeholder="enter your name...">
</div>
<div>
@@ -44,8 +43,7 @@ export const HTMLFragments = {
<option value="no" selected>No</option>
<option value="yes">Yes</option>
</select>
</div>
</div>`,
</div>`,
START_GAME_PROMPT:
`<div>
<button id='start-game-button'>Start Game</button>
@@ -80,18 +78,18 @@ export const HTMLFragments = {
<button id='role-info-button' class='app-button'>Roles in This Game <img src='/images/info.svg'/></button>
</div>
</div>
<div id='game-role'>
<div id='game-role' tabindex="0">
<h4 id='role-name'></h4>
<img alt='role' id='role-image'/>
<p id='role-description'></p>
</div>
<div id='game-role-back'>
<div id='game-role-back' tabindex="0">
<h4>Double-click here to show your role</h4>
<p>(Double-click here again to hide)</p>
</div>
<div id='game-people-container'>
<label id='players-alive-label'></label>
<div id="spectator-count"></div>
<div id="spectator-count" tabindex="0"></div>
<div id='game-player-list'></div>
</div>`,
SPECTATOR_GAME_VIEW:
@@ -121,7 +119,7 @@ export const HTMLFragments = {
</div>
<div id='game-people-container'>
<label id='players-alive-label'></label>
<div id="spectator-count"></div>
<div id="spectator-count" tabindex="0"></div>
<div id='game-player-list'></div>
</div>`,
TRANSFER_MOD_MODAL:
@@ -155,7 +153,7 @@ export const HTMLFragments = {
</div>
</div>
</div>
<div id='play-pause'>
<div id='play-pause' tabindex="0">
<div id="play-pause-placeholder"></div>
</div>
</div>
@@ -166,7 +164,7 @@ export const HTMLFragments = {
</div>
<div id="game-players-container">
<label id='players-alive-label'></label>
<div id="spectator-count"></div>
<div id="spectator-count" tabindex="0"></div>
<div id='game-player-list'>
<div class='evil-players'>
<label class='evil'>Team Evil</label>
@@ -206,18 +204,18 @@ export const HTMLFragments = {
<button id='role-info-button' class='app-button'>Roles in This Game <img src='/images/info.svg'/></button>
</div>
</div>
<div id='game-role'>
<div id='game-role' tabindex="0">
<h4 id='role-name'></h4>
<img alt='role' id='role-image'/>
<p id='role-description'></p>
</div>
<div id='game-role-back'>
<div id='game-role-back' tabindex="0">
<h4>Double-click here to show your role</h4>
<p>(Double-click here again to hide)</p>
</div>
<div id='game-people-container'>
<label id='players-alive-label'></label>
<div id="spectator-count"></div>
<div id="spectator-count" tabindex="0"></div>
<div id='game-player-list'></div>
</div>
</div>`,
@@ -280,7 +278,7 @@ export const HTMLFragments = {
<h2>Roles in this game:</h2>
<div id='game-role-info-container'></div>
<div class='modal-button-container'>
<button id='close-role-info-modal-button' class='app-button cancel'>Close</button>
<button id='close-role-info-modal-button' class='app-button cancel' >Close</button>
</div>
</div>`,
END_OF_GAME_VIEW:
@@ -339,7 +337,9 @@ export const HTMLFragments = {
<div id="deck-list"></div>
</div>`,
DECK_SELECT_ROLE:
`<div class="role-name"></div>
`<div class="role-name">
</div>
<div class="role-options">
<img tabindex="0" class="role-include" src="images/add.svg" title="add one" alt="add one"/>
<img tabindex="0" class="role-info" src="images/info.svg" title="info" alt="info"/>

View File

@@ -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);
}
}

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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;