mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 05:14:54 +00:00
feat: support sidebar zoom (#1190)
This commit is contained in:
92
apps/web/src/components/workspace-slider-bar/DragLine.tsx
Normal file
92
apps/web/src/components/workspace-slider-bar/DragLine.tsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import { styled } from '@affine/component';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
const StyledDragLine = styled.div(({ theme }) => {
|
||||
return {
|
||||
width: '5px',
|
||||
height: '100%',
|
||||
position: 'absolute',
|
||||
top: '0',
|
||||
right: '-10px',
|
||||
cursor: 'col-resize',
|
||||
};
|
||||
});
|
||||
|
||||
export type DragLineProps = {
|
||||
onDrag?: (params: { movementX: number; movementY: number }) => void;
|
||||
initialPosition?: { x: number; y: number };
|
||||
leftOffset?: number;
|
||||
rightOffset?: number;
|
||||
};
|
||||
|
||||
export const DragLine = ({
|
||||
onDrag,
|
||||
leftOffset,
|
||||
rightOffset,
|
||||
initialPosition,
|
||||
}: DragLineProps) => {
|
||||
const isDragging = useRef(false);
|
||||
const lineRef = useRef<HTMLDivElement>(null);
|
||||
const recordPosition = useRef({ x: 0, y: 0 });
|
||||
useEffect(() => {
|
||||
const onMouseMove = (e: MouseEvent) => {
|
||||
if (!isDragging.current) return;
|
||||
|
||||
const movementX = e.clientX - recordPosition.current.x;
|
||||
const movementY = e.clientY - recordPosition.current.y;
|
||||
|
||||
if (
|
||||
(rightOffset !== undefined &&
|
||||
initialPosition &&
|
||||
initialPosition.x + rightOffset < recordPosition.current.x) ||
|
||||
(leftOffset !== undefined &&
|
||||
initialPosition &&
|
||||
recordPosition.current.x - initialPosition.x < leftOffset)
|
||||
) {
|
||||
recordPosition.current.x = e.clientX;
|
||||
recordPosition.current.y = e.clientY;
|
||||
document.body.style.cursor = 'not-allowed';
|
||||
|
||||
return;
|
||||
}
|
||||
document.body.style.cursor = 'col-resize';
|
||||
|
||||
onDrag?.({ movementX, movementY });
|
||||
recordPosition.current.x = e.clientX;
|
||||
recordPosition.current.y = e.clientY;
|
||||
};
|
||||
|
||||
const onMouseUp = () => {
|
||||
isDragging.current = false;
|
||||
document.body.style.cursor = '';
|
||||
};
|
||||
document.addEventListener('mousemove', onMouseMove);
|
||||
document.addEventListener('mouseup', onMouseUp);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
document.removeEventListener('mouseup', onMouseUp);
|
||||
};
|
||||
}, [initialPosition, leftOffset, onDrag, rightOffset]);
|
||||
return (
|
||||
<StyledDragLine
|
||||
ref={lineRef}
|
||||
//The mouse event is used instead of the drag event because the drag event triggers the drag image display
|
||||
onMouseDown={e => {
|
||||
e.preventDefault();
|
||||
isDragging.current = true;
|
||||
const position = lineRef.current?.getBoundingClientRect();
|
||||
recordPosition.current = {
|
||||
x: position?.x || 0,
|
||||
y: position?.y || 0,
|
||||
};
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
isDragging.current = false;
|
||||
|
||||
console.log('onMouseUp');
|
||||
}}
|
||||
></StyledDragLine>
|
||||
);
|
||||
};
|
||||
|
||||
export default DragLine;
|
||||
@@ -20,6 +20,7 @@ import { usePageHelper } from '@/hooks/use-page-helper';
|
||||
import { useGlobalState } from '@/store/app';
|
||||
import { useModal } from '@/store/globalModal';
|
||||
|
||||
import StyledDragLine from './DragLine';
|
||||
import { Arrow } from './icons';
|
||||
import {
|
||||
StyledArrowButton,
|
||||
@@ -32,6 +33,8 @@ import {
|
||||
} from './style';
|
||||
import { WorkspaceSelector } from './WorkspaceSelector/WorkspaceSelector';
|
||||
|
||||
const MAX_WIDTH = 534;
|
||||
const MIN_WIDTH = 256;
|
||||
const FavoriteList = ({ showList }: { showList: boolean }) => {
|
||||
const { openPage } = usePageHelper();
|
||||
const pageList = useGlobalState(store => store.dataCenterPageList);
|
||||
@@ -67,6 +70,7 @@ const FavoriteList = ({ showList }: { showList: boolean }) => {
|
||||
export const WorkSpaceSliderBar = () => {
|
||||
const { triggerQuickSearchModal } = useModal();
|
||||
const [showSubFavorite, setShowSubFavorite] = useState(true);
|
||||
const [sideBarWidth, setSideBarWidth] = useState(256);
|
||||
const currentWorkspace = useGlobalState(
|
||||
useCallback(store => store.currentDataCenterWorkspace, [])
|
||||
);
|
||||
@@ -88,7 +92,17 @@ export const WorkSpaceSliderBar = () => {
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<StyledSliderBar show={show}>
|
||||
<StyledSliderBar show={show} width={sideBarWidth}>
|
||||
{show && (
|
||||
<StyledDragLine
|
||||
initialPosition={{ x: MIN_WIDTH, y: 0 }}
|
||||
rightOffset={MAX_WIDTH - MIN_WIDTH}
|
||||
leftOffset={0}
|
||||
onDrag={({ movementX }) => {
|
||||
setSideBarWidth(sideBarWidth + movementX);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<Tooltip
|
||||
content={show ? t('Collapse sidebar') : t('Expand sidebar')}
|
||||
placement="right"
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
import { displayFlex, styled, textEllipsis } from '@affine/component';
|
||||
import Link from 'next/link';
|
||||
import { CSSProperties } from 'react';
|
||||
|
||||
export const StyledSliderBar = styled.div<{ show: boolean }>(
|
||||
({ theme, show }) => {
|
||||
return {
|
||||
width: show ? '256px' : '0',
|
||||
height: '100vh',
|
||||
minHeight: '450px',
|
||||
background: theme.colors.hubBackground,
|
||||
boxShadow: theme.shadow.modal,
|
||||
transition: 'width .15s, padding .15s',
|
||||
position: 'relative',
|
||||
zIndex: theme.zIndex.modal,
|
||||
padding: show ? '24px 12px' : '24px 0',
|
||||
flexShrink: 0,
|
||||
};
|
||||
}
|
||||
);
|
||||
export const StyledSliderBar = styled.div<{
|
||||
show: boolean;
|
||||
width: CSSProperties['width'];
|
||||
}>(({ theme, show, width }) => {
|
||||
return {
|
||||
width: show ? width : '0',
|
||||
height: '100vh',
|
||||
minHeight: '450px',
|
||||
background: theme.colors.hubBackground,
|
||||
boxShadow: theme.shadow.modal,
|
||||
transition: 'width .15s, padding .15s',
|
||||
position: 'relative',
|
||||
zIndex: theme.zIndex.modal,
|
||||
padding: show ? '24px 12px' : '24px 0',
|
||||
flexShrink: 0,
|
||||
};
|
||||
});
|
||||
export const StyledSliderBarWrapper = styled.div(() => {
|
||||
return {
|
||||
height: '100%',
|
||||
|
||||
Reference in New Issue
Block a user