Skip to content

Commit

Permalink
feat(core): add draghandle to doc page title (#9079)
Browse files Browse the repository at this point in the history
  • Loading branch information
pengx17 committed Dec 10, 2024
1 parent 115caa7 commit 4335b0d
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 75 deletions.
1 change: 1 addition & 0 deletions packages/frontend/component/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export * from './ui/checkbox';
export * from './ui/date-picker';
export * from './ui/divider';
export * from './ui/dnd';
export * from './ui/drag-handle';
export * from './ui/editable';
export * from './ui/empty';
export * from './ui/error-message';
Expand Down
19 changes: 19 additions & 0 deletions packages/frontend/component/src/ui/drag-handle/index.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { cssVarV2 } from '@toeverything/theme/v2';
import { style } from '@vanilla-extract/css';

export const root = style({
cursor: 'grab',
color: cssVarV2.icon.secondary,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
});

export const svg = style({
borderRadius: 8,
selectors: {
[`${root}[data-dragging="true"] &, ${root}:hover &`]: {
backgroundColor: cssVarV2.layer.background.hoverOverlay,
},
},
});
39 changes: 39 additions & 0 deletions packages/frontend/component/src/ui/drag-handle/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { clsx } from 'clsx';
import { forwardRef } from 'react';

import * as styles from './index.css';

export const DragHandle = forwardRef<
HTMLDivElement,
{
className?: string;
dragging?: boolean;
}
>(({ className, dragging, ...props }, ref) => {
return (
<div
{...props}
ref={ref}
data-dragging={dragging}
className={clsx(styles.root, className)}
>
<svg
width="10"
height="22"
viewBox="0 0 10 22"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={styles.svg}
>
<circle cx="3" cy="7" r="1" fill="currentColor" />
<circle cx="7" cy="7" r="1" fill="currentColor" />
<circle cx="3" cy="11" r="1" fill="currentColor" />
<circle cx="7" cy="11" r="1" fill="currentColor" />
<circle cx="3" cy="15" r="1" fill="currentColor" />
<circle cx="7" cy="15" r="1" fill="currentColor" />
</svg>
</div>
);
});

DragHandle.displayName = 'DragHandle';
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { Loading, Scrollable } from '@affine/component';
import { EditorLoading } from '@affine/component/page-detail-skeleton';
import { Button, IconButton } from '@affine/component/ui/button';
import { Modal, useConfirmModal } from '@affine/component/ui/modal';
import { useDocCollectionPageTitle } from '@affine/core/components/hooks/use-block-suite-workspace-page-title';
import { GlobalDialogService } from '@affine/core/modules/dialogs';
import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta';
import { EditorService } from '@affine/core/modules/editor';
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
Expand Down Expand Up @@ -433,7 +433,10 @@ const PageHistoryManager = ({
const editor = useService(EditorService).editor;
const [mode, setMode] = useState<DocMode>(editor.mode$.value);

const title = useDocCollectionPageTitle(docCollection, pageId);
const docDisplayMetaService = useService(DocDisplayMetaService);
const i18n = useI18n();

const title = useLiveData(docDisplayMetaService.title$(pageId));

const onConfirmRestore = useCallback(() => {
openConfirmModal({
Expand Down Expand Up @@ -467,7 +470,7 @@ const PageHistoryManager = ({
snapshotPage={snapshotPage}
mode={mode}
onModeChange={setMode}
title={title}
title={i18n.t(title)}
/>

<PageHistoryList
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { style, type StyleRule } from '@vanilla-extract/css';

export const docEditorRoot = style({
display: 'block',
background: cssVar('backgroundPrimaryColor'),
overflowX: 'clip',
});

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { style } from '@vanilla-extract/css';

export const root = style({
position: 'relative',
height: '100%',
width: '100%',
});

export const header = style({
display: 'flex',
height: '100%',
Expand All @@ -24,3 +30,18 @@ export const iconButtonContainer = style({
alignItems: 'center',
gap: 10,
});

export const dragHandle = style({
cursor: 'grab',
position: 'absolute',
top: 0,
bottom: 0,
left: -16,
width: 16,
opacity: 0,
selectors: {
[`${root}:hover &, ${root}[data-dragging="true"] &`]: {
opacity: 1,
},
},
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {
Divider,
DragHandle,
type InlineEditHandle,
observeResize,
useDraggable,
} from '@affine/component';
import { SharePageButton } from '@affine/core/components/affine/share-page-modal';
import { FavoriteButton } from '@affine/core/components/blocksuite/block-suite-header/favorite';
Expand All @@ -13,11 +15,13 @@ import { DetailPageHeaderPresentButton } from '@affine/core/components/blocksuit
import { BlocksuiteHeaderTitle } from '@affine/core/components/blocksuite/block-suite-header/title';
import { EditorModeSwitch } from '@affine/core/components/blocksuite/block-suite-mode-switch';
import { useRegisterCopyLinkCommands } from '@affine/core/components/hooks/affine/use-register-copy-link-commands';
import { useDocCollectionPageTitle } from '@affine/core/components/hooks/use-block-suite-workspace-page-title';
import { HeaderDivider } from '@affine/core/components/pure/header';
import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta';
import { EditorService } from '@affine/core/modules/editor';
import { JournalService } from '@affine/core/modules/journal';
import { ViewIcon, ViewTitle } from '@affine/core/modules/workbench';
import type { AffineDNDData } from '@affine/core/types/dnd';
import { useI18n } from '@affine/i18n';
import type { Doc } from '@blocksuite/affine/store';
import { useLiveData, useService, type Workspace } from '@toeverything/infra';
import { forwardRef, useCallback, useEffect, useRef, useState } from 'react';
Expand Down Expand Up @@ -60,7 +64,11 @@ export function JournalPageHeader({ page, workspace }: PageHeaderProps) {

const { hideShare, hideToday } =
useDetailPageHeaderResponsive(containerWidth);
const title = useDocCollectionPageTitle(workspace.docCollection, page?.id);

const docDisplayMetaService = useService(DocDisplayMetaService);
const i18n = useI18n();
const title = i18n.t(useLiveData(docDisplayMetaService.title$(page.id)));

return (
<Header className={styles.header} ref={containerRef}>
<ViewTitle title={title} />
Expand Down Expand Up @@ -106,7 +114,10 @@ export function NormalPageHeader({ page, workspace }: PageHeaderProps) {
);
}, []);

const title = useDocCollectionPageTitle(workspace.docCollection, page?.id);
const docDisplayMetaService = useService(DocDisplayMetaService);
const i18n = useI18n();
const title = i18n.t(useLiveData(docDisplayMetaService.title$(page.id)));

const editor = useService(EditorService).editor;
const currentMode = useLiveData(editor.mode$);

Expand Down Expand Up @@ -148,8 +159,12 @@ export function NormalPageHeader({ page, workspace }: PageHeaderProps) {
);
}

export function DetailPageHeader(props: PageHeaderProps) {
const { page, workspace } = props;
export function DetailPageHeader(
props: PageHeaderProps & {
onDragging?: (dragging: boolean) => void;
}
) {
const { page, workspace, onDragging } = props;
const journalService = useService(JournalService);
const isJournal = !!useLiveData(journalService.journalDate$(page.id));
const isInTrash = page.meta?.trash;
Expand All @@ -159,9 +174,42 @@ export function DetailPageHeader(props: PageHeaderProps) {
docId: page.id,
});

return isJournal && !isInTrash ? (
<JournalPageHeader {...props} />
) : (
<NormalPageHeader {...props} />
const { dragRef, dragHandleRef, dragging } =
useDraggable<AffineDNDData>(() => {
return {
data: {
from: {
at: 'doc-detail:header',
docId: page.id,
},
entity: {
type: 'doc',
id: page.id,
},
},
disableDragPreview: true,
};
}, [page.id]);

const inner =
isJournal && !isInTrash ? (
<JournalPageHeader {...props} />
) : (
<NormalPageHeader {...props} />
);

useEffect(() => {
onDragging?.(dragging);
}, [dragging, onDragging]);

return (
<div className={styles.root} ref={dragRef} data-dragging={dragging}>
<DragHandle
ref={dragHandleRef}
dragging={dragging}
className={styles.dragHandle}
/>
{inner}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { cssVar } from '@toeverything/theme';
import { cssVarV2 } from '@toeverything/theme/v2';
import { style } from '@vanilla-extract/css';

export const mainContainer = style({
Expand Down Expand Up @@ -39,6 +40,11 @@ export const affineDocViewport = style({
zIndex: -1,
},
},
selectors: {
'&[data-dragging="true"]': {
backgroundColor: cssVarV2.layer.background.hoverOverlay,
},
},
});

export const scrollbar = style({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,10 +249,16 @@ const DetailPageImpl = memo(function DetailPageImpl() {
setHasScrollTop(hasScrollTop);
}, []);

const [dragging, setDragging] = useState(false);

return (
<FrameworkScope scope={editor.scope}>
<ViewHeader>
<DetailPageHeader page={doc.blockSuiteDoc} workspace={workspace} />
<DetailPageHeader
page={doc.blockSuiteDoc}
workspace={workspace}
onDragging={setDragging}
/>
</ViewHeader>
<ViewBody>
<div
Expand All @@ -267,6 +273,7 @@ const DetailPageImpl = memo(function DetailPageImpl() {
<Scrollable.Viewport
onScroll={handleScroll}
ref={scrollViewportRef}
data-dragging={dragging}
className={clsx(
'affine-page-viewport',
styles.affineDocViewport,
Expand Down
4 changes: 4 additions & 0 deletions packages/frontend/core/src/types/dnd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ export interface AffineDNDData extends DNDData {
at: 'doc-property:manager';
workspaceId: string;
}
| {
at: 'doc-detail:header';
docId: string;
}
| {
at: 'external'; // for blocksuite or external apps
};
Expand Down

0 comments on commit 4335b0d

Please sign in to comment.