Skip to content

Commit a4777ad

Browse files
committed
wip
1 parent d8a90c1 commit a4777ad

File tree

6 files changed

+96
-40
lines changed

6 files changed

+96
-40
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React from "react"
2+
import Drop from "@/components/drops/drop"
3+
import Options from "./options"
4+
import useAutocomplete from "./useAutocomplete"
5+
6+
const Autocomplete = ({ value, autocompleteProps, tagretRef }) => {
7+
const { autocompleteOpen, suggestions } = useAutocomplete({ value, autocompleteProps })
8+
9+
return (
10+
autocompleteOpen &&
11+
tagretRef?.current && (
12+
<Drop
13+
width={60}
14+
target={tagretRef.current}
15+
align={{ top: "bottom", left: "left" }}
16+
animation
17+
background="inputBg"
18+
margin={[1, 0, 0]}
19+
round={1}
20+
close={() => {}}
21+
onClickOutside={() => {}}
22+
onEsc={() => {}}
23+
>
24+
<Options suggestions={suggestions} />
25+
</Drop>
26+
)
27+
)
28+
}
29+
30+
export default Autocomplete
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from "react"
2+
import { StyledOption } from "./styled"
3+
4+
const Options = ({ suggestions = [] } = {}) => {
5+
return (
6+
<ul id="autocomplete-list" role="listbox">
7+
{suggestions.map(({ value, label }) => (
8+
<StyledOption key={value} role="option">
9+
{label}
10+
</StyledOption>
11+
))}
12+
</ul>
13+
)
14+
}
15+
16+
export default Options
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import styled from "styled-components"
2+
3+
export const StyledOption = styled.li`
4+
&:hover {
5+
background-color: red;
6+
}
7+
8+
&:focus {
9+
background-color: red;
10+
}
11+
`
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { useState, useEffect } from "react"
2+
3+
const useAutocomplete = ({ value, autocompleteProps = {} } = {}) => {
4+
const [autocompleteOpen, setAutocompleteOpen] = useState()
5+
const { suggestions = [] } = autocompleteProps || {}
6+
7+
useEffect(() => {
8+
if (suggestions.length) {
9+
setAutocompleteOpen(!!value.length)
10+
}
11+
}, [suggestions, value, setAutocompleteOpen])
12+
13+
return { autocompleteOpen, suggestions }
14+
}
15+
16+
export default useAutocomplete

src/components/input/input.js

Lines changed: 18 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
import React, { useRef } from "react"
1+
import React, { useRef, useMemo } from "react"
22
import Flex from "@/components/templates/flex"
33
import { TextMicro } from "@/components/typography"
4-
import Drop from "@/components/drops/drop"
54
import { Input, LabelText } from "./styled"
6-
import { useEffect } from "react"
7-
import { useState } from "react"
5+
import Autocomplete from "./autocomplete"
86

97
const Error = ({ error }) => {
108
const errorMessage = error === true ? "invalid" : error
@@ -16,18 +14,6 @@ const Error = ({ error }) => {
1614
)
1715
}
1816

19-
const Suggestions = ({ suggestions = [] } = {}) => {
20-
return (
21-
<ul role="listbox">
22-
{suggestions.map(({ value, label }) => (
23-
<li key={value} role="option">
24-
{label}
25-
</li>
26-
))}
27-
</ul>
28-
)
29-
}
30-
3117
export const TextInput = ({
3218
error,
3319
disabled,
@@ -51,14 +37,17 @@ export const TextInput = ({
5137
...props
5238
}) => {
5339
const inputContainerRef = useRef()
54-
const [autocompleteOpen, setAutocompleteOpen] = useState()
55-
const { suggestions = [] } = autocompleteProps || {}
5640

57-
useEffect(() => {
58-
if (suggestions.length) {
59-
setAutocompleteOpen(!!value.length)
60-
}
61-
}, [suggestions, value, setAutocompleteOpen])
41+
const autocompleteInputProps = useMemo(
42+
() =>
43+
autocompleteProps
44+
? {
45+
"aria-autocomplete": "list",
46+
"aria-controls": "autocomplete-list",
47+
}
48+
: {},
49+
[]
50+
)
6251

6352
return (
6453
<Flex gap={0.5} column className={className} {...containerStyles} as="label">
@@ -85,6 +74,7 @@ export const TextInput = ({
8574
ref={inputRef}
8675
error={error}
8776
hasValue={!!value}
77+
{...autocompleteInputProps}
8878
{...props}
8979
/>
9080

@@ -97,22 +87,11 @@ export const TextInput = ({
9787
</Flex>
9888
{typeof hint === "string" ? <TextMicro color="textLite">{hint}</TextMicro> : !!hint && hint}
9989
{!hideErrorMessage ? <Error error={error} /> : null}
100-
{autocompleteOpen && inputContainerRef?.current && (
101-
<Drop
102-
width={60}
103-
target={inputContainerRef.current}
104-
align={{ top: "bottom", left: "left" }}
105-
animation
106-
background="inputBg"
107-
margin={[1, 0, 0]}
108-
round={1}
109-
close={() => {}}
110-
onClickOutside={() => {}}
111-
onEsc={() => {}}
112-
>
113-
<Suggestions suggestions={suggestions} />
114-
</Drop>
115-
)}
90+
<Autocomplete
91+
value={value}
92+
autocompleteProps={autocompleteProps}
93+
tagretRef={inputContainerRef}
94+
/>
11695
</Flex>
11796
)
11897
}

src/components/input/input.stories.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ export const Basic = args => <TextInput {...args} />
1616
export const WithAutocomplete = () => {
1717
const [value, setValue] = useState("")
1818
const autocompleteProps = {
19-
suggestions: [{ value: "one", label: "one" }],
19+
suggestions: [
20+
{ value: "one", label: "one" },
21+
{ value: "two", label: "two" },
22+
{ value: "three", label: "three" },
23+
],
2024
}
2125

2226
return (

0 commit comments

Comments
 (0)