<div class="demo-container" style="height: 666px;">
<div class="acl-side-navigation__condensed">
<div class="acl-side-navigation__condensed-items">
<div class="acl-side-navigation__condensed-item">
<a class="acl-side-navigation__condensed-item-link" href="#">
<div class="acl-side-navigation__condensed-item-icon"><i class="aforza-icons">acl_dashboard</i>
</div>
<div class="acl-side-navigation__condensed-item-text">Dashboard</div>
</a>
</div>
<div class="acl-side-navigation__condensed-item">
<a class="acl-side-navigation__condensed-item-link" href="#">
<div class="acl-side-navigation__condensed-item-icon"><i class="aforza-icons">acl_visit</i> </div>
<div class="acl-side-navigation__condensed-item-text">Visits</div>
</a>
</div>
<div class="acl-side-navigation__condensed-item">
<a class="acl-side-navigation__condensed-item-link" href="#">
<div class="acl-side-navigation__condensed-item-icon"><i class="aforza-icons">acl_agenda</i>
</div>
<div class="acl-side-navigation__condensed-item-text">Agenda</div>
</a>
</div>
<div class="acl-side-navigation__condensed-item">
<a class="acl-side-navigation__condensed-item-link" href="#">
<div class="acl-side-navigation__condensed-item-icon"><i class="aforza-icons">acl_route</i> </div>
<div class="acl-side-navigation__condensed-item-text">Route Builder Page</div>
</a>
</div>
</div>
</div>
</div>
<div class="demo-container" style="height: 666px;">
<div class="acl-side-navigation__condensed">
<div class="acl-side-navigation__condensed-items">
<div class="acl-side-navigation__condensed-item">
<a class="acl-side-navigation__condensed-item-link" href="#">
<div class="acl-side-navigation__condensed-item-icon"><i class="aforza-icons">acl_dashboard</i>
</div>
<div class="acl-side-navigation__condensed-item-text">Dashboard</div>
</a>
</div>
<div class="acl-side-navigation__condensed-item">
<a class="acl-side-navigation__condensed-item-link" href="#">
<div class="acl-side-navigation__condensed-item-icon"><i class="aforza-icons">acl_visit</i> </div>
<div class="acl-side-navigation__condensed-item-text">Visits</div>
</a>
</div>
<div class="acl-side-navigation__condensed-item">
<a class="acl-side-navigation__condensed-item-link" href="#">
<div class="acl-side-navigation__condensed-item-icon"><i class="aforza-icons">acl_agenda</i>
</div>
<div class="acl-side-navigation__condensed-item-text">Agenda</div>
</a>
</div>
<div class="acl-side-navigation__condensed-item">
<a class="acl-side-navigation__condensed-item-link" href="#">
<div class="acl-side-navigation__condensed-item-icon"><i class="aforza-icons">acl_route</i> </div>
<div class="acl-side-navigation__condensed-item-text">Route Builder Page</div>
</a>
</div>
</div>
</div>
</div>
/* No context defined. */
class ACLSearchboxSuggestions {
constructor(suggestions, filters) {
this.suggestions = suggestions;
this.filters = filters;
this.filterChips = '';
}
autocomplete(inp, arr, filters) {
var currentFocus;
let chipSet;
let allChips;
let selectedChips;
let filterCount;
const filterButtonEl = document.querySelector('.acl-searchbox__filter-button');
const closeFiltersButtonEl = document.querySelector('.acl-searchbox__filters-close');
const filterBannerEl = document.querySelector('.acl-searchbox__filters-banner');
const filterBannerResultsEl = document.querySelector('.acl-searchbox__filters-banner-preview');
const selectedFilterCountLabel = document.querySelector('.acl-searchbox__filter-selected-count');
const resultsEl = document.querySelector('.acl-searchbox__results');
const filterPanel = document.querySelector('.acl-searchbox__filters-chips');
const searchboxHeader = document.querySelector('.acl-searchbox__header');
const searchboxFilters = document.querySelector('.acl-searchbox__filters');
closeFiltersButtonEl.addEventListener('click', function() {
toggleFilterPanel();
filterBannerEl.classList.remove('acl-searchbox__filters-banner--hidden');
});
filterButtonEl.addEventListener('click', function() {
toggleFilterPanel();
filterBannerEl.classList.add('acl-searchbox__filters-banner--hidden');
});
addFilters(filters);
/*execute a function when someone writes in the text field:*/
inp.addEventListener('input', function(e) {
var a,
b,
i,
val = this.value;
/*close any already open lists of autocompleted values*/
closeAllLists();
if (!val) {
return false;
} else if (val.length > 2) {
currentFocus = -1;
/*create a DIV element that will contain the items (values):*/
a = document.createElement('DIV');
a.setAttribute('id', this.id + 'acl-autocomplete-list');
a.setAttribute('class', 'acl-autocomplete__items');
/*append the DIV element as a child of the autocomplete container:*/
resultsEl.appendChild(a);
resultsEl.addEventListener('click', function(e) {
let autocompleteText = e.target.dataset.autocompleteItemName;
if (autocompleteText) {
inp.value = e.target.dataset.autocompleteItemName;
}
});
/*for each item in the array...*/
for (i = 0; i < arr.length; i++) {
if (
arr[i].primary.toUpperCase().includes(val.toUpperCase()) ||
arr[i].secondary.toUpperCase().includes(val.toUpperCase())
) {
/*create a DIV element for each matching element:*/
b = document.createElement('DIV');
b.classList.add('acl-autocomplete__item');
b.setAttribute('data-autocomplete-item-name', `${arr[i].primary} ${arr[i].secondary}`);
b.setAttribute('data-autocomplete-item-id', `${arr[i].id}`);
//b.setAttribute();
b.innerHTML += `<i class="material-icons">${arr[i].icon}</i> <strong>${arr[i].primary} </strong> - ${arr[i].secondary}`;
a.appendChild(b);
} else {
b = document.createElement('DIV');
b.classList.add('acl-autocomplete__item');
//b.setAttribute("data-autocomplete-item-name", `${arr[i].primary} ${arr[i].secondary}`);
//b.setAttribute();
b.innerHTML = `No results`;
a.appendChild(b);
break;
}
}
}
});
/*execute a function presses a key on the keyboard:*/
inp.addEventListener('keydown', function(e) {
var x = document.getElementById(this.id + 'acl-autocomplete-list');
if (x) x = x.getElementsByTagName('div');
if (e.keyCode == 40) {
/*If the arrow DOWN key is pressed,
increase the currentFocus variable:*/
currentFocus++;
/*and and make the current item more visible:*/
addActive(x);
} else if (e.keyCode == 38) {
//up
/*If the arrow UP key is pressed,
decrease the currentFocus variable:*/
currentFocus--;
/*and and make the current item more visible:*/
addActive(x);
} else if (e.keyCode == 13) {
/*If the ENTER key is pressed, prevent the form from being submitted,*/
e.preventDefault();
if (currentFocus > -1) {
/*and simulate a click on the "active" item:*/
if (x) {
x[currentFocus].click();
}
}
}
});
function addActive(x) {
/*a function to classify an item as "active":*/
if (!x) return false;
/*start by removing the "active" class on all items:*/
removeActive(x);
if (currentFocus >= x.length) currentFocus = 0;
if (currentFocus < 0) currentFocus = x.length - 1;
/*add class "autocomplete-active":*/
x[currentFocus].classList.add('autocomplete-active');
}
function removeActive(x) {
/*a function to remove the "active" class from all autocomplete items:*/
for (var i = 0; i < x.length; i++) {
x[i].classList.remove('autocomplete-active');
}
}
function closeAllLists(elmnt) {
/*close all autocomplete lists in the document,
except the one passed as an argument:*/
var x = document.getElementsByClassName('acl-autocomplete__items');
for (var i = 0; i < x.length; i++) {
if (elmnt != x[i] && elmnt != inp) {
x[i].parentNode.removeChild(x[i]);
}
}
}
function addFilters(filters) {
if (filterPanel) {
for (var i = 0; i < filters.length; i++) {
filterPanel.innerHTML += `<div class="acl-chip acl-ripple-upgraded" role="row" data-filter-text="${filters[i].name}" id="${filters[i].id}"
style="--acl-ripple-fg-size:57px; --acl-ripple-fg-scale:1.94633; --acl-ripple-fg-translate-start:16.4414px,
-21.9688px; --acl-ripple-fg-translate-end:19.3672px, -12.5px;">
<span role="button" tabindex="0" class="acl-chip__text">${filters[i].name}</span>
<div class="acl-chip__checkmark">
<svg class="acl-chip__checkmark-svg" viewBox="-3 -3 30 30">
<path class="" fill="white" stroke="none" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/><path d="M0 0h24v24H0z" fill="none"/>
</svg>
</div>
</div>`;
}
getAllChips();
}
}
function toggleFilterPanel() {
searchboxFilters.classList.toggle('acl-searchbox__filters--hidden');
searchboxHeader.classList.toggle('acl-searchbox__header--hidden');
setSelectedFilterCount();
setFilterBannerPreview();
}
function getAllChips() {
const chipSetEls = Array.from(document.querySelectorAll('.acl-chip-set'));
chipSetEls.forEach(el => {
chipSet = new acl.MDCChipSet(el);
});
return chipSet;
}
function getSelectedChips() {
allChips = getAllChips();
selectedChips = allChips.chips.filter(element => element.selected == true);
return selectedChips;
}
function setSelectedFilterCount() {
const selectedFilters = getSelectedChips();
filterCount = selectedFilters.length;
selectedFilterCountLabel.innerHTML = filterCount;
if (selectedFilters.length > 0) {
selectedFilterCountLabel.classList.add('acl-searchbox__filter-selected-count--visible');
} else {
selectedFilterCountLabel.classList.remove('acl-searchbox__filter-selected-count--visible');
filterBannerEl.classList.add('acl-searchbox__filters-banner--hidden');
}
}
function setFilterBannerPreview() {
const selectedFilters = getSelectedChips();
filterBannerResultsEl.innerHTML = '';
if (selectedFilters.length > 0) {
selectedFilters.slice(0, 2).forEach(function(element) {
filterBannerResultsEl.innerHTML += `<div class="acl-searchbox__filters-banner-item" data-filter-id="${element.id}" id="${element.id}-preview">
${element.root_.dataset.filterText}
<svg class="acl-searchbox__filters-banner-item-close" viewBox="-3 -3 30 30">
<path class="" fill="#1FACEC" stroke="none" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/><path d="M0 0h24v24H0z" fill="none"/>
</svg>
</div>`;
});
if (selectedFilters.length > 2) {
filterBannerResultsEl.innerHTML += `<div class="acl-searchbox__filters-more">+ ${selectedFilters.length -
2} more</div>`;
const searchboxFilterPreviewMore = document.querySelector('.acl-searchbox__filters-more');
searchboxFilterPreviewMore.addEventListener('click', function() {
toggleFilterPanel();
filterBannerEl.classList.add('acl-searchbox__filters-banner--hidden');
});
}
}
let filterPreviewEls = document.querySelectorAll('.acl-searchbox__filters-banner-item');
for (const filterEl of filterPreviewEls) {
filterEl.addEventListener('click', function(event) {
const filterItems = getAllChips();
filterItems.chips.filter(obj => {
if (obj.selected == true && obj.id == event.target.dataset.filterId) {
obj.selected = false;
event.target.innerHTML = '';
}
});
setSelectedFilterCount();
setFilterBannerPreview();
});
}
}
document.addEventListener('click', function(e) {
closeAllLists(e.target);
});
}
}
export { ACLSearchboxSuggestions };
Buttons allow users to take actions, and make choices, with a single tap.
npm install ..//button<button class="acl-button">
<div class="acl-button__ripple"></div>
<span class="acl-button__label">Button</span>
</button>NOTE: Examples here use the generic
<button>, but users can also apply theacl-buttonclass to<a>elements.
@import "../button/acl-button";The button will work without JavaScript, but you can enhance it to have a ripple effect by instantiating MDCRipple on the root element. See MDC Ripple for details.
import {MDCRipple} from '..//ripple';
const buttonRipple = new MDCRipple(document.querySelector('.acl-button'));See Importing the JS component for more information on how to import JavaScript.
To style a contained button, add the acl-button--raised class to the <button> element for a contained button with elevation, or the acl-button--unelevated class for a contained button flush with the surface.
To style an outlined button, add the class acl-button--outlined to the <button> element.
We recommend using Material Icons from Google Fonts:
<head>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
</head>However, you can also use SVG, Font Awesome, or any other icon library you wish.
To add an icon, add an element with the acl-button__icon class inside the button element and set the attribute aria-hidden="true". The icon is set to 18px to meet legibility requirements.
<button class="acl-button">
<div class="acl-button__ripple"></div>
<i class="material-icons acl-button__icon" aria-hidden="true">favorite</i>
<span class="acl-button__label">Button</span>
</button>It’s also possible to use an SVG icon:
<button class="acl-button">
<div class="acl-button__ripple"></div>
<svg class="acl-button__icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="...">
...
</svg>
<span class="acl-button__label">Button</span>
</button>Certain icons make more sense to appear after the button’s text label rather than before. This can be accomplished by
putting the icon markup after the acl-button__label element.
<button class="acl-button">
<div class="acl-button__ripple"></div>
<span class="acl-button__label">Button</span>
<i class="material-icons acl-button__icon" aria-hidden="true">favorite</i>
</button>NOTE: The
acl-button__labelelement is required in order for the trailing icon to be styled appropriately.
To disable a button, add the disabled attribute directly to the <button>, or set the disabled attribute on the <fieldset> containing the button.
Disabled buttons cannot be interacted with and have no visual interaction effect.
<button class="acl-button" disabled>
<div class="acl-button__ripple"></div>
<span class="acl-button__label">Button</span>
</button>Material Design spec advises that touch targets should be at least 48 x 48 px. To meet this requirement, add the following to your button:
<div class="acl-touch-target-wrapper">
<button class="acl-button acl-button--touch">
<div class="acl-button__ripple"></div>
<span class="acl-button__label">My Accessible Button</span>
<div class="acl-button__touch"></div>
</button>
</div>Note that the outer acl-touch-target-wrapper element is only necessary if you want to avoid potentially overlapping touch targets on adjacent elements (due to collapsing margins).
| CSS Class | Description |
|---|---|
acl-button |
Mandatory. Defaults to a text button that is flush with the surface. |
acl-button__ripple |
Mandatory. Indicates the element which shows the ripple styling. |
acl-button--raised |
Optional. Styles a contained button that is elevated above the surface. |
acl-button--unelevated |
Optional. Styles a contained button that is flush with the surface. |
acl-button--outlined |
Optional. Styles an outlined button that is flush with the surface. |
acl-button__label |
Recommended.* Indicates the element containing the button’s text label. |
acl-button__icon |
Optional. Indicates the element containing the button’s icon. |
*NOTE: The
acl-button__labelelement is required for buttons with a trailing icon, but it is currently optional for buttons with no icon or a leading icon. In the latter cases, it is acceptable for the text label to simply exist directly within theacl-buttonelement. However, theacl-button__labelclass may become mandatory for all cases in the future, so it is recommended to always include it to be future-proof.
To customize a button’s color and properties, you can use the following mixins.
MDC Button uses MDC Theme‘s primary color by default. Use the following mixins to customize it.
| Mixin | Description |
|---|---|
acl-button-filled-accessible($container-fill-color) |
Sets the container fill color for a contained (raised or unelevated) button, and updates the button’s ink, icon, and ripple colors to meet accessibility standards |
These mixins will override the color of the container, ink, outline or ripple. It is up to you to ensure your button meets accessibility standards.
| Mixin | Description |
|---|---|
acl-button-container-fill-color($color) |
Sets the container fill color to the given color. |
acl-button-icon-color($color) |
Sets the icon color to the given color. |
acl-button-ink-color($color) |
Sets the ink color to the given color, and sets the icon color to the given color unless acl-button-icon-color is also used. |
acl-button-density($density-scale) |
Sets density scale for button. Supported density scale values (-3, -2, -1, 0). |
acl-button-height($height) |
Sets custom height of button. |
acl-button-shape-radius($radius, $density-scale, $rtl-reflexive) |
Sets rounded shape to button with given radius size. $density-scale is only required when $radius value is in percentage unit, defaults to $acl-button-density-default-scale. Set $rtl-reflexive to true to flip radius values in RTL context, defaults to false. |
acl-button-horizontal-padding($padding) |
Sets horizontal padding to the given number. |
acl-button-outline-color($color) |
Sets the outline color to the given color. |
acl-button-outline-width($width, $padding) |
Sets the outline width to the given number (defaults to 2px) and adjusts padding accordingly. $padding is only required in cases where acl-button-horizontal-padding is also included with a custom value. |
In browsers that fully support CSS custom properties, the above mixins will work if you pass in a MDC Theme property (e.g. primary) as an argument. However, Edge does not fully support CSS custom properties. If you are using the acl-button-container-fill-color mixin, you must pass in an actual color value for support in Edge.