You are here:

NYPL Design Toolkit

Version: 0.1.36

Buttons And Menus

Basic Button

A generic button with an inverted hover state to be used for standard actions.

Example

.nypl-basic-button
  

<button class="nypl-basic-button">Log in</button>

Primary Action Button

A blue-colored button used for request actions.

Example

.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.

Example

.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).

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.

Example
.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.

Example
.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.

Example
.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 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 or nypl-menu-button_right with
  • a nested button of class nypl-menu-button_button, referencing the controlled menu ID via aria-controls, and default aria-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.

Example

.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 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.

Example

.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()
})
}
});