diff --git a/packages/frontend/core/src/components/page-list/collections/collection-list-item.css.ts b/packages/frontend/core/src/components/page-list/collections/collection-list-item.css.ts
index 253497a715..edb3eabb27 100644
--- a/packages/frontend/core/src/components/page-list/collections/collection-list-item.css.ts
+++ b/packages/frontend/core/src/components/page-list/collections/collection-list-item.css.ts
@@ -106,6 +106,7 @@ export const titleCell = style({
maxWidth: 'calc(100% - 64px)',
flex: 1,
whiteSpace: 'nowrap',
+ userSelect: 'none',
});
export const titleCellMain = style({
overflow: 'hidden',
diff --git a/packages/frontend/core/src/components/page-list/collections/collection-list-item.tsx b/packages/frontend/core/src/components/page-list/collections/collection-list-item.tsx
index 3cadf80521..8a1d8ead8b 100644
--- a/packages/frontend/core/src/components/page-list/collections/collection-list-item.tsx
+++ b/packages/frontend/core/src/components/page-list/collections/collection-list-item.tsx
@@ -5,6 +5,7 @@ import type { PropsWithChildren } from 'react';
import { useCallback, useMemo } from 'react';
import { Link } from 'react-router-dom';
+import { selectionStateAtom, useAtom } from '../scoped-atoms';
import type {
CollectionListItemProps,
DraggableTitleCellData,
@@ -172,14 +173,28 @@ function CollectionListItemWrapper({
children,
draggable,
}: collectionListWrapperProps) {
+ const [selectionState, setSelectionActive] = useAtom(selectionStateAtom);
const handleClick = useCallback(
(e: React.MouseEvent) => {
- if (onClick) {
+ if (!selectionState.selectable) {
+ return;
+ }
+ if (e.shiftKey) {
stopPropagation(e);
- onClick();
+ setSelectionActive(true);
+ onClick?.();
+ return;
+ }
+ if (selectionState.selectionActive) {
+ return onClick?.();
}
},
- [onClick]
+ [
+ onClick,
+ selectionState.selectable,
+ selectionState.selectionActive,
+ setSelectionActive,
+ ]
);
const commonProps = useMemo(
diff --git a/packages/frontend/core/src/components/page-list/docs/page-list-item.css.ts b/packages/frontend/core/src/components/page-list/docs/page-list-item.css.ts
index 253497a715..edb3eabb27 100644
--- a/packages/frontend/core/src/components/page-list/docs/page-list-item.css.ts
+++ b/packages/frontend/core/src/components/page-list/docs/page-list-item.css.ts
@@ -106,6 +106,7 @@ export const titleCell = style({
maxWidth: 'calc(100% - 64px)',
flex: 1,
whiteSpace: 'nowrap',
+ userSelect: 'none',
});
export const titleCellMain = style({
overflow: 'hidden',
diff --git a/packages/frontend/core/src/components/page-list/docs/page-list-item.tsx b/packages/frontend/core/src/components/page-list/docs/page-list-item.tsx
index 70d0cbab30..8bb8071050 100644
--- a/packages/frontend/core/src/components/page-list/docs/page-list-item.tsx
+++ b/packages/frontend/core/src/components/page-list/docs/page-list-item.tsx
@@ -6,6 +6,7 @@ import type { PropsWithChildren } from 'react';
import { useCallback, useMemo } from 'react';
import { WorkbenchLink } from '../../../modules/workbench/view/workbench-link';
+import { selectionStateAtom, useAtom } from '../scoped-atoms';
import type { DraggableTitleCellData, PageListItemProps } from '../types';
import { usePageDisplayProperties } from '../use-page-display-properties';
import { ColWrapper, formatDate, stopPropagation } from '../utils';
@@ -237,14 +238,22 @@ function PageListItemWrapper({
children,
draggable,
}: PageListWrapperProps) {
+ const [selectionState, setSelectionActive] = useAtom(selectionStateAtom);
const handleClick = useCallback(
(e: React.MouseEvent) => {
- if (onClick) {
- stopPropagation(e);
- onClick();
+ if (!selectionState.selectable) {
+ return false;
}
+ stopPropagation(e);
+ if (e.shiftKey) {
+ setSelectionActive(true);
+ onClick?.();
+ return true;
+ }
+ onClick?.();
+ return false;
},
- [onClick]
+ [onClick, selectionState.selectable, setSelectionActive]
);
const commonProps = useMemo(
@@ -255,7 +264,7 @@ function PageListItemWrapper({
className: styles.root,
'data-clickable': !!onClick || !!to,
'data-dragging': isDragging,
- onClick: handleClick,
+ onClick: onClick ? handleClick : undefined,
}),
[pageId, draggable, onClick, to, isDragging, handleClick]
);
diff --git a/packages/frontend/core/src/components/page-list/group-definitions.css.ts b/packages/frontend/core/src/components/page-list/group-definitions.css.ts
index 254c267abb..20fc12f5cc 100644
--- a/packages/frontend/core/src/components/page-list/group-definitions.css.ts
+++ b/packages/frontend/core/src/components/page-list/group-definitions.css.ts
@@ -25,6 +25,7 @@ export const pageCount = style({
fontSize: cssVar('fontBase'),
lineHeight: '1.6em',
color: cssVar('textSecondaryColor'),
+ marginRight: '12px',
});
export const favouritedIcon = style({
diff --git a/packages/frontend/core/src/components/page-list/list.tsx b/packages/frontend/core/src/components/page-list/list.tsx
index 52cbae8d6e..76dbc16a49 100644
--- a/packages/frontend/core/src/components/page-list/list.tsx
+++ b/packages/frontend/core/src/components/page-list/list.tsx
@@ -67,6 +67,7 @@ const useItemSelectionStateEffect = () => {
return;
}
setSelectionActive(false);
+ selectionState.onSelectedIdsChange?.([]);
};
const escHandler = (e: KeyboardEvent) => {
@@ -75,6 +76,7 @@ const useItemSelectionStateEffect = () => {
}
if (e.key === 'Escape') {
setSelectionActive(false);
+ selectionState.onSelectedIdsChange?.([]);
}
};
@@ -88,6 +90,7 @@ const useItemSelectionStateEffect = () => {
}
return;
}, [
+ selectionState,
selectionState.selectable,
selectionState.selectionActive,
setSelectionActive,
diff --git a/packages/frontend/core/src/components/page-list/page-group.tsx b/packages/frontend/core/src/components/page-list/page-group.tsx
index 5c845ccbe5..35c56a1c6a 100644
--- a/packages/frontend/core/src/components/page-list/page-group.tsx
+++ b/packages/frontend/core/src/components/page-list/page-group.tsx
@@ -329,7 +329,7 @@ function pageMetaToListItemProp(
createDate: new Date(item.createDate),
updatedDate: item.updatedDate ? new Date(item.updatedDate) : undefined,
to: props.rowAsLink && !props.selectable ? `/${item.id}` : undefined,
- onClick: props.selectable ? toggleSelection : undefined,
+ onClick: toggleSelection,
icon: (
,
operations: props.operationsRenderer?.(item),
selectable: props.selectable,
@@ -412,7 +412,7 @@ function tagMetaToListItemProp(
tagId: item.id,
title: item.title,
to: props.rowAsLink && !props.selectable ? `/tag/${item.id}` : undefined,
- onClick: props.selectable ? toggleSelection : undefined,
+ onClick: toggleSelection,
color: item.color,
pageCount: item.pageCount,
operations: props.operationsRenderer?.(item),
diff --git a/packages/frontend/core/src/components/page-list/tags/tag-list-item.css.ts b/packages/frontend/core/src/components/page-list/tags/tag-list-item.css.ts
index 2763a12974..e3a09d33d8 100644
--- a/packages/frontend/core/src/components/page-list/tags/tag-list-item.css.ts
+++ b/packages/frontend/core/src/components/page-list/tags/tag-list-item.css.ts
@@ -105,6 +105,7 @@ export const titleCell = style({
maxWidth: 'calc(100% - 64px)',
flex: 1,
whiteSpace: 'nowrap',
+ userSelect: 'none',
});
export const titleCellMain = style({
overflow: 'hidden',
diff --git a/packages/frontend/core/src/components/page-list/tags/tag-list-item.tsx b/packages/frontend/core/src/components/page-list/tags/tag-list-item.tsx
index 270229616a..a1c2bea7b0 100644
--- a/packages/frontend/core/src/components/page-list/tags/tag-list-item.tsx
+++ b/packages/frontend/core/src/components/page-list/tags/tag-list-item.tsx
@@ -5,6 +5,7 @@ import type { PropsWithChildren } from 'react';
import { useCallback, useMemo } from 'react';
import { Link } from 'react-router-dom';
+import { selectionStateAtom, useAtom } from '../scoped-atoms';
import type { DraggableTitleCellData, TagListItemProps } from '../types';
import { ColWrapper, stopPropagation } from '../utils';
import * as styles from './tag-list-item.css';
@@ -165,14 +166,28 @@ function TagListItemWrapper({
children,
draggable,
}: TagListWrapperProps) {
+ const [selectionState, setSelectionActive] = useAtom(selectionStateAtom);
const handleClick = useCallback(
(e: React.MouseEvent) => {
- if (onClick) {
+ if (!selectionState.selectable) {
+ return;
+ }
+ if (e.shiftKey) {
stopPropagation(e);
- onClick();
+ setSelectionActive(true);
+ onClick?.();
+ return;
+ }
+ if (selectionState.selectionActive) {
+ return onClick?.();
}
},
- [onClick]
+ [
+ onClick,
+ selectionState.selectable,
+ selectionState.selectionActive,
+ setSelectionActive,
+ ]
);
const commonProps = useMemo(
diff --git a/packages/frontend/core/src/modules/workbench/view/workbench-link.tsx b/packages/frontend/core/src/modules/workbench/view/workbench-link.tsx
index 5ceda1ef3a..4a7f7fccf0 100644
--- a/packages/frontend/core/src/modules/workbench/view/workbench-link.tsx
+++ b/packages/frontend/core/src/modules/workbench/view/workbench-link.tsx
@@ -20,6 +20,9 @@ export const WorkbenchLink = ({
(event: React.MouseEvent) => {
event.preventDefault();
event.stopPropagation();
+ if (onClick?.(event)) {
+ return;
+ }
if (event.ctrlKey || event.metaKey) {
if (appSettings.enableMultiView && environment.isDesktop) {
@@ -34,7 +37,6 @@ export const WorkbenchLink = ({
} else {
workbench.open(to);
}
- onClick?.(event);
},
[appSettings.enableMultiView, basename, onClick, to, workbench]
);