Skip to content

Commit fecc293

Browse files
authored
fix: Minor updates and fixes to Checkbox and Autocomplete components (#111)
Signed-off-by: Remington Breeze <[email protected]>
1 parent fe799c5 commit fecc293

File tree

7 files changed

+133
-33
lines changed

7 files changed

+133
-33
lines changed

v2/components/autocomplete/autocomplete.scss

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@
1010
z-index: 3;
1111
position: absolute;
1212
white-space: nowrap;
13-
max-height: 6em;
13+
max-height: 12em;
1414
overflow-y: auto;
15-
margin-top: 0.5em;
1615
border-radius: 3px;
1716
background-color: white;
1817
border: 1px solid $argo-color-gray-4;
@@ -21,6 +20,10 @@
2120
box-shadow: 1px 2px 2px rgba(0, 0, 0, 0.05);
2221
line-height: 0.5em;
2322

23+
&--inverted {
24+
bottom: 50px;
25+
}
26+
2427
&__item {
2528
z-index: 2;
2629
padding: 0.75em 0;
@@ -30,9 +33,17 @@
3033
border-bottom: 1px solid $argo-color-gray-4;
3134
box-sizing: border-box;
3235

36+
&:hover,
37+
&--selected {
38+
border-radius: 3px;
39+
}
40+
41+
&:hover {
42+
background-color: $argo-color-gray-3;
43+
}
44+
3345
&--selected {
34-
border-bottom: 1px solid $sky;
35-
box-shadow: 0px 1px 0px 0px $sky;
46+
background-color: $argo-color-teal-3;
3647
}
3748
}
3849

v2/components/autocomplete/autocomplete.tsx

Lines changed: 74 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Key, KeybindingContext, useNav} from 'react-keyhooks';
1+
import {Key, KeybindingContext, KeybindingProvider, useNav} from 'react-keyhooks';
22
import * as React from 'react';
33
import {Input, InputProps, SetInputFxn, useDebounce, useInput} from '../input/input';
44
import ThemeDiv from '../theme-div/theme-div';
@@ -27,18 +27,36 @@ export const Autocomplete = (
2727
icon?: string;
2828
inputref?: React.MutableRefObject<HTMLInputElement>;
2929
}
30+
) => {
31+
return (
32+
<KeybindingProvider>
33+
<RenderAutocomplete {...props} />
34+
</KeybindingProvider>
35+
);
36+
};
37+
38+
export const RenderAutocomplete = (
39+
props: React.InputHTMLAttributes<HTMLInputElement> & {
40+
items: string[];
41+
inputStyle?: React.CSSProperties;
42+
onItemClick?: (item: string) => void;
43+
icon?: string;
44+
inputref?: React.MutableRefObject<HTMLInputElement>;
45+
}
3046
) => {
3147
const [curItems, setCurItems] = React.useState(props.items || []);
3248
const nullInputRef = React.useRef<HTMLInputElement>(null);
3349
const inputRef = props.inputref || nullInputRef;
3450
const autocompleteRef = React.useRef(null);
3551
const [showSuggestions, setShowSuggestions] = React.useState(false);
3652
const [pos, nav, reset] = useNav(props.items.length);
53+
const menuRef = React.useRef(null);
3754

3855
React.useEffect(() => {
3956
function unfocus(e: any) {
4057
if (autocompleteRef.current && !autocompleteRef.current.contains(e.target)) {
4158
setShowSuggestions(false);
59+
reset();
4260
}
4361
}
4462

@@ -82,6 +100,7 @@ export const Autocomplete = (
82100
useKeybinding(Key.ENTER, () => {
83101
if (showSuggestions && props.onItemClick) {
84102
props.onItemClick(curItems[pos]);
103+
setShowSuggestions(false);
85104
return true;
86105
}
87106
return false;
@@ -109,6 +128,38 @@ export const Autocomplete = (
109128
delete trimmedProps.inputStyle;
110129
delete trimmedProps.onItemClick;
111130

131+
const [inverted, setInverted] = React.useState(false);
132+
133+
const checkDirection = () => {
134+
if (autocompleteRef && autocompleteRef.current && menuRef.current && !(event.target === menuRef.current)) {
135+
const node = inputRef.current;
136+
if (node && menuRef.current) {
137+
const rect = node.getBoundingClientRect();
138+
const computedStyle = window.getComputedStyle(node);
139+
const marginBottom = parseInt(computedStyle.marginBottom, 10) || 0;
140+
let menuTop = rect.bottom + marginBottom;
141+
if (window.innerHeight - (menuTop + menuRef.current.offsetHeight) < 30) {
142+
if (!inverted) {
143+
setInverted(true);
144+
}
145+
} else {
146+
if (inverted) {
147+
setInverted(false);
148+
}
149+
}
150+
}
151+
}
152+
};
153+
154+
React.useEffect(() => {
155+
document.addEventListener('scroll', checkDirection, true);
156+
document.addEventListener('resize', checkDirection, true);
157+
return () => {
158+
document.removeEventListener('scroll', checkDirection);
159+
document.removeEventListener('resize', checkDirection);
160+
};
161+
});
162+
112163
return (
113164
<div className='autocomplete' ref={autocompleteRef} style={style as any}>
114165
<Input
@@ -121,24 +172,29 @@ export const Autocomplete = (
121172
props.onChange(e);
122173
}
123174
}}
124-
onFocus={() => setShowSuggestions(true)}
175+
onFocus={() => {
176+
checkDirection();
177+
setShowSuggestions(true);
178+
}}
125179
/>
126-
<ThemeDiv className='autocomplete__items' hidden={!showSuggestions || (props.items || []).length < 1}>
127-
{(curItems || []).map((i, n) => (
128-
<div
129-
key={i}
130-
onClick={() => {
131-
if (props.onItemClick) {
132-
props.onItemClick(i);
133-
}
134-
props.onChange({target: {value: i}} as React.ChangeEvent<HTMLInputElement>);
135-
setShowSuggestions(false);
136-
}}
137-
className={`autocomplete__items__item ${pos === n ? 'autocomplete__items__item--selected' : ''}`}>
138-
{i}
139-
</div>
140-
))}
141-
</ThemeDiv>
180+
<div ref={menuRef}>
181+
<ThemeDiv className={`autocomplete__items ${inverted ? 'autocomplete__items--inverted' : ''}`} hidden={!showSuggestions || (props.items || []).length < 1}>
182+
{(curItems || []).map((i, n) => (
183+
<div
184+
key={i}
185+
onClick={() => {
186+
props.onChange({target: {value: i}} as React.ChangeEvent<HTMLInputElement>);
187+
setShowSuggestions(false);
188+
if (props.onItemClick) {
189+
props.onItemClick(i);
190+
}
191+
}}
192+
className={`autocomplete__items__item ${pos === n ? 'autocomplete__items__item--selected' : ''}`}>
193+
{i}
194+
</div>
195+
))}
196+
</ThemeDiv>
197+
</div>
142198
</div>
143199
);
144200
};

v2/components/checkbox/checkbox.scss

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
@import '../../styles/colors.scss';
22

33
.checkbox {
4+
$size: 1.25em;
5+
width: $size;
6+
height: $size;
7+
padding: 3px;
8+
border: 2px solid $argo-color-gray-7;
9+
border-radius: 3px;
10+
display: flex;
11+
align-items: center;
12+
justify-content: center;
13+
color: rgba(0, 0, 0, 0);
14+
15+
&--selected {
16+
border-color: $argo-color-teal-6;
17+
background-color: $argo-color-teal-6;
18+
color: white;
19+
}
20+
421
&__item {
522
height: 2em;
623
padding: 0 5px;
@@ -24,9 +41,6 @@
2441
background-color: $argo-color-teal-3;
2542
color: $argo-color-teal-8;
2643
font-weight: 500;
27-
i {
28-
color: $argo-color-teal-6;
29-
}
3044
}
3145
}
3246
}

v2/components/checkbox/checkbox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const Checkbox = (props: {value?: boolean; onChange?: (value: boolean) =>
2424
syncValue(!value);
2525
}}
2626
style={props.style}>
27-
<i className={`fa fa-${value ? 'check-square' : 'square'}`} />
27+
<i className='fa fa-check' />
2828
</div>
2929
);
3030
};

v2/package.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "argo-ux",
3-
"version": "1.1.13",
3+
"version": "1.1.15",
44
"main": "index.js",
55
"license": "MIT",
66
"dependencies": {
@@ -17,9 +17,7 @@
1717
"portable-fetch": "^3.0.0",
1818
"react-helmet": "^6.1.0",
1919
"react-hot-loader": "^3.1.3",
20-
"react-keyhooks": "^0.2.2",
2120
"react-router-dom": "^5.2.0",
22-
2321
"typescript": "^4.1.2",
2422
"web-vitals": "^1.0.1",
2523
"webpack-dev-server": "^3.11.2"
@@ -28,7 +26,8 @@
2826
"moment": "^2.29.1",
2927
"react": "^16.9.3",
3028
"react-dom": "^16.9.3",
31-
"rxjs": "^6.6.6"
29+
"rxjs": "^6.6.6",
30+
"react-keyhooks": "^0.2.2"
3231
},
3332
"scripts": {
3433
"start": "start-storybook",
@@ -58,7 +57,6 @@
5857
},
5958
"devDependencies": {
6059
"@babel/core": "^7.14.0",
61-
"dtslint": "^4.0.9",
6260
"@storybook/addon-actions": "^6.2.9",
6361
"@storybook/addon-controls": "^6.2.9",
6462
"@storybook/addon-essentials": "^6.2.9",
@@ -67,10 +65,13 @@
6765
"@storybook/react": "^6.2.9",
6866
"babel-loader": "^8.2.2",
6967
"copy-webpack-plugin": "^6.3.2",
68+
"dtslint": "^4.0.9",
7069
"mini-css-extract-plugin": "^1.3.9",
7170
"raw-loader": "^4.0.2",
72-
"react-dom": "^16.9.3",
7371
"react": "^16.9.3",
72+
"react-dom": "^16.9.3",
73+
"react-keyhooks": "^0.2.2",
74+
"rxjs": "^6.6.6",
7475
"sass": "^1.32.8",
7576
"sass-loader": "^10.1.1",
7677
"storybook": "^6.2.9",

v2/utils/utils.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,14 @@ export const useTimeout = (fx: () => void, timeoutMs: number, dependencies: any[
7878
return () => clearInterval(to);
7979
}, dependencies);
8080
};
81+
82+
export const debounce = (fxn: () => any, ms: number) => {
83+
let timer: any;
84+
return () => {
85+
clearTimeout(timer);
86+
timer = setTimeout(() => {
87+
timer = null;
88+
fxn.apply(this);
89+
}, ms);
90+
};
91+
};

v2/yarn.lock

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9820,6 +9820,13 @@ run-queue@^1.0.0, run-queue@^1.0.3:
98209820
dependencies:
98219821
aproba "^1.1.1"
98229822

9823+
rxjs@^6.6.6:
9824+
version "6.6.7"
9825+
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
9826+
integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
9827+
dependencies:
9828+
tslib "^1.9.0"
9829+
98239830
98249831
version "5.1.1"
98259832
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
@@ -10935,7 +10942,7 @@ ts-pnp@^1.1.6:
1093510942
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
1093610943
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
1093710944

10938-
tslib@^1.8.0, tslib@^1.8.1:
10945+
tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
1093910946
version "1.14.1"
1094010947
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
1094110948
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==

0 commit comments

Comments
 (0)