feat: add animation to tab button (#965)
This commit is contained in:
@@ -6,6 +6,7 @@ export const StyledSettingContainer = styled('div')(() => {
|
|||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
padding: '0 0 20px 48px',
|
padding: '0 0 20px 48px',
|
||||||
height: '100vh',
|
height: '100vh',
|
||||||
|
marginTop: '48px',
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -25,14 +26,6 @@ export const StyledSettingContent = styled('div')(() => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export const StyledSettingTabContainer = styled('ul')(() => {
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
display: 'flex',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export const WorkspaceSettingTagItem = styled('li')<{ isActive?: boolean }>(
|
export const WorkspaceSettingTagItem = styled('li')<{ isActive?: boolean }>(
|
||||||
({ theme, isActive }) => {
|
({ theme, isActive }) => {
|
||||||
{
|
{
|
||||||
@@ -46,10 +39,6 @@ export const WorkspaceSettingTagItem = styled('li')<{ isActive?: boolean }>(
|
|||||||
lineHeight: theme.font.lineHeight,
|
lineHeight: theme.font.lineHeight,
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
transition: 'all 0.15s ease',
|
transition: 'all 0.15s ease',
|
||||||
borderBottom: `2px solid ${
|
|
||||||
isActive ? theme.colors.primaryColor : 'none'
|
|
||||||
}`,
|
|
||||||
':hover': { color: theme.colors.primaryColor },
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import {
|
import {
|
||||||
StyledSettingContainer,
|
StyledSettingContainer,
|
||||||
StyledSettingContent,
|
StyledSettingContent,
|
||||||
StyledSettingSidebar,
|
|
||||||
StyledSettingTabContainer,
|
|
||||||
WorkspaceSettingTagItem,
|
WorkspaceSettingTagItem,
|
||||||
} from '@/components/workspace-setting/style';
|
} from '@/components/workspace-setting/style';
|
||||||
import { ReactElement, ReactNode, useState } from 'react';
|
import {
|
||||||
|
ReactElement,
|
||||||
|
ReactNode,
|
||||||
|
useState,
|
||||||
|
CSSProperties,
|
||||||
|
useEffect,
|
||||||
|
startTransition,
|
||||||
|
} from 'react';
|
||||||
import {
|
import {
|
||||||
GeneralPage,
|
GeneralPage,
|
||||||
MembersPage,
|
MembersPage,
|
||||||
@@ -19,6 +24,7 @@ import { WorkspaceUnit } from '@affine/datacenter';
|
|||||||
import { useTranslation } from '@affine/i18n';
|
import { useTranslation } from '@affine/i18n';
|
||||||
import { PageListHeader } from '@/components/header';
|
import { PageListHeader } from '@/components/header';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
|
import { styled } from '@affine/component';
|
||||||
|
|
||||||
const useTabMap = () => {
|
const useTabMap = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -73,11 +79,48 @@ const useTabMap = () => {
|
|||||||
return { activeTabPanelRender, tableArr, handleTabChange, activeTab };
|
return { activeTabPanelRender, tableArr, handleTabChange, activeTab };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const StyledIndicator = styled.div(({ theme }) => {
|
||||||
|
return {
|
||||||
|
height: '2px',
|
||||||
|
background: theme.colors.primaryColor,
|
||||||
|
position: 'absolute',
|
||||||
|
left: '0',
|
||||||
|
bottom: '0',
|
||||||
|
transition: 'left .3s, width .3s',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const StyledTabButtonWrapper = styled.div(() => {
|
||||||
|
return {
|
||||||
|
display: 'flex',
|
||||||
|
position: 'relative',
|
||||||
|
};
|
||||||
|
});
|
||||||
const WorkspaceSetting = () => {
|
const WorkspaceSetting = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { currentWorkspace } = useAppState();
|
const { currentWorkspace } = useAppState();
|
||||||
const { activeTabPanelRender, tableArr, handleTabChange, activeTab } =
|
const { activeTabPanelRender, tableArr, handleTabChange, activeTab } =
|
||||||
useTabMap();
|
useTabMap();
|
||||||
|
const [indicatorState, setIndicatorState] = useState<
|
||||||
|
Pick<CSSProperties, 'left' | 'width'>
|
||||||
|
>({
|
||||||
|
left: 0,
|
||||||
|
width: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const tabButton = document.querySelector(
|
||||||
|
`[data-setting-tab-button="${activeTab}"]`
|
||||||
|
);
|
||||||
|
if (tabButton instanceof HTMLElement) {
|
||||||
|
startTransition(() => {
|
||||||
|
setIndicatorState({
|
||||||
|
width: `${tabButton.offsetWidth}px`,
|
||||||
|
left: `${tabButton.offsetLeft}px`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [activeTab]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
@@ -86,23 +129,23 @@ const WorkspaceSetting = () => {
|
|||||||
<PageListHeader icon={<SettingsIcon />}>{t('Settings')}</PageListHeader>
|
<PageListHeader icon={<SettingsIcon />}>{t('Settings')}</PageListHeader>
|
||||||
|
|
||||||
<StyledSettingContainer>
|
<StyledSettingContainer>
|
||||||
<StyledSettingSidebar>
|
<StyledTabButtonWrapper>
|
||||||
<StyledSettingTabContainer>
|
{tableArr.map(({ name }) => {
|
||||||
{tableArr.map(({ name }) => {
|
return (
|
||||||
return (
|
<WorkspaceSettingTagItem
|
||||||
<WorkspaceSettingTagItem
|
key={name}
|
||||||
key={name}
|
isActive={activeTab === name}
|
||||||
isActive={activeTab === name}
|
data-setting-tab-button={name}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleTabChange(name);
|
handleTabChange(name);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
</WorkspaceSettingTagItem>
|
</WorkspaceSettingTagItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</StyledSettingTabContainer>
|
<StyledIndicator style={indicatorState} />
|
||||||
</StyledSettingSidebar>
|
</StyledTabButtonWrapper>
|
||||||
|
|
||||||
<StyledSettingContent>
|
<StyledSettingContent>
|
||||||
{currentWorkspace && activeTabPanelRender?.(currentWorkspace)}
|
{currentWorkspace && activeTabPanelRender?.(currentWorkspace)}
|
||||||
|
|||||||
Reference in New Issue
Block a user