feat(richtext-lexical): add new paragraph button below the editor (#10530)
Fixes https://github.com/payloadcms/payload/issues/10448 https://github.com/user-attachments/assets/dfcd4ab6-8e41-4a1b-b642-876a0737d9ae
This commit is contained in:
@@ -305,6 +305,8 @@ The Rich Text Field editor configuration has an `admin` property with the follow
|
||||
| --- | --- |
|
||||
| **`placeholder`** | Set this property to define a placeholder string for the field. |
|
||||
| **`hideGutter`** | Set this property to `true` to hide this field's gutter within the Admin Panel. |
|
||||
| **`hideInsertParagraphAtEnd`** | Set this property to `true` to hide the "+" button that appears at the end of the editor |
|
||||
|
||||
|
||||
### Disable the gutter
|
||||
|
||||
|
||||
@@ -100,22 +100,23 @@
|
||||
|
||||
&__tableAddColumns:after,
|
||||
&__tableAddRows:after {
|
||||
background-image: url(../../../../../lexical/ui/icons/Add/index.svg);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
content: ' ';
|
||||
display: flex;
|
||||
content: '+';
|
||||
font-size: 1.4rem;
|
||||
border-radius: $style-radius-s;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.4;
|
||||
color: var(--theme-elevation-500);
|
||||
}
|
||||
|
||||
&__tableAddColumns:hover,
|
||||
&__tableAddRows:hover {
|
||||
background-color: var(--theme-elevation-200);
|
||||
background-color: var(--theme-elevation-150);
|
||||
}
|
||||
|
||||
&__tableAddRows {
|
||||
@@ -178,9 +179,14 @@
|
||||
mix-blend-mode: screen;
|
||||
}
|
||||
|
||||
&__tableAddColumns:after,
|
||||
&__tableAddRows:after {
|
||||
background-image: url(../../../../../lexical/ui/icons/Add/light.svg);
|
||||
&__tableAddColumns,
|
||||
&__tableAddRows {
|
||||
background-color: var(--theme-elevation-50);
|
||||
}
|
||||
|
||||
&__tableAddColumns:hover,
|
||||
&__tableAddRows:hover {
|
||||
background-color: var(--theme-elevation-100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,13 @@ import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary.js'
|
||||
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin.js'
|
||||
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin.js'
|
||||
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin.js'
|
||||
import { BLUR_COMMAND, COMMAND_PRIORITY_LOW, FOCUS_COMMAND } from 'lexical'
|
||||
import {
|
||||
$createParagraphNode,
|
||||
$getRoot,
|
||||
BLUR_COMMAND,
|
||||
COMMAND_PRIORITY_LOW,
|
||||
FOCUS_COMMAND,
|
||||
} from 'lexical'
|
||||
import * as React from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
@@ -15,6 +21,7 @@ import { EditorPlugin } from './EditorPlugin.js'
|
||||
import './LexicalEditor.scss'
|
||||
import { AddBlockHandlePlugin } from './plugins/handles/AddBlockHandlePlugin/index.js'
|
||||
import { DraggableBlockPlugin } from './plugins/handles/DraggableBlockPlugin/index.js'
|
||||
import { InsertParagraphAtEndPlugin } from './plugins/InsertParagraphAtEnd/index.js'
|
||||
import { MarkdownShortcutPlugin } from './plugins/MarkdownShortcut/index.js'
|
||||
import { SlashMenuPlugin } from './plugins/SlashMenu/index.js'
|
||||
import { TextPlugin } from './plugins/TextPlugin/index.js'
|
||||
@@ -104,6 +111,7 @@ export const LexicalEditor: React.FC<
|
||||
}
|
||||
ErrorBoundary={LexicalErrorBoundary}
|
||||
/>
|
||||
<InsertParagraphAtEndPlugin />
|
||||
<TextPlugin features={editorConfig.features} />
|
||||
<OnChangePlugin
|
||||
// Selection changes can be ignored here, reducing the
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
@import '../../../scss/styles';
|
||||
|
||||
@layer payload-default {
|
||||
.rich-text-lexical--show-gutter {
|
||||
.insert-paragraph-at-end {
|
||||
padding: 4px 0px 2px 40px;
|
||||
}
|
||||
}
|
||||
.insert-paragraph-at-end {
|
||||
height: 24px;
|
||||
margin-top: -16px;
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
padding: 4px 0px 2px 0px;
|
||||
|
||||
&-inside {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: transparent;
|
||||
transition: background-color 0.1s ease-in-out;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
border-radius: $style-radius-s;
|
||||
color: var(--theme-elevation-500);
|
||||
|
||||
span {
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
|
||||
.insert-paragraph-at-end-inside {
|
||||
background-color: var(--theme-elevation-100);
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
.insert-paragraph-at-end:hover {
|
||||
.insert-paragraph-at-end-inside {
|
||||
background-color: var(--theme-elevation-50);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
||||
'use client'
|
||||
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||
import { $createParagraphNode, $getRoot } from 'lexical'
|
||||
import React from 'react'
|
||||
|
||||
import './index.scss'
|
||||
import { useEditorConfigContext } from '../../config/client/EditorConfigProvider.js'
|
||||
const baseClass = 'insert-paragraph-at-end'
|
||||
|
||||
export const InsertParagraphAtEndPlugin: React.FC = () => {
|
||||
const [editor] = useLexicalComposerContext()
|
||||
const { editorConfig } = useEditorConfigContext()
|
||||
|
||||
if (editorConfig?.admin?.hideInsertParagraphAtEnd) {
|
||||
return null
|
||||
}
|
||||
|
||||
const onClick = () => {
|
||||
editor.update(() => {
|
||||
const paragraphNode = $createParagraphNode()
|
||||
$getRoot().append(paragraphNode)
|
||||
paragraphNode.select()
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div aria-label="Insert Paragraph" className={baseClass} onClick={onClick}>
|
||||
<div className={`${baseClass}-inside`}>
|
||||
<span>+</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -24,6 +24,10 @@ export type LexicalFieldAdminProps = {
|
||||
* Controls if the gutter (padding to the left & gray vertical line) should be hidden. @default false
|
||||
*/
|
||||
hideGutter?: boolean
|
||||
/**
|
||||
* Controls if the insert paragraph at the end button should be hidden. @default false
|
||||
*/
|
||||
hideInsertParagraphAtEnd?: boolean
|
||||
/**
|
||||
* Changes the placeholder text in the editor if no content is present.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user