DEV Community

Cover image for Provide a preview of the suggestion as users type in a text area
Phuoc Nguyen
Phuoc Nguyen

Posted on • Originally published at phuoc.ng

Provide a preview of the suggestion as users type in a text area

In our last post, we introduced an autocomplete feature. Today, we'll take it to the next level by adding a preview of the suggestion inline and giving users the ability to insert the suggestion with just a press of the Tab key. This pattern is commonly used in popular email clients, like Gmail.

Get ready to learn how to implement this awesome functionality!

Preparing the mirrored element

In the previous post, we displayed a list of suggestions when the cursor was at the end of the text area. But to show a preview of the suggestion inline without disrupting the current textarea content, we only displayed a single suggestion. To check if the cursor is at the end of the text area, we compared the selectionStart property with the length of the text area value.

const currentValue = textarea.value;
const cursorPos = textarea.selectionStart;
if (cursorPos !== currentValue.length) {
    // Hide the suggestion if there is ...
    return;
}
Enter fullscreen mode Exit fullscreen mode

To create a mirrored element of the text area, we used three elements: two text nodes representing the text before and after the cursor, and an empty span element representing the current caret. But since we can't customize the appearance of a text node, we replaced the text nodes with span elements.

The elements before and after the cursor are two span elements that represent the text before and after the cursor. We've updated the post-cursor element so that it now displays the first matching suggestion instead of the entire text before the cursor. This way, users can see the suggestion that's coming up next.

To simplify the process, we choose the first suggestion that matches the word being typed. However, it's up to you to decide which suggestion best matches the keyword and implement your own mechanism accordingly.

const currentValue = textarea.value;
const cursorPos = textarea.selectionStart;
const textBeforeCursor = currentValue.substring(0, cursorPos);

const preCursorEle = document.createElement('span');
preCursorEle.textContent = textBeforeCursor;
preCursorEle.classList.add('container__pre-cursor');

const postCursorEle = document.createElement('span');
postCursorEle.classList.add('container__post-cursor');

// Fill the element after the cursor with a single suggestion
postCursorEle.textContent = matches[0];

const caretEle = document.createElement('span');
caretEle.innerHTML = ' ';

mirroredEle.innerHTML = '';
mirroredEle.append(preCursorEle, caretEle, postCursorEle);
Enter fullscreen mode Exit fullscreen mode

To style the elements before and after the cursor, we added classes called container__pre-cursor and container__post-cursor, respectively. We made the text before the cursor invisible by setting the color property of the container__pre-cursor class to transparent. To make the suggested text stand out from the current content, we made it slightly blurry by setting the opacity property of the container__post-cursor class.

Here's an example of how these classes could look:

.container__pre-cursor {
    color: transparent;
}
.container__post-cursor {
    opacity: 0.4;
}
Enter fullscreen mode Exit fullscreen mode

Using the Tab key for suggestions

Let's talk about how to use the Tab key to insert suggestions into your text. First, we'll add an event listener for keydown events on our text area. This will allow us to check whether the Tab key is pressed by using the key property.

Once we've identified that the Tab key has been pressed, we'll check if there's a match from our suggestions list by ensuring that the content of the post element isn't empty. If there is a match, pressing Tab will insert that suggestion into our text area.

Here's some sample code to help illustrate this process:

textarea.addEventListener('keydown', (e) => {
    if (e.key !== 'Tab') {
        return;
    }
    const postCursorEle = mirroredEle.querySelector('.container__post-cursor');
    if (postCursorEle.textContent !== '') {
        e.preventDefault();
        replaceCurrentWord(postCursorEle.textContent);
        mirroredEle.innerHTML = '';
    }
});
Enter fullscreen mode Exit fullscreen mode

If all the conditions are met, we use the preventDefault() function to prevent the default behavior of the Tab key, which would normally bring users to the next focusable field. Then we use the replaceCurrentWord() function to replace the word currently being typed with the suggested word, which is the content of the post-cursor element.

Finally, we reset the content of the mirrored element to empty.

By using the Tab key in this way, you can easily insert suggestions into your text without interrupting your flow of thought. With these changes, we've added inline previews and keyboard accessibility to our autocomplete feature, making it even more user-friendly!

Take a look at the final demo below. To give it a try, simply type any keyword from the list of suggestions provided.

const suggestions = [
    "You're the best.",
    "I'm humbled and grateful.",
    "You knocked me off my feet!",
    "My heart is still smiling.",
    "Your thoughtfulness is a gift I will always treasure.",
    "Sometimes the simplest things mean the most.",
    "The banana bread was fabulous. You made my day.",
    "I'm touched beyond words.",
    "All I can say is wow! (Except, of course, I'm grateful.)",
    "My heart just keeps thanking you and thanking you.",
    "You're a blessing to me.",
    "Thank you for being my angel.",
];
Enter fullscreen mode Exit fullscreen mode


It's highly recommended that you visit the original post to play with the interactive demos.

If you found this series helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!

If you want more helpful content like this, feel free to follow me:

Top comments (0)