We’re all familiar with the concept of autocompletion, right? You type something into a search box and it tries to guess what you’re looking for as you type, displaying suggestions, often below the cursor. While we’re used to autocomplete on eCommerce sites that redirect to search or product pages, an underrated usage is when used as a secondary search pattern to augment the typing experience.
In modern web applications, there’s no reason a composition box has to be a dull, plain text area, or limit itself to rich text formatting. Social and productivity apps like Twitter, Slack, Notion, Google Docs, and Asana have popularized the “@mention” pattern, allowing you to reference other users as you type. You can mention another person, a channel, a file, or some other queryable object using triggers, such as the @ or # characters. This opens a panel with suggestions, letting you complete your message with the right reference.
The text box acts as a search input, and the suggestions panel acts as a typing assistant, allowing users to reference the right resource without leaving their keyboard. When implemented correctly, everything is only a few keystrokes away, including when users misspell something.
Along with powering a composition box, this pattern drives consistency in user-generated content. Hashtags are a good example: users are empowered to create semi-structured data in a free-form context, which then helps categorize content without needing to post-process it. Once users have mentioned other people in a document, referenced resources, or added several hashtags, you get a graph of connections across all the resources available on your app, making it a lot simpler to recommend related content and understand how users think.
The basics of building @mentions
Beyond letting users find what they want, a great @mention autocomplete feature should be as fluid as possible. The goal is to create a seamless typing experience where the pattern behaves as an assistant that learns as you type and helps you out, but knows when to get out of your way. You can keep typing, ignoring the suggestions and letting them go away, or you can leverage them to complete your message without friction.
On Twitter, which popularized the pattern with mentions and hashtags, the panel closes as soon as the word being typed is no longer considered a token, to avoid bugging users who want out. Twitter user handles don’t support spaces, so it closes the panel immediately after a space.
Slack works a bit differently, allowing spaces to let you search full names. It uses different heuristics to determine what signals that users want out.
When selecting a suggestion, Twitter closes the panel, replaces the token, and adds a space so the user can keep typing seamlessly. This kind of attention to detail might seem insignificant in isolation, but when they add up, they give a sense of fluidity that empowers users to embrace the pattern instead of fighting it.
When you start adding mentions in a composition box like this, they become part of your text, but should also retain full interactivity to let users edit them.
On Twitter, for example, you can “focus” a mention by either clicking on it or navigating the text box with the
Right arrow keys. Twitter detects it and reopens the panel with the mentions as the search query. It ensures who is notified when the tweet is sent, and allows you to edit the mention in case of a mistake.
One way to build such experiences with minimal effort is using the open-source Autocomplete library. Autocomplete is designed to integrate best with Algolia, but works with any source, static or remote. It lets you build multi-source dynamic and accessible autocomplete experiences, and works great for @mention features.
Mixing different types of suggestions
Having a symbol per result type works well when you have a few, distinct types, such as “@” for people, and “#” for hashtags. As soon as you have more types with blurrier limits, chances are good that users are unable to remember them all. Isolating them could make the experience more cumbersome.
Instead, assigning more than a single type per symbol with federated search (multi-source) helps discover all possible types without having to “learn” too many patterns.
On Slack, suggestions are mixed and differentiated with visual cues (such as different icons and badges). Still, the results look similar to how you experience them in the rest of the app. For example, people suggestions show the users’ avatar, display name, and status. This helps users feel more confident about who or what they mention.
On Notion, suggestions are grouped by type. Unlike a typical search experience that favors per-result relevance, this approach favors consistency: until you refine the query, you always get dates first, then people, then links. This helps users build muscle memory as they use the tool, by setting expectations regarding where things are.
Grouping by type is achievable either by querying multiple sources at once, or using grouping mechanisms such as Autocomplete’s Reshape API, that transform results after retrieving them.
Another cool Notion pattern is the dynamic placeholder, or predictive suggestion, that they inject based on the active suggestion. By default, the placeholder helps users take action by hinting about what they can do. Then, as they browse, the placeholder updates, letting users know what to expect if they select a suggestion.
Peeking into Notion’s code, you can see how they leverage CSS Custom Properties to do this: every time you move through suggestions, they set the CSS variable
content property on a
::before pseudo-element. Nifty!
When drawing results from multiple sources, it can become harder to control the number of results. That’s because each source might return the number of requested suggestions, or less, when it doesn’t have enough matches. This can result in a “jumpy” UI, where the number of results fluctuate as the user types.
You can mitigate this either with a fixed height panel containing a scrollbar, or by using combine and limit mechanisms like Autocomplete’s Reshape API.
Thinking outside the search results
When you work on search and discovery every day as I do, you start seeing it everywhere. It’s fantastic how creative you can get with the @mention pattern when you go beyond how it is typically implemented.
If you’re using Slack, you might be used to looking for emojis by typing “:” then refining by name. While it doesn’t look like search or mentions, it uses the same exact mechanisms: you open a suggestions panel with a special character, search for the right item, and “apply” it on select.
This is even more striking on Notion, where the panel doesn’t look like search results at all.
What’s interesting here is how versatile the pattern can be when changing simple things like item templates and styling results differently. It integrates even better in a composition box and creates a fluid experience that users recognize across all the apps they use.
Going beyond type completion
Mentions are the most common use case when using dynamic suggestions in a composition box, but you can go a lot further. While mentions help you “complete” a sentence and enhance the typing experience, a composition box can also be a conversational interface between the user and the app.
On Notion, typing the special character “/” gives you access to inserting actions. You still get to refine suggestions by typing further, but instead of filling the input, selecting a result creates a brand new block of a given type.
This pattern, commonly known as “shortcuts” or “slash commands” was popularized in-game chats and has become a standard in general-purpose chat applications like Slack and Discord.
Shortcuts are interesting because it lets users perform common tasks in one place, without having to look for the feature. For example, it’s common to do impromptu Zoom meetings with remote coworkers and usually requires sending a Zoom link over Slack. But having to open Zoom, copy the link, then paste it into Slack is cumbersome. The “/zoom” shortcut removes those hurdles by centralizing common tasks in a single interface.
While features like slash commands used to be dedicated to power users, they’re now emerging in more and more apps and targeting all kinds of users.
Ultimately, augmenting the typing experience isn’t about unlocking “power features” but about uncovering content, as well as reducing friction and the cognitive load: instead of teaching users about the complexity of your system ahead of time, you’re bringing the right information at the right time, where and when users need it.