Better responsive sidebar

Also fix a i18n missing string and add some `role` attributes for
accessibility.
This commit is contained in:
Lucas Verney 2016-08-01 12:01:11 +02:00
parent 40f6223bd0
commit 2b3207ec44
14 changed files with 95 additions and 40 deletions

View File

@ -130,7 +130,7 @@ export function loginUser(username, passwordOrToken, endpoint, rememberMe, redir
// Remember me connection
if (passwordOrToken.expires < new Date()) {
// Token has expired
return loginUserFailure("Your session expired… =(");
return loginUserFailure("app.login.expired");
}
time = Math.floor(Date.now() / 1000);
passphrase = passwordOrToken.token;

View File

@ -77,7 +77,7 @@ class LoginFormCSSIntl extends Component {
{
this.props.error ?
<div className="row">
<div className="alert alert-danger" id="loginFormError">
<div className="alert alert-danger" id="loginFormError" role="alert">
<p>
<span className="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> { errorMessage }
</p>
@ -88,7 +88,7 @@ class LoginFormCSSIntl extends Component {
{
this.props.info ?
<div className="row">
<div className="alert alert-info" id="loginFormInfo">
<div className="alert alert-info" id="loginFormInfo" role="alert">
<p>{ infoMessage }</p>
</div>
</div>

View File

@ -29,7 +29,7 @@ class FilterBarCSSIntl extends Component {
<FormattedMessage {...filterMessages["app.filter.whatAreWeListeningToToday"]} />
</p>
<div className="col-xs-12 col-sm-6 col-md-4 input-group">
<form className="form-inline" onSubmit={this.handleChange} aria-describedby="filterInputDescription">
<form className="form-inline" onSubmit={this.handleChange} aria-describedby="filterInputDescription" role="search">
<div className="form-group" styleName="form-group">
<input type="text" className="form-control" placeholder={formatMessage(filterMessages["app.filter.filter"])} aria-label={formatMessage(filterMessages["app.filter.filter"])} value={this.props.filterText} onChange={this.handleChange} ref="filterTextInput" />
</div>

View File

@ -68,7 +68,7 @@ class PaginationCSSIntl extends Component {
// Push first page
pagesButton.push(
<li className="page-item" key={key}>
<Link className="page-link" title={formatMessage(paginationMessages["app.pagination.goToPageWithoutMarkup"], { pageNumber: 1})} to={this.props.buildLinkToPage(1)}>
<Link role="button" className="page-link" title={formatMessage(paginationMessages["app.pagination.goToPageWithoutMarkup"], { pageNumber: 1})} to={this.props.buildLinkToPage(1)}>
<FormattedHTMLMessage {...paginationMessages["app.pagination.goToPage"]} values={{ pageNumber: 1 }} />
</Link>
</li>
@ -95,7 +95,7 @@ class PaginationCSSIntl extends Component {
const title = formatMessage(paginationMessages["app.pagination.goToPageWithoutMarkup"], { pageNumber: i });
pagesButton.push(
<li className={className} key={key}>
<Link className="page-link" title={title} to={this.props.buildLinkToPage(i)}>
<Link role="button" className="page-link" title={title} to={this.props.buildLinkToPage(i)}>
<FormattedHTMLMessage {...paginationMessages["app.pagination.goToPage"]} values={{ pageNumber: i }} />
{currentSpan}
</Link>
@ -117,7 +117,7 @@ class PaginationCSSIntl extends Component {
// Push last page
pagesButton.push(
<li className="page-item" key={key}>
<Link className="page-link" title={title} to={this.props.buildLinkToPage(this.props.nPages)}>
<Link role="button" className="page-link" title={title} to={this.props.buildLinkToPage(this.props.nPages)}>
<FormattedHTMLMessage {...paginationMessages["app.pagination.goToPage"]} values={{ pageNumber: this.props.nPages }} />
</Link>
</li>
@ -126,8 +126,8 @@ class PaginationCSSIntl extends Component {
if (pagesButton.length > 1) {
return (
<div>
<nav className="pagination-nav" styleName="nav" aria-label={formatMessage(paginationMessages["app.pagination.pageNavigation"])}>
<ul className="pagination" styleName="pointer">
<nav className="pagination-nav" styleName="nav" aria-label={formatMessage(paginationMessages["app.pagination.pageNavigation"])} role="navigation" >
<ul className="pagination" styleName="pointer" role="group">
{ pagesButton }
</ul>
</nav>

View File

@ -25,13 +25,21 @@ class SidebarLayoutIntl extends Component {
return (
<div>
<div className="col-xs-12 col-md-1 col-lg-2" styleName="sidebar">
<button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#main-navbar" aria-expanded="false" styleName="toggle">
<span className="sr-only">
<FormattedMessage {...sidebarLayoutMessages["app.sidebarLayout.toggleNavigation"]} />
</span>
<span className="icon-bar" styleName="icon-bar"></span>
<span className="icon-bar" styleName="icon-bar"></span>
<span className="icon-bar" styleName="icon-bar"></span>
</button>
<h1 className="text-center" styleName="title">
<IndexLink to="/" styleName="link">
<img alt="A" src="./app/assets/img/ampache-blue.png" styleName="imgTitle" />
<span className="hidden-md">mpache</span>
</IndexLink>
</h1>
<nav aria-label={formatMessage(sidebarLayoutMessages["app.sidebarLayout.mainNavigationMenu"])}>
<nav className="collapse" styleName="collapse" aria-label={formatMessage(sidebarLayoutMessages["app.sidebarLayout.mainNavigationMenu"])} id="main-navbar" role="navigation">
<div className="navbar text-center" styleName="icon-navbar">
<div className="container-fluid" styleName="container-fluid">
<ul className="nav navbar-nav" styleName="nav">

File diff suppressed because one or more lines are too long

48
app/dist/index.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
app/dist/style.css vendored

File diff suppressed because one or more lines are too long

View File

@ -38,6 +38,7 @@ module.exports = {
"app.sidebarLayout.mainNavigationMenu": "Main navigation menu", // ARIA label for the main navigation menu
"app.sidebarLayout.search": "Search", // Search
"app.sidebarLayout.settings": "Settings", // Settings
"app.sidebarLayout.toggleNavigation": "Toggle navigation", // Screen reader description of toggle navigation button
"app.songs.genre": "Genre", // Genre (song)
"app.songs.length": "Length", // Length (song)
"app.songs.title": "Title", // Title (song)

View File

@ -38,6 +38,7 @@ module.exports = {
"app.sidebarLayout.mainNavigationMenu": "Menu principal", // ARIA label for the main navigation menu
"app.sidebarLayout.search": "Rechercher", // Search
"app.sidebarLayout.settings": "Préférences", // Settings
"app.sidebarLayout.toggleNavigation": "Afficher le menu", // Screen reader description of toggle navigation button
"app.songs.genre": "Genre", // Genre (song)
"app.songs.length": "Durée", // Length (song)
"app.songs.title": "Titre", // Title (song)

View File

@ -48,6 +48,11 @@ const messages = [
id: "app.sidebarLayout.search",
description: "Search",
defaultMessage: "Search"
},
{
id: "app.sidebarLayout.toggleNavigation",
description: "Screen reader description of toggle navigation button",
defaultMessage: "Toggle navigation"
}
];

View File

@ -35,7 +35,7 @@ function _parseToJSON (responseText) {
function _checkAPIErrors (jsonData) {
if (jsonData.error) {
return Promise.reject(jsonData.error.cdata + " (" + jsonData.error.code + ")");
return Promise.reject(jsonData.error.__cdata + " (" + jsonData.error.code + ")");
} else if (!jsonData) {
// No data returned
return Promise.reject(new i18nRecord({

View File

@ -15,12 +15,15 @@ $condensedNavPadding: 5px;
left: 0;
z-index: 1000;
display: block;
padding: 20px;
padding: $mainPadding;
overflow-x: hidden;
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
background-color: $background;
color: white;
border-right: 1px solid $lightgrey;
}
.collapse {
display: block;
}
/* Sidebar elements */
@ -59,6 +62,14 @@ $condensedNavPadding: 5px;
}
/* Sidebar navigation */
button.toggle {
background-color: $foreground;
}
.icon-bar {
background-color: $background;
}
.icon-navbar {
background-color: #555;
font-size: 1.2em;
@ -86,6 +97,7 @@ $condensedNavPadding: 5px;
*/
.main-panel {
padding: $mainPadding;
z-index: -10;
}
/*
@ -118,4 +130,32 @@ $condensedNavPadding: 5px;
.sidebar {
position: static;
}
.title {
float: left;
margin-bottom: 0;
}
button.toggle {
display: block;
margin-top: 0;
margin-bottom: 0;
}
.collapse {
clear: both;
}
}
:global {
@media (max-width: 991px) {
.collapse {
display: none;
padding-top: $titleMarginBottom;
}
.collapsing {
padding-top: $titleMarginBottom;
}
}
}