Dash Text Annotate 0.1.0: Text span annotation inside your Dash app

I’ve released Dash Text Annotate, an open-source component for selecting and labeling passages in a Dash app. It works with plain text and returns structured annotations to ordinary Python callbacks.

Use it to mark people, organizations, dates, or your own categories in documents. It supports overlapping labels, visible passage badges, keyboard passage search, relabeling, undo/redo, and read-only review. Your app controls storage and document loading.

Live annotation demo: label a person and a date, undo, redo, and save.

python -m pip install dash-text-annotate==0.1.0

Here’s a small complete app:

import json
from dash import Dash, Input, Output, html
from dash_text_annotate import DashTextAnnotate

app = Dash(__name__)
app.layout = html.Div([
    DashTextAnnotate(
        id="annotator",
        text="Acme opened an office in Berlin.",
        tag="ORG",
        tag_colors={"ORG": "#79b9a5"},
    ),
    html.Pre(id="annotations"),
])

@app.callback(Output("annotations", "children"), Input("annotator", "entities"))
def show_annotations(entities):
    return json.dumps(entities or [], ensure_ascii=False, indent=2)

if __name__ == "__main__":
    app.run(debug=True)

Each annotation has a stable ID, start/end offsets, the selected text, and a label. The default offsets are Python Unicode code-point indices, so text[start:end] gives you the exact passage, including when the document contains emoji.

Python 3.10+ and Dash 3/4 are supported. The package includes its JavaScript and CSS; there is no Node.js installation or CDN requirement for users. It is MIT licensed and powered by Recogito Text Annotator.

Feedback welcome in the issue tracker, especially experiences with different documents, keyboard workflows, and Dash themes.

Very cool!

For some reason the screenshot is coming through for me… could you try sharing some more screenshots of the feature? Would love to see it in action.

Thanks for sharing :relieved_face:

Seems like I cannot edit the original post. Here the broken gif:

annotation-demo

I noticed you’re using Python code-point offsets rather than UTF-16 offsets. That makes a lot of sense for Python callbacks.

One edge case I’m curious about is grapheme clusters. For example, e followed by a combining accent, or an emoji made up of several code points.

The offsets can be technically correct while still splitting what the user sees as a single character.

Does the selection logic prevent that, or is it something the application using the component would need to handle?

Might be worth testing with decomposed Unicode text, especially for multilingual annotation.

This is a cool package, and just wanted to point out that it’s still being actively maintained. There was a new release last month. Verified to work on Dash 3 and Dash 4