NYPL Design Toolkit
Version: 0.1.36NYPL Design Toolkit
- About This Toolkit
- Buttons And Menus
- Color Accessibility Table
- Color Reference
- Forms
- Layout
- General Microformats
- SVG Index
- Tables And Data
- Visible Focus
Resources
- Landmark roles & Regions
- Skip Links
- Development Checklist
- Glossary
- NYPL User Experience & Visual Design Project Index
- Visible Focus
Examples
- Discovery home
- Discovery search results
- Discovery detail page
- Discovery request page
- Discovery request form
- Discovery request confirmation page
Buttons And Menus
Basic Button
A generic button with an inverted hover state to be used for standard actions.
.nypl-basic-button
<button class="nypl-basic-button">Log in</button>
Primary Action Button
A blue-colored button used for request actions.
.nypl-primary-button
<button class="nypl-primary-button">Request a Button</button>
Buttons With Spinners
For situations where there might be a delay between user submission and server response longer than half a second, it is recommended to add an additional nypl-spinner-button
class to the button. Once the user clicks or taps the button, an additional spinning
class should be activated so that an animation is displayed on the button that indicates the user has to wait for server response. It is also recommended to disable the button so that the user cannot double-click.
Accessibility note: This is a visual-only progressive enhancement recommendation and should not be relied on as the only indicator of state.
.nypl-spinner-button
.spinning
<button class="nypl-basic-button nypl-spinner-button">Click To Activate!</button>
<button class="nypl-primary-button nypl-spinner-button">Click To Activate!</button>
// example jQuery-based activation code
$(".nypl-spinner-button").on("click touchend", function(e) {
var self = $(e.target);
self.toggleClass("spinning");
self.blur();
self.attr("disabled", "true");
setTimeout(function () {
self.toggleClass("spinning")
self.removeAttr("disabled");
}, 2000)
})
Link Button
A link-styled button for situations when you want to clearly differentiate the desired/default action from a secondary action (as displayed in the example).
.nypl-link-button
<button class="nypl-link-button">Cancel</button>
<button class="nypl-basic-button">Submit</button>
Short Buttons
This pattern is for use where the design intent requires a button that is shorter in height than the normal buttons available. In this example we use the Short Button pattern to activate a filter modal.
.nypl-short-button
.nypl-icon
<button class="nypl-short-button" type="button" name="button">
Filter Results
<svg aria-hidden="true" class="nypl-icon" preserveAspectRatio="xMidYMid meet" viewBox="0 0 19 22">
<title>filter.icon.3</title>
<g>
<circle cx="6.65947" cy="2.31986" r="1.31924"/>
<circle cx="13.18733" cy="1.31986" r="1.31895"/>
<circle cx="9.56477" cy="5.46901" r="1.31927"/>
<g>
<path d="M7.74355,22.50683a.95047.95047,0,0,1-.95022-.95022V11.28645L.25259,4.23413A.95041.95041,0,1,1,1.64824,2.94366l7.04554,7.598v11.015A.95047.95047,0,0,1,7.74355,22.50683Z"/>
<path d="M11.60384,19.73881a.95047.95047,0,0,1-.95022-.95022V10.5478l7.126-7.81485a.95047.95047,0,0,1,1.41049,1.27439l-6.636,7.27293v7.50832A.95047.95047,0,0,1,11.60384,19.73881Z"/>
</g>
</g>
</svg>
</button>
Cancel Filter Button
In a scenario where we have filters activated, we need to allow the user to unset each filter. The "x" icon is added inline and uses the nypl-icon
class.
.nypl-unset-filter
.nypl-icon
<button class="nypl-unset-filter">Filter
<svg aria-hidden="true" class="nypl-icon" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32" class="svgIcon">
<title>x.close.icon</title>
<path d="M17.91272,15.97339l5.65689-5.65689A1.32622,1.32622,0,0,0,21.694,8.44093L16.04938,14.0856l-5.65082-5.725A1.32671,1.32671,0,1,0,8.51,10.22454l5.66329,5.73712L8.43038,21.7046a1.32622,1.32622,0,1,0,1.87557,1.87557l5.73088-5.73088,5.65074,5.72441a1.32626,1.32626,0,1,0,1.88852-1.86261Z"/>
</svg>
</button>
Dialog / Modal Close Button
For dialogs and modals a user must have the capablitliy to close the dialog or modal without a submission or state changing action to the page or form. The aria-controls
attribute should be set to reference the id
or appropriate aria-label
of the module it is acting upon.
.nypl-x-close-button
.nypl-icon
<button type="button" name="close" class="nypl-x-close-button">Close
<svg aria-hidden="true" aria-controls="nypl-dialog-or-modal" class="nypl-icon" preserveAspectRatio="xMidYMid meet" viewBox="0 0 100 100" >
<title>x-close-rev</title>
<path d="M82.07922,14.06287a48.0713,48.0713,0,1,0,0,68.01563A48.15148,48.15148,0,0,0,82.07922,14.06287ZM65.06232,60.84845A2.97437,2.97437,0,1,1,60.827,65.0257L48.154,52.18756,35.30133,65.04022a2.97432,2.97432,0,1,1-4.20636-4.2063L43.97473,47.95416,31.27362,35.08746A2.97542,2.97542,0,0,1,35.509,30.90729L48.18213,43.7467,60.84149,31.0874a2.97432,2.97432,0,0,1,4.2063,4.20636L52.36108,47.98047Z"/>
</svg>
</button>
Generic Menu Buttons
Generic menu buttons are used for situations where it is desirable to disclose certain information to the user without requiring a page load (for example a newsletter subscription form). The disclosed information should not be excessive (be reasonable). The elements themselves are:
- The main container, with class of either
nypl-menu-button_left
ornypl-menu-button_right
with - a nested
button
of classnypl-menu-button_button
, referencing the controlled menu ID viaaria-controls
, and defaultaria-expanded
being false, - a nested container of class
nypl-menu-button_menu
which has the contents of the menu itself and with the corresponding controlled ID, also hidden by default and a “menu”role
.
The button contains an nypl-icon
displaying the “down wedge” (
) to indicate that the button in question is a collapsible menu. JavaScript must be used to show/hide the menus; the example uses jQuery.
.nypl-menu-button_right
.nypl-menu-button_left
<div class="nypl-menu-button_right">
<button aria-haspopup="true"
aria-expanded="false"
aria-controls="nypl-menu-button_menu1"
class="nypl-menu-button_button">
Right menu
<svg aria-hidden="true" class="nypl-icon" preserveAspectRatio="xMidYMid meet" viewBox="0 0 68 24"><title>wedge down icon</title><polygon points="67.938 0 34 24 0 0 10 0 34.1 16.4 58.144 0 67.938 0" /></svg>
</button>
<div id="nypl-menu-button_menu1"
class="hidden nypl-menu-button_menu"
role="menu">
This is a container with things inside and it is
<strong>aligned to the right</strong> of the button.
</div>
</div>
<div class="nypl-menu-button_left">
<button aria-haspopup="true"
aria-expanded="false"
aria-controls="nypl-menu-button_menu2"
class="nypl-menu-button_button">
Left menu
<svg aria-hidden="true" class="nypl-icon" preserveAspectRatio="xMidYMid meet" viewBox="0 0 68 24"><title>wedge down icon</title><polygon points="67.938 0 34 24 0 0 10 0 34.1 16.4 58.144 0 67.938 0" /></svg>
</button>
<div id="nypl-menu-button_menu2"
class="hidden nypl-menu-button_menu"
role="menu">
This is a container with things inside and it is
<strong>aligned to the left</strong> of the button.
</div>
</div>
$(".nypl-menu-button_button").on("click touchend", function(e) {
e.preventDefault();
var self = $(e.target);
var parent = self.parent();
var expanded = self.attr("aria-expanded") == "true";
// hide all in page
$(".nypl-menu-button_menu").addClass("hidden")
$(".nypl-menu-button_button").removeClass("active").attr("aria-expanded", "false")
// do for this one
if (!expanded) {
parent.find(".nypl-menu-button_menu").removeClass("hidden")
self.toggleClass("active").attr("aria-expanded", "true")
}
});
Navigation Menu Buttons
Navigation menu buttons are a variant of the Generic Menu Button that display a list of link targets for a user to select from.
The main challenge with Navigation Menu Buttons is the JavaScript involved to make them accessible via keyboard shortcuts. The Navigation Menu Button must conform to the same keyboard shortcuts that control the select
element.
.nypl-navigation-button
<div class="nypl-navigation-button">
<button class="nypl-navigation-button_button"
aria-expanded="false"
aria-controls="nypl-navigation-button_list1"
id="nypl-navigation-button_button">
Search Quick Links
<svg aria-hidden="true" class="nypl-icon" preserveAspectRatio="xMidYMid meet" viewBox="0 0 68 24"><title>wedge down icon</title><polygon points="67.938 0 34 24 0 0 10 0 34.1 16.4 58.144 0 67.938 0" /></svg>
</button>
<ul id="nypl-navigation-button_list1"
class="nypl-navigation-button_list hidden"
role="menu"
aria-labelledby="nypl-navigation-button_button">
<li role="none"><a href="//duckduckgo.com" role="menuitem" tabindex="-1">Duck Duck Go</a></li>
<li role="none"><a href="//google.com" role="menuitem" tabindex="-1">Google</a></li>
<li role="none"><a href="//bing.com" role="menuitem" tabindex="-1">Bing</a></li>
</ul>
</div>
$(".nypl-navigation-button_button").on("click touchend", function(e) {
e.preventDefault();
var selected = 0;
var self = $(e.target);
var parent = self.parent();
var item_count = parent.find("li").length;
var expanded = self.attr("aria-expanded") == "true";
// hide all in page
$(".nypl-navigation-button_list").addClass("hidden")
$(".nypl-navigation-button_button").removeClass("active").attr("aria-expanded", "false")
// do for this one
if (!expanded) {
parent.find(".nypl-navigation-button_list").removeClass("hidden")
self.toggleClass("active").attr("aria-expanded", "true")
// simple and incomplete example keyboard interaction
parent.find("li:first-child a").focus()
parent.on("keydown", function (ee) {
switch (ee.keyCode) {
case 27: // ESC
parent.off("keydown")
parent.find(".nypl-navigation-button_list").addClass("hidden")
self.removeClass("active").attr("aria-expanded", "false").focus()
break
case 32: // SPACE
break
case 38: // UP
ee.preventDefault();
if (selected == 0) {
selected = item_count - 1;
} else {
selected--;
}
break
case 40: // DOWN
ee.preventDefault();
if (selected >= item_count - 1) {
selected = 0;
} else {
selected++;
}
break
}
parent.find("li:nth-child("+(selected+1)+") a").focus()
})
}
});