From 71ab75e30eabdc45ccd260909cc5d86a879af126 Mon Sep 17 00:00:00 2001 From: CatsJuice Date: Thu, 28 Nov 2024 07:25:06 +0000 Subject: [PATCH] feat(mobile): mobile experimental feature setting (#8922) close AF-1802 ![CleanShot 2024-11-26 at 10.02.27.gif](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/LakojjjzZNf6ogjOVwKE/09d24e35-a524-497d-b5aa-840bf74f128f.gif) --- .../src/modules/feature-flag/constant.ts | 2 +- .../frontend/component/src/ui/modal/modal.tsx | 2 +- .../component/src/ui/modal/styles.css.ts | 25 +++++ .../component/src/ui/switch/index.css.ts | 26 +++-- .../component/src/ui/switch/switch.tsx | 33 ++++++- .../dialogs/setting/experimental/index.tsx | 96 +++++++++++++++++++ .../setting/experimental/styles.css.ts | 52 ++++++++++ .../core/src/mobile/dialogs/setting/index.tsx | 2 + .../src/mobile/dialogs/setting/row.layout.tsx | 8 +- .../src/mobile/dialogs/setting/style.css.ts | 2 + 10 files changed, 236 insertions(+), 12 deletions(-) create mode 100644 packages/frontend/core/src/mobile/dialogs/setting/experimental/index.tsx create mode 100644 packages/frontend/core/src/mobile/dialogs/setting/experimental/styles.css.ts diff --git a/packages/common/infra/src/modules/feature-flag/constant.ts b/packages/common/infra/src/modules/feature-flag/constant.ts index 385f935ae12cb..fd62fa098c8e7 100644 --- a/packages/common/infra/src/modules/feature-flag/constant.ts +++ b/packages/common/infra/src/modules/feature-flag/constant.ts @@ -174,7 +174,7 @@ export const AFFINE_FLAGS = { 'com.affine.settings.workspace.experimental-features.enable-theme-editor.name', description: 'com.affine.settings.workspace.experimental-features.enable-theme-editor.description', - configurable: isCanaryBuild, + configurable: isCanaryBuild && !isMobile, defaultState: isCanaryBuild, }, enable_local_workspace: { diff --git a/packages/frontend/component/src/ui/modal/modal.tsx b/packages/frontend/component/src/ui/modal/modal.tsx index cc6a2ab9d2caa..108796be25bd1 100644 --- a/packages/frontend/component/src/ui/modal/modal.tsx +++ b/packages/frontend/component/src/ui/modal/modal.tsx @@ -48,7 +48,7 @@ export interface ModalProps extends DialogProps { /** * @default 'fadeScaleTop' */ - animation?: 'fadeScaleTop' | 'none' | 'slideBottom'; + animation?: 'fadeScaleTop' | 'none' | 'slideBottom' | 'slideRight'; /** * Whether to show the modal in full screen mode */ diff --git a/packages/frontend/component/src/ui/modal/styles.css.ts b/packages/frontend/component/src/ui/modal/styles.css.ts index 15770ad02a062..88d8c03c87195 100644 --- a/packages/frontend/component/src/ui/modal/styles.css.ts +++ b/packages/frontend/component/src/ui/modal/styles.css.ts @@ -51,12 +51,23 @@ const contentHideSlideBottom = keyframes({ from: { transform: 'translateY(0)' }, to: { transform: 'translateY(100%)' }, }); +const contentShowSlideRight = keyframes({ + from: { transform: 'translateX(100%)' }, + to: { transform: 'translateX(0)' }, +}); +const contentHideSlideRight = keyframes({ + from: { transform: 'translateX(0)' }, + to: { transform: 'translateX(100%)' }, +}); const modalContentViewTransitionNameFadeScaleTop = generateIdentifier( 'modal-content-fade-scale-top' ); const modalContentViewTransitionNameSlideBottom = generateIdentifier( 'modal-content-slide-bottom' ); +const modalContentViewTransitionNameSlideRight = generateIdentifier( + 'modal-content-slide-right' +); export const modalOverlay = style({ position: 'fixed', inset: 0, @@ -105,6 +116,13 @@ export const modalContentWrapper = style({ [`${vtScopeSelector(modalVTScope)} &.anim-slideBottom.vt-active`]: { viewTransitionName: modalContentViewTransitionNameSlideBottom, }, + '&.anim-slideRight': { + animation: `${contentShowSlideRight} 0.23s ease`, + animationFillMode: 'forwards', + }, + [`${vtScopeSelector(modalVTScope)} &.anim-slideRight.vt-active`]: { + viewTransitionName: modalContentViewTransitionNameSlideRight, + }, }, }); globalStyle( @@ -121,6 +139,13 @@ globalStyle( animationFillMode: 'forwards', } ); +globalStyle( + `::view-transition-old(${modalContentViewTransitionNameSlideRight})`, + { + animation: `${contentHideSlideRight} 0.23s ease`, + animationFillMode: 'forwards', + } +); export const modalContent = style({ vars: { diff --git a/packages/frontend/component/src/ui/switch/index.css.ts b/packages/frontend/component/src/ui/switch/index.css.ts index 1c6b70212abbd..c5af1000b425b 100644 --- a/packages/frontend/component/src/ui/switch/index.css.ts +++ b/packages/frontend/component/src/ui/switch/index.css.ts @@ -1,6 +1,18 @@ import { cssVar } from '@toeverything/theme'; -import { style } from '@vanilla-extract/css'; +import { createVar, style } from '@vanilla-extract/css'; + +export const switchHeightVar = createVar('switchSize'); +export const switchPaddingVar = createVar('switchPadding'); +const switchWidthVar = createVar('switchWidth'); +const dotSizeVar = createVar('dotSize'); + export const labelStyle = style({ + vars: { + [switchHeightVar]: '26px', + [switchPaddingVar]: '3px', + [switchWidthVar]: `calc((${switchHeightVar} - ${switchPaddingVar}) * 2)`, + [dotSizeVar]: `calc(${switchHeightVar} - ${switchPaddingVar} * 2)`, + }, display: 'flex', alignItems: 'center', gap: '10px', @@ -12,8 +24,8 @@ export const inputStyle = style({ }); export const switchStyle = style({ position: 'relative', - width: '46px', - height: '26px', + height: switchHeightVar, + width: switchWidthVar, background: cssVar('toggleDisableBackgroundColor'), borderRadius: '37px', transition: '200ms all', @@ -22,12 +34,12 @@ export const switchStyle = style({ transition: 'all .2s cubic-bezier(0.27, 0.2, 0.25, 1.51)', content: '""', position: 'absolute', - width: '20px', - height: '20px', + width: dotSizeVar, + height: dotSizeVar, borderRadius: '50%', top: '50%', background: cssVar('toggleCircleBackgroundColor'), - transform: 'translate(3px, -50%)', + transform: `translate(${switchPaddingVar}, -50%)`, }, }, }); @@ -36,7 +48,7 @@ export const switchCheckedStyle = style({ selectors: { '&:before': { borderColor: cssVar('pureBlack10'), - transform: 'translate(23px,-50%)', + transform: `translate(calc(${switchHeightVar} - ${switchPaddingVar}), -50%)`, }, }, }); diff --git a/packages/frontend/component/src/ui/switch/switch.tsx b/packages/frontend/component/src/ui/switch/switch.tsx index b8a78ac9f7dae..f7b97df244d3c 100644 --- a/packages/frontend/component/src/ui/switch/switch.tsx +++ b/packages/frontend/component/src/ui/switch/switch.tsx @@ -1,7 +1,8 @@ // components/switch.tsx +import { assignInlineVars } from '@vanilla-extract/dynamic'; import clsx from 'clsx'; import type { HTMLAttributes, ReactNode } from 'react'; -import { useCallback, useState } from 'react'; +import { useCallback, useMemo, useState } from 'react'; import * as styles from './index.css'; @@ -10,6 +11,14 @@ export type SwitchProps = Omit, 'onChange'> & { onChange?: (checked: boolean) => void; children?: ReactNode; disabled?: boolean; + /** + * The height of the switch (including the padding) + */ + size?: number; + /** + * The padding of the switch + */ + padding?: number; }; export const Switch = ({ @@ -18,8 +27,13 @@ export const Switch = ({ children, className, disabled, + style, + size: propsSize, + padding: propsPadding, ...otherProps }: SwitchProps) => { + const size = propsSize ?? (BUILD_CONFIG.isMobileEdition ? 24 : 26); + const padding = propsPadding ?? (BUILD_CONFIG.isMobileEdition ? 2 : 3); const [checkedState, setCheckedState] = useState(checkedProp); const checked = onChangeProp ? checkedProp : checkedState; @@ -35,8 +49,23 @@ export const Switch = ({ [disabled, onChangeProp] ); + const labelStyle = useMemo( + () => ({ + ...assignInlineVars({ + [styles.switchHeightVar]: `${size}px`, + [styles.switchPaddingVar]: `${padding}px`, + }), + ...style, + }), + [size, padding, style] + ); + return ( -