From 8454e4f1e067f2cd3c11a91f93b069f0d936c264 Mon Sep 17 00:00:00 2001
From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com>
Date: Mon, 15 Apr 2024 19:45:03 +0530
Subject: [PATCH] [WEB-986] fix: editor slash command positioning (#4186)
* fix: table selected cell border
* chore: add syncing message when revalidating page data
* fix: slash command positioning
* fix: mentions list dropdown positioning
---
packages/editor/core/src/styles/editor.css | 12 ++++-----
packages/editor/core/src/styles/table.css | 13 +--------
.../editor/core/src/ui/extensions/index.tsx | 2 +-
.../core/src/ui/mentions/mention-list.tsx | 2 +-
.../src/extensions/slash-commands.tsx | 27 ++++++++++---------
.../pages/editor/header/extra-options.tsx | 9 ++++++-
web/components/pages/editor/header/root.tsx | 3 +++
.../projects/[projectId]/pages/[pageId].tsx | 3 ++-
8 files changed, 36 insertions(+), 35 deletions(-)
diff --git a/packages/editor/core/src/styles/editor.css b/packages/editor/core/src/styles/editor.css
index 63bc5a6d6..4cb4e9772 100644
--- a/packages/editor/core/src/styles/editor.css
+++ b/packages/editor/core/src/styles/editor.css
@@ -49,15 +49,12 @@
}
}
-/* Custom list item styles */
-
/* Custom gap cursor styles */
.ProseMirror-gapcursor::after {
border-top: 1px solid rgb(var(--color-text-100)) !important;
}
-/* Custom TODO list checkboxes – shoutout to this awesome tutorial: https://moderncss.dev/pure-css-custom-checkbox-style/ */
-
+/* to-do list */
ul[data-type="taskList"] li {
font-size: 1rem;
line-height: 1.5;
@@ -143,6 +140,7 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
text-decoration: line-through;
text-decoration-thickness: 2px;
}
+/* end to-do list */
/* Overwrite tippy-box original max-width */
@@ -238,7 +236,7 @@ div[data-type="horizontalRule"] {
margin-bottom: 0;
& > div {
- border-bottom: 1px solid rgb(var(--color-text-100));
+ border-bottom: 1px solid rgb(var(--color-border-200));
}
}
@@ -277,7 +275,7 @@ span:focus .fake-cursor {
z-index: 1;
}
-/* number, bulleted and to-do lists */
+/* numbered, bulleted and to-do lists spacing */
.prose ol:where(.prose > :first-child):not(:where([class~="not-prose"], [class~="not-prose"] *)),
.prose
ul:not([data-type="taskList"]):where(.prose > :first-child):not(:where([class~="not-prose"], [class~="not-prose"] *)),
@@ -306,7 +304,7 @@ ul:not([data-type="taskList"]) ol {
ul[data-type="taskList"] ul[data-type="taskList"] {
margin-top: 0.6rem;
}
-/* end number, bulleted and to-do lists */
+/* end numbered, bulleted and to-do lists spacing */
/* tailwind typography */
.prose :where(h1):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
diff --git a/packages/editor/core/src/styles/table.css b/packages/editor/core/src/styles/table.css
index 433b77bfe..d5adac9b5 100644
--- a/packages/editor/core/src/styles/table.css
+++ b/packages/editor/core/src/styles/table.css
@@ -31,17 +31,6 @@
}
}
-.table-wrapper table td > *,
-.table-wrapper table th > * {
- margin: 0 !important;
- padding: 0.25rem 0 !important;
-}
-
-.table-wrapper table td.has-focus,
-.table-wrapper table th.has-focus {
- box-shadow: rgba(var(--color-primary-300), 0.1) 0px 0px 0px 2px inset !important;
-}
-
.table-wrapper table th {
font-weight: 500;
text-align: left;
@@ -49,7 +38,7 @@
}
.table-wrapper table .selectedCell {
- border-color: rgba(var(--color-primary-100));
+ outline: 0.5px solid rgba(var(--color-primary-100));
}
/* table dropdown */
diff --git a/packages/editor/core/src/ui/extensions/index.tsx b/packages/editor/core/src/ui/extensions/index.tsx
index 1a68ee46e..bf7f36067 100644
--- a/packages/editor/core/src/ui/extensions/index.tsx
+++ b/packages/editor/core/src/ui/extensions/index.tsx
@@ -69,7 +69,7 @@ export const CoreEditorExtensions = (
CustomQuoteExtension,
CustomHorizontalRule.configure({
HTMLAttributes: {
- class: "my-4",
+ class: "my-4 border-custom-border-400",
},
}),
CustomKeymap,
diff --git a/packages/editor/core/src/ui/mentions/mention-list.tsx b/packages/editor/core/src/ui/mentions/mention-list.tsx
index cd0bf8354..b9ac11d13 100644
--- a/packages/editor/core/src/ui/mentions/mention-list.tsx
+++ b/packages/editor/core/src/ui/mentions/mention-list.tsx
@@ -135,7 +135,7 @@ export const MentionList = forwardRef((props: MentionListProps, ref) => {
return (
{isLoading ? (
Loading...
diff --git a/packages/editor/extensions/src/extensions/slash-commands.tsx b/packages/editor/extensions/src/extensions/slash-commands.tsx
index 049accb27..752fbe63c 100644
--- a/packages/editor/extensions/src/extensions/slash-commands.tsx
+++ b/packages/editor/extensions/src/extensions/slash-commands.tsx
@@ -247,14 +247,15 @@ export const updateScrollView = (container: HTMLElement, item: HTMLElement) => {
};
const CommandList = ({ items, command }: { items: CommandItemProps[]; command: any; editor: any; range: any }) => {
+ // states
const [selectedIndex, setSelectedIndex] = useState(0);
+ // refs
+ const commandListContainer = useRef
(null);
const selectItem = useCallback(
(index: number) => {
const item = items[index];
- if (item) {
- command(item);
- }
+ if (item) command(item);
},
[command, items]
);
@@ -289,8 +290,6 @@ const CommandList = ({ items, command }: { items: CommandItemProps[]; command: a
setSelectedIndex(0);
}, [items]);
- const commandListContainer = useRef(null);
-
useLayoutEffect(() => {
const container = commandListContainer?.current;
@@ -299,29 +298,31 @@ const CommandList = ({ items, command }: { items: CommandItemProps[]; command: a
if (item && container) updateScrollView(container, item);
}, [selectedIndex]);
- return items.length > 0 ? (
+ if (items.length <= 0) return null;
+
+ return (
{items.map((item, index) => (
))}
- ) : null;
+ );
};
interface CommandListInstance {
@@ -338,10 +339,12 @@ const renderItems = () => {
editor: props.editor,
});
+ const tippyContainer = document.querySelector(".active-editor") ?? document.querySelector("#editor-container");
+
// @ts-expect-error Tippy overloads are messed up
popup = tippy("body", {
getReferenceClientRect: props.clientRect,
- appendTo: () => document.querySelector(".active-editor") ?? document.querySelector("#editor-container"),
+ appendTo: tippyContainer,
content: component.element,
showOnCreate: true,
interactive: true,
diff --git a/web/components/pages/editor/header/extra-options.tsx b/web/components/pages/editor/header/extra-options.tsx
index 1b00cce34..3615cfa1b 100644
--- a/web/components/pages/editor/header/extra-options.tsx
+++ b/web/components/pages/editor/header/extra-options.tsx
@@ -19,13 +19,14 @@ import { IPageStore } from "@/store/pages/page.store";
type Props = {
editorRef: React.RefObject;
handleDuplicatePage: () => void;
+ isSyncing: boolean;
pageStore: IPageStore;
projectId: string;
readOnlyEditorRef: React.RefObject;
};
export const PageExtraOptions: React.FC = observer((props) => {
- const { editorRef, handleDuplicatePage, pageStore, projectId, readOnlyEditorRef } = props;
+ const { editorRef, handleDuplicatePage, isSyncing, pageStore, projectId, readOnlyEditorRef } = props;
// states
const [gptModalOpen, setGptModal] = useState(false);
// store hooks
@@ -52,6 +53,12 @@ export const PageExtraOptions: React.FC = observer((props) => {
{isSubmitting === "submitting" ? "Saving..." : "Saved"}
)}
+ {isSyncing && (
+
+
+ Syncing...
+
+ )}
{is_locked && (
diff --git a/web/components/pages/editor/header/root.tsx b/web/components/pages/editor/header/root.tsx
index b3bae94ba..f48921191 100644
--- a/web/components/pages/editor/header/root.tsx
+++ b/web/components/pages/editor/header/root.tsx
@@ -11,6 +11,7 @@ type Props = {
editorRef: React.RefObject
;
readOnlyEditorRef: React.RefObject;
handleDuplicatePage: () => void;
+ isSyncing: boolean;
markings: IMarking[];
pageStore: IPageStore;
projectId: string;
@@ -28,6 +29,7 @@ export const PageEditorHeaderRoot: React.FC = observer((props) => {
markings,
readOnlyEditorReady,
handleDuplicatePage,
+ isSyncing,
pageStore,
projectId,
sidePeekVisible,
@@ -61,6 +63,7 @@ export const PageEditorHeaderRoot: React.FC = observer((props) => {
{
});
// fetching page details
- const { data: swrPageDetails } = useSWR(
+ const { data: swrPageDetails, isValidating } = useSWR(
pageId ? `PAGE_DETAILS_${pageId}` : null,
pageId ? () => getPageById(pageId.toString()) : null,
{
@@ -120,6 +120,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
editorReady={editorReady}
readOnlyEditorReady={readOnlyEditorReady}
handleDuplicatePage={handleDuplicatePage}
+ isSyncing={isValidating}
markings={markings}
pageStore={pageStore}
projectId={projectId.toString()}