Skip to content

Commit

Permalink
Added keyboard accessibility to toolbar toggle - Fixes #47
Browse files Browse the repository at this point in the history
Reviewed by: michelle, riley
  • Loading branch information
jdan committed Sep 27, 2015
1 parent a55c4b6 commit 861574e
Show file tree
Hide file tree
Showing 11 changed files with 186 additions and 142 deletions.
8 changes: 8 additions & 0 deletions element.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ function buildElement(type, props, ...children) {
if (propName === "onClick") {
let handler = props[propName];
$el.click(handler);

// Some passed-in props need to be set with $.attr
// Currently we do this for role and aria-*
} else if (/^aria-/.test(propName) || propName === "role") {
let value = props[propName];
$el.attr(propName, value);

// All other props can go right to $.prop
} else {
let value = props[propName];
$el.prop(propName, value);
Expand Down
16 changes: 10 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,20 +82,24 @@ class Toolbar {
e.preventDefault();
e.stopPropagation();
$toolbar.toggleClass("tota11y-expanded");
$toolbar.attr("aria-expanded", $toolbar.is(".tota11y-expanded"));
};

let $toggle = (
<a href="#"
className="tota11y-toolbar-toggle"
onClick={handleToggleClick}>
<div className="tota11y-toolbar-logo">
<button aria-controls="tota11y-toolbar"
className="tota11y-toolbar-toggle"
onClick={handleToggleClick}
aria-label="[tota11y] Toggle menu">
<div aria-hidden="true" className="tota11y-toolbar-logo">
{$logo}
</div>
</a>
</button>
);

$toolbar = (
<div className="tota11y tota11y-toolbar">
<div id="tota11y-toolbar" className="tota11y tota11y-toolbar"
role="region"
aria-expanded="false">
<div className="tota11y-toolbar-body">
{$plugins}
</div>
Expand Down
74 changes: 11 additions & 63 deletions less/tota11y.less
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
@import "variables.less";
@import "base.less";

@descriptionWidth: 200px;
@pluginPadding: 12px;
@controlMargin: 15px;
@indicatorSize: 16px;
@indicatorFontSize: 13px;

@togglePadding: 7px;
@toggleCollapsedWidth: 35px;
@toggleHeight: 25px;
Expand All @@ -21,8 +15,10 @@
z-index: @z-index--UI;

&-toggle {
background-color: @darkGray;
display: block;
padding: @togglePadding;
width: 100%;
}

&-logo {
Expand All @@ -44,61 +40,13 @@
}
}

.tota11y-plugins {
&-separator {
font-size: 12px;
margin: @togglePadding @controlMargin 0;
text-transform: uppercase;
}
}

.tota11y-plugin {
.tota11y-no-select;
border-bottom: 1px solid @darkBorderColor;

&-label {
align-items: center;
display: flex;
padding: @pluginPadding @pluginPadding @pluginPadding 0;
margin: 0;

&:hover {
cursor: pointer;
}
}

&-control {
margin: 0 @controlMargin;
}

&-checkbox {
display: none;
}

&-indicator {
border-radius: @indicatorSize;
border: 1px solid @lightBorderColor;
color: transparent;
font-size: @indicatorFontSize;
height: @indicatorSize;
line-height: @indicatorSize;
padding: 0 0 0 1px;
width: @indicatorSize;
}
&-checkbox:checked + &-indicator {
background-color: @kaGreen;
border-color: @kaGreen;
color: white;
}

&-title {
font-weight: bold;
}

&-description {
font-size: @fontSizeSmall;
font-style: italic;
width: @descriptionWidth;
margin-right: 3px;
}
.tota11y-sr-only {
border: 0;
clip: rect(0,0,0,0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
57 changes: 36 additions & 21 deletions plugins/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
* cleanup: code to run when the plugin is deactivated from the toolbar
*/

let $ = require("jquery");
let InfoPanel = require("./shared/info-panel");
let template = require("../templates/plugin.handlebars");

require("./style.less");

class Plugin {
constructor() {
this.panel = new InfoPanel(this.getTitle());
this.panel = new InfoPanel(this);
this.$checkbox = null;
}

Expand Down Expand Up @@ -51,20 +51,38 @@ class Plugin {
* Renders the plugin view.
*/
render(clickHandler) {
let templateData = {
title: this.getTitle(),
description: this.getDescription()
};

let $plugin = $(template(templateData));

this.$checkbox = $plugin.find(".tota11y-plugin-checkbox");
this.$checkbox.click((e) => {
e.stopPropagation();
clickHandler(this);
});

return $plugin;
this.$checkbox = (
<input
className="tota11y-plugin-checkbox tota11y-sr-only"
type="checkbox"
onClick={() => clickHandler(this)} />
);

let $switch = (
<label className="tota11y-plugin-switch">
{this.$checkbox}
<div aria-hidden="true"
className="tota11y-plugin-indicator">
&#x2713;
</div>
<div className="tota11y-plugin-info">
<div className="tota11y-plugin-title">
{this.getTitle()}
</div>
<div className="tota11y-plugin-description">
{this.getDescription()}
</div>
</div>
</label>
);

let $el = (
<li role="menu-item" className="tota11y-plugin">
{$switch}
</li>
);

return $el;
}

/**
Expand All @@ -82,10 +100,7 @@ class Plugin {
this.cleanup();
this.panel.destroy();

// If we toggle the plugin ourselves, the checkbox will already be
// unchecked. If another plugin becomes active, however, this method
// will be called and will uncheck the checkbox.
this.$checkbox.attr("checked", false);
this.$checkbox.prop("checked", false);
}
}

Expand Down
5 changes: 4 additions & 1 deletion plugins/headings/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ class HeadingsPlugin extends Plugin {
}

getDescription() {
return "Highlights headings (<h1>, <h2>, etc) and order violations";
return `
Highlights headings (&lt;h1&gt;, &lt;h2&gt;, etc) and
order violations
`;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion plugins/shared/info-panel/error.handlebars
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<li class="tota11y-info-error">
<a href="#" class="tota11y-info-error-scroll">
<a aria-label="Scroll to error" href="#" class="tota11y-info-error-scroll">
<div class="tota11y-info-error-scroll-glyph tota11y-info-error-scroll-lens"></div>
<div class="tota11y-info-error-scroll-glyph tota11y-info-error-scroll-handle"></div>
</a>
Expand Down
60 changes: 45 additions & 15 deletions plugins/shared/info-panel/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,24 @@
let $ = require("jquery");
let annotate = require("../annotate")("info-panel");

let template = require("./template.handlebars");
let errorTemplate = require("./error.handlebars");
let tabTemplate = require("./tab.handlebars");
require("./style.less");

const INITIAL_PANEL_MARGIN_PX = 10;
const COLLAPSED_CLASS_NAME = "tota11y-collapsed";
const HIDDEN_CLASS_NAME = "tota11y-info-hidden";

class InfoPanel {
constructor(title) {
this.title = title;
constructor(plugin) {
this.plugin = plugin;

this.about = null;
this.summary = null;
this.errors = [];

this.$el = null;
}

/**
* Sets the title of the info panel
*/
setTitle(title) {
this.title = title;
}

/**
* Sets the contents of the about section as HTML
*/
Expand All @@ -69,7 +61,16 @@ class InfoPanel {

_addTab(title, html) {
// Create and append a tab marker
let $tab = $(tabTemplate({title}));
let $tab = (
<li className="tota11y-info-tab">
<a className="tota11y-info-tab-anchor" href="#">
<span className="tota11y-info-tab-anchor-text">
{title}
</span>
</a>
</li>
);

this.$el.find(".tota11y-info-tabs").append($tab);

// Create and append the tab content
Expand Down Expand Up @@ -113,6 +114,9 @@ class InfoPanel {
e.preventDefault();
e.stopPropagation();
this.$el.addClass(HIDDEN_CLASS_NAME);

// (a11y) Bring the focus back to the plugin's checkbox
this.plugin.$checkbox.focus();
});

// Append the info panel to the body. In reality we'll likely want
Expand Down Expand Up @@ -183,9 +187,32 @@ class InfoPanel {

let hasContent = false;

this.$el = $(template({
title: this.title,
}));
this.$el = (
<div className="tota11y tota11y-info" tabindex="-1">
<header className="tota11y-info-title">
{this.plugin.getTitle()}
<span className="tota11y-info-controls">
<label className="tota11y-info-annotation-toggle">
Annotate:
{" "}
<input
className="toggle-annotation"
type="checkbox"
checked="checked" />
</label>
<a aria-label="Close info panel"
href="#"
className="tota11y-info-dismiss-trigger">
&times;
</a>
</span>
</header>
<div className="tota11y-info-body">
<div className="tota11y-info-sections" />
<ul role="tablist" className="tota11y-info-tabs" />
</div>
</div>
);

// Add the appropriate tabs based on which information the info panel
// was provided, then highlight the most important one.
Expand Down Expand Up @@ -319,6 +346,9 @@ class InfoPanel {
this.initAndPosition();
}

// (a11y) Shift focus to the newly-opened info panel
this.$el.focus();

return this.$el;
}

Expand Down
5 changes: 0 additions & 5 deletions plugins/shared/info-panel/tab.handlebars

This file was deleted.

18 changes: 0 additions & 18 deletions plugins/shared/info-panel/template.handlebars

This file was deleted.

Loading

0 comments on commit 861574e

Please sign in to comment.