feat(core): full width scroll area for plans (#4708)
This commit is contained in:
@@ -10,12 +10,18 @@ export const recurringRadioGroup = style({
|
|||||||
export const radioButtonDiscount = style({
|
export const radioButtonDiscount = style({
|
||||||
marginLeft: '4px',
|
marginLeft: '4px',
|
||||||
color: 'var(--affine-primary-color)',
|
color: 'var(--affine-primary-color)',
|
||||||
|
fontWeight: 400,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const planCardsWrapper = style({
|
export const planCardsWrapper = style({
|
||||||
|
marginLeft: 'calc(-1 * var(--setting-modal-gap-x))',
|
||||||
|
paddingLeft: 'var(--setting-modal-gap-x)',
|
||||||
|
paddingRight: 'calc(var(--setting-modal-gap-x) + 300px)',
|
||||||
|
width: 'var(--setting-modal-width)',
|
||||||
marginTop: '24px',
|
marginTop: '24px',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
overflowX: 'auto',
|
overflowX: 'auto',
|
||||||
|
scrollSnapType: 'x mandatory',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const planCard = style({
|
export const planCard = style({
|
||||||
@@ -24,11 +30,18 @@ export const planCard = style({
|
|||||||
borderRadius: '16px',
|
borderRadius: '16px',
|
||||||
padding: '20px',
|
padding: '20px',
|
||||||
border: '1px solid var(--affine-border-color)',
|
border: '1px solid var(--affine-border-color)',
|
||||||
|
position: 'relative',
|
||||||
|
|
||||||
selectors: {
|
selectors: {
|
||||||
'&:not(:last-child)': {
|
'&:not(:last-child)': {
|
||||||
marginRight: '16px',
|
marginRight: '16px',
|
||||||
},
|
},
|
||||||
|
'&::before': {
|
||||||
|
content: '',
|
||||||
|
position: 'absolute',
|
||||||
|
right: 'calc(100% + var(--setting-modal-gap-x))',
|
||||||
|
scrollSnapAlign: 'start',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -37,6 +50,7 @@ export const currentPlanCard = style([
|
|||||||
{
|
{
|
||||||
borderWidth: '2px',
|
borderWidth: '2px',
|
||||||
borderColor: 'var(--affine-primary-color)',
|
borderColor: 'var(--affine-primary-color)',
|
||||||
|
boxShadow: 'var(--affine-shadow-2)',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import { WorkspaceDetailSkeleton } from '@affine/component/setting-components';
|
|||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { ContactWithUsIcon } from '@blocksuite/icons';
|
import { ContactWithUsIcon } from '@blocksuite/icons';
|
||||||
import { Modal, type ModalProps } from '@toeverything/components/modal';
|
import { Modal, type ModalProps } from '@toeverything/components/modal';
|
||||||
import { Suspense, useCallback } from 'react';
|
import { debounce } from 'lodash-es';
|
||||||
|
import { Suspense, useCallback, useEffect, useRef } from 'react';
|
||||||
|
|
||||||
import { useCurrentLoginStatus } from '../../../hooks/affine/use-current-login-status';
|
import { useCurrentLoginStatus } from '../../../hooks/affine/use-current-login-status';
|
||||||
import { AccountSetting } from './account-setting';
|
import { AccountSetting } from './account-setting';
|
||||||
@@ -37,6 +38,39 @@ export const SettingModal = ({
|
|||||||
|
|
||||||
const generalSettingList = useGeneralSettingList();
|
const generalSettingList = useGeneralSettingList();
|
||||||
|
|
||||||
|
const modalContentRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!modalProps.open) return;
|
||||||
|
let animationFrameId: number;
|
||||||
|
const onResize = debounce(() => {
|
||||||
|
cancelAnimationFrame(animationFrameId);
|
||||||
|
animationFrameId = requestAnimationFrame(() => {
|
||||||
|
if (!modalContentRef.current) return;
|
||||||
|
|
||||||
|
const contentWidth = modalContentRef.current.offsetWidth;
|
||||||
|
const computedStyle = window.getComputedStyle(modalContentRef.current);
|
||||||
|
const marginX = parseInt(computedStyle.marginLeft, 10);
|
||||||
|
const paddingX = parseInt(computedStyle.paddingLeft, 10);
|
||||||
|
modalContentRef.current?.style.setProperty(
|
||||||
|
'--setting-modal-width',
|
||||||
|
`${contentWidth + marginX * 2 + paddingX * 2}px`
|
||||||
|
);
|
||||||
|
modalContentRef.current?.style.setProperty(
|
||||||
|
'--setting-modal-gap-x',
|
||||||
|
`${marginX + paddingX}px`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}, 200);
|
||||||
|
window.addEventListener('resize', onResize);
|
||||||
|
onResize();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
cancelAnimationFrame(animationFrameId);
|
||||||
|
window.removeEventListener('resize', onResize);
|
||||||
|
};
|
||||||
|
}, [modalProps.open]);
|
||||||
|
|
||||||
const onGeneralSettingClick = useCallback(
|
const onGeneralSettingClick = useCallback(
|
||||||
(key: GeneralSettingKeys) => {
|
(key: GeneralSettingKeys) => {
|
||||||
onSettingClick({
|
onSettingClick({
|
||||||
@@ -84,7 +118,11 @@ export const SettingModal = ({
|
|||||||
onAccountSettingClick={onAccountSettingClick}
|
onAccountSettingClick={onAccountSettingClick}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div data-testid="setting-modal-content" className={style.wrapper}>
|
<div
|
||||||
|
data-testid="setting-modal-content"
|
||||||
|
className={style.wrapper}
|
||||||
|
ref={modalContentRef}
|
||||||
|
>
|
||||||
<div className={style.content}>
|
<div className={style.content}>
|
||||||
{activeTab === 'workspace' && workspaceId ? (
|
{activeTab === 'workspace' && workspaceId ? (
|
||||||
<Suspense fallback={<WorkspaceDetailSkeleton />}>
|
<Suspense fallback={<WorkspaceDetailSkeleton />}>
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ export const wrapper = style({
|
|||||||
maxWidth: '560px',
|
maxWidth: '560px',
|
||||||
margin: '0 auto',
|
margin: '0 auto',
|
||||||
padding: '40px 15px 20px 15px',
|
padding: '40px 15px 20px 15px',
|
||||||
overflow: 'hidden auto',
|
|
||||||
|
|
||||||
// children
|
// children
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
|||||||
Reference in New Issue
Block a user