From 810abce4e655174c5de3b4d2d73de47338843513 Mon Sep 17 00:00:00 2001 From: isral Duke Date: Wed, 9 Apr 2025 16:38:52 -0500 Subject: [PATCH 1/3] Initial commit of autocomplete --- docs/_includes/markup/autocomplete.njk | 11 + docs/_layouts/base.njk | 4 + docs/css/autocomplete.css | 17 + docs/extras/autocomplete.md | 31 ++ docs/extras/background-texture.md | 2 +- docs/img/illustrations/illus-autocomplete.png | Bin 0 -> 8151 bytes docs/js/autocomplete.js | 306 ++++++++++++++++++ 7 files changed, 370 insertions(+), 1 deletion(-) create mode 100644 docs/_includes/markup/autocomplete.njk create mode 100755 docs/css/autocomplete.css create mode 100644 docs/extras/autocomplete.md create mode 100644 docs/img/illustrations/illus-autocomplete.png create mode 100755 docs/js/autocomplete.js diff --git a/docs/_includes/markup/autocomplete.njk b/docs/_includes/markup/autocomplete.njk new file mode 100644 index 00000000..c8b4a18a --- /dev/null +++ b/docs/_includes/markup/autocomplete.njk @@ -0,0 +1,11 @@ +
+
+ + + + +
    + +
    +
    +
    diff --git a/docs/_layouts/base.njk b/docs/_layouts/base.njk index 3a846607..f55791af 100644 --- a/docs/_layouts/base.njk +++ b/docs/_layouts/base.njk @@ -23,11 +23,13 @@ + {% else %} + {% endif %} {{ title }} | Pelican, Louisiana’s Design System @@ -59,9 +61,11 @@ {% if env.production %} + {% else %} + {% endif %} diff --git a/docs/css/autocomplete.css b/docs/css/autocomplete.css new file mode 100755 index 00000000..26ee41a2 --- /dev/null +++ b/docs/css/autocomplete.css @@ -0,0 +1,17 @@ +.accessible-autocomplete { + position: relative; +} + +.list-group-autocomplete { + display: none; + /* initial view */ + position: absolute; + width: 100%; + z-index: 1000; +} +.list-group-item[aria-selected="true"], +.list-group-item:hover { + color: var(--theme-gray-white); + background-color: var(--theme-ui); + cursor: pointer; +} diff --git a/docs/extras/autocomplete.md b/docs/extras/autocomplete.md new file mode 100644 index 00000000..471a3db0 --- /dev/null +++ b/docs/extras/autocomplete.md @@ -0,0 +1,31 @@ +--- +title: Autocomplete +summary: Autocomplete with screenreader support. +tags: Autocomplete +layout: guide +eleventyNavigation: + key: Autocomplete + parent: Extras + order: 10 + excerpt: Autocomplete with screenreader support. + img: /img/illustrations/illus-autocomplete.png +--- + +## Best Practices + +Autocompletes benefit users with domain knowledge about what they’re choosing. If the available options are unknown to the user then it’s better to use checkboxes, radios, or selects because they can easily refer to the options. + +## Usage + +You’ll need to add the following resources to your project. The autocomplete isn’t included in Pelican by default. Be aware that you’ll need to define your own data source. The included JS file uses fake data for the demo. + +- JS: [`autocomplete.js`](/js/autocomplete.js) +- CSS: [`autocomplete.css`](/css/autocomplete.css) + +{% include 'markup/autocomplete.njk' %} + +```html +{% include 'markup/autocomplete.njk' %} +``` + + diff --git a/docs/extras/background-texture.md b/docs/extras/background-texture.md index 4f174134..69ab4b11 100644 --- a/docs/extras/background-texture.md +++ b/docs/extras/background-texture.md @@ -6,7 +6,7 @@ layout: guide eleventyNavigation: key: Background Texture parent: Extras - order: 10 + order: 20 excerpt: Scalable vector graphic backgrounds which can add an ecological flavor to projects which use Pelican. img: /img/illustrations/illus-bg-tile.png --- diff --git a/docs/img/illustrations/illus-autocomplete.png b/docs/img/illustrations/illus-autocomplete.png new file mode 100644 index 0000000000000000000000000000000000000000..fed37e591221d8aab134ce9c2b2f908bccb42b77 GIT binary patch literal 8151 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 literal 0 HcmV?d00001 diff --git a/docs/js/autocomplete.js b/docs/js/autocomplete.js new file mode 100755 index 00000000..02f3d52f --- /dev/null +++ b/docs/js/autocomplete.js @@ -0,0 +1,306 @@ +// JS adapted from https://haltersweb.github.io/Accessibility/autocomplete.html +// chargpt used to convert to vanilla js + +// Standard Namespacing +var NAME = NAME || {}; + + + + +// accessibility helpers + +(function () { + 'use strict'; + + NAME.keyboard = { + back: 8, tab: 9, enter: 13, shift: 16, ctrl: 17, alt: 18, + esc: 27, space: 32, pageUp: 33, pageDown: 34, + end: 35, home: 36, left: 37, up: 38, right: 39, + down: 40, del: 46, command: 91 + }; + + NAME.focusables = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex], [contenteditable]'; + + NAME.general = {}; + NAME.general.senseClickOutside = function (evtTarget, container) { + return !container.contains(evtTarget); + }; + + NAME.general.debounce = function (func, delay, immediate) { + let timeout, result; + return function (...args) { + const context = this; + const later = function () { + timeout = null; + if (!immediate) result = func.apply(context, args); + }; + const callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, delay); + if (callNow) result = func.apply(context, args); + return result; + }; + }; + + NAME.access = {}; + + NAME.access.blockFocus = function (blockedContainers, focusInstead) { + blockedContainers.forEach(container => { + container.setAttribute('aria-hidden', 'true'); + container.addEventListener('focusin', function (e) { + if (container.getAttribute('aria-hidden') === 'true') { + focusInstead.focus(); + e.stopPropagation(); + e.preventDefault(); + } + }, { passive: false }); + }); + }; + + NAME.access.removeBlockFocus = function (blockedContainers) { + blockedContainers.forEach(container => { + container.removeAttribute('aria-hidden'); + container.replaceWith(container.cloneNode(true)); // quick way to remove event listener + }); + }; + + NAME.access.ariaExpand = function (expander, expandingContainer) { + expander.setAttribute('aria-expanded', 'true'); + expandingContainer.setAttribute('aria-hidden', 'false'); + }; + + NAME.access.ariaContract = function (expander, expandingContainer) { + expander.setAttribute('aria-expanded', 'false'); + expandingContainer.setAttribute('aria-hidden', 'true'); + }; + + NAME.access.ariaHideContent = function (hideContainers) { + hideContainers.forEach(container => { + const focusables = container.querySelectorAll('a, button, input, select, textarea'); + container.setAttribute('aria-hidden', 'true'); + focusables.forEach(elem => { + elem.setAttribute('tabindex', '-1'); + elem.setAttribute('data-focusable-hidden-elem', 'true'); + }); + }); + }; + + NAME.access.ariaShowContent = function (blockedContainers) { + blockedContainers.forEach(container => { + const focusables = container.querySelectorAll('[data-focusable-hidden-elem]'); + container.removeAttribute('aria-hidden'); + focusables.forEach(elem => { + elem.removeAttribute('tabindex'); + elem.removeAttribute('data-focusable-hidden-elem'); + }); + }); + }; + + NAME.access.tagTrigger = function (optionalTrigger) { + const trigger = optionalTrigger || document.activeElement; + trigger.setAttribute('data-trigger', 'true'); + }; + + NAME.access.focusTrigger = function (optionalTrigger) { + const trigger = optionalTrigger || document.querySelector('[data-trigger="true"]'); + if (trigger) { + trigger.focus(); + trigger.removeAttribute('data-trigger'); + } + }; + + NAME.access.announcements = function (ariaContainer, textToRead) { + ariaContainer.textContent = textToRead; + setTimeout(() => { + ariaContainer.textContent = ''; + }, 1000); + }; + + NAME.access.duplicateTextForReading = function (ariaContainer, elements) { + let textToBeRead = ''; + elements.forEach(el => { + textToBeRead += el.textContent + ' '; + }); + NAME.access.announcements(ariaContainer, textToBeRead.trim()); + }; +})(); + + + + +// autocomplete js + +(function (NAME) { + 'use strict'; + + const widget = document.querySelector('[data-widget="accessible-autocomplete"]'); + const input = widget.querySelector('#search'); + const clearText = document.getElementById('clearText'); + const resultsContainer = widget.querySelector('#results'); + const liveRegion = widget.querySelector('[aria-live]'); + const key = NAME.keyboard; + const directions = "Keyboard users, use up and down arrows to review and enter to select. Touch device users, explore by touch or with swipe gestures."; + const liMarkup = id => `
  • `; + + const fakeResults = [ + ['apple', 'avocado', 'banana', 'cucumber', 'eggplant', 'kiwi'], + ['banana', 'cucumber', 'eggplant'], + ['cucumber'] + ]; + + let inputVal = ""; + let results = []; + + function fakeAjaxResults() { + const len = input.value.length; + if (len === 0 || len > 3) return []; + if (len === 1) return fakeResults[0]; + if (len === 2) return fakeResults[1]; + if (len === 3) return fakeResults[2]; + } + + function positionResults() { + if (resultsContainer.style.width) return; + const rect = input.getBoundingClientRect(); + resultsContainer.style.left = rect.left + 'px'; + resultsContainer.style.top = (rect.top + input.offsetHeight) + 'px'; + resultsContainer.style.minWidth = input.offsetWidth + 'px'; + } + + function buildListHtml(results) { + resultsContainer.innerHTML = results.map((r, idx) => liMarkup('') + r + '
  • ').join(''); + resultsContainer.style.display = 'block'; + input.setAttribute('aria-expanded', 'true'); + } + + function announceResults() { + const textToRead = results.length ? `${results.length} results are available. ${directions}` : "No search results"; + NAME.access.announcements(liveRegion, textToRead); + } + + function markSelected(selection) { + if (!selection) return; + selection.setAttribute('aria-selected', 'true'); + selection.id = 'selectedOption'; + input.setAttribute('aria-activedescendant', 'selectedOption'); + } + + function clearSelected() { + input.setAttribute('aria-activedescendant', ''); + resultsContainer.querySelectorAll('[aria-selected="true"]').forEach(el => { + el.setAttribute('aria-selected', 'false'); + el.removeAttribute('id'); + }); + } + + function closeResults() { + clearSelected(); + resultsContainer.style.display = 'none'; + input.setAttribute('aria-expanded', 'false'); + } + + function autocomplete() { + if (input.value === inputVal) return; + inputVal = input.value; + results = fakeAjaxResults(); + if (!results.length) { + closeResults(); + } else { + buildListHtml(results); + announceResults(); + } + } + + function arrowing(kc) { + if (!results.length) return; + const activeItem = resultsContainer.querySelector('[aria-selected="true"]'); + let nextItem = null; + if (kc === key.down) { + nextItem = activeItem ? activeItem.nextElementSibling : resultsContainer.querySelector('li'); + } + if (kc === key.up) { + nextItem = activeItem ? activeItem.previousElementSibling : resultsContainer.querySelector('li:last-child'); + } + clearSelected(); + if (nextItem) markSelected(nextItem); + } + + function populating() { + const selectedItem = resultsContainer.querySelector('[aria-selected="true"]'); + input.value = selectedItem ? selectedItem.textContent : inputVal; + } + + function eventListeners() { + document.addEventListener('click', e => { + if (!input.contains(e.target) && !resultsContainer.contains(e.target)) { + closeResults(); + } + }); + + input.addEventListener('keyup', e => { + const kc = e.keyCode; + if (![key.up, key.down, key.tab, key.enter, key.esc].includes(kc)) { + autocomplete(); + } + }); + + input.addEventListener('keydown', e => { + const kc = e.keyCode; + if (kc === key.tab) { + closeResults(); + } + if (kc === key.enter) { + e.preventDefault(); + closeResults(); + } + if (kc === key.up || kc === key.down) { + e.preventDefault(); + arrowing(kc); + populating(); + } + if (kc === key.esc) { + input.value = inputVal; + closeResults(); + } + }); + + resultsContainer.addEventListener('click', e => { + input.value = e.target.textContent; + closeResults(); + input.focus(); + }); + + clearText.addEventListener('click', () => { + inputVal = ''; + input.value = ''; + }); + } + + function init() { + eventListeners(); + positionResults(); + } + + init(); +})(NAME); + + + + +// show-code.js + +(function (NAME) { + 'use strict'; + + const codeContainers = document.querySelectorAll('[data-code]'); + codeContainers.forEach(container => { + const id = container.getAttribute('data-code'); + const htmlElem = document.getElementById(id); + if (!htmlElem) return; + let html = htmlElem.innerHTML; + const noTabs = html.match(/[^<]*/)[0].replace(/\n/, "").length; + const re = new RegExp("\n\t{" + noTabs + "}|^\t{" + noTabs + "}", "g"); + html = html.replace(//g, '>').replace(re, '\n'); + container.innerHTML = `
    ${html}
    `; + }); +})(NAME); \ No newline at end of file From e4b3373cc7852bf9314b0dad76e6edc5bf11fc74 Mon Sep 17 00:00:00 2001 From: isral Duke Date: Wed, 9 Apr 2025 16:47:05 -0500 Subject: [PATCH 2/3] updated package.json --- docs/extras/autocomplete.md | 4 ++++ docs/whats-new/index.md | 4 ++++ package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/extras/autocomplete.md b/docs/extras/autocomplete.md index 471a3db0..32830074 100644 --- a/docs/extras/autocomplete.md +++ b/docs/extras/autocomplete.md @@ -28,4 +28,8 @@ You’ll need to add the following resources to your project. The autocomplete i {% include 'markup/autocomplete.njk' %} ``` +## Resources +This accessible autocomplete is adapted from Accessibility repo on Github. + +- [Halter’s Web Accessibility](https://github.com/haltersweb/Accessibility) diff --git a/docs/whats-new/index.md b/docs/whats-new/index.md index 73dc21c4..a85e958d 100644 --- a/docs/whats-new/index.md +++ b/docs/whats-new/index.md @@ -16,6 +16,10 @@ You can help improve Pelican. Visit the [Feedback Page](/feedback) to learn how We’re continually improving Pelican. The following changes are listed by the date we completed each change. +## 2.4.0: April 10, 2024 + +- Adds an accessible [Autocomplete](/extras/autocomplete) + ## 2.3.1: February 17, 2025 - Fixed a [Form Section Header](/form-controls/form-section-header/) CSS bug diff --git a/package-lock.json b/package-lock.json index b6ca2644..0635b6d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@la-ots/pelican", - "version": "2.3.1", + "version": "2.4.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@la-ots/pelican", - "version": "2.3.1", + "version": "2.4.0", "license": "CC0-1.0", "devDependencies": { "@11ty/eleventy": "^2.0.1", diff --git a/package.json b/package.json index 27ee6808..245fa9ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@la-ots/pelican", - "version": "2.3.1", + "version": "2.4.0", "description": "Pelican Design System for Louisiana OTS", "repository": "git://github.com/la-ots/pelican.git", "license": "CC0-1.0", From 65fda6c0b2f1bb63638fbf9d0f3594a8caf9d1e9 Mon Sep 17 00:00:00 2001 From: isral Duke Date: Wed, 23 Apr 2025 11:19:56 -0500 Subject: [PATCH 3/3] update docs --- docs/extras/autocomplete.md | 4 ++-- docs/whats-new/index.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/extras/autocomplete.md b/docs/extras/autocomplete.md index 32830074..5a5f7afc 100644 --- a/docs/extras/autocomplete.md +++ b/docs/extras/autocomplete.md @@ -13,11 +13,11 @@ eleventyNavigation: ## Best Practices -Autocompletes benefit users with domain knowledge about what they’re choosing. If the available options are unknown to the user then it’s better to use checkboxes, radios, or selects because they can easily refer to the options. +The Autocomplete benefits users with domain knowledge about what they’re choosing. If the available options are unknown to the user then it’s better to use [checkboxes](/form-controls/checkboxes/), [radios](/form-controls/radios/), or [selects](/form-controls/select/) because the users can easily refer to the options. ## Usage -You’ll need to add the following resources to your project. The autocomplete isn’t included in Pelican by default. Be aware that you’ll need to define your own data source. The included JS file uses fake data for the demo. +You’ll need to add the following resources to your project. The autocomplete isn’t included in Pelican by default. It inherits styles from the [List Group](/components/list-group/). Be aware that you’ll need to define your own data source. The included JS file uses fake data for the demo. - JS: [`autocomplete.js`](/js/autocomplete.js) - CSS: [`autocomplete.css`](/css/autocomplete.css) diff --git a/docs/whats-new/index.md b/docs/whats-new/index.md index a85e958d..7aa092f8 100644 --- a/docs/whats-new/index.md +++ b/docs/whats-new/index.md @@ -16,7 +16,7 @@ You can help improve Pelican. Visit the [Feedback Page](/feedback) to learn how We’re continually improving Pelican. The following changes are listed by the date we completed each change. -## 2.4.0: April 10, 2024 +## 2.4.0: April 25, 2024 - Adds an accessible [Autocomplete](/extras/autocomplete)