Skip to content

Commit

Permalink
fix: Minor updates and fixes to Checkbox and Autocomplete components (#…
Browse files Browse the repository at this point in the history
…111)

Signed-off-by: Remington Breeze <remington@breeze.software>
  • Loading branch information
rbreeze authored Jul 1, 2021
1 parent fe799c5 commit fecc293
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 33 deletions.
19 changes: 15 additions & 4 deletions v2/components/autocomplete/autocomplete.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}
}

Expand Down
92 changes: 74 additions & 18 deletions v2/components/autocomplete/autocomplete.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -27,18 +27,36 @@ export const Autocomplete = (
icon?: string;
inputref?: React.MutableRefObject<HTMLInputElement>;
}
) => {
return (
<KeybindingProvider>
<RenderAutocomplete {...props} />
</KeybindingProvider>
);
};

export const RenderAutocomplete = (
props: React.InputHTMLAttributes<HTMLInputElement> & {
items: string[];
inputStyle?: React.CSSProperties;
onItemClick?: (item: string) => void;
icon?: string;
inputref?: React.MutableRefObject<HTMLInputElement>;
}
) => {
const [curItems, setCurItems] = React.useState(props.items || []);
const nullInputRef = React.useRef<HTMLInputElement>(null);
const inputRef = props.inputref || nullInputRef;
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();
}
}

Expand Down Expand Up @@ -82,6 +100,7 @@ export const Autocomplete = (
useKeybinding(Key.ENTER, () => {
if (showSuggestions && props.onItemClick) {
props.onItemClick(curItems[pos]);
setShowSuggestions(false);
return true;
}
return false;
Expand Down Expand Up @@ -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 (
<div className='autocomplete' ref={autocompleteRef} style={style as any}>
<Input
Expand All @@ -121,24 +172,29 @@ export const Autocomplete = (
props.onChange(e);
}
}}
onFocus={() => setShowSuggestions(true)}
onFocus={() => {
checkDirection();
setShowSuggestions(true);
}}
/>
<ThemeDiv className='autocomplete__items' hidden={!showSuggestions || (props.items || []).length < 1}>
{(curItems || []).map((i, n) => (
<div
key={i}
onClick={() => {
if (props.onItemClick) {
props.onItemClick(i);
}
props.onChange({target: {value: i}} as React.ChangeEvent<HTMLInputElement>);
setShowSuggestions(false);
}}
className={`autocomplete__items__item ${pos === n ? 'autocomplete__items__item--selected' : ''}`}>
{i}
</div>
))}
</ThemeDiv>
<div ref={menuRef}>
<ThemeDiv className={`autocomplete__items ${inverted ? 'autocomplete__items--inverted' : ''}`} hidden={!showSuggestions || (props.items || []).length < 1}>
{(curItems || []).map((i, n) => (
<div
key={i}
onClick={() => {
props.onChange({target: {value: i}} as React.ChangeEvent<HTMLInputElement>);
setShowSuggestions(false);
if (props.onItemClick) {
props.onItemClick(i);
}
}}
className={`autocomplete__items__item ${pos === n ? 'autocomplete__items__item--selected' : ''}`}>
{i}
</div>
))}
</ThemeDiv>
</div>
</div>
);
};
20 changes: 17 additions & 3 deletions v2/components/checkbox/checkbox.scss
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -24,9 +41,6 @@
background-color: $argo-color-teal-3;
color: $argo-color-teal-8;
font-weight: 500;
i {
color: $argo-color-teal-6;
}
}
}
}
2 changes: 1 addition & 1 deletion v2/components/checkbox/checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const Checkbox = (props: {value?: boolean; onChange?: (value: boolean) =>
syncValue(!value);
}}
style={props.style}>
<i className={`fa fa-${value ? 'check-square' : 'square'}`} />
<i className='fa fa-check' />
</div>
);
};
Expand Down
13 changes: 7 additions & 6 deletions v2/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "argo-ux",
"version": "1.1.13",
"version": "1.1.15",
"main": "index.js",
"license": "MIT",
"dependencies": {
Expand All @@ -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"
Expand All @@ -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",
Expand Down Expand Up @@ -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",
Expand All @@ -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",
Expand Down
11 changes: 11 additions & 0 deletions v2/utils/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
};
9 changes: 8 additions & 1 deletion v2/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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==
Expand Down

0 comments on commit fecc293

Please sign in to comment.