♻️(frontend) better handling css doc states
We simplify the way we handle different doc states (deleted / readonly) in the CSS, we avoid props drilling and are more component focused.
This commit is contained in:
@@ -119,6 +119,10 @@ test.describe('Doc Trashbin', () => {
|
|||||||
await row.getByText(subDocName).click();
|
await row.getByText(subDocName).click();
|
||||||
await verifyDocName(page, subDocName);
|
await verifyDocName(page, subDocName);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator('.--docs--editor-container.--docs--doc-deleted'),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
await expect(page.getByLabel('Alert deleted document')).toBeVisible();
|
await expect(page.getByLabel('Alert deleted document')).toBeVisible();
|
||||||
await expect(page.getByRole('button', { name: 'Share' })).toBeDisabled();
|
await expect(page.getByRole('button', { name: 'Share' })).toBeDisabled();
|
||||||
await expect(page.locator('.bn-editor')).toHaveAttribute(
|
await expect(page.locator('.bn-editor')).toHaveAttribute(
|
||||||
|
|||||||
@@ -260,6 +260,10 @@ test.describe('Doc Visibility: Public', () => {
|
|||||||
await expect(card).toBeVisible();
|
await expect(card).toBeVisible();
|
||||||
await expect(card.getByText('Reader')).toBeVisible();
|
await expect(card.getByText('Reader')).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
otherPage.locator('.--docs--editor-container.--docs--doc-readonly'),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
const otherEditor = await getEditor({ page: otherPage });
|
const otherEditor = await getEditor({ page: otherPage });
|
||||||
await expect(otherEditor).toHaveAttribute('contenteditable', 'false');
|
await expect(otherEditor).toHaveAttribute('contenteditable', 'false');
|
||||||
await expect(otherEditor.getByText('Hello Public Viewonly')).toBeVisible();
|
await expect(otherEditor.getByText('Hello Public Viewonly')).toBeVisible();
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import {
|
|||||||
useUploadStatus,
|
useUploadStatus,
|
||||||
} from '../hook';
|
} from '../hook';
|
||||||
import { useEditorStore } from '../stores';
|
import { useEditorStore } from '../stores';
|
||||||
|
import { cssEditor } from '../styles';
|
||||||
import { DocsBlockNoteEditor } from '../types';
|
import { DocsBlockNoteEditor } from '../types';
|
||||||
import { randomColor } from '../utils';
|
import { randomColor } from '../utils';
|
||||||
|
|
||||||
@@ -169,7 +170,7 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
|
|||||||
}, [setEditor, editor]);
|
}, [setEditor, editor]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box ref={refEditorContainer}>
|
<Box ref={refEditorContainer} $css={cssEditor}>
|
||||||
{errorAttachment && (
|
{errorAttachment && (
|
||||||
<Box $margin={{ bottom: 'big', top: 'none', horizontal: 'large' }}>
|
<Box $margin={{ bottom: 'big', top: 'none', horizontal: 'large' }}>
|
||||||
<TextErrors
|
<TextErrors
|
||||||
@@ -225,12 +226,14 @@ export const BlockNoteReader = ({ initialContent }: BlockNoteReaderProps) => {
|
|||||||
useHeadings(editor);
|
useHeadings(editor);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BlockNoteView
|
<Box $css={cssEditor}>
|
||||||
editor={editor}
|
<BlockNoteView
|
||||||
editable={false}
|
editor={editor}
|
||||||
theme="light"
|
editable={false}
|
||||||
formattingToolbar={false}
|
theme="light"
|
||||||
slashMenu={false}
|
formattingToolbar={false}
|
||||||
/>
|
slashMenu={false}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import clsx from 'clsx';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { css } from 'styled-components';
|
import { css } from 'styled-components';
|
||||||
|
|
||||||
@@ -12,8 +13,6 @@ import { TableContent } from '@/docs/doc-table-content/';
|
|||||||
import { useSkeletonStore } from '@/features/skeletons';
|
import { useSkeletonStore } from '@/features/skeletons';
|
||||||
import { useResponsiveStore } from '@/stores';
|
import { useResponsiveStore } from '@/stores';
|
||||||
|
|
||||||
import { cssEditor } from '../styles';
|
|
||||||
|
|
||||||
import { BlockNoteEditor, BlockNoteReader } from './BlockNoteEditor';
|
import { BlockNoteEditor, BlockNoteReader } from './BlockNoteEditor';
|
||||||
|
|
||||||
interface DocEditorContainerProps {
|
interface DocEditorContainerProps {
|
||||||
@@ -55,10 +54,13 @@ export const DocEditorContainer = ({
|
|||||||
>
|
>
|
||||||
<Box $css="flex:1;" $position="relative" $width="100%">
|
<Box $css="flex:1;" $position="relative" $width="100%">
|
||||||
<Box
|
<Box
|
||||||
$padding={{ top: 'md' }}
|
$padding={{ top: 'md', bottom: '2rem' }}
|
||||||
$background="white"
|
$background="white"
|
||||||
$css={cssEditor(readOnly, isDeletedDoc)}
|
className={clsx('--docs--editor-container', {
|
||||||
className="--docs--editor-container"
|
'--docs--doc-readonly': readOnly,
|
||||||
|
'--docs--doc-deleted': isDeletedDoc,
|
||||||
|
})}
|
||||||
|
$height="100%"
|
||||||
>
|
>
|
||||||
{docEditor}
|
{docEditor}
|
||||||
</Box>
|
</Box>
|
||||||
@@ -77,7 +79,9 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
|
|||||||
const { isDesktop } = useResponsiveStore();
|
const { isDesktop } = useResponsiveStore();
|
||||||
const { provider, isReady } = useProviderStore();
|
const { provider, isReady } = useProviderStore();
|
||||||
const { isEditable, isLoading } = useIsCollaborativeEditable(doc);
|
const { isEditable, isLoading } = useIsCollaborativeEditable(doc);
|
||||||
const readOnly = !doc.abilities.partial_update || !isEditable || isLoading;
|
const isDeletedDoc = !!doc.deleted_at;
|
||||||
|
const readOnly =
|
||||||
|
!doc.abilities.partial_update || !isEditable || isLoading || isDeletedDoc;
|
||||||
const { setIsSkeletonVisible } = useSkeletonStore();
|
const { setIsSkeletonVisible } = useSkeletonStore();
|
||||||
const isProviderReady = isReady && provider;
|
const isProviderReady = isReady && provider;
|
||||||
|
|
||||||
@@ -117,7 +121,7 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
|
|||||||
<BlockNoteEditor doc={doc} provider={provider} />
|
<BlockNoteEditor doc={doc} provider={provider} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
isDeletedDoc={!!doc.deleted_at}
|
isDeletedDoc={isDeletedDoc}
|
||||||
readOnly={readOnly}
|
readOnly={readOnly}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -89,6 +89,10 @@ const LinkSelected = ({ url, title }: LinkSelectedProps) => {
|
|||||||
background-color: ${colorsTokens['greyscale-100']};
|
background-color: ${colorsTokens['greyscale-100']};
|
||||||
}
|
}
|
||||||
transition: background-color 0.2s ease-in-out;
|
transition: background-color 0.2s ease-in-out;
|
||||||
|
|
||||||
|
.--docs--doc-deleted & {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
{emoji ? (
|
{emoji ? (
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import { css } from 'styled-components';
|
import { css } from 'styled-components';
|
||||||
|
|
||||||
export const cssEditor = (readonly: boolean, isDeletedDoc: boolean) => css`
|
export const cssEditor = css`
|
||||||
&,
|
&,
|
||||||
& > .bn-container,
|
& > .bn-container,
|
||||||
& .ProseMirror {
|
& .ProseMirror {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding-bottom: 2rem;
|
}
|
||||||
|
|
||||||
|
& .ProseMirror {
|
||||||
/**
|
/**
|
||||||
* WCAG Accessibility contrast fixes for BlockNote editor
|
* WCAG Accessibility contrast fixes for BlockNote editor
|
||||||
*/
|
*/
|
||||||
@@ -131,13 +132,6 @@ export const cssEditor = (readonly: boolean, isDeletedDoc: boolean) => css`
|
|||||||
.bn-block-outer:not([data-prev-depth-changed]):before {
|
.bn-block-outer:not([data-prev-depth-changed]):before {
|
||||||
border-left: none;
|
border-left: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
${isDeletedDoc &&
|
|
||||||
`
|
|
||||||
.node-interlinkingLinkInline button {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
& .bn-editor {
|
& .bn-editor {
|
||||||
@@ -187,8 +181,10 @@ export const cssEditor = (readonly: boolean, isDeletedDoc: boolean) => css`
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (width <= 560px) {
|
@media screen and (width <= 560px) {
|
||||||
|
.--docs--doc-readonly & .bn-editor {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
& .bn-editor {
|
& .bn-editor {
|
||||||
${readonly && `padding-left: 10px;`}
|
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
.bn-side-menu[data-block-type='heading'][data-level='1'] {
|
.bn-side-menu[data-block-type='heading'][data-level='1'] {
|
||||||
|
|||||||
Reference in New Issue
Block a user