Koala logo Design

Rich text

The Portal uses the Trix editor for rich text input, loaded on demand via the _TrixEditor partial. It is used for transaction notes in both full-page and side tray contexts.

Integration pattern

Trix is loaded lazily via a shared partial Pages/Shared/_TrixEditor.cshtml. The partial dynamically injects the Trix CSS, JavaScript, and custom styles only once per page. A hidden <input> stores the HTML content, bound to the <trix-editor> via the input attribute.

<!-- Hidden input stores the HTML content -->
<input id="note-content" type="hidden" name="NoteContent"/>

<!-- Trix editor bound to the hidden input -->
<div class="border border-gray-300 dark:border-gray-600 rounded-lg overflow-hidden">
    <trix-editor id="trix-editor"
                 class="trix-content"
                 input="note-content"
                 placeholder="Write your note...">
    </trix-editor>
</div>

<!-- Load the Trix partial (CSS + JS + custom styles) -->
<partial name="_TrixEditor"/>

Editor appearance

The editor has a sticky toolbar with formatting buttons, a content area with custom typography styles, and full dark mode support. File uploads are disabled via a trix-file-accept event listener.

This is an example of rich text content with various formatting options.

The editor supports:

  • Bold, italic, and strikethrough text
  • Links to external URLs
  • Headings and blockquotes
  • Bullet and numbered lists

Custom toolbar styling

The _TrixEditor partial injects custom CSS that overrides the default Trix toolbar to match the app's design. Key customisations include sticky toolbar positioning, uniform button sizing, hidden file upload tools, and responsive button visibility on mobile.

<!-- Key toolbar overrides in _TrixEditor partial -->
trix-toolbar {
    position: sticky;
    top: 0;
    z-index: 1;
    background: white;
    border-bottom: 1px solid rgb(209 213 219);
}
trix-toolbar .trix-button {
    border: none !important;
    border-left: 1px solid rgb(209 213 219) !important;
    height: 2.5rem !important;
    width: 2.5rem !important;
}
trix-toolbar .trix-button-group--file-tools {
    display: none !important;
}

/* Dark mode */
.dark trix-toolbar {
    background: rgb(31 41 55);
    border-bottom-color: rgb(75 85 99);
}
.dark trix-toolbar .trix-button {
    filter: invert(0.8);
}

/* Hide less-used buttons on mobile */
@media (max-width: 639px) {
    trix-toolbar .trix-button--icon-strike,
    trix-toolbar .trix-button--icon-heading-1,
    trix-toolbar .trix-button--icon-code { display: none !important; }
}

Side tray usage

The Trix editor is used in the "Add note" side tray for transactions. The form uses x-target="side-tray-content" for AJAX submission, with the submit button in the fixed tray footer linked via form="add-note-form". The <partial name="_TrixEditor"/> is included inside the tray content so it loads with the AJAX response.

<div id="side-tray-content" class="flex-1 flex flex-col min-h-0">
    <div class="shrink-0 flex items-center justify-between px-6 sm:px-8 py-4">
        <h2 class="text-xl font-semibold text-gray-900 dark:text-white">Add note</h2>
        <button type="button" x-on:click="$dispatch('close-side-tray')" ...>...</button>
    </div>
    <div class="flex-1 overflow-y-auto px-6 sm:px-8 py-6">
        <form id="add-note-form" method="post" x-target="side-tray-content">
            <input id="modal-note-content" type="hidden" name="NoteContent"/>
            <div class="border border-gray-300 dark:border-gray-600 rounded-lg overflow-hidden">
                <trix-editor id="modal-trix-editor"
                             class="trix-content"
                             input="modal-note-content"
                             placeholder="Write your note...">
                </trix-editor>
            </div>
            <span asp-validation-for="NoteContent" class="mt-2 block"></span>
        </form>
    </div>
    <div class="shrink-0 border-t border-gray-200 dark:border-gray-700 px-6 sm:px-8 py-4 flex justify-end">
        <button type="submit" form="add-note-form" koala-loading koala-btn="Primary">
            Add note
        </button>
    </div>
    <partial name="_TrixEditor"/>
</div>

Content rendering

Stored HTML content is rendered read-only using the trix-content CSS class for consistent typography, or within a prose container. Both have matching dark mode styles defined in the partial.

Meeting notes

Discussed the following items with the client:

  • Property chain confirmed - no issues
  • Mortgage offer valid until 15 April 2026
  • Local authority search results expected next week
"Client confirmed they are happy to proceed at the agreed price."