diff --git a/src/components/Atoms/TextInputWithDropdown/TextInputWithDropdown.js b/src/components/Atoms/TextInputWithDropdown/TextInputWithDropdown.js
index 69cfbcb4f..c03e8a530 100644
--- a/src/components/Atoms/TextInputWithDropdown/TextInputWithDropdown.js
+++ b/src/components/Atoms/TextInputWithDropdown/TextInputWithDropdown.js
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from 'react';
+import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import Input from '../Input/Input';
@@ -7,7 +7,6 @@ import {
Container,
Dropdown,
DropdownList,
- DropdownItem,
DropdownItemSelectable,
TextItalic
} from './TextInputWithDropdown.style';
@@ -37,16 +36,44 @@ const TextInputWithDropdown = React.forwardRef(
label,
dropdownInstruction = null,
className = '',
+ hideBorder = false,
...otherInputProps
},
- ref
+ forwardedRef
) => {
const [activeOption, setActiveOption] = useState(-1);
const [forceClosed, setForceClosed] = useState(false);
+ const dropdownRef = useRef(null);
+ const containerRef = useRef(null);
+
useEffect(() => {
- // reset if options change
+ const handleClickOutside = event => {
+ if (dropdownRef.current
+ && !dropdownRef.current.contains(event.target)
+ && !containerRef.current.contains(event.target)) {
+ setForceClosed(true);
+ }
+ };
+
+ // Only add the listeners if we have options showing
+ if (options.length > 0 && !forceClosed) {
+ ['mousedown', 'touchstart'].forEach(event => document.addEventListener(event, handleClickOutside));
+ }
+
+ return () => {
+ ['mousedown', 'touchstart'].forEach(event => document.removeEventListener(event, handleClickOutside));
+ };
+ }, [options.length, forceClosed, onChange]);
+
+ const closeDropdown = () => {
+ setForceClosed(true);
setActiveOption(-1);
+ };
+
+ // Reset forceClosed when options change
+ useEffect(() => {
setForceClosed(false);
+ setActiveOption(-1);
}, [options]);
const down = () => (activeOption < options.length - 1
@@ -89,6 +116,7 @@ const TextInputWithDropdown = React.forwardRef(
onSelect,
dropdownInstruction,
activeOption,
+ closeDropdown,
resetActiveOption: () => setActiveOption(-1)
};
@@ -96,16 +124,19 @@ const TextInputWithDropdown = React.forwardRef(
- {options.length > 0 && forceClosed === false && (
+ {options.length > 0 && !forceClosed && (
)}
@@ -113,14 +144,15 @@ const TextInputWithDropdown = React.forwardRef(
}
);
-const Options = ({
+const Options = React.forwardRef(({
options,
dropdownInstruction,
onSelect,
activeOption,
+ closeDropdown,
resetActiveOption,
...rest
-}) => {
+}, ref) => {
// Reset 'activeOption' when the list is unfocused.
const onBlur = e => {
const { target } = e;
@@ -136,6 +168,7 @@ const Options = ({
return (
{dropdownInstruction && (
-
- {dropdownInstruction}
-
+
+
+ {dropdownInstruction}
+
+
)}
{options.map((option, index) => (
);
-};
+});
TextInputWithDropdown.propTypes = {
options: PropTypes.arrayOf(PropTypes.string).isRequired,
@@ -183,7 +223,8 @@ TextInputWithDropdown.propTypes = {
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
className: PropTypes.string,
- dropdownInstruction: PropTypes.string
+ dropdownInstruction: PropTypes.string,
+ hideBorder: PropTypes.bool
};
Options.propTypes = {
@@ -191,7 +232,11 @@ Options.propTypes = {
onSelect: PropTypes.func.isRequired,
dropdownInstruction: PropTypes.string,
activeOption: PropTypes.number.isRequired,
- resetActiveOption: PropTypes.func.isRequired
+ resetActiveOption: PropTypes.func.isRequired,
+ hideBorder: PropTypes.bool,
+ closeDropdown: PropTypes.func
};
+TextInputWithDropdown.displayName = 'TextInputWithDropdown';
+
export default TextInputWithDropdown;
diff --git a/src/components/Atoms/TextInputWithDropdown/TextInputWithDropdown.style.js b/src/components/Atoms/TextInputWithDropdown/TextInputWithDropdown.style.js
index 92cd0614f..d2e4ad0bf 100644
--- a/src/components/Atoms/TextInputWithDropdown/TextInputWithDropdown.style.js
+++ b/src/components/Atoms/TextInputWithDropdown/TextInputWithDropdown.style.js
@@ -16,7 +16,7 @@ const Dropdown = styled.div`
max-height: 300px;
overflow: auto;
background-color: ${({ theme }) => theme.color('white')};
- border: 1px solid;
+ border: ${({ hideBorder }) => (hideBorder ? 'none' : '1px solid')};
margin-top: -1px;
width: 100%;
diff --git a/src/components/Molecules/SchoolLookup/SchoolLookup.js b/src/components/Molecules/SchoolLookup/SchoolLookup.js
index a2164b80e..192371d5f 100644
--- a/src/components/Molecules/SchoolLookup/SchoolLookup.js
+++ b/src/components/Molecules/SchoolLookup/SchoolLookup.js
@@ -25,6 +25,7 @@ const SchoolLookup = React.forwardRef(
dropdownInstruction = 'Please select a school from the list below',
notFoundMessage = "Sorry, we can't find this school",
onSelect,
+ hideBorder = false,
...rest
},
ref
@@ -39,6 +40,7 @@ const SchoolLookup = React.forwardRef(
placeholder,
notFoundMessage,
dropdownInstruction,
+ hideBorder,
...rest
};
@@ -52,7 +54,10 @@ SchoolLookup.propTypes = {
label: PropTypes.string,
placeholder: PropTypes.string,
dropdownInstruction: PropTypes.string,
- notFoundMessage: PropTypes.string
+ notFoundMessage: PropTypes.string,
+ hideBorder: PropTypes.bool
};
+SchoolLookup.displayName = 'SchoolLookup';
+
export default SchoolLookup;