diff --git a/packages/frontend/core/src/components/app-sidebar/category-divider/index.css.ts b/packages/frontend/core/src/components/app-sidebar/category-divider/index.css.ts index 229aee59649e6..699a95c55ee69 100644 --- a/packages/frontend/core/src/components/app-sidebar/category-divider/index.css.ts +++ b/packages/frontend/core/src/components/app-sidebar/category-divider/index.css.ts @@ -64,3 +64,30 @@ export const collapseIcon = style({ }, }, }); + +// ------------- mobile ------------- +export const mobileRoot = style([ + root, + { + height: 25, + padding: '0 16px', + selectors: { + '&[data-collapsible="true"]:hover': { + backgroundColor: 'transparent', + }, + '&[data-collapsible="true"]:active': { + backgroundColor: cssVarV2('layer/background/hoverOverlay'), + }, + }, + }, +]); +export const mobileLabel = style([ + label, + { + color: cssVarV2('text/primary'), + fontSize: 20, + lineHeight: '25px', + letterSpacing: -0.45, + fontWeight: 400, + }, +]); diff --git a/packages/frontend/core/src/components/app-sidebar/category-divider/index.tsx b/packages/frontend/core/src/components/app-sidebar/category-divider/index.tsx index 3407939d0f436..a459c01e6706e 100644 --- a/packages/frontend/core/src/components/app-sidebar/category-divider/index.tsx +++ b/packages/frontend/core/src/components/app-sidebar/category-divider/index.tsx @@ -9,6 +9,7 @@ export type CategoryDividerProps = PropsWithChildren< label: string; className?: string; collapsed?: boolean; + mobile?: boolean; setCollapsed?: (collapsed: boolean) => void; } & { [key: `data-${string}`]: unknown; @@ -22,6 +23,7 @@ export const CategoryDivider = forwardRef( children, className, collapsed, + mobile, setCollapsed, ...otherProps }: CategoryDividerProps, @@ -31,14 +33,15 @@ export const CategoryDivider = forwardRef( return (
setCollapsed?.(!collapsed)} + data-mobile={mobile} data-collapsed={collapsed} data-collapsible={collapsible} {...otherProps} > -
+
{label} {collapsible ? ( { + const mobile = useContext(ExplorerMobileContext); const section = useService(ExplorerService).sections[name]; const collapsed = useLiveData(section.collapsed$); @@ -62,6 +70,7 @@ export const CollapsibleSection = ({ data-testid={testId} > - {actions} + {mobile ? null : actions} - + {children} diff --git a/packages/frontend/core/src/modules/explorer/views/mobile.context.ts b/packages/frontend/core/src/modules/explorer/views/mobile.context.ts new file mode 100644 index 0000000000000..2943d1a275758 --- /dev/null +++ b/packages/frontend/core/src/modules/explorer/views/mobile.context.ts @@ -0,0 +1,8 @@ +import { createContext } from 'react'; + +/** + * To enable mobile manually + * > Using `environment.isMobile` directly will affect current web entry on mobile + * > So we control it manually for now + */ +export const ExplorerMobileContext = createContext(false); diff --git a/packages/frontend/core/src/modules/explorer/views/tree/node.css.ts b/packages/frontend/core/src/modules/explorer/views/tree/node.css.ts index d4f259a7f8253..6e83be77322b5 100644 --- a/packages/frontend/core/src/modules/explorer/views/tree/node.css.ts +++ b/packages/frontend/core/src/modules/explorer/views/tree/node.css.ts @@ -36,6 +36,14 @@ export const itemRoot = style({ }, }, }); +export const itemMain = style({ + display: 'flex', + alignItems: 'center', + width: 0, + flex: 1, + position: 'relative', + gap: 12, +}); export const itemRenameAnchor = style({ pointerEvents: 'none', position: 'absolute', @@ -55,31 +63,26 @@ export const itemContent = style({ export const postfix = style({ display: 'flex', alignItems: 'center', - right: '4px', + right: 0, position: 'absolute', opacity: 0, pointerEvents: 'none', selectors: { [`${itemRoot}:hover &`]: { - justifySelf: 'flex-end', - position: 'initial', opacity: 1, - pointerEvents: 'all', + pointerEvents: 'initial', + position: 'initial', }, }, }); -export const icon = style({ - color: cssVarV2('icon/primary'), - fontSize: '20px', -}); -export const emojiIcon = style({ - width: '20px', - height: '20px', +export const iconContainer = style({ display: 'flex', - justifyContent: 'center', + alignContent: 'center', alignItems: 'center', + width: 20, + height: 20, color: cssVarV2('icon/primary'), - fontSize: cssVar('--affine-font-sm'), + fontSize: 20, }); export const collapsedIconContainer = style({ width: '16px', @@ -103,13 +106,6 @@ export const collapsedIconContainer = style({ }, }, }); -export const iconsContainer = style({ - display: 'flex', - alignItems: 'center', - justifyContent: 'flex-start', - width: '44px', - flexShrink: 0, -}); export const collapsedIcon = style({ transition: 'transform 0.2s ease-in-out', selectors: { @@ -182,3 +178,67 @@ export const draggedOverEffect = style({ }, }, }); + +// ---------- mobile ---------- +export const mobileItemRoot = style([ + itemRoot, + { + padding: '8px', + borderRadius: 0, + flexDirection: 'row-reverse', + gap: 12, + selectors: { + '&:hover': { + background: 'transparent', + }, + '&:active': { + background: cssVar('hoverColor'), + }, + '&[data-active="true"]': { + background: 'transparent', + }, + }, + + ':after': { + content: '', + width: `calc(100% + ${levelIndent})`, + height: 0.5, + background: cssVar('borderColor'), + bottom: 0, + position: 'absolute', + right: 0, + }, + }, +]); +export const mobileItemMain = style([itemMain, {}]); + +export const mobileIconContainer = style([ + iconContainer, + { + width: 32, + height: 32, + fontSize: 24, + }, +]); + +export const mobileCollapsedIconContainer = style([ + collapsedIconContainer, + { + fontSize: 16, + }, +]); +export const mobileItemContent = style([ + itemContent, + { + fontSize: 17, + lineHeight: '22px', + letterSpacing: -0.43, + fontWeight: 400, + }, +]); +export const mobileContentContainer = style([ + contentContainer, + { + marginTop: 0, + }, +]); diff --git a/packages/frontend/core/src/modules/explorer/views/tree/node.tsx b/packages/frontend/core/src/modules/explorer/views/tree/node.tsx index de2cdeca2a26b..a660d8d867969 100644 --- a/packages/frontend/core/src/modules/explorer/views/tree/node.tsx +++ b/packages/frontend/core/src/modules/explorer/views/tree/node.tsx @@ -37,6 +37,7 @@ import { useState, } from 'react'; +import { ExplorerMobileContext } from '../mobile.context'; import { ExplorerTreeContext } from './context'; import { DropEffect } from './drop-effect'; import * as styles from './node.css'; @@ -108,6 +109,7 @@ export const ExplorerTreeNode = ({ onDrop?: (data: DropTargetDropEvent) => void; dropEffect?: ExplorerTreeNodeDropEffect; } & { [key in `data-${string}`]?: any }) => { + const mobile = useContext(ExplorerMobileContext); const t = useI18n(); const cid = useId(); const context = useContext(ExplorerTreeContext); @@ -306,35 +308,74 @@ export const ExplorerTreeNode = ({ const content = (
-
+
+ +
+ +
- + {emoji ?? + (Icon && ( + + ))} +
+ +
+ {name} +
+ + {postfix} +
{ + // prevent jump to page + e.stopPropagation(); + e.preventDefault(); + }} + > + {inlineOperations.map(({ view }, index) => ( + {view} + ))} + {menuOperations.length > 0 && ( + ( + {view} + ))} + > + + + + + )}
- {emoji ? ( -
{emoji}
- ) : ( - Icon && ( - - ) - )}
+ {renameable && renaming && ( )} - -
{name}
- - {postfix} -
{ - // prevent jump to page - e.stopPropagation(); - e.preventDefault(); - }} - > - {inlineOperations.map(({ view }, index) => ( - {view} - ))} - {menuOperations.length > 0 && ( - ( - {view} - ))} - > - - - - - )} -
); @@ -391,7 +401,10 @@ export const ExplorerTreeNode = ({ {...otherProps} >