Trix Rich Text Editor

repository·main·Indexed 12 days ago

https://github.com/basecamp/trix

A WYSIWYG rich text editor for everyday writing tasks like messages, comments, and articles. Trix uses a sophisticated internal document model to ensure consistent HTML output and integrates with HTML forms via Element Internals. It supports custom toolbar attributes, internal and external actions, native browser constraint validation, and file attachment handling. Version 2.1.19.

Tokens
10.3K
Snippets
35
Records
41
Agent score
98%

What's inside Trix

  1. Work with Trix.Document

    main

    The content of an editor is a document, represented by a Trix.Document instance.

    • Retrieve: Use editor.getDocument().
    • Convert to String: Use document.toString() to get an unformatted JavaScript string.
    • Immutability: Documents are immutable. Every change creates a new document instance. This allows for easy snapshots and undo functionality.
    • Equality: Use document.isEqualTo(otherDocument) to compare two documents.
    var document = element.editor.getDocument()
    
    // Convert to string
    document.toString() 
    
    // Compare equality
    var isSame = document.isEqualTo(element.editor.getDocument())
  2. Build the Trix Ruby gem

    main

    To build and publish the action_text-trix Ruby gem, follow these steps in order:

    1. Navigate to the package directory.
    2. Run bundle exec rake sync to update necessary files. Note: You must commit the changes generated by this command to git.
    3. Run bundle exec rake build to compile the gem.
    4. Push the resulting gem files located in the pkg/ directory using gem push.
    cd action_text-trix
    bundle exec rake sync
    bundle exec rake build
    gem push pkg/*.gem
  3. Install Trix via CDN or npm

    main

    You can quickly start using Trix by including the CSS and UMD JavaScript files from an npm CDN in your <head>.

    Alternatively, install the trix npm package and import it into your application. You can listen for the trix-before-initialize event to configure Trix.config before the editor is ready.

    <head>
      …
      <link rel="stylesheet" type="text/css" href="https://unpkg.com/trix@2.0.8/dist/trix.css">
      <script type="text/javascript" src="https://unpkg.com/trix@2.0.8/dist/trix.umd.min.js"></script>
    </head>
    import Trix from "trix"
    
    document.addEventListener("trix-before-initialize", () => {
      // Change Trix.config if you need
    })
  4. Style Trix formatted content

    main

    To ensure visual consistency between the editor and the rendered stored content, apply a CSS class (e.g., trix-content) to both the <trix-editor> element and the container used to display stored content. The default trix.css provides styles for basic formatting (lists, code blocks, block quotes) under the .trix-content class.

    <!-- In the editor -->
    <trix-editor class="trix-content"></trix-editor>
    
    <!-- When displaying stored content -->
    <div class="trix-content">Stored content here</div>
  5. Integrate Trix with HTML forms

    main

    To submit Trix content via a standard form, define a hidden input with a specific id and reference that id in the <trix-editor> using the input attribute. Trix will automatically sync the editor's content to this hidden input.

    To populate the editor with existing content, set the value attribute on the associated hidden input.

    Note: If an editor has both HTML content inside its tags AND an associated input element, Trix will prioritize the input element's value and ignore the inner HTML.

    <form action="/submit" method="POST">
      <!-- The ID here is referenced by the editor below -->
      <input id="x" type="hidden" name="content" value="Initial content">
      <trix-editor input="x"></trix-editor>
    </form>
  6. Provide an accessible name for `<trix-editor>`

    main

    To ensure accessibility, <trix-editor> elements should be associated with a <label>. You can achieve this in two ways:

    1. Using id and for: Assign an id to the <trix-editor> and reference it using the for attribute on a <label>.
    2. Nesting inside a <label>: Wrap the <trix-editor> inside a <label>.

    Warning: If you nest the editor inside a <label>, you must render the corresponding <trix-toolbar> element outside of the <label> element.

    Additionally, you can use [aria-label] or [aria-labelledby] attributes for accessibility.

    <!-- Style 1: id and for -->
    <label for="editor">Editor</label>
    <trix-editor id="editor"></trix-editor>
    
    <!-- Style 2: Nesting (Toolbar must be outside) -->
    <trix-toolbar id="editor-toolbar"></trix-toolbar>
    <label>
      Editor
      <trix-editor toolbar="editor-toolbar"></trix-editor>
    </label>
  7. Add custom attributes to the toolbar

    main

    You can add buttons to the toolbar that apply formatting using the data-trix-attribute attribute.

    • Text Attributes: Use data-trix-attribute="<attribute name>" to apply styles like bold to a text selection. Use data-trix-key="<key>" to define a keyboard shortcut (e.g., data-trix-key="b" for meta+b).
    • Block Attributes: If the attribute is defined in Trix.config.blockAttributes, it will apply to the entire block (e.g., a quote attribute that toggles a <blockquote>).
    <!-- Bold button with keyboard shortcut meta+b -->
    <button type="button" class="bold" data-trix-attribute="bold" data-trix-key="b"></button>
    
    <!-- Block attribute button (e.g., quote) -->
    <button type="button" class="quote" data-trix-attribute="quote"></button>
  8. Validate a Trix editor

    main

    Trix supports native browser constraint validation. Adding the required attribute to a <trix-editor> makes it invalid if it is empty.

    You can also perform custom validation by listening to the trix-change event and using the setCustomValidity(message) method on the editor element.

    To access the underlying document for validation logic, use editorElement.editor.getDocument().

    <!-- Native required validation -->
    <input id="x" type="hidden" name="content">
    <trix-editor input="x" required></trix-editor>
    // Custom validation on change
    addEventListener("trix-change", (event) => {
      const editorElement = event.target
      const trixDocument = editorElement.editor.getDocument()
      
      const isValid = (doc) => {
        // custom logic here
        return true
      }
    
      if (isValid(trixDocument)) {
        editorElement.setCustomValidity("")
      } else {
        editorElement.setCustomValidity("The document is not valid.")
      }
    })
  9. Build Trix from Source

    main

    To build Trix from the source repository, use yarn and rollup.

    1. Install dependencies: yarn install
    2. Generate distribution files: yarn build
    3. Run a watch process for development: yarn watch
    4. Run a development server: yarn dev
    5. Run a single command to watch JS/styles and serve: yarn start
    6. Run tests in headless mode: yarn test
    $ yarn install
    $ yarn build
    $ yarn watch
    $ yarn dev
    $ yarn test
  10. Disable a Trix editor

    main

    To disable an editor, add the disabled attribute to the <trix-editor> tag. A disabled editor cannot be edited, cannot receive focus, and its value will be ignored during form submission.

    You can also toggle the disabled state programmatically using the .disabled property or the .toggleAttribute("disabled", bool) method.

    <trix-editor disabled></trix-editor>
    const editor = document.getElementById("editor")
    
    // Via attribute
    editor.toggleAttribute("disabled", false)
    
    // Via property
    editor.disabled = true
  11. Customize the toolbar placement

    main

    By default, Trix places the toolbar immediately before the editor. To place the toolbar in a specific location, use the toolbar attribute on the <trix-editor> to reference the id of a <trix-toolbar> element.

    <main>
      <trix-toolbar id="my_toolbar"></trix-toolbar>
      <div class="more-stuff-inbetween"></div>
      <trix-editor toolbar="my_toolbar"></trix-editor>
    </main>
  12. Invoke internal and custom Trix actions

    main

    Trix supports both built-in internal actions and user-defined external actions via the data-trix-action attribute.

    • Internal Actions: Includes undo, redo, link, increaseBlockLevel, and decreaseBlockLevel.
    • External Custom Actions: Prefix your action name with x- (e.g., data-trix-action="x-log"). To handle these, listen for the trix-action-invoke event. The event object provides target (the editor), invokingElement (the button), and actionName (the string from the data attribute).
    <!-- Internal action example -->
    <button type="button" class="block-level decrease" data-trix-action="decreaseBlockLevel"></button>
    
    <!-- Custom action example -->
    <button id="log-button" type="button" data-trix-action="x-log"></button>
    document.addEventListener("trix-action-invoke", function(event) {
      const { target, invokingElement, actionName } = event
    
      if (actionName === "x-log") {
        console.log(`Custom ${actionName} invoked from ${invokingElement.id} button on ${target.id} trix-editor`)
      }
    })