chore(richtext-*): improved rich text editor styles and interaction (#7817)

## Description

- Improves the standard typography styles of the rich text editors.
- Improve styles of Lexical relationship, inline-relationship, upload,
and blocks features.
- Improves drag and drop interaction for Lexical.
- Adds a dark mode style for Lexical inline toolbar, floating link editor,
and slash menu.

- [x] I have read and understand the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository.

## Type of change

<!-- Please delete options that are not relevant. -->

- [x] Chore (non-breaking change which does not add functionality)

## Checklist:

- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] Existing test suite passes locally with my changes
- [ ] I have made corresponding changes to the documentation
This commit is contained in:
Tylan Davis
2024-08-23 10:50:53 -04:00
committed by GitHub
parent 49c0709fed
commit a2d68f84e1
31 changed files with 341 additions and 282 deletions

View File

@@ -21,8 +21,8 @@
--theme-baseline-body-size: #{$baseline-body-size};
--font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
sans-serif;
--font-serif: Georgia, 'Bitstream Charter', 'Charis SIL', Utopia, 'URW Bookman L', serif;
--font-mono: monospace;
--font-serif: 'Georgia', 'Bitstream Charter', 'Charis SIL', Utopia, 'URW Bookman L', serif;
--font-mono: 'SF Mono', Menlo, Consolas, Monaco, monospace;
--style-radius-s: #{$style-radius-s};
--style-radius-m: #{$style-radius-m};
@@ -146,13 +146,13 @@ h6 {
}
p {
margin: 0 0 $baseline;
margin: 0;
}
ul,
ol {
padding-left: $baseline;
margin: 0 0 $baseline;
margin: 0;
}
:focus-visible {

View File

@@ -16,7 +16,7 @@
}
%h1 {
margin: 0 0 base(1);
margin: 0;
font-size: base(1.6);
line-height: base(1.8);
@@ -27,7 +27,7 @@
}
%h2 {
margin: 0 0 base(1);
margin: 0;
font-size: base(1.3);
line-height: base(1.6);
@@ -37,7 +37,7 @@
}
%h3 {
margin: 0 0 base(1);
margin: 0;
font-size: base(1);
line-height: base(1.2);
@@ -48,7 +48,7 @@
}
%h4 {
margin: 0 0 $baseline;
margin: 0;
font-size: base(0.8);
line-height: base(1);
letter-spacing: -0.375px;

View File

@@ -17,7 +17,7 @@
}
}
margin: 0 0 1.5em;
margin-block: base(0.4);
&__header {
h3 {

View File

@@ -7,19 +7,24 @@
.inline-block {
@extend %body;
@include shadow-sm;
padding: calc(var(--base) * 0.125) calc(var(--base) * 0.125) calc(var(--base) * 0.125) calc(var(--base) * 0.3);
padding: base(0.1);
padding-inline-start: base(0.4);
display: flex;
align-items: center;
background: var(--theme-input-bg);
border: 1px solid var(--theme-elevation-100);
border-radius: $style-radius-m;
outline: 1px solid var(--theme-elevation-100);
border-radius: $style-radius-s;
max-width: calc(var(--base) * 15);
font-family: var(--font-body);
margin-right: $style-stroke-width-m;
margin-left: $style-stroke-width-m;
margin-right: base(0.2);
margin-left: base(0.2);
&::selection {
background: transparent;
}
&:hover {
border: 1px solid var(--theme-elevation-150);
outline: 1px solid var(--theme-elevation-150);
}
&__wrap {
@@ -28,8 +33,8 @@
}
&--selected {
box-shadow: $focus-box-shadow;
outline: none;
background: var(--theme-success-100);
outline: 1px solid var(--theme-success-400);
}
&__editButton.btn {
@@ -47,13 +52,24 @@
display: flex;
align-items: center;
flex-shrink: 0;
margin-left: calc(var(--base) * 0.15);
margin-left: base(0.4);
& > .btn {
width: base(1);
height: base(1);
&:not(:disabled):hover {
background: var(--theme-elevation-100);
}
& > * {
height: 100%;
}
}
svg {
width: 20px;
height: 20px;
width: 16px;
height: 16px;
}
}
@@ -61,7 +77,7 @@
margin: 0;
line {
stroke-width: $style-stroke-width-m;
stroke-width: base(0.2);
}
&:disabled {

View File

@@ -5,7 +5,15 @@ import type { Data, FormState } from 'payload'
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js'
import { $findMatchingParent, mergeRegister } from '@lexical/utils'
import { getTranslation } from '@payloadcms/translations'
import { formatDrawerSlug, useConfig, useEditDepth, useModal, useTranslation } from '@payloadcms/ui'
import {
CloseMenuIcon,
EditIcon,
formatDrawerSlug,
useConfig,
useEditDepth,
useModal,
useTranslation,
} from '@payloadcms/ui'
import {
$getSelection,
$isLineBreakNode,
@@ -293,7 +301,9 @@ export function LinkEditor({ anchorElem }: { anchorElem: HTMLElement }): React.R
}}
tabIndex={0}
type="button"
/>
>
<EditIcon />
</button>
{!isAutoLink && (
<button
aria-label="Remove link"
@@ -306,7 +316,9 @@ export function LinkEditor({ anchorElem }: { anchorElem: HTMLElement }): React.R
}}
tabIndex={0}
type="button"
/>
>
<CloseMenuIcon />
</button>
)}
</React.Fragment>
)}

View File

@@ -1,17 +1,11 @@
@import '../../../../../scss/styles.scss';
html[data-theme='light'] {
.link-editor {
@include shadow-m;
}
}
.link-editor {
z-index: 1;
display: flex;
align-items: center;
background: var(--color-base-0);
padding: 0 3.72px 0 6.25px;
background: var(--theme-input-bg);
padding: 4px 4px 4px 12px;
vertical-align: middle;
position: absolute;
top: 0;
@@ -19,8 +13,11 @@ html[data-theme='light'] {
opacity: 0;
border-radius: $style-radius-m;
transition: opacity 0.2s;
height: 37.5px;
will-change: transform;
box-shadow:
0px 1px 2px 1px rgba(0, 0, 0, 0.1),
0px 4px 16px 0px rgba(0, 0, 0, 0.1),
0px -4px 16px 0px rgba(0, 0, 0, 0.1);
.link-input {
display: flex;
@@ -29,15 +26,14 @@ html[data-theme='light'] {
flex-wrap: nowrap;
min-height: 28px;
box-sizing: border-box;
padding: 2px 4px;
font-size: 15px;
@extend %body;
border: 0;
outline: 0;
position: relative;
font-family: var(--font-body);
&__label-pure {
color: var(--color-base-1000);
color: var(--theme-elevation-1000);
margin-right: 15px;
display: block;
white-space: nowrap;
@@ -45,42 +41,46 @@ html[data-theme='light'] {
}
a {
text-decoration: none;
text-decoration: underline;
display: block;
white-space: nowrap;
overflow: hidden;
margin-right: 15px;
margin-right: base(0.4);
text-overflow: ellipsis;
color: var(--color-blue-600);
border-bottom: 1px dotted;
color: var(--theme-success-750);
&:hover {
color: var(--color-blue-400);
color: var(--theme-success-850);
}
}
}
button {
all: unset;
display: flex;
align-items: center;
justify-content: center;
background-size: 16px;
background-position: center;
background-repeat: no-repeat;
width: 30px;
height: 30px;
cursor: pointer;
color: var(--color-base-600);
color: var(--theme-elevation-600);
border-radius: $style-radius-m;
&:hover:not([disabled]) {
background-color: var(--color-base-100);
color: var(--theme-elevation-800);
background-color: var(--theme-elevation-100);
}
}
}
.link-edit {
background-image: url(../../../../../lexical/ui/icons/Edit/index.svg);
}
.link-trash {
background-image: url(../../../../../lexical/ui/icons/Remove/index.svg);
html[data-theme='light'] {
.link-editor {
box-shadow:
0px 1px 2px 1px rgba(0, 0, 0, 0.05),
0px 4px 8px 0px rgba(0, 0, 0, 0.05),
0px -4px 16px 0px rgba(0, 0, 0, 0.05);
}
}

View File

@@ -11,7 +11,7 @@
border-radius: $style-radius-m;
max-width: calc(var(--base) * 15);
font-family: var(--font-body);
margin: 0 0 1.5em;
margin-block: base(0.5);
&:hover {
border: 1px solid var(--theme-elevation-150);

View File

@@ -4,13 +4,14 @@ html[data-theme='dark'] {
.fixed-toolbar {
&__dropdown-items {
background: var(--theme-elevation-0);
transition: background 0.2s cubic-bezier(0, 0.2, 0.2, 1);
.toolbar-popup__dropdown-item {
color: var(--theme-elevation-900);
&:hover:not([disabled]),
&.active {
background-color: var(--theme-elevation-100);
background: var(--theme-elevation-100);
}
.icon {
@@ -23,13 +24,15 @@ html[data-theme='dark'] {
&__button {
&.active,
&:hover:not([disabled]) {
background-color: var(--theme-elevation-100);
background: var(--theme-elevation-100);
}
}
&__dropdown {
transition: background-color 0.15s cubic-bezier(0, 0.2, 0.2, 1);
&:hover:not([disabled]) {
background-color: var(--theme-elevation-100);
background: var(--theme-elevation-100);
}
&-caret:after {
@@ -70,7 +73,7 @@ html[data-theme='dark'] {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 2px;
gap: 0;
z-index: 1;
.icon {
@@ -87,13 +90,6 @@ html[data-theme='dark'] {
}
}
.toolbar-popup {
&__dropdown,
&__button {
border-radius: 0;
}
}
+ .editor-container {
> .editor-scroller > .editor {
> .ContentEditable__root {

View File

@@ -1,16 +1,10 @@
@import '../../../../../scss/styles';
html[data-theme='light'] {
.inline-toolbar-popup {
@include shadow-m;
}
}
.inline-toolbar-popup {
display: flex;
align-items: center;
background: var(--color-base-0);
padding: 0 3.72px 0 6.25px;
background: var(--theme-elevation-50);
padding: base(0.2);
vertical-align: middle;
position: absolute;
top: 0;
@@ -19,16 +13,19 @@ html[data-theme='light'] {
opacity: 0;
border-radius: $style-radius-m;
transition: opacity 0.2s;
height: 37.5px;
will-change: transform;
box-shadow:
0px 1px 2px 1px rgba(0, 0, 0, 0.1),
0px 4px 16px 0px rgba(0, 0, 0, 0.2),
0px -4px 8px 0px rgba(0, 0, 0, 0.1);
.caret {
z-index: 93;
position: absolute;
top: calc(100% - 16px);
border: 12px solid transparent;
top: calc(100% - 24px);
border: base(0.4) solid transparent;
pointer-events: none;
border-top-color: var(--color-base-0);
border-top-color: var(--theme-input-bg);
}
&__group {
@@ -39,14 +36,21 @@ html[data-theme='light'] {
.icon {
min-width: 20px;
height: 20px;
color: var(--color-base-600);
color: var(--theme-elevation-600);
}
.divider {
width: 1px;
height: 15px;
background-color: var(--color-base-100);
background-color: var(--theme-border-color);
margin: 0 6.25px;
}
}
}
html[data-theme='light'] {
.inline-toolbar-popup {
box-shadow:
0px 1px 2px 1px rgba(0, 0, 0, 0.05),
0px 4px 8px 0px rgba(0, 0, 0, 0.1);
}
}

View File

@@ -236,7 +236,7 @@ function InlineToolbar({
horizontalPosition: 'center',
specialHandlingForCaret: true,
targetRect: rangeRect,
verticalGap: 10,
verticalGap: 8,
})
}
} else {

View File

@@ -12,13 +12,15 @@
border-radius: $style-radius-m;
cursor: pointer;
padding: 0;
transition: background-color 0.15s cubic-bezier(0, 0.2, 0.2, 1);
&.spaced {
margin-right: 2px;
}
&.active {
background-color: var(--color-base-100);
background-color: var(--them-elevation-150);
color: var(--theme-text);
.icon {
opacity: 1;
@@ -34,6 +36,6 @@
}
&:hover:not([disabled]) {
background-color: var(--color-base-100);
background-color: var(--theme-elevation-100);
}
}

View File

@@ -5,17 +5,20 @@
align-items: center;
vertical-align: middle;
justify-content: center;
height: 30px;
gap: base(0.2);
height: base(1.5);
border: 0;
background: none;
border-radius: $style-radius-m;
cursor: pointer;
position: relative;
padding: 0 10px;
padding: 0 base(0.4) 0 base(0.3);
transition: background-color 0.15s cubic-bezier(0, 0.2, 0.2, 1);
&-label {
color: var(--color-base-600);
padding: 0 10px;
color: var(--theme-elevation-600);
padding-block: 0;
padding-inline: base(0.2) base(0.4);
}
&:disabled {
@@ -27,11 +30,11 @@
}
&:hover:not([disabled]) {
background-color: var(--color-base-100);
background-color: var(--theme-elevation-100);
}
.active {
background-color: var(--color-base-100);
background-color: var(--theme-elevation-100);
.toolbar-popup__dropdown-caret {
&:after {
@@ -41,28 +44,29 @@
}
&-caret {
width: base(0.4);
display: flex;
align-items: center;
justify-content: center;
transform: rotate(45deg);
&:after {
transform: rotate(180deg);
display: block;
content: ' ';
position: absolute;
top: 13px;
/* Vector 3 */
width: 7px;
width: 4px;
height: 4px;
opacity: 0.3;
background-image: url(../../../../lexical/ui/icons/Caret/index.svg);
background-position-y: 0;
background-position-x: 0;
transform: translateY(-2px);
border: solid 1px var(--theme-elevation-600);
border-width: 0 1px 1px 0;
}
}
&-items {
position: absolute;
background: var(--color-base-0);
background: var(--theme-elevation-0);
border-radius: $style-radius-m;
min-width: 132.5px;
max-width: 200px;
@@ -71,7 +75,8 @@
.toolbar-popup__dropdown-item {
all: unset; // reset all default button styles
cursor: pointer;
color: var(--color-base-900);
color: var(--theme-elevation-900);
transition: background-color 0.15s cubic-bezier(0, 0.2, 0.2, 1);
.text {
overflow: hidden;
@@ -81,7 +86,7 @@
&:hover:not([disabled]),
&.active {
background-color: var(--color-base-100);
background-color: var(--theme-elevation-100);
}
padding-left: 6.25px;
@@ -97,7 +102,7 @@
.icon {
min-width: 20px;
height: 20px;
color: var(--color-base-600);
color: var(--theme-elevation-600);
}
}
}

View File

@@ -11,7 +11,7 @@
border: 1px solid var(--theme-elevation-100);
position: relative;
font-family: var(--font-body);
margin: 0 0 1.5em;
margin-block: base(0.5);
.btn {
margin: 0;

View File

@@ -25,19 +25,31 @@
}
&--show-gutter {
> .rich-text-lexical__wrap > .editor-container > .editor-scroller > .editor > div > .editor-placeholder {
> .rich-text-lexical__wrap
> .editor-container
> .editor-scroller
> .editor
> div
> .editor-placeholder {
left: 3rem;
}
}
&:not(&--show-gutter) > .rich-text-lexical__wrap > .editor-container > .editor-scroller > .editor > div > .editor-placeholder {
&:not(&--show-gutter)
> .rich-text-lexical__wrap
> .editor-container
> .editor-scroller
> .editor
> div
> .editor-placeholder {
left: 0;
}
.editor-placeholder {
position: absolute;
top: 8px;
font-size: 15px;
font-size: base(0.8);
line-height: 1.5;
color: var(--theme-elevation-500);
/* Prevent text selection */
user-select: none;

View File

@@ -1,15 +1,9 @@
@import '../../../scss/styles.scss';
html[data-theme='light'] {
.slash-menu-popup {
@include shadow-lg;
}
}
.slash-menu-popup {
background: var(--color-base-0);
background: var(--theme-input-bg);
width: 200px;
color: var(--color-base-800);
color: var(--theme-elevation-800);
border-radius: $style-radius-m;
list-style: none;
font-family: var(--font-body);
@@ -17,6 +11,10 @@ html[data-theme='light'] {
overflow-y: auto;
z-index: 10;
position: absolute;
box-shadow:
0px 1px 2px 1px rgba(0, 0, 0, 0.1),
0px 4px 16px 0px rgba(0, 0, 0, 0.2),
0px -4px 8px 0px rgba(0, 0, 0, 0.1);
&__group {
padding-bottom: 8px;
@@ -24,7 +22,7 @@ html[data-theme='light'] {
&__group-title {
padding-left: 10px;
color: var(--color-base-600);
color: var(--theme-elevation-600);
font-size: 10px;
}
@@ -35,7 +33,7 @@ html[data-theme='light'] {
box-sizing: border-box;
background: none;
border: none;
color: var(--color-base-900);
color: var(--theme-elevation-900);
display: flex;
align-items: center;
height: 30px;
@@ -43,7 +41,7 @@ html[data-theme='light'] {
cursor: pointer;
&--selected {
background: var(--color-base-100);
background: var(--theme-elevation-100);
}
&-text {
@@ -54,8 +52,16 @@ html[data-theme='light'] {
}
.icon {
color: var(--color-base-500);
color: var(--theme-elevation-500);
min-width: fit-content;
}
}
}
html[data-theme='light'] {
.slash-menu-popup {
box-shadow:
0px 1px 2px 1px rgba(0, 0, 0, 0.05),
0px 4px 8px 0px rgba(0, 0, 0, 0.1);
}
}

View File

@@ -48,16 +48,15 @@
.draggable-block-target-line {
pointer-events: none;
background: var(--theme-elevation-200);
//border: 1px solid var(--theme-elevation-650);
border-radius: $style-radius-m;
height: 50px;
background: var(--theme-success-400);
border-radius: 1px;
height: base(0.2);
position: absolute;
left: 0;
top: 0;
opacity: 0;
will-change: transform;
transition: transform 0.04s;
transition: transform 0.1s;
}
/* This targets Firefox 57+. The transition looks ugly on firefox, thus we disable it here */

View File

@@ -348,14 +348,8 @@ function useDraggableBlockMenu(
const highlightElem = document.createElement('div')
highlightElem.className = 'lexical-block-highlighter'
// if html data-theme is dark, set the highlighter color to white
if (document.documentElement.getAttribute('data-theme') === 'dark') {
highlightElem.style.backgroundColor = 'white'
} else {
highlightElem.style.backgroundColor = 'black'
}
highlightElem.style.transition = 'opacity 0.1s ease-in-out'
highlightElem.style.backgroundColor = 'var(--theme-elevation-1000'
highlightElem.style.transition = 'opacity 0.5s ease-in-out'
highlightElem.style.zIndex = '1'
highlightElem.style.pointerEvents = 'none'
highlightElem.style.boxSizing = 'border-box'
@@ -374,8 +368,8 @@ function useDraggableBlockMenu(
highlightElem.style.opacity = '0'
setTimeout(() => {
highlightElem.remove()
}, 500)
}, 1000)
}, 3000)
}, 120)
})

View File

@@ -1,7 +1,7 @@
'use client'
import { getCollapsedMargins } from '../utils/getCollapsedMargins.js'
import { highlightElemOriginalPosition } from './highlightElemOriginalPosition.js'
const TARGET_LINE_HALF_HEIGHT = 25
const TARGET_LINE_HALF_HEIGHT = 0
const TEXT_BOX_HORIZONTAL_PADDING = -24
const DEBUG = false
@@ -115,31 +115,14 @@ export function setTargetLine(
const left = TEXT_BOX_HORIZONTAL_PADDING - offsetLeft
targetLineElem.style.width = `calc(${anchorWidth}px - ${offsetWidth})`
targetLineElem.style.opacity = '.4'
targetLineElem.style.opacity = '.8'
/**
* Move around element below or above the line (= the target / targetBlockElem). Creates "space" for the targetLineElem
*
* Not needed for empty paragraphs, as an empty paragraph is enough space for the targetLineElem anyways.
*/
//targetBlockElem.style.opacity = '0.4'
const buffer = 12 // creates more spacing/padding so target line is not directly next to the targetBlockElem
if (!isFoundNodeEmptyParagraph) {
if (isBelow) {
targetBlockElem.style.marginBottom = TARGET_LINE_HALF_HEIGHT * 2 + buffer + 'px'
targetLineElem.style.transform = `translate(${left}px, calc(${top}px - ${'0px'}))`
} else {
targetBlockElem.style.marginTop = TARGET_LINE_HALF_HEIGHT * 2 + buffer + 'px'
targetLineElem.style.transform = `translate(${left}px, calc(${top - TARGET_LINE_HALF_HEIGHT * 2}px - ${'0px'}))`
}
} else {
targetLineElem.style.transform = `translate(${left}px, ${top - TARGET_LINE_HALF_HEIGHT}px)`
}
// if (DEBUG) {
// //targetBlockElem.style.border = '3px solid red'
// highlightElemOriginalPosition(debugHighlightRef, targetBlockElem, anchorElem)
// }
if (DEBUG) {
//targetBlockElem.style.border = '3px solid red'
highlightElemOriginalPosition(debugHighlightRef, targetBlockElem, anchorElem)
}
targetLineElem.style.transform = `translate(${left}px, calc(${top}px - ${'2px'}))`
/**
* Properly reset previous targetBlockElem styles

View File

@@ -20,24 +20,20 @@ export function setHandlePosition(
let top: number
const shouldDisplayHandleInCenter = targetRect.height < 60
const isBlockStyle = ['lexical-block', 'lexical-upload', 'lexical-relationship'].some((classes) =>
targetElem.firstElementChild?.classList.contains(classes),
)
if (!shouldDisplayHandleInCenter) {
if (!isBlockStyle) {
// No need to let line height affect the re-positioning of the floating element if line height has no
// visual effect on the element. Otherwise, the floating element will be positioned incorrectly.
const actualLineHeight = doesLineHeightAffectElement(targetElem)
? parseInt(targetStyle.lineHeight, 10)
: 0
top =
targetRect.top + (actualLineHeight - floatingElemRect.height) / 2 - anchorElementRect.top - 1 // 1px inaccuracy
top = targetRect.top + (actualLineHeight - floatingElemRect.height) / 2 - anchorElementRect.top
} else {
top =
targetRect.top -
floatingElemRect.height / 2 -
anchorElementRect.top +
targetRect.height / 2 -
1 // 1px inaccuracy
top = targetRect.top + 8 - anchorElementRect.top
}
const left = leftOffset

View File

@@ -4,55 +4,85 @@
&__ltr {
text-align: left;
}
&__ltr {
text-align: left;
}
&__rtl {
text-align: right;
}
&__paragraph {
margin: 0 0 1.5em;
font-size: base(0.8);
margin-bottom: 0.55em;
position: relative;
line-height: 1.5;
letter-spacing: normal;
}
// No bottom margin for last paragraph in editor. This also created nice animations when adding a new line at the end
.ContentEditable__root > &__paragraph:last-child {
margin-bottom: 0;
.ContentEditable__root {
font-size: base(0.8);
}
&__quote {
margin: 0 0 10px 20px;
font-size: 15px;
color: rgb(101, 103, 107);
border-left-color: rgb(206, 208, 212);
border-left-width: 4px;
border-left-style: solid;
padding-left: 16px;
font-size: base(0.8);
margin-block: base(0.8);
margin-inline: base(0.2);
border-inline-start-color: var(--theme-elevation-150);
border-inline-start-width: base(0.2);
border-inline-start-style: solid;
padding-inline-start: base(0.6);
padding-block: base(0.2);
}
&__h1 {
font-size: 2.8rem;
line-height: 1.125;
color: rgb(5, 5, 5);
font-weight: 500;
font-size: base(1.4);
font-weight: 700;
margin-block: 0.5em 0.4em;
line-height: base(1.2);
letter-spacing: normal;
}
&__h2 {
font-size: 2rem;
color: rgb(5, 5, 5);
font-size: base(1.25);
font-weight: 700;
margin-block: 0.55em 0.4em;
line-height: base(1.2);
letter-spacing: normal;
}
&__h3 {
font-size: 1.4rem;
color: rgb(101, 103, 107);
font-size: base(1.1);
font-weight: 700;
margin-block: 0.6em 0.4em;
line-height: base(1.3);
letter-spacing: normal;
}
&__h4 {
font-size: base(1);
font-weight: 700;
margin-block: 0.65em 0.4em;
line-height: base(1.4);
letter-spacing: normal;
}
&__h5 {
font-size: base(0.9);
font-weight: 700;
margin-block: 0.7em 0.4em;
line-height: base(1.5);
letter-spacing: normal;
}
&__h6 {
font-size: base(0.8);
font-weight: 700;
margin-block: 0.75em 0.4em;
line-height: base(1.5);
letter-spacing: 0.1em;
}
&__indent {
--lexical-indent-base-value: 40px;
--lexical-indent-base-value: base(2);
}
&__textBold {
@@ -86,10 +116,15 @@
}
&__textCode {
background-color: rgb(240, 242, 245);
padding: 1px 0.25rem;
font-family: Menlo, Consolas, Monaco, monospace;
font-size: 94%;
background-color: var(--theme-elevation-50);
border: 1px solid var(--theme-elevation-150);
color: var(--theme-error-600);
padding: base(0.1) base(0.2);
font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace;
font-size: 0.875em;
border-radius: var(--style-radius-s);
box-decoration-break: clone;
-webkit-box-decoration-break: clone;
}
&__hashtag {
@@ -102,7 +137,7 @@
}
&__link {
color: var(--color-blue-600);
color: var(--theme-success-750);
text-decoration: none;
border-bottom: 1px dotted;
}
@@ -143,7 +178,7 @@
&__ol1 {
padding: 0;
list-style-position: outside;
margin: 0 0 1.5em;
margin: base(0.4) 0 base(0.8);
}
&__ol2 {
@@ -176,7 +211,7 @@
&__ul {
padding: 0;
margin: 0 0 1.5em;
margin: base(0.4) 0 base(0.8);
list-style-position: outside;
}
@@ -185,16 +220,16 @@
}
&__listItem {
margin: 0 0 0.4em 16px;
font-size: base(0.8);
margin: 0 0 0.4em base(0.8);
}
&__listItemChecked,
&__listItemUnchecked {
position: relative;
margin-left: 8px;
margin-right: 8px;
padding-left: 24px;
padding-right: 24px;
margin-inline: 0;
padding-left: base(1.2);
padding-right: base(1.2);
list-style-type: none;
outline: none;
}
@@ -206,9 +241,9 @@
&__listItemUnchecked:before,
&__listItemChecked:before {
content: '';
width: 16px;
height: 16px;
top: 2px;
width: base(0.8);
height: base(0.8);
top: base(0.1);
left: 0;
cursor: pointer;
display: block;
@@ -224,26 +259,28 @@
&__listItemUnchecked:focus:before,
&__listItemChecked:focus:before {
box-shadow: 0 0 0 2px #a6cdfe;
border-radius: $style-radius-m;
outline: 0;
box-shadow: 0 0 3px 3px var(--theme-success-400);
border: 1px solid var(--theme-elevation-250);
border-radius: var(--style-radius-s);
}
&__listItemUnchecked:before {
border: 1px solid #999;
border-radius: $style-radius-m;
border: 1px solid var(--theme-elevation-250);
border-radius: $style-radius-s;
}
&__listItemChecked:before {
border: 1px solid rgb(61, 135, 245);
border-radius: $style-radius-m;
background-color: #3d87f5;
border: 1px solid var(--theme-elevation-500);
border-radius: $style-radius-s;
background-color: var(--theme-elevation-100);
background-repeat: no-repeat;
}
&__listItemChecked:after {
content: '';
cursor: pointer;
border-color: #fff;
border-color: var(--theme-text);
border-style: solid;
position: absolute;
display: block;
@@ -325,30 +362,16 @@
&__embedBlockFocus {
outline: 2px solid rgb(60, 132, 244);
}
.ContentEditable__root {
&:first-child {
margin-top: 0;
}
}
}
html[data-theme='dark'] {
.LexicalEditorTheme {
&__h1,
&__h2 {
color: rgb(255, 255, 255);
}
&__h3 {
color: rgb(148, 151, 157);
}
&__link {
color: var(--color-blue-600);
}
&__quote {
color: rgb(193, 198, 206);
border-left-color: var(--theme-elevation-150);
}
&__textCode {
background-color: rgb(0, 0, 0);
}
.LexicalEditorTheme__textCode {
color: var(--theme-warning-600);
}
}

View File

@@ -1,3 +1,3 @@
<svg width="7" height="4" viewBox="0 0 7 4" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.25 3.5L3.75 1L6.25 3.5" stroke="#000000" />
<path d="M1.25 3.5L3.75 1L6.25 3.5" />
</svg>

Before

Width:  |  Height:  |  Size: 158 B

After

Width:  |  Height:  |  Size: 142 B

View File

@@ -1,6 +1,6 @@
'use client'
const VERTICAL_GAP = 10
const HORIZONTAL_OFFSET = 5
const HORIZONTAL_OFFSET = 32
// TODO: needs refactoring
// This is supposed to position the floatingElem based on the parent (anchorElem) and the target (targetRect) which is usually the selected text.

View File

@@ -21,8 +21,8 @@
--theme-baseline-body-size: #{$baseline-body-size};
--font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
sans-serif;
--font-serif: Georgia, 'Bitstream Charter', 'Charis SIL', Utopia, 'URW Bookman L', serif;
--font-mono: monospace;
--font-serif: 'Georgia', 'Bitstream Charter', 'Charis SIL', Utopia, 'URW Bookman L', serif;
--font-mono: 'SF Mono', Menlo, Consolas, Monaco, monospace;
--style-radius-s: #{$style-radius-s};
--style-radius-m: #{$style-radius-m};
@@ -146,13 +146,13 @@ h6 {
}
p {
margin: 0 0 $baseline;
margin: 0;
}
ul,
ol {
padding-left: $baseline;
margin: 0 0 $baseline;
margin: 0;
}
:focus-visible {

View File

@@ -16,7 +16,7 @@
}
%h1 {
margin: 0 0 base(1);
margin: 0;
font-size: base(1.6);
line-height: base(1.8);
@@ -27,7 +27,7 @@
}
%h2 {
margin: 0 0 base(1);
margin: 0;
font-size: base(1.3);
line-height: base(1.6);
@@ -37,7 +37,7 @@
}
%h3 {
margin: 0 0 base(1);
margin: 0;
font-size: base(1);
line-height: base(1.2);
@@ -48,7 +48,7 @@
}
%h4 {
margin: 0 0 $baseline;
margin: 0;
font-size: base(0.8);
line-height: base(1);
letter-spacing: -0.375px;

View File

@@ -2,7 +2,6 @@
.rich-text-link {
position: relative;
text-decoration: underline;
.popup {
position: absolute;
@@ -35,11 +34,6 @@
font-weight: 600;
cursor: pointer;
margin: 0;
&:hover,
&:focus-visible {
text-decoration: underline;
}
}
}
@@ -78,7 +72,9 @@
border: 0;
background-color: transparent;
padding: 0;
text-decoration: underline;
color: var(--theme-success-600);
text-decoration: none;
border-bottom: 1px dotted;
cursor: text;
&:focus,

View File

@@ -39,7 +39,14 @@
&__editor {
font-family: var(--font-serif);
font-size: base(0.8);
letter-spacing: 0.02em;
line-height: 1.5;
*[data-slate-node='element'] {
margin-top: 0.75em;
position: relative;
line-height: 1.5;
letter-spacing: normal;
}
h1,
h2,
@@ -47,39 +54,49 @@
h4,
h5,
h6 {
font-family: var(--font-body);
line-height: 1.125;
letter-spacing: 0;
font-weight: 700;
letter-spacing: normal;
}
h1[data-slate-node='element'] {
font-size: base(1.5);
margin: base(1) 0 base(0.5);
font-size: base(1.4);
margin-block: 0.5em 0.4em;
line-height: base(1.2);
letter-spacing: normal;
}
h2[data-slate-node='element'] {
font-size: base(1.25);
margin: base(1) 0 base(0.5);
margin-block: 0.55em 0.4em;
line-height: base(1.2);
letter-spacing: normal;
}
h3[data-slate-node='element'] {
font-size: base(1.125);
margin: base(0.75) 0 base(0.5);
font-size: base(1.1);
margin-block: 0.6em 0.4em;
line-height: base(1.3);
letter-spacing: normal;
}
h4[data-slate-node='element'] {
font-size: base(1);
margin: base(0.5) 0 base(0.5);
margin-block: 0.65em 0.4em;
line-height: base(1.4);
letter-spacing: normal;
}
h5[data-slate-node='element'] {
font-size: base(0.875);
margin: base(0.25) 0 base(0.25);
font-size: base(0.9);
margin-block: 0.7em 0.4em;
line-height: base(1.5);
letter-spacing: normal;
}
h6[data-slate-node='element'] {
font-size: base(0.75);
margin: base(0.25) 0 base(0.25);
font-size: base(0.8);
margin-block: 0.75em 0.4em;
line-height: base(1.5);
}
}

View File

@@ -21,8 +21,8 @@
--theme-baseline-body-size: #{$baseline-body-size};
--font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
sans-serif;
--font-serif: Georgia, 'Bitstream Charter', 'Charis SIL', Utopia, 'URW Bookman L', serif;
--font-mono: monospace;
--font-serif: 'Georgia', 'Bitstream Charter', 'Charis SIL', Utopia, 'URW Bookman L', serif;
--font-mono: 'SF Mono', Menlo, Consolas, Monaco, monospace;
--style-radius-s: #{$style-radius-s};
--style-radius-m: #{$style-radius-m};
@@ -146,13 +146,13 @@ h6 {
}
p {
margin: 0 0 $baseline;
margin: 0;
}
ul,
ol {
padding-left: $baseline;
margin: 0 0 $baseline;
margin: 0;
}
:focus-visible {

View File

@@ -16,7 +16,7 @@
}
%h1 {
margin: 0 0 base(1);
margin: 0;
font-size: base(1.6);
line-height: base(1.8);
@@ -27,7 +27,7 @@
}
%h2 {
margin: 0 0 base(1);
margin: 0;
font-size: base(1.3);
line-height: base(1.6);
@@ -37,7 +37,7 @@
}
%h3 {
margin: 0 0 base(1);
margin: 0;
font-size: base(1);
line-height: base(1.2);
@@ -48,7 +48,7 @@
}
%h4 {
margin: 0 0 $baseline;
margin: 0;
font-size: base(0.8);
line-height: base(1);
letter-spacing: -0.375px;

View File

@@ -21,8 +21,8 @@
--theme-baseline-body-size: #{$baseline-body-size};
--font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
sans-serif;
--font-serif: Georgia, 'Bitstream Charter', 'Charis SIL', Utopia, 'URW Bookman L', serif;
--font-mono: monospace;
--font-serif: 'Georgia', 'Bitstream Charter', 'Charis SIL', Utopia, 'URW Bookman L', serif;
--font-mono: 'SF Mono', Menlo, Consolas, Monaco, monospace;
--style-radius-s: #{$style-radius-s};
--style-radius-m: #{$style-radius-m};
@@ -45,8 +45,8 @@
@include mid-break {
--gutter-h: #{base(2)};
--app-header-height: calc(var(--base) * 2.8);
--doc-controls-height: calc(var(--base) * 2.5);
--app-header-height: calc(var(--base) * 2.4);
--doc-controls-height: calc(var(--base) * 2.4);
}
@include small-break {
@@ -146,13 +146,13 @@ h6 {
}
p {
margin: 0 0 $baseline;
margin: 0;
}
ul,
ol {
padding-left: $baseline;
margin: 0 0 $baseline;
margin: 0;
}
:focus-visible {

View File

@@ -16,7 +16,7 @@
}
%h1 {
margin: 0 0 base(1);
margin: 0;
font-size: base(1.6);
line-height: base(1.8);
@@ -27,7 +27,7 @@
}
%h2 {
margin: 0 0 base(1);
margin: 0;
font-size: base(1.3);
line-height: base(1.6);
@@ -37,7 +37,7 @@
}
%h3 {
margin: 0 0 base(1);
margin: 0;
font-size: base(1);
line-height: base(1.2);
@@ -48,7 +48,7 @@
}
%h4 {
margin: 0 0 $baseline;
margin: 0;
font-size: base(0.8);
line-height: base(1);
letter-spacing: -0.375px;

View File

@@ -77,7 +77,6 @@ export interface Config {
export interface UserAuthOperations {
forgotPassword: {
email: string;
password: string;
};
login: {
email: string;
@@ -89,7 +88,6 @@ export interface UserAuthOperations {
};
unlock: {
email: string;
password: string;
};
}
/**