mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-11 20:08:37 +00:00
feat(core): adjust app sidebar's style (#6162)
This commit is contained in:
@@ -60,7 +60,7 @@ export const resizeHandleContainer = style({
|
|||||||
opacity: 0,
|
opacity: 0,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
cursor: 'ew-resize',
|
cursor: 'col-resize',
|
||||||
'@media': {
|
'@media': {
|
||||||
'(max-width: 600px)': {
|
'(max-width: 600px)': {
|
||||||
// do not allow resizing on small screen
|
// do not allow resizing on small screen
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ import {
|
|||||||
import { SidebarHeader } from './sidebar-header';
|
import { SidebarHeader } from './sidebar-header';
|
||||||
|
|
||||||
export type AppSidebarProps = PropsWithChildren<{
|
export type AppSidebarProps = PropsWithChildren<{
|
||||||
hasBackground?: boolean;
|
clientBorder?: boolean;
|
||||||
|
translucentUI?: boolean;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export type History = {
|
export type History = {
|
||||||
@@ -37,7 +38,11 @@ export type History = {
|
|||||||
const MAX_WIDTH = 480;
|
const MAX_WIDTH = 480;
|
||||||
const MIN_WIDTH = 256;
|
const MIN_WIDTH = 256;
|
||||||
|
|
||||||
export function AppSidebar(props: AppSidebarProps): ReactElement {
|
export function AppSidebar({
|
||||||
|
children,
|
||||||
|
clientBorder,
|
||||||
|
translucentUI,
|
||||||
|
}: AppSidebarProps): ReactElement {
|
||||||
const [open, setOpen] = useAtom(appSidebarOpenAtom);
|
const [open, setOpen] = useAtom(appSidebarOpenAtom);
|
||||||
const [width, setWidth] = useAtom(appSidebarWidthAtom);
|
const [width, setWidth] = useAtom(appSidebarWidthAtom);
|
||||||
const [floating, setFloating] = useAtom(appSidebarFloatingAtom);
|
const [floating, setFloating] = useAtom(appSidebarFloatingAtom);
|
||||||
@@ -70,9 +75,9 @@ export function AppSidebar(props: AppSidebarProps): ReactElement {
|
|||||||
};
|
};
|
||||||
}, [open, setFloating, setOpen, width]);
|
}, [open, setFloating, setOpen, width]);
|
||||||
|
|
||||||
const transparent = environment.isDesktop && !props.hasBackground;
|
|
||||||
const isMacosDesktop = environment.isDesktop && environment.isMacOs;
|
const isMacosDesktop = environment.isDesktop && environment.isMacOs;
|
||||||
const hasRightBorder = !environment.isDesktop || !transparent;
|
const hasRightBorder =
|
||||||
|
!environment.isDesktop || (!clientBorder && !translucentUI);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -88,17 +93,17 @@ export function AppSidebar(props: AppSidebarProps): ReactElement {
|
|||||||
onResizing={setResizing}
|
onResizing={setResizing}
|
||||||
onWidthChange={setWidth}
|
onWidthChange={setWidth}
|
||||||
className={navWrapperStyle}
|
className={navWrapperStyle}
|
||||||
resizeHandleVerticalPadding={transparent ? 16 : 0}
|
resizeHandleOffset={clientBorder ? 8 : 0}
|
||||||
data-transparent={transparent}
|
resizeHandleVerticalPadding={clientBorder ? 16 : 0}
|
||||||
|
data-transparent
|
||||||
data-has-border={hasRightBorder}
|
data-has-border={hasRightBorder}
|
||||||
data-testid="app-sidebar-wrapper"
|
data-testid="app-sidebar-wrapper"
|
||||||
data-is-macos-electron={isMacosDesktop}
|
data-is-macos-electron={isMacosDesktop}
|
||||||
data-has-background={environment.isDesktop && props.hasBackground}
|
|
||||||
>
|
>
|
||||||
<nav className={navStyle} data-testid="app-sidebar">
|
<nav className={navStyle} data-testid="app-sidebar">
|
||||||
<SidebarHeader />
|
<SidebarHeader />
|
||||||
<div className={navBodyStyle} data-testid="sliderBar-inner">
|
<div className={navBodyStyle} data-testid="sliderBar-inner">
|
||||||
{props.children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</ResizePanel>
|
</ResizePanel>
|
||||||
|
|||||||
@@ -169,13 +169,8 @@ export const RootAppSidebar = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AppSidebar
|
<AppSidebar
|
||||||
hasBackground={
|
clientBorder={appSettings.clientBorder}
|
||||||
!(
|
translucentUI={appSettings.enableBlurBackground}
|
||||||
appSettings.enableBlurBackground &&
|
|
||||||
environment.isDesktop &&
|
|
||||||
environment.isMacOs
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<MoveToTrash.ConfirmModal
|
<MoveToTrash.ConfirmModal
|
||||||
open={trashConfirmOpen}
|
open={trashConfirmOpen}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export const appStyle = style({
|
|||||||
inset: 0,
|
inset: 0,
|
||||||
opacity: `var(--affine-noise-opacity, 0)`,
|
opacity: `var(--affine-noise-opacity, 0)`,
|
||||||
backgroundRepeat: 'repeat',
|
backgroundRepeat: 'repeat',
|
||||||
backgroundSize: '3%',
|
backgroundSize: '50px',
|
||||||
// todo: figure out how to use vanilla-extract webpack plugin to inject img url
|
// todo: figure out how to use vanilla-extract webpack plugin to inject img url
|
||||||
backgroundImage: `var(--noise-background)`,
|
backgroundImage: `var(--noise-background)`,
|
||||||
},
|
},
|
||||||
@@ -29,7 +29,7 @@ export const appStyle = style({
|
|||||||
});
|
});
|
||||||
globalStyle(`html[data-theme="light"] ${appStyle}`, {
|
globalStyle(`html[data-theme="light"] ${appStyle}`, {
|
||||||
vars: {
|
vars: {
|
||||||
'--affine-noise-opacity': '0.35',
|
'--affine-noise-opacity': '0.2',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
globalStyle(`html[data-theme="dark"] ${appStyle}`, {
|
globalStyle(`html[data-theme="dark"] ${appStyle}`, {
|
||||||
@@ -51,11 +51,14 @@ export const mainContainerStyle = style({
|
|||||||
flex: 1,
|
flex: 1,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
maxWidth: '100%',
|
maxWidth: '100%',
|
||||||
|
transition: 'margin-left 0.2s ease',
|
||||||
selectors: {
|
selectors: {
|
||||||
'&[data-show-padding="true"]': {
|
'&[data-client-border="true"]': {
|
||||||
|
borderRadius: 6,
|
||||||
margin: '8px',
|
margin: '8px',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
// todo: is this performance intensive?
|
// todo: is this performance intensive?
|
||||||
|
// TODO: not match with design's shadow, theme missing
|
||||||
filter: 'drop-shadow(0px 0px 4px rgba(66,65,73,.14))',
|
filter: 'drop-shadow(0px 0px 4px rgba(66,65,73,.14))',
|
||||||
'@media': {
|
'@media': {
|
||||||
print: {
|
print: {
|
||||||
@@ -65,7 +68,10 @@ export const mainContainerStyle = style({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'&[data-show-padding="true"]:before': {
|
'&[data-client-border="true"][data-side-bar-open="true"]': {
|
||||||
|
marginLeft: 0,
|
||||||
|
},
|
||||||
|
'&[data-client-border="true"]:before': {
|
||||||
content: '""',
|
content: '""',
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
height: '8px',
|
height: '8px',
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { clsx } from 'clsx';
|
import { clsx } from 'clsx';
|
||||||
|
import { useAtomValue } from 'jotai';
|
||||||
import type { HTMLAttributes, PropsWithChildren, ReactElement } from 'react';
|
import type { HTMLAttributes, PropsWithChildren, ReactElement } from 'react';
|
||||||
import { forwardRef } from 'react';
|
import { forwardRef } from 'react';
|
||||||
|
|
||||||
import { AppSidebarFallback } from '../app-sidebar';
|
import { AppSidebarFallback, appSidebarOpenAtom } from '../app-sidebar';
|
||||||
import { appStyle, mainContainerStyle, toolStyle } from './index.css';
|
import { appStyle, mainContainerStyle, toolStyle } from './index.css';
|
||||||
|
|
||||||
export type WorkspaceRootProps = PropsWithChildren<{
|
export type WorkspaceRootProps = PropsWithChildren<{
|
||||||
@@ -33,25 +34,25 @@ export const AppContainer = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
export interface MainContainerProps extends HTMLAttributes<HTMLDivElement> {
|
export interface MainContainerProps extends HTMLAttributes<HTMLDivElement> {
|
||||||
className?: string;
|
clientBorder?: boolean;
|
||||||
padding?: boolean;
|
|
||||||
transparent?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MainContainer = forwardRef<
|
export const MainContainer = forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
PropsWithChildren<MainContainerProps>
|
PropsWithChildren<MainContainerProps>
|
||||||
>(function MainContainer(
|
>(function MainContainer(
|
||||||
{ className, padding, children, transparent, ...props },
|
{ className, children, clientBorder, ...props },
|
||||||
ref
|
ref
|
||||||
): ReactElement {
|
): ReactElement {
|
||||||
|
const appSideBarOpen = useAtomValue(appSidebarOpenAtom);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
{...props}
|
{...props}
|
||||||
className={clsx(mainContainerStyle, className)}
|
className={clsx(mainContainerStyle, className)}
|
||||||
data-is-macos={environment.isDesktop && environment.isMacOs}
|
data-is-macos={environment.isDesktop && environment.isMacOs}
|
||||||
data-show-padding={!!padding}
|
data-transparent={false}
|
||||||
data-transparent={transparent}
|
data-client-border={clientBorder}
|
||||||
|
data-side-bar-open={appSideBarOpen}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
|
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
|
||||||
import type { PropsWithChildren, ReactNode } from 'react';
|
import type { PropsWithChildren, ReactNode } from 'react';
|
||||||
import { lazy, Suspense, useCallback, useEffect, useState } from 'react';
|
import { lazy, Suspense, useCallback, useEffect, useState } from 'react';
|
||||||
import { matchPath, useParams } from 'react-router-dom';
|
import { matchPath } from 'react-router-dom';
|
||||||
import { Map as YMap } from 'yjs';
|
import { Map as YMap } from 'yjs';
|
||||||
|
|
||||||
import { openQuickSearchModalAtom, openSettingModalAtom } from '../atoms';
|
import { openQuickSearchModalAtom, openSettingModalAtom } from '../atoms';
|
||||||
@@ -152,10 +152,6 @@ export const WorkspaceLayoutInner = ({ children }: PropsWithChildren) => {
|
|||||||
const handleDragEnd = useSidebarDrag();
|
const handleDragEnd = useSidebarDrag();
|
||||||
|
|
||||||
const { appSettings } = useAppSettingHelper();
|
const { appSettings } = useAppSettingHelper();
|
||||||
const { pageId } = useParams();
|
|
||||||
|
|
||||||
// todo: refactor this that the root layout do not need to check route state
|
|
||||||
const isInPageDetail = !!pageId;
|
|
||||||
|
|
||||||
const upgradeStatus = useWorkspaceStatus(currentWorkspace, s => s.upgrade);
|
const upgradeStatus = useWorkspaceStatus(currentWorkspace, s => s.upgrade);
|
||||||
|
|
||||||
@@ -185,10 +181,7 @@ export const WorkspaceLayoutInner = ({ children }: PropsWithChildren) => {
|
|||||||
paths={pathGenerator}
|
paths={pathGenerator}
|
||||||
/>
|
/>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
<MainContainer
|
<MainContainer clientBorder={appSettings.clientBorder}>
|
||||||
transparent={isInPageDetail}
|
|
||||||
padding={appSettings.clientBorder}
|
|
||||||
>
|
|
||||||
<Suspense>
|
<Suspense>
|
||||||
{upgradeStatus?.needUpgrade || upgradeStatus?.upgrading ? (
|
{upgradeStatus?.needUpgrade || upgradeStatus?.upgrading ? (
|
||||||
<WorkspaceUpgrade />
|
<WorkspaceUpgrade />
|
||||||
|
|||||||
Reference in New Issue
Block a user