diff --git a/v2/components/autocomplete/autocomplete.scss b/v2/components/autocomplete/autocomplete.scss index cd42c450..9acf8758 100644 --- a/v2/components/autocomplete/autocomplete.scss +++ b/v2/components/autocomplete/autocomplete.scss @@ -10,9 +10,8 @@ z-index: 3; position: absolute; white-space: nowrap; - max-height: 6em; + max-height: 12em; overflow-y: auto; - margin-top: 0.5em; border-radius: 3px; background-color: white; border: 1px solid $argo-color-gray-4; @@ -21,6 +20,10 @@ box-shadow: 1px 2px 2px rgba(0, 0, 0, 0.05); line-height: 0.5em; + &--inverted { + bottom: 50px; + } + &__item { z-index: 2; padding: 0.75em 0; @@ -30,9 +33,17 @@ border-bottom: 1px solid $argo-color-gray-4; box-sizing: border-box; + &:hover, + &--selected { + border-radius: 3px; + } + + &:hover { + background-color: $argo-color-gray-3; + } + &--selected { - border-bottom: 1px solid $sky; - box-shadow: 0px 1px 0px 0px $sky; + background-color: $argo-color-teal-3; } } diff --git a/v2/components/autocomplete/autocomplete.tsx b/v2/components/autocomplete/autocomplete.tsx index aa91bc20..3bae6b54 100644 --- a/v2/components/autocomplete/autocomplete.tsx +++ b/v2/components/autocomplete/autocomplete.tsx @@ -1,4 +1,4 @@ -import {Key, KeybindingContext, useNav} from 'react-keyhooks'; +import {Key, KeybindingContext, KeybindingProvider, useNav} from 'react-keyhooks'; import * as React from 'react'; import {Input, InputProps, SetInputFxn, useDebounce, useInput} from '../input/input'; import ThemeDiv from '../theme-div/theme-div'; @@ -27,6 +27,22 @@ export const Autocomplete = ( icon?: string; inputref?: React.MutableRefObject; } +) => { + return ( + + + + ); +}; + +export const RenderAutocomplete = ( + props: React.InputHTMLAttributes & { + items: string[]; + inputStyle?: React.CSSProperties; + onItemClick?: (item: string) => void; + icon?: string; + inputref?: React.MutableRefObject; + } ) => { const [curItems, setCurItems] = React.useState(props.items || []); const nullInputRef = React.useRef(null); @@ -34,11 +50,13 @@ export const Autocomplete = ( const autocompleteRef = React.useRef(null); const [showSuggestions, setShowSuggestions] = React.useState(false); const [pos, nav, reset] = useNav(props.items.length); + const menuRef = React.useRef(null); React.useEffect(() => { function unfocus(e: any) { if (autocompleteRef.current && !autocompleteRef.current.contains(e.target)) { setShowSuggestions(false); + reset(); } } @@ -82,6 +100,7 @@ export const Autocomplete = ( useKeybinding(Key.ENTER, () => { if (showSuggestions && props.onItemClick) { props.onItemClick(curItems[pos]); + setShowSuggestions(false); return true; } return false; @@ -109,6 +128,38 @@ export const Autocomplete = ( delete trimmedProps.inputStyle; delete trimmedProps.onItemClick; + const [inverted, setInverted] = React.useState(false); + + const checkDirection = () => { + if (autocompleteRef && autocompleteRef.current && menuRef.current && !(event.target === menuRef.current)) { + const node = inputRef.current; + if (node && menuRef.current) { + const rect = node.getBoundingClientRect(); + const computedStyle = window.getComputedStyle(node); + const marginBottom = parseInt(computedStyle.marginBottom, 10) || 0; + let menuTop = rect.bottom + marginBottom; + if (window.innerHeight - (menuTop + menuRef.current.offsetHeight) < 30) { + if (!inverted) { + setInverted(true); + } + } else { + if (inverted) { + setInverted(false); + } + } + } + } + }; + + React.useEffect(() => { + document.addEventListener('scroll', checkDirection, true); + document.addEventListener('resize', checkDirection, true); + return () => { + document.removeEventListener('scroll', checkDirection); + document.removeEventListener('resize', checkDirection); + }; + }); + return (
setShowSuggestions(true)} + onFocus={() => { + checkDirection(); + setShowSuggestions(true); + }} /> - +
+ +
); }; diff --git a/v2/components/checkbox/checkbox.scss b/v2/components/checkbox/checkbox.scss index 792e17b0..724f6dfa 100644 --- a/v2/components/checkbox/checkbox.scss +++ b/v2/components/checkbox/checkbox.scss @@ -1,6 +1,23 @@ @import '../../styles/colors.scss'; .checkbox { + $size: 1.25em; + width: $size; + height: $size; + padding: 3px; + border: 2px solid $argo-color-gray-7; + border-radius: 3px; + display: flex; + align-items: center; + justify-content: center; + color: rgba(0, 0, 0, 0); + + &--selected { + border-color: $argo-color-teal-6; + background-color: $argo-color-teal-6; + color: white; + } + &__item { height: 2em; padding: 0 5px; @@ -24,9 +41,6 @@ background-color: $argo-color-teal-3; color: $argo-color-teal-8; font-weight: 500; - i { - color: $argo-color-teal-6; - } } } } diff --git a/v2/components/checkbox/checkbox.tsx b/v2/components/checkbox/checkbox.tsx index 6737f504..19ae4b51 100644 --- a/v2/components/checkbox/checkbox.tsx +++ b/v2/components/checkbox/checkbox.tsx @@ -24,7 +24,7 @@ export const Checkbox = (props: {value?: boolean; onChange?: (value: boolean) => syncValue(!value); }} style={props.style}> - + ); }; diff --git a/v2/package.json b/v2/package.json index c3cc436d..12f99681 100644 --- a/v2/package.json +++ b/v2/package.json @@ -1,6 +1,6 @@ { "name": "argo-ux", - "version": "1.1.13", + "version": "1.1.15", "main": "index.js", "license": "MIT", "dependencies": { @@ -17,9 +17,7 @@ "portable-fetch": "^3.0.0", "react-helmet": "^6.1.0", "react-hot-loader": "^3.1.3", - "react-keyhooks": "^0.2.2", "react-router-dom": "^5.2.0", - "typescript": "^4.1.2", "web-vitals": "^1.0.1", "webpack-dev-server": "^3.11.2" @@ -28,7 +26,8 @@ "moment": "^2.29.1", "react": "^16.9.3", "react-dom": "^16.9.3", - "rxjs": "^6.6.6" + "rxjs": "^6.6.6", + "react-keyhooks": "^0.2.2" }, "scripts": { "start": "start-storybook", @@ -58,7 +57,6 @@ }, "devDependencies": { "@babel/core": "^7.14.0", - "dtslint": "^4.0.9", "@storybook/addon-actions": "^6.2.9", "@storybook/addon-controls": "^6.2.9", "@storybook/addon-essentials": "^6.2.9", @@ -67,10 +65,13 @@ "@storybook/react": "^6.2.9", "babel-loader": "^8.2.2", "copy-webpack-plugin": "^6.3.2", + "dtslint": "^4.0.9", "mini-css-extract-plugin": "^1.3.9", "raw-loader": "^4.0.2", - "react-dom": "^16.9.3", "react": "^16.9.3", + "react-dom": "^16.9.3", + "react-keyhooks": "^0.2.2", + "rxjs": "^6.6.6", "sass": "^1.32.8", "sass-loader": "^10.1.1", "storybook": "^6.2.9", diff --git a/v2/utils/utils.tsx b/v2/utils/utils.tsx index 5a53053d..5c9f5c25 100644 --- a/v2/utils/utils.tsx +++ b/v2/utils/utils.tsx @@ -78,3 +78,14 @@ export const useTimeout = (fx: () => void, timeoutMs: number, dependencies: any[ return () => clearInterval(to); }, dependencies); }; + +export const debounce = (fxn: () => any, ms: number) => { + let timer: any; + return () => { + clearTimeout(timer); + timer = setTimeout(() => { + timer = null; + fxn.apply(this); + }, ms); + }; +}; diff --git a/v2/yarn.lock b/v2/yarn.lock index 07f2c42a..63890821 100644 --- a/v2/yarn.lock +++ b/v2/yarn.lock @@ -9820,6 +9820,13 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" +rxjs@^6.6.6: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + safe-buffer@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -10935,7 +10942,7 @@ ts-pnp@^1.1.6: resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== -tslib@^1.8.0, tslib@^1.8.1: +tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==