diff --git a/dist/demo/demo.html b/dist/demo/demo.html index cb3050f..ce90b68 100644 --- a/dist/demo/demo.html +++ b/dist/demo/demo.html @@ -11,7 +11,7 @@
Front-end stack, CLI, and cross-utility library for design systems. Created by NYC Opportunity for NYCO Patterns, ACCESS NYC Patterns, and Growing Up/Generation NYC Patterns.
diff --git a/dist/toggle.html b/dist/toggle.html index a292ce3..d96c1ea 100644 --- a/dist/toggle.html +++ b/dist/toggle.html @@ -11,7 +11,7 @@The Toggle utility uses JavaScript to expand and collapse elements based on user interaction. This will toggle dynamic aria attributes as well as dynamic classes on both the toggling element and target of the toggle. The class “hidden” will be toggled on the target element and the class “active” will be toggled on the toggling element and target element. The target is selected using the static aria-controls
attribute by its id
.
Elements should have the hidden or active state set before initialization.
+Elements must have the hidden or active state classes and attributes set before initialization.
Hidden
@@ -30,7 +30,7 @@Active @@ -40,24 +40,18 @@
The use of the dynamic aria-expanded
attribute on the toggling element is recommended for toggling elements as it will announce that the target of the toggle is “expanded” or “collapsed.” Optionally, the attribute aria-pressed
can be used instead to announce that the toggle button is “pressed” or “not pressed”. These attributes provide different feedback to screenreaders and are appropriate for different component types. aria-expanded
would be used for patterns such as
collapsible sections
and aria-pressed
would be used for
toggle buttons
or switches. A full list of dynamic and static attributes is described below.
Placement of the target should follow the toggling element so that it appears next in order on the page for screen readers. For targets that are far apart or appear in a different section of the page, the Anchor Toggle may be more appropriate.
-Elements that have aria-hidden set to true
should not contain focusable elements. Setting their tabindex to -1
will prevent them from being focused on. For convenience, child elements in the target element that have their tabindex
set will be toggled.
<button aria-controls="toggle-target" aria-expanded="false" data-js="toggle" type="button">
- Toggle
-</button>
-
-<div aria-hidden="true" class="hidden" id="toggle-target">
- <p>Targeted Toggle Element</p>
-
- <a href='#' tabindex="-1">A Focusable Child Element</a>
-</div>
+ Placement of the target should follow the toggling element so that it appears next in order on the page for screen readers. For targets that are far apart or appear in a different section of the page, the Anchor Toggle may be more appropriate as it will shift focus to the target.
+Elements that have aria-hidden set to true
should not contain focusable elements. Setting their tabindex to -1
will prevent them from being focused on. For convenience, child elements in the target element will have their tabindex
toggled. Refer to the full list of potentially focusable elements below that will be toggled.
The Toggle Utility supports having more than one toggle element per toggle target. An example use case is for “close” buttons within dialogue elements.
<button aria-controls="toggle-target" aria-expanded="false" data-js="toggle" type="button">
Toggle
@@ -69,9 +63,29 @@ Markup
<button tabindex="-1" aria-controls="main-menu" aria-expanded="false" data-js="toggle">
Close
</button>
+</div>
+ In addition to listening to “click” events on <a>
and <button>
tags the utility will listen to the “change” event on form elements: <input>
, <select>
, and <textarea>
. Their targets will toggled based on passing HTML5 form validation of the element. The target will only be toggled if the form element has a value when it is required or if the value matches a required pattern.
<label for="question-1">Question 1</label>
+
+<select id="question-1" name="question[1]" aria-controls="next-question" aria-expanded="false" required="true">
+ <option value="">Please select 1 or 2</option>
+ <option value="option-1">Option 1</option>
+ <option value="option-2">Option 2</option>
+</select>
+
+<div id="next-question" class="hidden" aria-expanded="false">
+ <label for="question-2">Question 2</label>
+
+ <select id="question-2" name="question[2]" tabindex="-1">
+ <option value="">Please select A or B</option>
+ <option value="option-a">Option A</option>
+ <option value="option-b">Option B</option>
+ </select>
</div>
Attributes on the Element, Target, and Target Children, such as aria-hidden
, aria-controls
, aria-expanded
, type
, and tabindex
help assistive technologies understand the relationship between each element and their respective states of visibility. These attributes should be present but they may be interchanged with others based on the use case. Below is an explanation of all attributes that can be used with the toggle utility. Static attributes will not change. Dynamic attributes will change when the toggle event is fired.
Attributes on the Element, Target, and the Target’s children, such as aria-hidden
, aria-controls
, aria-expanded
, type
, and tabindex
help assistive technologies understand the relationship between each element and their respective states of visibility. Some attributes are required on the element on page load.
Some attributes may be interchanged with others based on the use case. Below is an explanation of all attributes that can be used with the toggle utility. Static attributes will not change. Dynamic attributes will change when the toggle event is fired.
Toggling Element Attributes
@@ -97,6 +111,18 @@tabindex
+ -1
to prevent it’s visibility from screen readers. Refer to the list below of potentially focusable elements that will be toggled.aria-expanded
@@ -214,8 +240,8 @@ tabindex
that needs to be set when the parent target is visible then the default value can be stored in this data attribute.tabindex
that needs to be set when the parent target is visible then the default value can be stored in this data attribute..matches()
method).namespace
+ toggle
. Ex; the namespace in the data-toggle-tabindex
selector (described above) would change the namespace in brackets; data-{{ namespace }}-tabindex
.inactiveClass
@@ -275,7 +311,7 @@ + Before/After Callback Instance Properties +
+Property | +Type | +Description | +
---|---|---|
+ element
+ |
+ + Node Element + | +The element that triggered the toggle. | +
+ event
+ |
+ + Click Event + | +The original click event. | +
+ focusable
+ |
+ + Node List + | +A list of elements within the toggle target that can receive focus. | +
+ others
+ |
+ + Node List + | +A list of other toggle elements that can trigger the toggle. | +
+ settings
+ |
+ + Object + | +The settings of the toggle instance. | +
+ target
+ |
+ + Node Element + | +The target toggle element. | +
'use strict';
+
+import Toggle from '@nycopportunity/patterns-framework/src/utilities/toggle/toggle';
+
+class MobileMenu {
+ constructor() {
+ this.selector = MobileMenu.selector;
+
+ this.namespace = MobileMenu.namespace;
+
+ this.selectors = MobileMenu.selectors;
+
+ this.toggle = new Toggle({
+ // Pass the pattern's custom selector
+ selector: this.selector,
+ // Pass the pattern's custom namespace
+ namespace: this.namespace,
+ // Pass a callback with functionality unique to the Mobile Menu Pattern
+ after: toggle => {
+ // Shift focus from the open to the close button in the Mobile Menu when toggled
+ if (toggle.target.classList.contains(Toggle.activeClass)) {
+ toggle.target.querySelector(this.selectors.CLOSE).focus();
+
+ // When the last focusable item in the list looses focus loop to the first
+ toggle.focusable.item(toggle.focusable.length - 1)
+ .addEventListener('blur', () => {
+ toggle.focusable.item(0).focus();
+ });
+ } else {
+ document.querySelector(this.selectors.OPEN).focus();
+ }
+ }
+ });
+
+ return this;
+ }
+}
+
+MobileMenu.selector = '[data-js*="mobile-menu"]';
+
+MobileMenu.namespace = 'mobile-menu';
+
+MobileMenu.selectors = {
+ CLOSE: '[data-js-mobile-menu*="close"]',
+ OPEN: '[data-js-mobile-menu*="open"]'
+};
+
+export default MobileMenu;
The script uses the Element.prototype.matches
, Element.prototype.removes
, Nodelist.prototype.forEach
methods which require polyfills for IE11 support.