mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-12-19 04:01:47 +03:00
Merge pull request #166 from toeverything/refactor/page-tree-styles
Refactor/page tree styles
This commit is contained in:
commit
22f325fbff
@ -1,34 +1,32 @@
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import {
|
||||
MuiBox as Box,
|
||||
MuiButton as Button,
|
||||
MuiCollapse as Collapse,
|
||||
MuiIconButton as IconButton,
|
||||
styled,
|
||||
} from '@toeverything/components/ui';
|
||||
import {
|
||||
AddIcon,
|
||||
ArrowDropDownIcon,
|
||||
ArrowRightIcon,
|
||||
} from '@toeverything/components/icons';
|
||||
import { services } from '@toeverything/datasource/db-service';
|
||||
import {
|
||||
usePageTree,
|
||||
useCalendarHeatmap,
|
||||
usePageTree,
|
||||
} from '@toeverything/components/layout';
|
||||
import { AddIcon } from '@toeverything/components/icons';
|
||||
import {
|
||||
MuiBox as Box,
|
||||
MuiCollapse as Collapse,
|
||||
styled,
|
||||
} from '@toeverything/components/ui';
|
||||
import { services } from '@toeverything/datasource/db-service';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
|
||||
const StyledContainer = styled('div')({
|
||||
const StyledBtn = styled('div')({
|
||||
height: '32px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
});
|
||||
|
||||
const StyledBtn = styled('div')({
|
||||
color: '#98ACBD',
|
||||
textTransform: 'none',
|
||||
fontSize: '12px',
|
||||
fontWeight: '600',
|
||||
cursor: 'pointer',
|
||||
userSelect: 'none',
|
||||
flex: 1,
|
||||
});
|
||||
|
||||
export type CollapsiblePageTreeProps = {
|
||||
@ -81,16 +79,14 @@ export function CollapsiblePageTree(props: CollapsiblePageTreeProps) {
|
||||
onMouseEnter={() => setNewPageBtnVisible(true)}
|
||||
onMouseLeave={() => setNewPageBtnVisible(false)}
|
||||
>
|
||||
<StyledContainer>
|
||||
<StyledBtn onClick={() => setOpen(prev => !prev)}>
|
||||
{open ? (
|
||||
<ArrowDropDownIcon sx={{ color: '#566B7D' }} />
|
||||
) : (
|
||||
<ArrowRightIcon sx={{ color: '#566B7D' }} />
|
||||
)}
|
||||
<StyledBtn onClick={() => setOpen(prev => !prev)}>
|
||||
{title}
|
||||
</StyledBtn>
|
||||
</StyledContainer>
|
||||
{title}
|
||||
</StyledBtn>
|
||||
|
||||
{newPageBtnVisible && (
|
||||
<AddIcon
|
||||
|
@ -1,20 +1,18 @@
|
||||
import styles from './tree-item.module.scss';
|
||||
import { AddIcon, MoreIcon } from '@toeverything/components/icons';
|
||||
import {
|
||||
MuiSnackbar as Snackbar,
|
||||
Cascader,
|
||||
CascaderItemProps,
|
||||
MuiDivider as Divider,
|
||||
MuiClickAwayListener as ClickAwayListener,
|
||||
IconButton,
|
||||
MuiClickAwayListener as ClickAwayListener,
|
||||
MuiSnackbar as Snackbar,
|
||||
styled,
|
||||
} from '@toeverything/components/ui';
|
||||
import React from 'react';
|
||||
import { NavLink, useNavigate } from 'react-router-dom';
|
||||
import { copyToClipboard } from '@toeverything/utils';
|
||||
import { services, TemplateFactory } from '@toeverything/datasource/db-service';
|
||||
import { NewFromTemplatePortal } from './NewFromTemplatePortal';
|
||||
import { useFlag } from '@toeverything/datasource/feature-flags';
|
||||
import { MoreIcon, AddIcon } from '@toeverything/components/icons';
|
||||
import { copyToClipboard } from '@toeverything/utils';
|
||||
import React from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { TreeItemMoreActions } from './styles';
|
||||
|
||||
const MESSAGES = {
|
||||
COPY_LINK_SUCCESS: 'Copyed link to clipboard',
|
||||
@ -47,6 +45,10 @@ function DndTreeItemMoreActions(props: ActionsProps) {
|
||||
set_alert_open(false);
|
||||
};
|
||||
const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
|
||||
if (anchorEl) {
|
||||
setAnchorEl(null);
|
||||
return;
|
||||
}
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
const handleClose = () => {
|
||||
@ -246,10 +248,11 @@ function DndTreeItemMoreActions(props: ActionsProps) {
|
||||
return (
|
||||
<ClickAwayListener onClickAway={() => handleClose()}>
|
||||
<div>
|
||||
<div className={styles['TreeItemMoreActions']}>
|
||||
<TreeItemMoreActions>
|
||||
<StyledAction>
|
||||
<IconButton
|
||||
size="small"
|
||||
hoverColor="#E0E6EB"
|
||||
onClick={handle_new_child_page}
|
||||
>
|
||||
<AddIcon />
|
||||
@ -262,14 +265,15 @@ function DndTreeItemMoreActions(props: ActionsProps) {
|
||||
<MoreIcon />
|
||||
</IconButton>
|
||||
</StyledAction>
|
||||
</div>
|
||||
</TreeItemMoreActions>
|
||||
|
||||
<Cascader
|
||||
items={menuList}
|
||||
anchorEl={anchorEl}
|
||||
placement="right-start"
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
></Cascader>
|
||||
/>
|
||||
<Snackbar
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
|
||||
open={alert_open}
|
||||
|
@ -1,21 +1,22 @@
|
||||
import React, {
|
||||
forwardRef,
|
||||
type CSSProperties,
|
||||
type HTMLAttributes,
|
||||
} from 'react';
|
||||
import { useParams, Link } from 'react-router-dom';
|
||||
import cx from 'clsx';
|
||||
import { CloseIcon } from '@toeverything/components/common';
|
||||
import {
|
||||
ArrowDropDownIcon,
|
||||
ArrowRightIcon,
|
||||
} from '@toeverything/components/icons';
|
||||
import { forwardRef, type HTMLAttributes } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import styles from './tree-item.module.scss';
|
||||
import { useFlag } from '@toeverything/datasource/feature-flags';
|
||||
|
||||
import MoreActions from './MoreActions';
|
||||
import { useTheme } from '@toeverything/components/ui';
|
||||
import {
|
||||
ActionButton,
|
||||
Counter,
|
||||
TextLink,
|
||||
TreeItemContainer,
|
||||
TreeItemContent,
|
||||
Wrapper,
|
||||
} from './styles';
|
||||
|
||||
export type TreeItemProps = {
|
||||
/** The main text to display on this line */
|
||||
value: string;
|
||||
@ -67,56 +68,34 @@ export const TreeItem = forwardRef<HTMLDivElement, TreeItemProps>(
|
||||
'BooleanPageTreeItemMoreActions',
|
||||
true
|
||||
);
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<li
|
||||
<Wrapper
|
||||
ref={wrapperRef}
|
||||
className={cx(
|
||||
styles['Wrapper'],
|
||||
clone && styles['clone'],
|
||||
ghost && styles['ghost'],
|
||||
indicator && styles['indicator'],
|
||||
disableSelection && styles['disableSelection'],
|
||||
disableInteraction && styles['disableInteraction']
|
||||
)}
|
||||
style={
|
||||
{
|
||||
'--spacing': `${indentationWidth * depth}px`,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
} as CSSProperties
|
||||
}
|
||||
clone={clone}
|
||||
ghost={ghost}
|
||||
disableSelection={disableSelection}
|
||||
disableInteraction={disableInteraction}
|
||||
spacing={`${indentationWidth * depth}px`}
|
||||
{...props}
|
||||
>
|
||||
<div
|
||||
ref={ref}
|
||||
className={styles['TreeItem']}
|
||||
style={style}
|
||||
title={value}
|
||||
>
|
||||
<Action onClick={onCollapse}>
|
||||
<TreeItemContainer ref={ref} style={style} title={value}>
|
||||
<ActionButton tabIndex={0} onClick={onCollapse}>
|
||||
{childCount !== 0 &&
|
||||
(collapsed ? (
|
||||
<ArrowRightIcon />
|
||||
) : (
|
||||
<ArrowDropDownIcon />
|
||||
))}
|
||||
</Action>
|
||||
</ActionButton>
|
||||
|
||||
<div className={styles['ItemContent']}>
|
||||
<Link
|
||||
className={styles['Text']}
|
||||
{...handleProps}
|
||||
<TreeItemContent {...handleProps}>
|
||||
<TextLink
|
||||
to={`/${workspace_id}/${pageId}`}
|
||||
style={{
|
||||
...(pageId === page_id && {
|
||||
color: theme.affine.palette.primary,
|
||||
}),
|
||||
}}
|
||||
active={pageId === page_id}
|
||||
>
|
||||
{value}
|
||||
</Link>
|
||||
</TextLink>
|
||||
{BooleanPageTreeItemMoreActions && (
|
||||
<MoreActions
|
||||
workspaceId={workspace_id}
|
||||
@ -127,71 +106,11 @@ export const TreeItem = forwardRef<HTMLDivElement, TreeItemProps>(
|
||||
|
||||
{/*{!clone && onRemove && <Remove onClick={onRemove} />}*/}
|
||||
{clone && childCount && childCount > 1 ? (
|
||||
<span className={styles['Count']}>
|
||||
{childCount}
|
||||
</span>
|
||||
<Counter>{childCount}</Counter>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</TreeItemContent>
|
||||
</TreeItemContainer>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export interface ActionProps extends React.HTMLAttributes<HTMLButtonElement> {
|
||||
active?: {
|
||||
fill: string;
|
||||
background: string;
|
||||
};
|
||||
// cursor?: CSSProperties['cursor'];
|
||||
cursor?: 'pointer' | 'grab';
|
||||
}
|
||||
|
||||
/** Customizable buttons */
|
||||
export function Action({
|
||||
active,
|
||||
className,
|
||||
cursor,
|
||||
style,
|
||||
...props
|
||||
}: ActionProps) {
|
||||
return (
|
||||
<button
|
||||
{...props}
|
||||
className={cx(styles['Action'], className)}
|
||||
tabIndex={0}
|
||||
style={
|
||||
{
|
||||
...style,
|
||||
'--fill': active?.fill,
|
||||
'--background': active?.background,
|
||||
} as CSSProperties
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function Handle(props: ActionProps) {
|
||||
return (
|
||||
<Action cursor="grab" data-cypress="draggable-handle" {...props}>
|
||||
<ArrowDropDownIcon />
|
||||
</Action>
|
||||
);
|
||||
}
|
||||
|
||||
export function Remove(props: ActionProps) {
|
||||
return (
|
||||
<Action
|
||||
{...props}
|
||||
active={{
|
||||
fill: 'rgba(255, 70, 70, 0.95)',
|
||||
background: 'rgba(255, 70, 70, 0.1)',
|
||||
}}
|
||||
>
|
||||
<CloseIcon style={{ fontSize: 12 }} />
|
||||
{/* <svg width="8" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.99998 -0.000206962C2.7441 -0.000206962 2.48794 0.0972617 2.29294 0.292762L0.292945 2.29276C-0.0980552 2.68376 -0.0980552 3.31682 0.292945 3.70682L7.58591 10.9998L0.292945 18.2928C-0.0980552 18.6838 -0.0980552 19.3168 0.292945 19.7068L2.29294 21.7068C2.68394 22.0978 3.31701 22.0978 3.70701 21.7068L11 14.4139L18.2929 21.7068C18.6829 22.0978 19.317 22.0978 19.707 21.7068L21.707 19.7068C22.098 19.3158 22.098 18.6828 21.707 18.2928L14.414 10.9998L21.707 3.70682C22.098 3.31682 22.098 2.68276 21.707 2.29276L19.707 0.292762C19.316 -0.0982383 18.6829 -0.0982383 18.2929 0.292762L11 7.58573L3.70701 0.292762C3.51151 0.0972617 3.25585 -0.000206962 2.99998 -0.000206962Z" />
|
||||
</svg> */}
|
||||
</Action>
|
||||
);
|
||||
}
|
||||
|
@ -1,10 +1,46 @@
|
||||
.Wrapper {
|
||||
import { styled } from '@toeverything/components/ui';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
export const TreeItemContainer = styled('div')`
|
||||
box-sizing: border-box;
|
||||
padding-left: var(--spacing);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #4c6275;
|
||||
`;
|
||||
|
||||
export const Wrapper = styled('li')<{
|
||||
spacing: string;
|
||||
clone?: boolean;
|
||||
ghost?: boolean;
|
||||
indicator?: boolean;
|
||||
disableSelection?: boolean;
|
||||
disableInteraction?: boolean;
|
||||
}>`
|
||||
box-sizing: border-box;
|
||||
padding-left: ${({ spacing }) => spacing};
|
||||
list-style: none;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
font-size: 14px;
|
||||
|
||||
${({ clone, disableSelection }) =>
|
||||
(clone || disableSelection) &&
|
||||
`width: 100%;
|
||||
.Text,
|
||||
.Count {
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}`}
|
||||
|
||||
${({ indicator }) =>
|
||||
indicator &&
|
||||
`width: 100%;
|
||||
.Text,
|
||||
.Count {
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}`}
|
||||
|
||||
${({ disableInteraction }) => disableInteraction && `pointer-events: none;`}
|
||||
|
||||
&:hover {
|
||||
background: #f5f7f8;
|
||||
border-radius: 5px;
|
||||
@ -17,7 +53,7 @@
|
||||
margin-top: 5px;
|
||||
pointer-events: none;
|
||||
|
||||
.TreeItem {
|
||||
${TreeItemContainer} {
|
||||
padding-right: 20px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 15px 15px 0 rgba(34, 33, 81, 0.1);
|
||||
@ -31,7 +67,7 @@
|
||||
z-index: 1;
|
||||
margin-bottom: -1px;
|
||||
|
||||
.TreeItem {
|
||||
${TreeItemContainer} {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
height: 8px;
|
||||
@ -62,56 +98,14 @@
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.TreeItem > * {
|
||||
${TreeItemContainer} > * {
|
||||
box-shadow: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
.TreeItem {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #4c6275;
|
||||
}
|
||||
|
||||
.ItemContent {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
color: #4c6275;
|
||||
padding-right: 0.5rem;
|
||||
overflow: hidden;
|
||||
|
||||
.TreeItemMoreActions {
|
||||
visibility: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
&:hover {
|
||||
.TreeItemMoreActions {
|
||||
visibility: visible;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.Text {
|
||||
flex-grow: 1;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
color: unset;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.Count {
|
||||
export const Counter = styled('span')`
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 0;
|
||||
@ -125,33 +119,12 @@
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
}
|
||||
`;
|
||||
|
||||
.disableInteraction {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.disableSelection,
|
||||
.clone {
|
||||
width: 100%;
|
||||
.Text,
|
||||
.Count {
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
.Collapse {
|
||||
svg {
|
||||
transition: transform 250ms ease;
|
||||
}
|
||||
|
||||
&.collapsed svg {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
|
||||
.Action {
|
||||
export const ActionButton = styled('button')<{
|
||||
background?: string;
|
||||
fill?: string;
|
||||
}>`
|
||||
display: flex;
|
||||
width: 12px;
|
||||
padding: 0 15px;
|
||||
@ -176,10 +149,11 @@
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--background, rgba(0, 0, 0, 0.05));
|
||||
background-color: ${({ background }) =>
|
||||
background ?? 'rgba(0, 0, 0, 0.05)'};
|
||||
|
||||
svg {
|
||||
fill: var(--fill, #788491);
|
||||
fill: ${({ fill }) => fill ?? '#788491'};
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,4 +161,45 @@
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0), 0 0px 0px 2px #4c9ffe;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const TreeItemMoreActions = styled('div')`
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
`;
|
||||
|
||||
export const TextLink = styled(Link)<{ active?: boolean }>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
text-decoration: none;
|
||||
user-select: none;
|
||||
color: ${({ theme, active }) =>
|
||||
active ? theme.affine.palette.primary : 'unset'};
|
||||
`;
|
||||
|
||||
export const TreeItemContent = styled('div')`
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
color: #4c6275;
|
||||
padding-right: 0.5rem;
|
||||
overflow: hidden;
|
||||
|
||||
&:hover {
|
||||
${TreeItemMoreActions} {
|
||||
visibility: visible;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
`;
|
Loading…
Reference in New Issue
Block a user