style: page editor width and layout updates (#6826)

This commit is contained in:
Aaryan Khandelwal
2025-03-26 21:10:44 +05:30
committed by GitHub
parent 993713925a
commit a25cd426a9
23 changed files with 402 additions and 364 deletions

View File

@@ -1,5 +1,7 @@
import { Extensions } from "@tiptap/core";
import React from "react";
// plane imports
import { cn } from "@plane/utils";
// components
import { DocumentContentLoader, PageRenderer } from "@/components/editors";
// constants
@@ -73,7 +75,11 @@ const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => {
if (!editor) return null;
if (!hasServerSynced && !hasServerConnectionFailed) return <DocumentContentLoader />;
const blockWidthClassName = cn("w-full max-w-[720px] mx-auto transition-all duration-200 ease-in-out", {
"max-w-[1152px]": displayConfig.wideLayout,
});
if (!hasServerSynced && !hasServerConnectionFailed) return <DocumentContentLoader className={blockWidthClassName} />;
return (
<PageRenderer
@@ -81,7 +87,7 @@ const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => {
bubbleMenuEnabled={bubbleMenuEnabled}
displayConfig={displayConfig}
editor={editor}
editorContainerClassName={editorContainerClassNames}
editorContainerClassName={cn(editorContainerClassNames, "document-editor")}
id={id}
tabIndex={tabIndex}
/>

View File

@@ -1,42 +1,51 @@
// ui
// plane imports
import { Loader } from "@plane/ui";
import { cn } from "@plane/utils";
export const DocumentContentLoader = () => (
<div className="size-full px-5">
<Loader className="relative space-y-4">
<div className="space-y-2">
<div className="py-2">
<Loader.Item width="100%" height="36px" />
</div>
<Loader.Item width="80%" height="22px" />
<div className="relative flex items-center gap-2">
<Loader.Item width="30px" height="30px" />
<Loader.Item width="30%" height="22px" />
</div>
<div className="py-2">
<Loader.Item width="60%" height="36px" />
</div>
<Loader.Item width="70%" height="22px" />
<Loader.Item width="30%" height="22px" />
<div className="relative flex items-center gap-2">
<Loader.Item width="30px" height="30px" />
<Loader.Item width="30%" height="22px" />
</div>
<div className="py-2">
<Loader.Item width="50%" height="30px" />
</div>
<Loader.Item width="100%" height="22px" />
<div className="py-2">
<Loader.Item width="30%" height="30px" />
</div>
<Loader.Item width="30%" height="22px" />
<div className="relative flex items-center gap-2">
type Props = {
className?: string;
};
export const DocumentContentLoader = (props: Props) => {
const { className } = props;
return (
<div className={cn("size-full", className)}>
<Loader className="relative space-y-4">
<div className="space-y-2">
<div className="py-2">
<Loader.Item width="100%" height="36px" />
</div>
<Loader.Item width="80%" height="22px" />
<div className="relative flex items-center gap-2">
<Loader.Item width="30px" height="30px" />
<Loader.Item width="30%" height="22px" />
</div>
<div className="py-2">
<Loader.Item width="60%" height="36px" />
</div>
<Loader.Item width="70%" height="22px" />
<Loader.Item width="30%" height="22px" />
<div className="relative flex items-center gap-2">
<Loader.Item width="30px" height="30px" />
<Loader.Item width="30%" height="22px" />
</div>
<div className="py-2">
<Loader.Item width="50%" height="30px" />
</div>
<Loader.Item width="100%" height="22px" />
<div className="py-2">
<Loader.Item width="30%" height="30px" />
</div>
<Loader.Item width="30%" height="22px" />
<div className="relative flex items-center gap-2">
<div className="py-2">
<Loader.Item width="30px" height="30px" />
</div>
<Loader.Item width="30%" height="22px" />
</div>
</div>
</div>
</Loader>
</div>
);
</Loader>
</div>
);
};

View File

@@ -132,7 +132,7 @@ export const PageRenderer = (props: IPageRenderer) => {
return (
<>
<div className="frame-renderer flex-grow w-full -mx-5" onMouseOver={handleLinkHover}>
<div className="frame-renderer flex-grow w-full" onMouseOver={handleLinkHover}>
<EditorContainer
displayConfig={displayConfig}
editor={editor}

View File

@@ -1,5 +1,7 @@
import { Extensions } from "@tiptap/core";
import { forwardRef, MutableRefObject } from "react";
// plane imports
import { cn } from "@plane/utils";
// components
import { PageRenderer } from "@/components/editors";
// constants
@@ -79,7 +81,7 @@ const DocumentReadOnlyEditor = (props: IDocumentReadOnlyEditor) => {
bubbleMenuEnabled={false}
displayConfig={displayConfig}
editor={editor}
editorContainerClassName={editorContainerClassName}
editorContainerClassName={cn(editorContainerClassName, "document-editor")}
id={id}
/>
);

View File

@@ -74,6 +74,7 @@ export const EditorContainer: FC<EditorContainerProps> = (props) => {
`editor-container cursor-text relative line-spacing-${displayConfig.lineSpacing ?? DEFAULT_DISPLAY_CONFIG.lineSpacing}`,
{
"active-editor": editor?.isFocused && editor?.isEditable,
"wide-layout": displayConfig.wideLayout,
},
displayConfig.fontSize ?? DEFAULT_DISPLAY_CONFIG.fontSize,
displayConfig.fontStyle ?? DEFAULT_DISPLAY_CONFIG.fontStyle,

View File

@@ -5,6 +5,7 @@ export const DEFAULT_DISPLAY_CONFIG: TDisplayConfig = {
fontSize: "large-font",
fontStyle: "sans-serif",
lineSpacing: "regular",
wideLayout: false,
};
export const ACCEPTED_FILE_MIME_TYPES = ["image/jpeg", "image/jpg", "image/png", "image/webp", "image/gif"];

View File

@@ -49,7 +49,7 @@ export const isValidHttpUrl = (string: string): boolean => {
try {
url = new URL(string);
} catch (_) {
} catch {
return false;
}

View File

@@ -29,4 +29,5 @@ export type TDisplayConfig = {
fontStyle?: TEditorFontStyle;
fontSize?: TEditorFontSize;
lineSpacing?: TEditorLineSpacing;
wideLayout?: boolean;
};

View File

@@ -8,7 +8,7 @@
-moz-user-select: text;
-ms-user-select: text;
user-select: text;
outline: none;
outline: none !important;
cursor: text;
font-family: var(--font-style);
font-size: var(--font-size-regular);

View File

@@ -1,3 +1,47 @@
:root {
/* text colors */
--editor-colors-gray-text: #5c5e63;
--editor-colors-peach-text: #ff5b59;
--editor-colors-pink-text: #f65385;
--editor-colors-orange-text: #fd9038;
--editor-colors-green-text: #0fc27b;
--editor-colors-light-blue-text: #17bee9;
--editor-colors-dark-blue-text: #266df0;
--editor-colors-purple-text: #9162f9;
/* end text colors */
/* layout */
--normal-content-width: 720px;
--wide-content-width: 1152px;
--normal-content-margin: 20px;
--wide-content-margin: 96px;
/* end layout */
}
/* text background colors */
[data-theme*="light"] {
--editor-colors-gray-background: #d6d6d8;
--editor-colors-peach-background: #ffd5d7;
--editor-colors-pink-background: #fdd4e3;
--editor-colors-orange-background: #ffe3cd;
--editor-colors-green-background: #c3f0de;
--editor-colors-light-blue-background: #c5eff9;
--editor-colors-dark-blue-background: #c9dafb;
--editor-colors-purple-background: #e3d8fd;
}
[data-theme*="dark"] {
--editor-colors-gray-background: #404144;
--editor-colors-peach-background: #593032;
--editor-colors-pink-background: #562e3d;
--editor-colors-orange-background: #583e2a;
--editor-colors-green-background: #1d4a3b;
--editor-colors-light-blue-background: #1f495c;
--editor-colors-dark-blue-background: #223558;
--editor-colors-purple-background: #3d325a;
}
/* end text background colors */
/* font size and style */
.editor-container {
--color-placeholder: rgba(var(--color-text-100), 0.5);
@@ -47,6 +91,8 @@
/* end font sizes and line heights */
/* font styles */
--font-style: "Inter", sans-serif;
&.sans-serif {
--font-style: "Inter", sans-serif;
}
@@ -102,3 +148,94 @@
}
/* end spacing */
}
/* end font size and style */
/* layout config */
#page-header-container {
container-name: page-header-container;
container-type: inline-size;
.page-header-content {
--header-width: var(--normal-content-width);
&.wide-layout {
--header-width: var(--wide-content-width);
}
padding-left: calc(((100% - var(--header-width)) / 2) - 10px);
}
}
#page-content-container {
container-name: page-content-container;
container-type: inline-size;
}
.editor-container.document-editor {
--editor-content-width: var(--normal-content-width);
&.wide-layout {
--editor-content-width: var(--wide-content-width);
}
.ProseMirror {
max-width: var(--editor-content-width);
margin: 0 auto;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
}
/* keep a static padding of 96px for wide layouts for container width >912px and <1344px */
@container page-header-container (min-width: 912px) and (max-width: 1344px) {
.page-header-content.wide-layout {
padding-left: var(--wide-content-margin) !important;
}
}
/* keep a static padding of 96px for wide layouts for container width <912px */
@container page-header-container (max-width: 912) {
.page-header-content.wide-layout {
padding-left: var(--wide-content-margin) !important;
}
}
/* end layout config */
/* keep a static padding of 20px for wide layouts for container width <760px */
@container page-header-container (max-width: 760px) {
.page-header-content {
padding-left: var(--normal-content-margin) !important;
}
}
/* end layout config */
/* keep a static padding of 96px for wide layouts for container width >912px and <1344px */
@container page-content-container (min-width: 912px) and (max-width: 1344px) {
.editor-container.wide-layout,
.page-title-container {
padding-left: var(--wide-content-margin);
padding-right: var(--wide-content-margin);
}
}
/* keep a static padding of 20px for wide layouts for container width <912px */
@container page-content-container (max-width: 912px) {
.editor-container.wide-layout,
.page-title-container {
padding-left: var(--normal-content-margin);
padding-right: var(--normal-content-margin);
}
}
/* keep a static padding of 20px for normal layouts for container width <760px */
@container page-content-container (max-width: 760px) {
.editor-container:not(.wide-layout),
.page-title-container {
padding-left: var(--normal-content-margin);
padding-right: var(--normal-content-margin);
}
.page-summary-container {
display: none;
}
}
/* end layout config */