Merge pull request #3835 from KDSBrowne/accessibility-05-update
[HTML5] - Accessibility update 05
This commit is contained in:
commit
835acfa195
@ -40,7 +40,7 @@ class Chat extends Component {
|
|||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={styles.chat}>
|
<div className={styles.chat}>
|
||||||
|
|
||||||
<header className={styles.header}>
|
<header className={styles.header}>
|
||||||
<div className={styles.title}>
|
<div className={styles.title}>
|
||||||
@ -83,7 +83,7 @@ class Chat extends Component {
|
|||||||
chatName={chatName}
|
chatName={chatName}
|
||||||
handleSendMessage={actions.handleSendMessage}
|
handleSendMessage={actions.handleSendMessage}
|
||||||
/>
|
/>
|
||||||
</section>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,10 @@ const intlMessages = defineMessages({
|
|||||||
id: 'app.chat.moreMessages',
|
id: 'app.chat.moreMessages',
|
||||||
description: 'Chat message when the user has unread messages below the scroll',
|
description: 'Chat message when the user has unread messages below the scroll',
|
||||||
},
|
},
|
||||||
|
emptyLogLabel: {
|
||||||
|
id: 'app.chat.emptyLogLabel',
|
||||||
|
description: 'aria-label used when chat log is empty',
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
class MessageList extends Component {
|
class MessageList extends Component {
|
||||||
@ -132,19 +136,20 @@ class MessageList extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { messages } = this.props;
|
const { messages, intl } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.messageListWrapper}>
|
<div className={styles.messageListWrapper}>
|
||||||
<div
|
<div
|
||||||
tabIndex="0"
|
|
||||||
role="log"
|
role="log"
|
||||||
aria-atomic="false"
|
tabIndex="0"
|
||||||
aria-live="polite"
|
|
||||||
aria-relevant="additions"
|
|
||||||
ref="scrollArea"
|
ref="scrollArea"
|
||||||
className={styles.messageList}
|
|
||||||
id={this.props.id}
|
id={this.props.id}
|
||||||
|
className={styles.messageList}
|
||||||
|
aria-live="polite"
|
||||||
|
aria-atomic="false"
|
||||||
|
aria-relevant="additions"
|
||||||
|
aria-label={intl.formatMessage(intlMessages.emptyLogLabel)}
|
||||||
>
|
>
|
||||||
{messages.map((message) => (
|
{messages.map((message) => (
|
||||||
<MessageListItem
|
<MessageListItem
|
||||||
|
4
bigbluebutton-html5/imports/ui/components/dropdown/list/styles.scss
Normal file → Executable file
4
bigbluebutton-html5/imports/ui/components/dropdown/list/styles.scss
Normal file → Executable file
@ -17,6 +17,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: $color-gray;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
.separator {
|
.separator {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
22
bigbluebutton-html5/imports/ui/components/dropdown/list/title/component.jsx
Executable file
22
bigbluebutton-html5/imports/ui/components/dropdown/list/title/component.jsx
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
import styles from '../styles';
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
description: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class DropdownListTitle extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { intl, description } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<li className={styles.title} aria-describedby="labelContext">{this.props.children}</li>
|
||||||
|
<div id="labelContext" aria-label={description}></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DropdownListTitle.propTypes = propTypes;
|
@ -15,7 +15,8 @@ import DropdownContent from '/imports/ui/components/dropdown/content/component';
|
|||||||
import DropdownList from '/imports/ui/components/dropdown/list/component';
|
import DropdownList from '/imports/ui/components/dropdown/list/component';
|
||||||
import DropdownListItem from '/imports/ui/components/dropdown/list/item/component';
|
import DropdownListItem from '/imports/ui/components/dropdown/list/item/component';
|
||||||
import DropdownListSeparator from '/imports/ui/components/dropdown/list/separator/component';
|
import DropdownListSeparator from '/imports/ui/components/dropdown/list/separator/component';
|
||||||
|
import DropdownListTitle from '/imports/ui/components/dropdown/list/title/component';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
user: React.PropTypes.shape({
|
user: React.PropTypes.shape({
|
||||||
name: React.PropTypes.string.isRequired,
|
name: React.PropTypes.string.isRequired,
|
||||||
@ -45,6 +46,10 @@ const messages = defineMessages({
|
|||||||
id: 'app.userlist.you',
|
id: 'app.userlist.you',
|
||||||
description: 'Text for identifying your user',
|
description: 'Text for identifying your user',
|
||||||
},
|
},
|
||||||
|
menuTitleContext: {
|
||||||
|
id: 'app.userlist.menuTitleContext',
|
||||||
|
description: 'adds context to userListItem menu title',
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const userActionsTransition = {
|
const userActionsTransition = {
|
||||||
@ -163,7 +168,7 @@ class UserListItem extends Component {
|
|||||||
if (!isDropdownVisible) {
|
if (!isDropdownVisible) {
|
||||||
const offsetPageTop =
|
const offsetPageTop =
|
||||||
(dropdownTrigger.offsetTop + dropdownTrigger.offsetHeight - scrollContainer.scrollTop);
|
(dropdownTrigger.offsetTop + dropdownTrigger.offsetHeight - scrollContainer.scrollTop);
|
||||||
|
|
||||||
nextState.dropdownOffset = window.innerHeight - offsetPageTop;
|
nextState.dropdownOffset = window.innerHeight - offsetPageTop;
|
||||||
nextState.dropdownDirection = 'bottom';
|
nextState.dropdownDirection = 'bottom';
|
||||||
}
|
}
|
||||||
@ -174,7 +179,7 @@ class UserListItem extends Component {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the dropdown is visible and is opened by the user
|
* Check if the dropdown is visible and is opened by the user
|
||||||
*
|
*
|
||||||
* @return True if is visible and opened by the user.
|
* @return True if is visible and opened by the user.
|
||||||
*/
|
*/
|
||||||
isDropdownActivedByUser() {
|
isDropdownActivedByUser() {
|
||||||
@ -184,8 +189,8 @@ class UserListItem extends Component {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the content fit on the screen, false otherwise.
|
* Return true if the content fit on the screen, false otherwise.
|
||||||
*
|
*
|
||||||
* @param {number} contentOffSetTop
|
* @param {number} contentOffSetTop
|
||||||
* @param {number} contentOffsetHeight
|
* @param {number} contentOffsetHeight
|
||||||
* @return True if the content fit on the screen, false otherwise.
|
* @return True if the content fit on the screen, false otherwise.
|
||||||
*/
|
*/
|
||||||
@ -230,7 +235,9 @@ class UserListItem extends Component {
|
|||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
role="button"
|
role="button"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
|
aria-live="assertive"
|
||||||
|
aria-relevant="additions"
|
||||||
className={cx(styles.userListItem, userItemContentsStyle)}>
|
className={cx(styles.userListItem, userItemContentsStyle)}>
|
||||||
{this.renderUserContents()}
|
{this.renderUserContents()}
|
||||||
</li>
|
</li>
|
||||||
@ -240,6 +247,7 @@ class UserListItem extends Component {
|
|||||||
renderUserContents() {
|
renderUserContents() {
|
||||||
const {
|
const {
|
||||||
user,
|
user,
|
||||||
|
intl,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
let actions = this.getAvailableActions();
|
let actions = this.getAvailableActions();
|
||||||
@ -277,13 +285,11 @@ class UserListItem extends Component {
|
|||||||
|
|
||||||
<DropdownList>
|
<DropdownList>
|
||||||
{
|
{
|
||||||
[
|
[
|
||||||
(<DropdownListItem
|
(<DropdownListTitle
|
||||||
className={styles.actionsHeader}
|
description={intl.formatMessage(messages.menuTitleContext)}>
|
||||||
key={_.uniqueId('action-header')}
|
{user.name}
|
||||||
label={user.name}
|
</DropdownListTitle>),
|
||||||
style={{ fontWeight: 600 }}
|
|
||||||
defaultMessage={user.name} />),
|
|
||||||
(<DropdownListSeparator key={_.uniqueId('action-separator')} />),
|
(<DropdownListSeparator key={_.uniqueId('action-separator')} />),
|
||||||
].concat(actions)
|
].concat(actions)
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,11 @@
|
|||||||
"app.chat.closeChatLabel": "Close {title}",
|
"app.chat.closeChatLabel": "Close {title}",
|
||||||
"app.chat.hideChatLabel": "Hide {title}",
|
"app.chat.hideChatLabel": "Hide {title}",
|
||||||
"app.chat.moreMessages": "More messages below",
|
"app.chat.moreMessages": "More messages below",
|
||||||
|
"app.userlist.menuTitleContext": "available options",
|
||||||
"app.userlist.chatlistitem.unreadSingular": "{count} New Message",
|
"app.userlist.chatlistitem.unreadSingular": "{count} New Message",
|
||||||
"app.userlist.chatlistitem.unreadPlural": "{count} New Messages",
|
"app.userlist.chatlistitem.unreadPlural": "{count} New Messages",
|
||||||
"app.chat.Label": "Chat",
|
"app.chat.Label": "Chat",
|
||||||
|
"app.chat.emptyLogLabel": "Chat log empty",
|
||||||
"app.media.Label": "Media",
|
"app.media.Label": "Media",
|
||||||
"app.presentation.presentationToolbar.prevSlideLabel": "Previous slide",
|
"app.presentation.presentationToolbar.prevSlideLabel": "Previous slide",
|
||||||
"app.presentation.presentationToolbar.prevSlideDescrip": "Change the presentation to the previous slide",
|
"app.presentation.presentationToolbar.prevSlideDescrip": "Change the presentation to the previous slide",
|
||||||
|
Loading…
Reference in New Issue
Block a user