wcag compliance

This commit is contained in:
Sharon Kennedy 2020-02-14 17:38:20 +01:00
parent 8f9f0fc8b0
commit 08981fd444
8 changed files with 111 additions and 22 deletions

View File

@ -6,15 +6,15 @@
font-family: $theme-font; font-family: $theme-font;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
min-height: 50vh; height: 60vh;
max-height: 100vh;
min-height: 180px;
border: 1px solid $theme-color; border: 1px solid $theme-color;
.message-window { .message-window {
background-color: $light-color; background-color: $light-color;
flex: 1 0 auto; flex: 1 1 auto;
padding: 0.5rem; padding: 0.5rem;
height: 300px;
max-height: 100%;
overflow: auto; overflow: auto;
display: flex; display: flex;
flex-direction: column-reverse; flex-direction: column-reverse;
@ -37,6 +37,7 @@
margin-top: 0.5rem; margin-top: 0.5rem;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
width: fit-content; width: fit-content;
border: 1px solid $theme-color;
} }
&.from-me { &.from-me {
@ -58,7 +59,6 @@
.text { .text {
background-color: $white; background-color: $white;
color: $dark-color; color: $dark-color;
border: 1px solid $theme-color;
border-radius: 15px 15px 15px 0; border-radius: 15px 15px 15px 0;
margin-right: 10%; margin-right: 10%;
} }
@ -101,4 +101,5 @@
cursor: pointer; cursor: pointer;
} }
} }
} }

View File

@ -0,0 +1,61 @@
@media (prefers-color-scheme: dark) {
.dock {
background: $dark-theme-color;
}
.loader {
color: $dark-theme-color;
}
#ocrcc-chatbox {
border: 1px solid $dark-theme-color;
.widget-header {
background-color: $dark-theme-color;
}
.message-window {
background-color: $dark-background-color;
}
.notices {
color: transparentize($light-text-color, 0.3);
}
.message {
.text {
border: 1px solid $light-text-color;
}
&.from-me {
.text {
background-color: $light-background-color;
color: $dark-text-color;
}
}
&.from-support {
.text {
background-color: $dark-theme-color;
color: $light-text-color;
}
}
}
.input-window {
form {
border-top: 1px solid $dark-theme-color;
}
input[type="text"] {
background-color: $light-background-color;
color: $dark-text-color;
}
input[type="submit"] {
background-color: $dark-theme-color;
color: $light-text-color;
}
}
}
}

View File

@ -10,7 +10,7 @@
animation: load7 1.8s infinite ease-in-out; animation: load7 1.8s infinite ease-in-out;
} }
.loader { .loader {
color: $teal; /*purple*/ color: $theme-color;
font-size: 10px; font-size: 10px;
margin: 1rem auto; margin: 1rem auto;
margin-bottom: 2rem; margin-bottom: 2rem;

View File

@ -1,8 +1,16 @@
$light-color: #FFF8F0; $light-color: #f6faff;
$dark-color: #22333B; $dark-color: #04090F;
$yellow: #FFFACD; $yellow: #FFFACD;
$teal: #008080; $dark-blue: #2660A4;
$white: #ffffff; $white: #ffffff;
$highlight-color: $yellow; $highlight-color: $yellow;
$theme-color: $teal; $theme-color: $dark-blue;
$theme-font: 'Assistant', 'Helvetica', sans-serif; $theme-font: 'Assistant', 'Helvetica', sans-serif;
/* Dark mode colors */
$dark-background-color: #0F1116;
$light-background-color: #ffffff;
$light-text-color: #ffffff;
$dark-text-color: #0F1116;
$dark-theme-color: #333C4B;

View File

@ -1,6 +1,4 @@
@import "variables";
@import "loader";
@import "chat";
@keyframes slideInUp { @keyframes slideInUp {
from { from {

View File

@ -179,6 +179,13 @@ class ChatBox extends React.Component {
this.setState({ messages }) this.setState({ messages })
} }
handleEscape = (e) => {
if (e.keyCode === 27 && this.props.opened) {
this.props.handleToggleOpen()
}
}
componentDidUpdate(prevProps, prevState) { componentDidUpdate(prevProps, prevState) {
if (prevState.client !== this.state.client) { if (prevState.client !== this.state.client) {
this.createRoom() this.createRoom()
@ -231,7 +238,12 @@ class ChatBox extends React.Component {
} }
} }
componentDidMount() {
document.addEventListener("keydown", this.handleEscape, false);
}
componentWillUnmount() { componentWillUnmount() {
document.removeEventListener("keydown", this.handleEscape, false);
this.leaveRoom(); this.leaveRoom();
} }
@ -253,12 +265,13 @@ class ChatBox extends React.Component {
render() { render() {
const { ready, messages, inputValue, userId, isRoomEncrypted } = this.state; const { ready, messages, inputValue, userId, isRoomEncrypted } = this.state;
const { opened, handleToggleOpen } = this.props; const { opened, handleToggleOpen } = this.props;
const inputLabel = 'Send a message...'
return ( return (
<div id="ocrcc-chatbox"> <div id="ocrcc-chatbox" aria-haspopup="dialog" aria-label="Open support chat">
<div className="widget-header"> <div className="widget-header">
<div className="widget-header-title"> <div className="widget-header-title">
{ isRoomEncrypted && <span>🔒</span> } Support Chat Support Chat
</div> </div>
<button <button
type="button" type="button"
@ -284,7 +297,7 @@ class ChatBox extends React.Component {
</div> </div>
<div className="notices"> <div className="notices">
{ {
isRoomEncrypted && <div>Messages in this chat are secured with end-to-end encryption.</div> isRoomEncrypted && <div role="status">Messages in this chat are secured with end-to-end encryption.</div>
} }
</div> </div>
</div> </div>
@ -294,6 +307,8 @@ class ChatBox extends React.Component {
type="text" type="text"
onChange={this.handleInputChange} onChange={this.handleInputChange}
value={inputValue} value={inputValue}
aria-label={inputLabel}
placeholder={inputLabel}
autoFocus={true} autoFocus={true}
ref={this.chatboxInput} ref={this.chatboxInput}
/> />

View File

@ -0,0 +1,5 @@
@import "variables";
@import "loader";
@import "widget";
@import "chat";
@import "dark_mode";

View File

@ -1,7 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Transition } from 'react-transition-group'; import { Transition } from 'react-transition-group';
import Chatbox from './chatbox'; import Chatbox from './chatbox';
import './widget.scss'; import './styles.scss';
class Widget extends Component { class Widget extends Component {
constructor(props) { constructor(props) {
@ -36,10 +36,10 @@ class Widget extends Component {
const { opened, showDock } = this.state; const { opened, showDock } = this.state;
return ( return (
<div className="docked-widget"> <div className="docked-widget" role="complementary">
<Transition in={opened} timeout={250} onExited={this.handleWidgetExit}> <Transition in={opened} timeout={250} onExited={this.handleWidgetExit}>
{(status) => ( {(status) => (
<div className={`widget widget-${status}`}> <div className={`widget widget-${status}`} aria-hidden={!opened}>
<Chatbox <Chatbox
handleToggleOpen={this.handleToggleOpen} handleToggleOpen={this.handleToggleOpen}
opened={opened} opened={opened}
@ -55,9 +55,10 @@ class Widget extends Component {
className="dock" className="dock"
onClick={this.handleToggleOpen} onClick={this.handleToggleOpen}
onKeyPress={this.handleToggleOpen} onKeyPress={this.handleToggleOpen}
aria-labelledby="open-chatbox-label"
> >
<span>Open support chat</span> <span id="open-chatbox-label">Open support chat</span>
<span className={`arrow ${opened ? 'opened' : 'closed'}`}></span> <span className={`arrow ${opened ? 'opened' : 'closed'}`} aria-label={`${opened ? 'Close' : 'Open'} support chat window`}></span>
</button> </button>
)} )}
</div> </div>