# Rich text editor

Published: November 24, 2024

Version: ^1.0.27

<img class="rounded-2xl border" src="/img/blog/1_0_26_full.png" alt="A rich text editor with a toolbar" />

Welp, we did it. As of today, Flux now ships with a rich text editor 🎉.

Just slap this one-liner anywhere in your app and you're off and editing:

```php
<flux:editor wire:model="content" />
```

We really sweat the details on this one and hope it shows.

## Configurable toolbar

<img class="rounded-2xl border" src="/img/blog/1_0_26_configure.png" alt="A rich text editor with a different toolbar configuration than before" />

```php
<flux:editor toolbar="heading | bold italic strike ~ link" />
```

To configure an editor's toolbar items, you can pass a custom arrangement into the `toolbar` prop as a string of item names mixed with separators (`|`) and spacers (`~`).

Because each of these items is a simple Blade component inside Flux, you can easily create your own Blade components and reference them by name inside the `toolbar` prop.

[Read more about configuring the toolbar ->](https://fluxui.dev/components/editor#configuring-items)

## Custom toolbar items

<img class="rounded-2xl border" src="/img/blog/1_0_26_custom.png" alt="An editor with a custom dropdown menu in the toolbar" />

If you want **complete** control over the toolbar, you can compose your own editor by assembling the Blade components yourself.

Here's an example of adding a custom dropdown menu to an editor's toolbar:

```php
<flux:editor>
    <flux:editor.toolbar>
        <flux:editor.heading />
        <flux:editor.separator />
        <flux:editor.bold />
        ...
        <flux:dropdown>
            <flux:editor.button icon="ellipsis-horizontal" tooltip="More" />

            <flux:menu>
                <flux:menu.item wire:click="..." icon="arrow-top-right-on-square">Preview</flux:menu.item>
                <flux:menu.item wire:click="..." icon="arrow-down-tray">Export</flux:menu.item>
                <flux:menu.item wire:click="..." icon="share">Share</flux:menu.item>
            </flux:menu>
        </flux:dropdown>
    </flux:editor.toolbar>

    <flux:editor.content />
</flux:editor>
```

As you can see, this is just Blade/HTML like any other component. You can style and assemble any other Flux components you like into the editor's toolbar.

[Read more about adding custom toolbar items ->](https://fluxui.dev/components/editor#custom-items)

## Mouse optional

<img class="rounded-2xl border" src="/img/blog/1_0_26_keyboard.gif" alt="Showing there is only one tab stop at a time on the editor toolbar" />

The editor's toolbar uses a roving tabindex so that you don't have to tab through every toolbar item as you tab along the page. The toolbar acts as a single tab stop that you can navigate using the arrow keys.

You can navigate sub menus within the toolbar using only your keyboard as well.

In fact, you can operate everything about this editor, easily, without ever touching your mouse.

## Markdown syntax

<img class="rounded-2xl border" src="/img/blog/1_0_26_markdown.gif" alt="Typing markdown syntax into the editor to trigger formatting" />

Although this is a _rich text_ editor, it supports Markdown syntax as a convenient way to control styling in your document as you edit.

## Shortcuts

<img class="rounded-2xl border" src="/img/blog/1_0_26_items.png" alt="All the available toolbar operation icons in a row" />

All the standard keyboard shortcuts you're familiar with from other editors like Google Docs are available to use as well.

Here are a few examples:
* `Cmd+B` Bold
* `Cmd+I` Italic
* `Cmd+K` Insert link

[Browse the available shortcut keys ->](https://fluxui.dev/components/editor#shortcut-keys)

## As a form field

<img class="rounded-2xl border" src="/img/blog/1_0_26_field.png" alt="An editor with a form field label and description" />

```php
<flux:editor label="Release notes" description="Explain what’s new in this release." />
```

We wanted this component to feel no different than a textarea field when using it inside a form.

This means tackling things like disabled and invalid states at both the field AND fieldset level, associating labels/descriptions with the editor, as well as focusing the editor when the field label is clicked.

## Screen readers

<img class="rounded-2xl border" src="/img/blog/1_0_26_tree.png" alt="A screenshot of the editor's accessibility tree in Chrome devtools" />

As you can see by the figure above, we worked hard to make sure the editor's accessibility tree was as descriptive and functional as possible.

Screen readers can easily discover and use all features inside the editor. This includes the tricky bits like toolbar sub-selects, tooltips, and insert-link popovers.

## Dynamic JS bundle

Currently, every bit of Flux's JavaScript is contained inside a `21.5KB` file.

Because of the enormity of a rich text editor and its dependancies, this component would add a whopping `85.3KB` to the the Flux bundle size.

The problem is that many pages in an app don't use a rich-text editor at all and it doesn't make sense to penalize them with a bigger bundle.

Therefore, we included the editor's JavaScript as a separate bundle that gets loaded in parallel on an as-needed basis. The editor's JS will only be included at the exact moment it's needed to keep everything else in your app feeling light and snappy. This includes edge cases like lazy-loading an editor long after a page has already been loaded.

## Localization

<img class="rounded-2xl border" src="/img/blog/1_0_26_spanish.png" alt="A screenshot of editor tooltip in spanish" />

All of the english copy used in this component is translatable by copying a predefined set of keys into your `lang/?.json` files.

[Read more about localization ->](https://fluxui.dev/components/editor#localization)

## Built on Tiptap & ProseMirror

Rather than wrapping a more batteries-included editor like [Quill](https://quilljs.com/) or [TinyMCE](https://www.tiny.cloud/), we opted to use [Tiptap](https://tiptap.dev/) under the hood for the editor's core functionality.

Tiptap is a convenience wrapper around the extremely powerful [ProseMirror](https://prosemirror.net/) project.

It's completely headless, meaning we have full control over all of the markup, visuals, and accessibility, without having to be responsible for the input/formatting interactions.

This means we can make the toolbar as customizable as everything else in Flux because we own all the HTML/CSS/JS for it.

Also, to help support and thank the ProseMirror project, we donated $1000 via their [GitHub sponsors profile](https://github.com/sponsors/marijnh).

## The future

For launch our goal was: a rock-solid editor that feels just as good to develop and use as any other component in Flux.

Now that we've accomplished that, we can start adding next-level features like image support and @mentions.

Stay tuned!

[Read the full editor documentation ->](https://fluxui.dev/components/editor)
