From 2d65faf9bbb248c8385c0a22e7f4b1d37c2d7d54 Mon Sep 17 00:00:00 2001 From: Danny Kim Date: Tue, 16 Aug 2022 13:29:23 -0400 Subject: [PATCH 1/3] feat: input-group component base styles with predictive search field --- ds-css-v2/demo-components/form/index.html | 32 ++ .../demo-components/input-group/index.html | 213 +++++++++++ ds-css-v2/index.html | 4 + ds-css-v2/js/cbp-components-js/demo.js | 61 ++++ ds-css-v2/js/utilities/autocomplete.js | 334 ++++++++++++++++++ ds-css-v2/js/utilities/new-autocomplete.js | 51 +++ .../styles/sass/cbp-components/_all.scss | 2 + .../sass/cbp-components/_autocomplete.scss | 31 ++ .../sass/cbp-components/_input-group.scss | 141 ++++++++ 9 files changed, 869 insertions(+) create mode 100644 ds-css-v2/demo-components/input-group/index.html create mode 100644 ds-css-v2/js/cbp-components-js/demo.js create mode 100644 ds-css-v2/js/utilities/autocomplete.js create mode 100644 ds-css-v2/js/utilities/new-autocomplete.js create mode 100644 ds-css-v2/styles/sass/cbp-components/_autocomplete.scss create mode 100644 ds-css-v2/styles/sass/cbp-components/_input-group.scss diff --git a/ds-css-v2/demo-components/form/index.html b/ds-css-v2/demo-components/form/index.html index 02243357..913c02d3 100644 --- a/ds-css-v2/demo-components/form/index.html +++ b/ds-css-v2/demo-components/form/index.html @@ -104,6 +104,38 @@

Password (Hash) Field

+
+
+
+ + Required. + +
+ + +
+
+
+ +
+

Input Group

+
+ + +
+
+ + +
+
+ + +
+
+
+
diff --git a/ds-css-v2/demo-components/input-group/index.html b/ds-css-v2/demo-components/input-group/index.html new file mode 100644 index 00000000..87dbc60f --- /dev/null +++ b/ds-css-v2/demo-components/input-group/index.html @@ -0,0 +1,213 @@ + + + + + + CBP Theme Boilerplate + + + + + + +
+
+
+

Input Group Components

+
+
+
+
+
+ + Required. + +
+ + +
+
+
+ +
+

Input Text Group

+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+
+ + Required. + +
+ + +
+
+
+ Pepperoni +
+ +
+
+
+ Mushroom +
+ +
+
+
+
+
+ +
+

Input Group

+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+
+ + +
+ + +
+
+
+ +
+

Search Field

+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+
+ + +
+
+ + +
+
+
+
+ +
+

Search Field w/ Predictive Text

+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+
+ + +
+
+ + +
+
    +
  • Uganda
  • +
  • United States of America
  • +
  • United Emerites
  • +
+
+
+
+ +
+

New Search Field w/ Predictive Text

+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+ Made with ♥️ by Creative Services +
+
+ + + + + + + + + + + \ No newline at end of file diff --git a/ds-css-v2/index.html b/ds-css-v2/index.html index ed1a2e5f..baa1eb65 100644 --- a/ds-css-v2/index.html +++ b/ds-css-v2/index.html @@ -60,6 +60,10 @@

Compl Dropdown + + Input Group + + Breadcrumb diff --git a/ds-css-v2/js/cbp-components-js/demo.js b/ds-css-v2/js/cbp-components-js/demo.js new file mode 100644 index 00000000..f5b75210 --- /dev/null +++ b/ds-css-v2/js/cbp-components-js/demo.js @@ -0,0 +1,61 @@ +const findDesc = (element) => { + const wrapper = element.closest(".cbp-form-wrapper"); + const descriptions = wrapper.querySelectorAll(".cbp-form__description"); + + return descriptions; +} + +const invalidateInputGroup = (event, id, type = 'element') => { + const { target: { checked } } = event; + const isComponent = type === 'component'; + const element = !isComponent && document.getElementById(id); + const component = isComponent && document.getElementById(id); + const input = component.querySelector('input'); + const desc = findDesc(component) + + if (checked) { + desc[0].hidden = true; + desc[1].hidden = false; + input.setCustomValidity("invalid"); + isComponent && component.classList.add("cbp-field-group--error"); + } else { + desc[0].hidden = false; + desc[1].hidden = true; + input.setCustomValidity(""); + isComponent && component.classList.remove("cbp-field-group--error"); + } +} + +const disableInputGroup = (event, id, type = 'element') => { + const { target: { checked } } = event; + const isComponent = type === 'component'; + const component = isComponent && document.getElementById(id); + const input = component.querySelector('input'); + const btn = component.querySelector('button'); + + if (checked) { + input.disabled = true; + btn.disabled = true; + } else { + input.disabled = false; + btn.disabled = false; + } +} + +const readOnlyInputGroup = (event, id, type = 'element') => { + const { target: { checked } } = event; + const isComponent = type === 'component'; + const component = isComponent && document.getElementById(id); + const input = component.querySelector('input'); + const btn = component.querySelector('button'); + + if (checked) { + component.classList.add('cbp-field-group--readonly'); + input.readOnly = true; + btn.disabled = true; + } else { + component.classList.remove('cbp-field-group--readonly'); + input.readOnly = false; + btn.disabled = false; + } +} \ No newline at end of file diff --git a/ds-css-v2/js/utilities/autocomplete.js b/ds-css-v2/js/utilities/autocomplete.js new file mode 100644 index 00000000..185326e5 --- /dev/null +++ b/ds-css-v2/js/utilities/autocomplete.js @@ -0,0 +1,334 @@ +const countries = [ + "Afghanistan", + "Albania", + "Algeria", + "Andorra", + "Angola", + "Anguilla", + "Antigua & Barbuda", + "Argentina", + "Armenia", + "Aruba", + "Australia", + "Austria", + "Azerbaijan", + "Bahamas", + "Bahrain", + "Bangladesh", + "Barbados", + "Belarus", + "Belgium", + "Belize", + "Benin", + "Bermuda", + "Bhutan", + "Bolivia", + "Bosnia & Herzegovina", + "Botswana", + "Brazil", + "British Virgin Islands", + "Brunei", + "Bulgaria", + "Burkina Faso", + "Burundi", + "Cambodia", + "Cameroon", + "Canada", + "Cape Verde", + "Cayman Islands", + "Central Arfrican Republic", + "Chad", + "Chile", + "China", + "Colombia", + "Congo", + "Cook Islands", + "Costa Rica", + "Cote D Ivoire", + "Croatia", + "Cuba", + "Curacao", + "Cyprus", + "Czech Republic", + "Denmark", + "Djibouti", + "Dominica", + "Dominican Republic", + "Ecuador", + "Egypt", + "El Salvador", + "Equatorial Guinea", + "Eritrea", + "Estonia", + "Ethiopia", + "Falkland Islands", + "Faroe Islands", + "Fiji", + "Finland", + "France", + "French Polynesia", + "French West Indies", + "Gabon", + "Gambia", + "Georgia", + "Germany", + "Ghana", + "Gibraltar", + "Greece", + "Greenland", + "Grenada", + "Guam", + "Guatemala", + "Guernsey", + "Guinea", + "Guinea Bissau", + "Guyana", + "Haiti", + "Honduras", + "Hong Kong", + "Hungary", + "Iceland", + "India", + "Indonesia", + "Iran", + "Iraq", + "Ireland", + "Isle of Man", + "Israel", + "Italy", + "Jamaica", + "Japan", + "Jersey", + "Jordan", + "Kazakhstan", + "Kenya", + "Kiribati", + "Kosovo", + "Kuwait", + "Kyrgyzstan", + "Laos", + "Latvia", + "Lebanon", + "Lesotho", + "Liberia", + "Libya", + "Liechtenstein", + "Lithuania", + "Luxembourg", + "Macau", + "Macedonia", + "Madagascar", + "Malawi", + "Malaysia", + "Maldives", + "Mali", + "Malta", + "Marshall Islands", + "Mauritania", + "Mauritius", + "Mexico", + "Micronesia", + "Moldova", + "Monaco", + "Mongolia", + "Montenegro", + "Montserrat", + "Morocco", + "Mozambique", + "Myanmar", + "Namibia", + "Nauro", + "Nepal", + "Netherlands", + "Netherlands Antilles", + "New Caledonia", + "New Zealand", + "Nicaragua", + "Niger", + "Nigeria", + "North Korea", + "Norway", + "Oman", + "Pakistan", + "Palau", + "Palestine", + "Panama", + "Papua New Guinea", + "Paraguay", + "Peru", + "Philippines", + "Poland", + "Portugal", + "Puerto Rico", + "Qatar", + "Reunion", + "Romania", + "Russia", + "Rwanda", + "Saint Pierre & Miquelon", + "Samoa", + "San Marino", + "Sao Tome and Principe", + "Saudi Arabia", + "Senegal", + "Serbia", + "Seychelles", + "Sierra Leone", + "Singapore", + "Slovakia", + "Slovenia", + "Solomon Islands", + "Somalia", + "South Africa", + "South Korea", + "South Sudan", + "Spain", + "Sri Lanka", + "St Kitts & Nevis", + "St Lucia", + "St Vincent", + "Sudan", + "Suriname", + "Swaziland", + "Sweden", + "Switzerland", + "Syria", + "Taiwan", + "Tajikistan", + "Tanzania", + "Thailand", + "Timor L'Este", + "Togo", + "Tonga", + "Trinidad & Tobago", + "Tunisia", + "Turkey", + "Turkmenistan", + "Turks & Caicos", + "Tuvalu", + "Uganda", + "Ukraine", + "United Arab Emirates", + "United Kingdom", + "United States of America", + "Uruguay", + "Uzbekistan", + "Vanuatu", + "Vatican City", + "Venezuela", + "Vietnam", + "Virgin Islands (US)", + "Yemen", + "Zambia", + "Zimbabwe", +]; + + +// Make sure the form has the autocomplete function switched off +function autocomplete(inp, arr) { + /*the autocomplete function takes two arguments, + the text field element and an array of possible autocompleted values:*/ + var currentFocus; + /*execute a function when someone writes in the text field:*/ + inp.addEventListener("input", function (e) { + debugger + var a, + b, + i, + val = this.value; + /*close any already open lists of autocompleted values*/ + closeAllLists(); + if (!val) { + return false; + } + currentFocus = -1; + /*create a DIV element that will contain the items (values):*/ + a = document.createElement("DIV"); + a.setAttribute("id", this.id + "autocomplete-list"); + a.setAttribute("class", "autocomplete-items"); + /*append the DIV element as a child of the autocomplete container:*/ + this.parentNode.appendChild(a); + /*for each item in the array...*/ + for (i = 0; i < arr.length; i++) { + /*check if the item starts with the same letters as the text field value:*/ + if (arr[i].substr(0, val.length).toUpperCase() == val.toUpperCase()) { + /*create a DIV element for each matching element:*/ + b = document.createElement("DIV"); + /*make the matching letters bold:*/ + b.innerHTML = "" + arr[i].substr(0, val.length) + ""; + b.innerHTML += arr[i].substr(val.length); + /*insert a input field that will hold the current array item's value:*/ + b.innerHTML += ""; + /*execute a function when someone clicks on the item value (DIV element):*/ + b.addEventListener("click", function (e) { + /*insert the value for the autocomplete text field:*/ + inp.value = this.getElementsByTagName("input")[0].value; + /*close the list of autocompleted values, + (or any other open lists of autocompleted values:*/ + closeAllLists(); + }); + a.appendChild(b); + } + } + }); + /*execute a function presses a key on the keyboard:*/ + inp.addEventListener("keydown", function (e) { + var x = document.getElementById(this.id + "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("autocomplete-items"); + for (var i = 0; i < x.length; i++) { + if (elmnt != x[i] && elmnt != inp) { + x[i].parentNode.removeChild(x[i]); + } + } + } + /*execute a function when someone clicks in the document:*/ + document.addEventListener("click", function (e) { + closeAllLists(e.target); + }); +} + + +/*initiate the autocomplete function on the "myInput" element, and pass along the countries array as possible autocomplete values:*/ +autocomplete(document.getElementById("myInput"), countries); \ No newline at end of file diff --git a/ds-css-v2/js/utilities/new-autocomplete.js b/ds-css-v2/js/utilities/new-autocomplete.js new file mode 100644 index 00000000..fd73b29e --- /dev/null +++ b/ds-css-v2/js/utilities/new-autocomplete.js @@ -0,0 +1,51 @@ +const getCountries = async () => { + try { + const response = await fetch("https://restcountries.com/v3.1/all"); + const data = await response.json(); + return data; + } catch (e) { + throw new Error(e); + } +}; + +const filterList = (arr, value) => ( + arr.filter(item => item.substr(0, value.length).toLowerCase() == value.toLowerCase()) +) + +const createListItem = (arr) => { + arr.forEach(element => { + const item = document.createElement('LI'); + item.innerHTML = element; + + return item; + }); +} + +const handleInput = (e, arr) => { + const { target: { value } } = e; + const parent = e.target.closest('.autocomplete'); + const list = filterList(arr, value); + const menu = list.length > 0 && document.createElement('UL'); + + if (value.length === 0) { + console.log('Remove Menu!'); + } else { + parent.insertAdjacentElement('afterend', menu); + + list.forEach(element => { + const item = document.createElement('LI'); + item.innerHTML = element; + + menu.appendChild(item); + }); + } +} + +const autocomplete2 = async (input) => { + const countries = await getCountries(); + const countriesName = countries.map(items => items.name.common).sort(); + + input.addEventListener('input', (e) => handleInput(e, countriesName)) +}; + +// autocomplete2(document.getElementById('autocomplete-demo')) diff --git a/ds-css-v2/styles/sass/cbp-components/_all.scss b/ds-css-v2/styles/sass/cbp-components/_all.scss index a8eba474..d4e96720 100644 --- a/ds-css-v2/styles/sass/cbp-components/_all.scss +++ b/ds-css-v2/styles/sass/cbp-components/_all.scss @@ -1,4 +1,5 @@ @import './accordion'; +@import './autocomplete'; @import './badges-chips-tags'; @import './breadcrumb'; @import './buttons'; @@ -7,6 +8,7 @@ @import './expand'; @import './footer'; @import './form'; +@import './input-group'; @import './link'; @import './modal'; @import './overflow-menu'; diff --git a/ds-css-v2/styles/sass/cbp-components/_autocomplete.scss b/ds-css-v2/styles/sass/cbp-components/_autocomplete.scss new file mode 100644 index 00000000..11eb5fd3 --- /dev/null +++ b/ds-css-v2/styles/sass/cbp-components/_autocomplete.scss @@ -0,0 +1,31 @@ +.cbp-autocomplete { + background-color: $cbp-white; + border: 1px solid $cbp-ui-neutral-base; + border-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; + margin-top: 0; + max-height: 216px; + padding-left: 0; +} + +.cbp-autocomplete__item { + height: 100%; + list-style-type: none; + padding-left: 16px; + width: 100%; +} + +.cbp-autocomplete__item > a { + color: $cbp-text-darkest; + height: 100%; + line-height: 0.7; + text-decoration: none; + width: 100%; + + &:hover { + background-color: $cbp-ui-neutral-darker; + } +} \ No newline at end of file diff --git a/ds-css-v2/styles/sass/cbp-components/_input-group.scss b/ds-css-v2/styles/sass/cbp-components/_input-group.scss new file mode 100644 index 00000000..270846e3 --- /dev/null +++ b/ds-css-v2/styles/sass/cbp-components/_input-group.scss @@ -0,0 +1,141 @@ +.cbp-field-group { + display: flex; + + & > input[type=password], + & > input[type=text] { + @extend .cbp-form__input; + border-right: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + flex: 1 1 auto; + width: auto; + + &:disabled { + cursor: pointer; + } + } + + & > button { + @extend .cbp-btn; + @extend .cbp-btn__secondary; + border-bottom-left-radius: 0; + border-top-left-radius: 0; + display: inline-block; + margin-left: -2px; + white-space: nowrap; + + &:disabled { + background-color: $cbp-disabled-dark; + color: $cbp-disabled-light; + } + } + + & > .square { + @extend .cbp-btn; + @extend .cbp-btn__square; + @extend .cbp-btn__square-secondary; + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin-left: -2px; + + &:disabled { + background-color: $cbp-disabled-dark; + color: $cbp-disabled-light; + } + } +} + +.cbp-field-group--error { + & > button { + @extend .cbp-btn__square-danger; + } + + & > .square { + @extend .cbp-btn__square-danger; + } +} + +.cbp-field-group--readonly { + & > button, + & > .square { + background-color: $cbp-ui-neutral-light; + color: $cbp-text-lightest; + cursor: not-allowed; + + &:hover:not([disabled]) { + background-color: $cbp-ui-neutral-light; + } + + &:disabled { + background-color: $cbp-base-neutral-light; + color: $cbp-text-lightest; + } + } +} + +.autocomplete { + position: relative; + + input[type="text"] { + margin-bottom: 0; + } +} + +.autocomplete-items { + background-color: $cbp-white; + border: 1px solid $cbp-ui-neutral-base; + border-top: none; + border-top-left-radius: 0px; + border-top-right-radius: 0px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + left: 0; + right: 0; + max-height: 216px; + overflow-y: scroll; + position: absolute; + top: 100%; + z-index: 99; +} + +.autocomplete-items div { + align-items: center; + background-color: $cbp-white; + border-bottom: 1px solid $cbp-ui-neutral-lighter; + color: $cbp-text-dark; + cursor: pointer; + display: flex; + font-size: 1rem; + font-style: italic; + font-weight: 400; + height: 36px; + letter-spacing: 0.3px; + padding-left: 16px; + + & > strong { + color: $cbp-text-darkest; + font-style: normal; + font-weight: 400; + } +} + +/*when hovering an item:*/ +.autocomplete-items div:hover { + background-color: $cbp-ui-neutral-darker; + color: $cbp-text-base; + & > strong { + color: $cbp-text-lightest; + font-weight: 700; + } +} + +/*when navigating through the items using the arrow keys:*/ +.autocomplete-active { + background-color: $cbp-focus-dark !important; + color: $cbp-text-base !important; + + & > strong { + color: $cbp-text-lightest !important; + font-weight: 700 !important; + } +} \ No newline at end of file From 456ebe4cd77cf8118b0ae440724ed5fe333f76c8 Mon Sep 17 00:00:00 2001 From: Danny Kim Date: Fri, 7 Oct 2022 11:32:18 -0400 Subject: [PATCH 2/3] chore: inital file upload component --- .../demo-components/input-group/index.html | 54 +++- ds-css-v2/js/cbp-components-js/fileupload.js | 133 +++++++++ .../styles/sass/cbp-components/_all.scss | 1 + .../sass/cbp-components/_fileupload.scss | 254 ++++++++++++++++++ 4 files changed, 440 insertions(+), 2 deletions(-) create mode 100644 ds-css-v2/js/cbp-components-js/fileupload.js create mode 100644 ds-css-v2/styles/sass/cbp-components/_fileupload.scss diff --git a/ds-css-v2/demo-components/input-group/index.html b/ds-css-v2/demo-components/input-group/index.html index 87dbc60f..5cd25165 100644 --- a/ds-css-v2/demo-components/input-group/index.html +++ b/ds-css-v2/demo-components/input-group/index.html @@ -158,7 +158,7 @@

Search Field w/ Predictive Text

-
+ + +
+
+
+ + Accepted files: .doc, .docx, .pdf, .jpg, .png, .gif. Max File size 10mb per file. Up to 5 files may be uploaded. + + + +
+
+ +
+

File Upload

+
+ + +
+
+ + +
+
+ + +
+