jingrow-ui/docs/components/text-editor.md
jingrow c7bac1a7a0
Some checks failed
Publish on NPM / publish (push) Has been cancelled
Build and Deploy Storybook / build (push) Has been cancelled
Tests / test (push) Has been cancelled
initial commit
2025-10-24 00:40:30 +08:00

14 KiB

Text Editor

The Text Editor component is used for rich-text editing. It is based on Tiptap.

Usage

The TextEditor component is very flexible in terms of layout and features. It provides building blocks like menus and slots for building any type of editor experience you might want.

Here is a basic version with fixed menu at the top.

<template>
  <TextEditor
    editor-class="prose-sm border max-w-none rounded-b-lg p-3 overflow-auto h-64 focus:outline-none"
    :fixedMenu="true"
    :content="content"
    @change="(val) => (content = val)"
    :mentions="mentions"
  />
</template>

<script setup>
import { TextEditor } from 'jingrow-ui'
let mentions = [
  { label: 'Husain Wrenn', value: 'hwrenn0@spotify.com' },
  { label: 'Gwenore Fitter', value: 'gfitter1@foxnews.com' },
  { label: 'Ricard Claussen', value: 'rclaussen2@imgur.com' },
  { label: 'Rickard Higford', value: 'rhigford3@multiply.com' },
  { label: 'Lazarus MacKey', value: 'lmackey4@prlog.org' },
  { label: 'Karrah Ege', value: 'kege5@prweb.com' },
  { label: 'Seward Godin', value: 'sgodin6@msu.edu' },
  { label: 'Milzie Sanches', value: 'msanches7@senate.gov' },
  { label: 'Walt Arrington', value: 'warrington8@tripod.com' },
  { label: 'Seline Bonifas', value: 'sbonifas9@hibu.com' },
]
</script>

If you are on Vue version 3.2 or earlier, you need to add this line in your main.js file:

app.config.unwrapInjectedRef = true

You can read more about it here: https://vuejs.org/guide/components/provide-inject.html#working-with-reactivity

Props

Name Default Value Description
content null String HTML string to set as the initial value in the editor
placeholder null String Placeholder text to show when the content is empty
editorClass null String | Object | Array Valid CSS class values
editable true Boolean Enable/disable editing
fixedMenu null true | false | Array See customizing menu
bubbleMenu null true | false | Array See customizing menu
floatingMenu null true | false | Array See customizing menu
extensions null Array Tiptap extensions
starterkitOptions null Object Options to pass to the Starterkit Extension
mentions null Array Array of {label, value} for mentions list

Customizing Menu

There are three types of menus available for the editor.

  • Fixed Menu: Menu that is always visible at a fixed place
  • Bubble Menu: Menu that shows up when you select some text
  • Floating Menu: Menu that shows up on a new line

You can choose to use any of these or a combination of these in your editor. Here are some examples of customized editors:

Fixed menu with custom buttons

You can customize which buttons show up in the menu by passing an array of button names. You can find the list of all buttons available here.

<template>
  <TextEditor
    editor-class="!prose-sm border max-w-none rounded-b-lg p-3 overflow-auto h-64 focus:outline-none"
    :fixedMenu="fixedMenuMinimalButtons"
    :content="content"
    @change="(val) => (content = val)"
  />
</template>
<script setup>
import { TextEditor } from 'jingrow-ui'
let content = ref('[initial html content]')
let fixedMenuMinimalButtons = [
  'Paragraph',
  ['Heading 2', 'Heading 3', 'Heading 4', 'Heading 5', 'Heading 6'],
  'Separator',
  'Bold',
  'Italic',
  'Separator',
  'Bullet List',
  'Numbered List',
  'Separator',
  'Link',
  'Blockquote',
  'Code',
]
</script>

Minimal editor with bubble menu

Setting bubbleMenu to true will show a bubble menu on text selection. You can also pass a list of button names, just like the previous example.

<template>
  <TextEditor
    editor-class="!prose-sm border max-w-none rounded-lg p-3 overflow-auto h-20 focus:outline-none"
    :bubbleMenu="true"
    :content="content"
    @change="(val) => (content = val)"
  />
</template>
<script setup>
import { TextEditor } from 'jingrow-ui'
let content = ref('[initial html content]')
</script>

Floating menu and bubble menu

You can combine multiple menus. You can also pass an array of button names.

<template>
  <TextEditor
    editor-class="!prose-sm border max-w-none rounded-lg p-3 overflow-auto h-20 focus:outline-none"
    :floatingMenu="true"
    :bubbleMenu="true"
  />
</template>
<script setup>
import { TextEditor } from 'jingrow-ui'
</script>

Comment Editor

An example of how to use slots and various features of the TextEditor to make a customized editor experience.

There are three slots available: top, bottom and editor. The top and bottom are slots for placing menus at the top or bottom of the editor. If you are using these slots, you must import and render the Menu components manually. They are available to import as TextEditorFixedMenu, TextEditorBubbleMenu, and TextEditorFloatingMenu.

The editor slot renders the TextEditorContent component, you can override it and render the TextEditorContent component if you want some custom behaviour.

Submit
<template>
  <Input class="mb-2" type="checkbox" v-model="editable" label="Editable" />
  <TextEditor
    class="rounded-lg border p-4"
    :editor-class="['prose-sm max-w-none min-h-[6rem]']"
    :content="content2"
    @change="(val) => (content2 = val)"
    :starterkit-options="{ heading: { levels: [2, 3, 4, 5, 6] } }"
    placeholder="Write something..."
    :editable="editable"
  >
    <template v-slot:editor="{ editor }">
      <TextEditorContent
        :class="[editable && 'max-h-[6rem] overflow-y-auto']"
        :editor="editor"
      />
    </template>
    <template v-slot:bottom>
      <div
        v-if="editable"
        class="mt-2 flex flex-col justify-between sm:flex-row sm:items-center"
      >
        <TextEditorFixedMenu
          class="-ml-1 overflow-x-auto"
          :buttons="fixedMenuMinimalButtons"
        />
        <div class="mt-2 flex items-center justify-end space-x-2 sm:mt-0">
          <Button appearance="primary"> Submit </Button>
        </div>
      </div>
    </template>
  </TextEditor>
</template>

<script setup>
import {
  TextEditor,
  TextEditorFixedMenu,
  TextEditorContent,
  Button,
  Input,
} from 'jingrow-ui'
let content = ref('Highly customized editor')
let editable = ref(true)
let fixedMenuMinimalButtons = [
  'Paragraph',
  ['Heading 2', 'Heading 3', 'Heading 4', 'Heading 5', 'Heading 6'],
  'Separator',
  'Bold',
  'Italic',
  'Separator',
  'Bullet List',
  'Numbered List',
  'Separator',
  'Link',
  'Blockquote',
  'Code',
]
</script>