I've been experimenting with a floating AI toolbar, designed for use in text
editors. When text is selected, an AI button will appear, which opens a dialog
for modifying your selection and generating new text. Try a demo of the UI
below.
When the height of a motion component changes, every element inside is
temporarily stretched into its new position. For example, this component will
animate and slightly distort when the contents of <p> grows taller.
This generally isn’t a problem, however when text is stretched during these
animations, it creates a poor reading experience. And because we’re generating
text word-by-word with AI, this will occur—try moving the sliders below to see
the effect.
To avoid this distortion, we can make the child a motion component, setting
its layout value to "position". This tells it to only animate its position,
not its size.
By doing this we can keep the animation without stretching the text—here’s what
it looks like.
This experience is preferable because the user is most likely reading this text
as it animates, watching a response being streamed in from AI. Without the
distortion it’s far easier to read.
I’ve set up AI generation using the
Vercel AI SDK. It’s very easy to get
started—once your Open AI API key is set up, we can create a server action named
continueConversation in Next.js, exactly like the following snippet.
Calling this action from the client, passing our prompt to content, will
return a stream of the results. Use the provided readStreamableValue function
with for await to read the result. You can see the expected console messages
below the snippet.
We can make this more useful by tracking every message received on the client,
and passing it back to the AI on every prompt. In this way the AI will have
memory of your previous prompts and its replies.
We can convert our AI setup into React code and place it inside a component,
creating an input to submit the user’s prompt, and returning the previous result
above it.
Tomatoes are a fruit despite their culinary usage.
I’m using Liveblocks Text Editor in my real application. The
editor is based on Lexical, and has
a number of features
such as real-time collaboration, comments, mentions, and notifications.
an exotic & nutriti
Natalie
fruit to your diet @Rachel then dragonfruit is|
Getting started is
simple, and because it’s a Lexical extension, you can extend your existing
editor with collaboration.
To integrate our AI solution into the text editor, we can modify our code
snippet from before, creating a button that submits a prompt to our queryAi
function. In this example we’re taking the currently selected text, asking the
AI to simplify it.
After the button’s been pressed, messages will update with the AI result.
However, we still haven’t added the message to the text editor yet. To do this,
we can create a button the replaces the current selection with the last result.
There’s still more work to be done, for example changing queryAi to add a
loading spinner, but you get the idea! Liveblocks Text Editor also enables a
number of other features out of the box, which are worth adding.
Being able to highlight text in your editor, and leave a comment, is a necessary
feature for modern editors. Liveblocks Text Editor allows you to do this—the
following snippet allows users to open a floating comment composer below their
highlighted text.
Selecting text in the editor, and pressing the button, will highlight the text
and create an attached thread and comment. To visually render each thread next
to its highlight, we can use two Liveblocks components which handle all
positioning for you.
AnchoredThreads
anchors threads vertically alongside the text—best for desktop.
FloatingThreads
floats popover threads under highlights—ideal for mobile.
Starfruit thrives in warm, tropical climates. It
soil and plenty of sunlight. The tree can grow up to 30 feet tall
and produces fruit year-round, with peak seasons varying by
that adds a unique flavor and aesthetic to various
Similarly, we can render a list of notifications using the
<InboxNotification>
component. Each notification is triggered when a user mentions you in a comment,
or when you’ve been mentioned inline in the editor.
Chris mentioned you in Untitled document
1h ago
How does this sound @Natalie?
Rachel invited you to My new document
2d ago
Accept
Decline
Rachel mentioned you in Untitled document
3d ago
You could try one of these alternatives?
You can also create fully custom notifications, and display those in your inbox
too, though we don’t need this now.
Try out a
live demo
that contains all the features listed above, and more. It’s open-source, and
free for you to use for any purpose. Make sure to
follow me on Twitter if you’d like to hear about
similar demos!