Skip to main content
← Back to Table of Contents

Summary

JSON-first rich text editor built on Filament RichEditor / TipTap — premium shell, Gravity icons, content limits with live feedback, responsive image pipeline, optional Spatie Media Library, YouTube embeds, block images, editor image overlay, fullscreen, autosave, paste cleanup, and keyboard-accessible toolbar.
Scope of this doc: only package-specific APIs (variant(), imageVariants(), youtube(), toolbar role presets, FlexRichContentRenderer, etc.). Everything else comes from Filament RichEditor — see Filament Rich Editor.

Quick start

Content is stored as a TipTap JSON document. Render HTML on the frontend with makeFlexRichContentRenderer() (see Rendering HTML).

Configuration catalog (package API)

FlexRichEditor-specific options only. The field extends Filament RichEditor; inherited Filament APIs are not duplicated here.

Shell & field chrome

Editor UX

Toolbar

Static helpers (presets): getFlexDefaultToolbarButtons(), getFlexFullToolbarButtons(), getFlexDefaultFloatingToolbars(), getFlexExtraTools(), getNativeComparisonToolbarButtons(). To override button layout, use Filament’s toolbarButtons() / floatingToolbars() / tools() with these presets — see Filament Rich Editor.

File attachments & images (package layer)

Requires Filament fileAttachments() / disk options to be enabled first. This table lists Flex processing and cleanup on top of that baseline.

HTML rendering

Built-in plugins (automatic): block images (always), YouTube (when youtube()), paste cleanup (when pasteCleanup()).

Shell variants

primary

secondary (default)

soft

flat


Shell sizes

sm

md (default)

lg


Focus outline


Word count


JSON debug badge


Content limits

Footer states: ok → warning (≥90% of max) → danger (over limit). Form save still runs server validation.

Hard limits — block typing past max

Hard mode calls editor.commands.undo() when the user exceeds max characters or words.

Min characters only

Max characters only

Max words only


Reading time

Config: config('filament-flex-fields.rich_editor.reading_time_words_per_minute').

Fullscreen


Distraction-free

Hides clearFormatting and clearContent in the toolbar while fullscreen is active.

Autosave

Saves editor JSON to localStorage. On reload, prompts to restore if a newer draft exists.
Default key pattern: {statePath}::{model:id|create}::user:{id}.

Paste cleanup


YouTube embeds

Requires ->youtube(). Adds toolbar button + TipTap extension + paste handler for YouTube URLs.
Accepted URL shapes: youtube.com/watch?v=, youtu.be/, youtube.com/embed/, youtube.com/shorts/. Rendered HTML preserves data-youtube-video iframes through FlexRichContentRenderer::toHtml() sanitization.

Block images (automatic)

FlexRichEditorBlockImagePlugin is always registered. Images inserted in the editor are block-level (not inline with paragraph text). No configuration required.

Image overlay (editor only)

When file attachments are enabled, selecting an image shows Edit and Delete controls (top-right overlay). Not included in frontend HTML output.
  • Edit → opens Filament attachFiles action (alt text, replace).
  • Delete → removes image from document.

Toolbar presets

Default Flex toolbar (no attachFiles)

Groups: undo/redo, formatting, headings dropdown, alignment dropdown, blockquote/code, lists dropdown, link, clear formatting/content.

Full toolbar (with attachments button)

Custom toolbar

Native Filament comparison (playground)


Toolbar roles

Presets in config('filament-flex-fields.rich_editor.toolbar_roles').

Author

Editor

Admin

Custom role (after publishing config)

Publish config:

Disabled toolbar tools

Works with string button names from toolbar groups. flexFullscreen and plugin tools (youtube) use their tool names.

Floating toolbars

Default paragraph bubble (bold, italic, underline, strike, link). Hidden when an image is selected.

Custom tools

Flex adds Gravity-icon tools via FlexRichEditor::getFlexExtraTools():
  • clearFormatting — clear nodes + marks
  • clearContent — empty document
When fullscreen() is enabled, flexFullscreen tool is appended automatically.

File attachments

Uploads use Filament’s attachment API (fileAttachments(), disk, directory, visibility). Flex adds scoped paths, optimization, variants, and orphan cleanup on top. Attachments are enabled when fileAttachments(true) or the toolbar includes attachFiles and Filament resolves hasFileAttachments().

Visibility


Scoped attachment directories

scopedAttachmentDirectory('rich-editor') resolves:
  • {prefix}/{model}/{id}/ when editing a record
  • {prefix}/drafts/{userId}/ on create forms

Images only

Restricts accepted MIME types to images (JPEG, PNG, GIF, WebP).

Max attachment size


Single-pass image optimization

Without named variants — resizes/optimizes the master file on upload.

Named image variants

Generates photo__thumb.webp, photo__large.webp, and photo.jpg.flex-variants.json.

Array config

Fluent RichEditorImageVariant objects

Variant keys: max_long_edge, max_width, max_height, webp, master, optimize.

Automatic attachment cleanup

Native disk (default on)

On save: compares image IDs in JSON before/after; deletes removed masters, variants, and .flex-variants.json manifests. Scoped directories also sweep unreferenced files.

Spatie Media Library

Disk pruner is skipped. Filament calls FileAttachmentProvider::cleanUpFileAttachments(exceptIds: [...]) on save.

Responsive images in HTML output

Lazy images on/off

Responsive srcset on/off

When variants are configured, responsiveImages() defaults to on if not set explicitly.

Image sizes attribute


Rendering HTML

Always use makeFlexRichContentRenderer() so disk, variants, plugins (YouTube), and lazy loading match the field.

In Filament infolist / table column

Standalone renderer

Example output

Blade view

Inertia / API controller


Alt text required


Accessibility

Built-in without extra configuration:

Spatie Media Library (optional)

1. Model — register conversions

2. Form

3. Render


Complete example: Filament Resource


Configuration recipes

Minimal blog post

Production article (native disk)

Author role (limited toolbar)


Package config

config/filament-flex-fields.php:
Publish:

Translations

Package strings: filament-flex-fields::default.rich_editor.* in resources/lang/en/default.php and resources/lang/pl/default.php. Toolbar labels reuse Filament: filament-forms::components.rich_editor.tools.*.

Publish translations

Key reference


Testing

PHP (package)

JavaScript unit tests

Playwright E2E (playground)


Playground

/admin/flex-fields-playground/flex-rich-editor — see Playground. Slug: flex-rich-editor Includes:
  • Native Filament RichEditor comparison
  • Full Article body demo (attachments, variants, limits, YouTube, fullscreen, autosave)
  • Variant grid: compact / secondary / soft / flat
  • Attachments-only and full-toolbar sections

Assets (CSS & JS)

Each field loads its own CSS bundle and Alpine component on demand (x-load). Optional support scripts load only when configured.

Does it duplicate Filament’s rich editor?

On a page with only FlexRichEditor: no double download of Filament’s rich-editor Alpine asset. The blade loads flex-rich-editor, not filament/forms → rich-editor. JS bundle: at build time, flex-rich-editor.js bundles Filament’s rich-editor-form-component (esbuild alias to vendor/filament/forms/dist/components/rich-editor.js) plus Flex chrome (~500 KB raw — same order of magnitude as native Filament). That is a single runtime script, not Filament + Flex side by side. CSS: Filament does not ship a separate rich-editor.css asset. Flex adds rich-editor-field.css for the fff-rich-editor-* shell and overrides on shared fi-fo-rich-editor-* markup classes. No second full editor stylesheet. Exception — playground comparison: the Flex Rich Editor playground page may render native RichEditor next to FlexRichEditor for demo purposes. That page loads both rich-editor and flex-rich-editor scripts — intentional, not typical production usage.

Performance notes

  • Footer stats use requestAnimationFrame batching (not per-keystroke DOM thrashing).
  • Image overlay sync runs on selection changes only.
  • Attachment manifest reads are cached per request during HTML rendering.
  • Bundle budget (CI): flex-rich-editor.js ~497 KB raw / ~157 KB gzip (aligned with Filament native).

Requirements & optional packages


Filament RichEditor baseline

FlexRichEditor extends Filament\Forms\Components\RichEditor. Options not documented on this page behave as in Filament.