SuggestiveInput
is a React component designed to provide autocomplete functionality. It allows users to type in an input field and dynamically receive suggestions based on their input, improving user experience and efficiency.
- Debounced fetching of suggestions for efficient performance.
- Customizable suggestion fetching function.
- Keyboard navigation for selecting suggestions.
- Customizable styling via a classes object.
- Support for loading and "no match" states with custom render options.
Install the package via npm or yarn:
npm install @mithya-team/suggestive-input-plugin
or
yarn add @mithya-team/suggestive-input-plugin
To use the SuggestiveInput
component, you'll need to have a function ready to fetch suggestions, typically from an API or a local source. Here's a basic example:
import React from "react";
import SuggestiveInput from "@mithya-team/suggestive-input-plugin";
const App = () => {
const handleSelection = (value) => {
console.log("User selected:", value);
};
const fetchSuggestions = async (input) => {
// Replace with actual suggestion logic
return ["apple", "banana", "cherry"].filter((item) => item.includes(input));
};
return (
<SuggestiveInput
fetchSuggestions={fetchSuggestions}
onSelection={handleSelection}
classes={{
root: "suggestive-input-root",
input: "suggestive-input-input",
suggestionList: "suggestive-input-list",
suggestionItem: "suggestive-input-item",
highlighted: "suggestive-input-highlighted",
}}
/>
);
};
export default App;
import React from "react";
import { useForm, Controller } from "react-hook-form";
import { SuggestiveInput } from "@mithya-team/suggestive-input-plugin";
const mockFetchSuggestions = async (input: string): Promise<string[]> => {
const allSuggestions = ["apple", "banana", "cherry", "date", "eggfruit"];
return allSuggestions.filter((suggestion) =>
suggestion.toLowerCase().includes(input.toLowerCase())
);
};
export const ReactFormExample: React.FC = () => {
const { control, handleSubmit } = useForm({
defaultValues: {
suggestiveInput: "", // Ensure this default value is aligned with the name given to the Controller
},
});
const onSubmit = (data: Record<string, unknown>) => {
console.log("Form Data: ", data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="suggestiveInput" // Ensure this name matches the key in defaultValues
control={control}
render={({ field }) => (
<SuggestiveInput
fetchSuggestions={mockFetchSuggestions}
onSelection={field.onChange} // Directly using field.onChange for selection
debounceTime={300}
defaultValue={field.value} // Using field.value for overriding components default value
classes={{
root: "suggestive-input-root",
input: "suggestive-input-input",
suggestionList: "suggestive-input-list",
suggestionItem: "suggestive-input-item",
highlighted: "suggestive-input-highlighted",
activeSuggestion: "suggestive-input-item-active",
}}
allowStrictSelection={false}
/>
)}
/>
<input type="submit" value="Submit" />
</form>
);
};
export default ReactFormExample;
export interface SuggestiveInputProps {
fetchSuggestions: (input: string) => Promise<string[]> | string[];
onSelection: (value: string) => void;
debounceTime?: number;
defaultValue?: string;
classes?: {
root?: string;
input?: string;
suggestionList?: string;
suggestionItem?: string;
activeSuggestion?: string;
highlighted?: string; // For highlighting matching parts of suggestions
noSuggestions?: string; // For styling the no suggestions message
loading?: string; // For styling the loading message
};
loadingComponent?: React.ReactNode; // Custom component for loading state
noSuggestionsComponent?: React.ReactNode; // Custom component when no suggestions found
allowStrictSelection?: boolean; // allow output to strictly match any option from suggestions
}
Here are CSS rules you might want to override for the default classes:
/* Root of the component */
.suggestive-input--root {
position: relative;
width: 300px; /* Adjust the width as needed */
}
/* Input field styling */
.suggestive-input--input {
width: 100%;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
}
/* Suggestion list styling */
.suggestive-input--list {
list-style: none;
margin: 0;
padding: 0;
position: absolute;
width: 100%;
background: white;
border: 1px solid #ccc;
border-top: none; /* Make it look connected to the input */
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
max-height: 200px; /* Adjust based on your need */
overflow-y: auto; /* Enable scroll if list is too long */
z-index: 1000; /* Ensure it's above other elements */
}
.suggestive-input--loading {
}
.suggestive-input--no-suggestion {
}
/* Individual suggestion item */
.suggestive-input--item {
padding: 8px;
cursor: pointer;
border-bottom: 1px solid #eee; /* subtle separator */
}
/* Highlighted text within suggestions */
.suggestive-input--highlighted {
background-color: yellow; /* Highlight color */
font-weight: bold; /* Make it bold */
}
/* Suggestion item - Hover and Active States */
.suggestive-input--item:hover,
.suggestive-input--item:active,
.suggestive-input--item.active {
/* class for active suggestion */
background-color: #f0f0f0; /* Slightly darker on hover */
}
.suggestive-input-item--active {
background-color: #f0f0f0; /* Highlight color */
}
The component can be fully customized via the classes
prop.
<SuggestiveInput
...
...
classes={{
root: "suggestive-input-root",
input: "suggestive-input-input",
suggestionList: "suggestive-input-list",
suggestionItem: "suggestive-input-item",
highlighted: "suggestive-input-highlighted",
activeSuggestion: "suggestive-input-item-active",
}}
...
/>
Checkout the playground code for implementation
Contributions are always welcome! If you encounter any issues or would like to contribute, please file an issue or submit a PR:
Issues: GitHub Issues Pull Requests: GitHub Pull Requests