mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
fix: app sidebar ui issues (#3783)
Co-authored-by: Alex Yang <himself65@outlook.com>
This commit is contained in:
@@ -3,13 +3,16 @@ import { style } from '@vanilla-extract/css';
|
||||
export const root = style({
|
||||
fontSize: 'var(--affine-font-xs)',
|
||||
minHeight: '16px',
|
||||
width: 'calc(100% + 6px)',
|
||||
userSelect: 'none',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
marginBottom: '4px',
|
||||
padding: '0 8px',
|
||||
selectors: {
|
||||
'&:not(:first-of-type)': {
|
||||
marginTop: '10px',
|
||||
marginTop: '16px',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -52,7 +52,6 @@ export const navStyle = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
zIndex: parseInt(baseTheme.zIndexModal),
|
||||
borderRight: '1px solid transparent',
|
||||
});
|
||||
|
||||
export const navHeaderStyle = style({
|
||||
@@ -76,6 +75,7 @@ export const navBodyStyle = style({
|
||||
height: 'calc(100% - 52px)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
rowGap: '4px',
|
||||
});
|
||||
|
||||
export const sidebarFloatMaskStyle = style({
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
export const linkItemRoot = style({
|
||||
color: 'inherit',
|
||||
display: 'contents',
|
||||
});
|
||||
|
||||
export const root = style({
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
borderRadius: '4px',
|
||||
textAlign: 'left',
|
||||
color: 'inherit',
|
||||
width: '100%',
|
||||
minHeight: '30px',
|
||||
userSelect: 'none',
|
||||
cursor: 'pointer',
|
||||
padding: '0 12px',
|
||||
fontSize: 'var(--affine-font-sm)',
|
||||
margin: '2px 0',
|
||||
marginTop: '4px',
|
||||
selectors: {
|
||||
'&:hover': {
|
||||
background: 'var(--affine-hover-color)',
|
||||
@@ -29,10 +37,8 @@ export const root = style({
|
||||
// 'linear-gradient(0deg, rgba(0, 0, 0, 0.04), rgba(0, 0, 0, 0.04)), rgba(0, 0, 0, 0.04)',
|
||||
// },
|
||||
'&[data-collapsible="true"]': {
|
||||
width: 'calc(100% + 8px)',
|
||||
transform: 'translateX(-8px)',
|
||||
paddingLeft: '4px',
|
||||
paddingRight: '12px',
|
||||
paddingRight: '4px',
|
||||
},
|
||||
'&[data-type="collection-list-item"][data-collapsible="false"][data-active="true"],&[data-type="favorite-list-item"][data-collapsible="false"][data-active="true"], &[data-type="favorite-list-item"][data-collapsible="false"]:hover, &[data-type="collection-list-item"][data-collapsible="false"]:hover':
|
||||
{
|
||||
@@ -41,6 +47,9 @@ export const root = style({
|
||||
paddingLeft: '20px',
|
||||
paddingRight: '12px',
|
||||
},
|
||||
[`${linkItemRoot}:first-of-type &`]: {
|
||||
marginTop: '0px',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -53,6 +62,12 @@ export const content = style({
|
||||
|
||||
export const postfix = style({
|
||||
justifySelf: 'flex-end',
|
||||
display: 'none',
|
||||
selectors: {
|
||||
[`${root}:hover &`]: {
|
||||
display: 'flex',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const icon = style({
|
||||
@@ -68,10 +83,15 @@ export const collapsedIconContainer = style({
|
||||
justifyContent: 'center',
|
||||
borderRadius: '2px',
|
||||
transition: 'transform 0.2s',
|
||||
color: 'inherit',
|
||||
selectors: {
|
||||
'&[data-collapsed="true"]': {
|
||||
transform: 'rotate(-90deg)',
|
||||
},
|
||||
'&[data-disabled="true"]': {
|
||||
opacity: 0.3,
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
'&:hover': {
|
||||
background: 'var(--affine-hover-color)',
|
||||
},
|
||||
@@ -103,8 +123,3 @@ export const collapsedIcon = style({
|
||||
export const spacer = style({
|
||||
flex: 1,
|
||||
});
|
||||
|
||||
export const linkItemRoot = style({
|
||||
color: 'inherit',
|
||||
display: 'contents',
|
||||
});
|
||||
|
||||
@@ -6,11 +6,13 @@ import { Link } from 'react-router-dom';
|
||||
|
||||
import * as styles from './index.css';
|
||||
|
||||
export interface MenuItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
export interface MenuItemProps extends React.HTMLAttributes<HTMLButtonElement> {
|
||||
icon?: React.ReactElement;
|
||||
active?: boolean;
|
||||
disabled?: boolean;
|
||||
collapsed?: boolean; // true, false, undefined. undefined means no collapse
|
||||
// true, false, undefined. undefined means no collapse
|
||||
collapsed?: boolean;
|
||||
// if onCollapsedChange is given, but collapsed is undefined, then we will render the collapse button as disabled
|
||||
onCollapsedChange?: (collapsed: boolean) => void;
|
||||
postfix?: React.ReactElement;
|
||||
}
|
||||
@@ -23,7 +25,7 @@ const stopPropagation: React.MouseEventHandler = e => {
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
export const MenuItem = React.forwardRef<HTMLDivElement, MenuItemProps>(
|
||||
export const MenuItem = React.forwardRef<HTMLButtonElement, MenuItemProps>(
|
||||
(
|
||||
{
|
||||
onClick,
|
||||
@@ -38,14 +40,9 @@ export const MenuItem = React.forwardRef<HTMLDivElement, MenuItemProps>(
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const collapsible = collapsed !== undefined;
|
||||
if (collapsible && !onCollapsedChange) {
|
||||
throw new Error(
|
||||
'onCollapsedChange is required when collapsed is defined'
|
||||
);
|
||||
}
|
||||
const collapsible = onCollapsedChange !== undefined;
|
||||
return (
|
||||
<div
|
||||
<button
|
||||
ref={ref}
|
||||
{...props}
|
||||
onClick={onClick}
|
||||
@@ -58,6 +55,7 @@ export const MenuItem = React.forwardRef<HTMLDivElement, MenuItemProps>(
|
||||
<div className={styles.iconsContainer} data-collapsible={collapsible}>
|
||||
{collapsible && (
|
||||
<div
|
||||
data-disabled={collapsed === undefined ? true : undefined}
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault(); // for links
|
||||
@@ -68,7 +66,7 @@ export const MenuItem = React.forwardRef<HTMLDivElement, MenuItemProps>(
|
||||
>
|
||||
<ArrowDownSmallIcon
|
||||
className={styles.collapsedIcon}
|
||||
data-collapsed={collapsed}
|
||||
data-collapsed={collapsed !== false}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@@ -84,21 +82,22 @@ export const MenuItem = React.forwardRef<HTMLDivElement, MenuItemProps>(
|
||||
{postfix}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
);
|
||||
MenuItem.displayName = 'MenuItem';
|
||||
|
||||
export const MenuLinkItem = React.forwardRef<HTMLDivElement, MenuLinkItemProps>(
|
||||
({ to, ...props }, ref) => {
|
||||
return (
|
||||
<Link to={to} className={styles.linkItemRoot}>
|
||||
{/* The <a> element rendered by Link does not generate display box due to `display: contents` style */}
|
||||
{/* Thus ref is passed to MenuItem instead of Link */}
|
||||
<MenuItem ref={ref} {...props}></MenuItem>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
);
|
||||
export const MenuLinkItem = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
MenuLinkItemProps
|
||||
>(({ to, ...props }, ref) => {
|
||||
return (
|
||||
<Link to={to} className={styles.linkItemRoot}>
|
||||
{/* The <a> element rendered by Link does not generate display box due to `display: contents` style */}
|
||||
{/* Thus ref is passed to MenuItem instead of Link */}
|
||||
<MenuItem ref={ref} {...props}></MenuItem>
|
||||
</Link>
|
||||
);
|
||||
});
|
||||
MenuLinkItem.displayName = 'MenuLinkItem';
|
||||
|
||||
@@ -12,7 +12,7 @@ export const root = style({
|
||||
userSelect: 'none',
|
||||
cursor: 'pointer',
|
||||
padding: '0 12px',
|
||||
margin: '12px 0',
|
||||
margin: '20px 0',
|
||||
position: 'relative',
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { assertExists } from '@blocksuite/global/utils';
|
||||
import { useAtom, useSetAtom } from 'jotai';
|
||||
import type { ReactElement } from 'react';
|
||||
import { useCallback, useLayoutEffect, useState } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import {
|
||||
appSidebarOpenAtom,
|
||||
@@ -18,16 +19,10 @@ export const ResizeIndicator = (props: ResizeIndicatorProps): ReactElement => {
|
||||
const [sidebarOpen, setSidebarOpen] = useAtom(appSidebarOpenAtom);
|
||||
const [isResizing, setIsResizing] = useAtom(appSidebarResizingAtom);
|
||||
|
||||
const [anchorLeft, setAnchorLeft] = useState(0);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!props.targetElement) return;
|
||||
const { left } = props.targetElement.getBoundingClientRect();
|
||||
setAnchorLeft(left);
|
||||
}, [props.targetElement]);
|
||||
|
||||
const onResizeStart = useCallback(() => {
|
||||
let resized = false;
|
||||
assertExists(props.targetElement);
|
||||
const { left: anchorLeft } = props.targetElement.getBoundingClientRect();
|
||||
|
||||
function onMouseMove(e: MouseEvent) {
|
||||
e.preventDefault();
|
||||
@@ -51,13 +46,7 @@ export const ResizeIndicator = (props: ResizeIndicatorProps): ReactElement => {
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}, [
|
||||
anchorLeft,
|
||||
props.targetElement,
|
||||
setIsResizing,
|
||||
setSidebarOpen,
|
||||
setWidth,
|
||||
]);
|
||||
}, [props.targetElement, setIsResizing, setSidebarOpen, setWidth]);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -4,7 +4,6 @@ export const baseContainer = style({
|
||||
padding: '4px 16px',
|
||||
display: 'flex',
|
||||
flexFlow: 'column nowrap',
|
||||
rowGap: '4px',
|
||||
});
|
||||
|
||||
export const scrollableContainerRoot = style({
|
||||
@@ -45,6 +44,7 @@ export const scrollableContainer = style([
|
||||
baseContainer,
|
||||
{
|
||||
height: '100%',
|
||||
padding: '4px 8px',
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -69,6 +69,7 @@ export const scrollbarThumb = style({
|
||||
position: 'relative',
|
||||
background: 'var(--affine-black-30)',
|
||||
borderRadius: '4px',
|
||||
overflow: 'hidden',
|
||||
selectors: {
|
||||
'&::before': {
|
||||
content: '""',
|
||||
|
||||
@@ -14,6 +14,7 @@ export const avatarImageStyle = style({
|
||||
height: '100%',
|
||||
objectFit: 'cover',
|
||||
objectPosition: 'center',
|
||||
display: 'block',
|
||||
});
|
||||
|
||||
const bottomAnimation = keyframes({
|
||||
|
||||
@@ -252,3 +252,11 @@ affine-block-hub {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
[role='button'] {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ export const scrollbarThumb = style({
|
||||
position: 'relative',
|
||||
background: 'var(--affine-divider-color)',
|
||||
width: '50%',
|
||||
overflow: 'hidden',
|
||||
borderRadius: '4px',
|
||||
':hover': {
|
||||
background: 'var(--affine-icon-color)',
|
||||
|
||||
Reference in New Issue
Block a user