fix(mobile): progress styles (#9001)

fix AF-1875, fix AF-1878, fix AF-1879
This commit is contained in:
pengx17
2024-12-04 06:56:33 +00:00
parent 82d133d64d
commit e4f94c7e3f
8 changed files with 64 additions and 112 deletions

View File

@@ -33,13 +33,15 @@ export const sliderRoot = style({
}); });
export const thumb = style({ export const thumb = style({
width: '4px', width: 28,
height: `calc(${progressHeight} + 2px)`, height: 28,
transform: 'translateY(-1px)', transform: 'translate(1px, -9px)',
borderRadius: '2px', borderRadius: '50%',
display: 'block', display: 'block',
background: cssVarV2('layer/insideBorder/primaryBorder'), background: cssVarV2('layer/background/primary'),
boxShadow: cssVar('overlayPanelShadow'),
opacity: 0, opacity: 0,
transition: 'opacity 0.1s ease-in-out',
selectors: { selectors: {
[`${root}:hover &, &:is(:focus-visible, :focus-within)`]: { [`${root}:hover &, &:is(:focus-visible, :focus-within)`]: {
opacity: 1, opacity: 1,
@@ -50,6 +52,7 @@ export const thumb = style({
export const label = style({ export const label = style({
width: '40px', width: '40px',
fontSize: cssVar('fontSm'), fontSize: cssVar('fontSm'),
textAlign: 'right',
}); });
export const indicator = style({ export const indicator = style({

View File

@@ -63,10 +63,16 @@ export const DocPropertyIconSelector = ({
return ( return (
<Menu <Menu
items={ items={
<IconsSelectorPanel <div
selectedIcon={propertyInfo.icon} style={{
onSelectedChange={onSelectedChange} padding: BUILD_CONFIG.isMobileEdition ? '0 20px' : undefined,
/> }}
>
<IconsSelectorPanel
selectedIcon={propertyInfo.icon}
onSelectedChange={onSelectedChange}
/>
</div>
} }
> >
<div className={styles.iconSelectorButton}> <div className={styles.iconSelectorButton}>

View File

@@ -1,6 +1,5 @@
import { PropertyValue } from '@affine/component'; import { PropertyValue } from '@affine/component';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import { NumberIcon } from '@blocksuite/icons/rc';
import { import {
type ChangeEventHandler, type ChangeEventHandler,
useCallback, useCallback,
@@ -8,11 +7,10 @@ import {
useState, useState,
} from 'react'; } from 'react';
import { ConfigModal } from '../../mobile';
import * as styles from './number.css'; import * as styles from './number.css';
import type { PropertyValueProps } from './types'; import type { PropertyValueProps } from './types';
const DesktopNumberValue = ({ value, onChange }: PropertyValueProps) => { export const NumberValue = ({ value, onChange }: PropertyValueProps) => {
const parsedValue = isNaN(Number(value)) ? null : value; const parsedValue = isNaN(Number(value)) ? null : value;
const [tempValue, setTempValue] = useState(parsedValue); const [tempValue, setTempValue] = useState(parsedValue);
const handleBlur = useCallback( const handleBlur = useCallback(
@@ -51,80 +49,3 @@ const DesktopNumberValue = ({ value, onChange }: PropertyValueProps) => {
</PropertyValue> </PropertyValue>
); );
}; };
const MobileNumberValue = ({
value,
onChange,
propertyInfo,
}: PropertyValueProps) => {
const parsedValue = isNaN(Number(value)) ? null : value;
const [tempValue, setTempValue] = useState(parsedValue);
const handleBlur = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
onChange(e.target.value.trim());
},
[onChange]
);
const handleOnChange: ChangeEventHandler<HTMLInputElement> = useCallback(
e => {
setTempValue(e.target.value.trim());
},
[]
);
const t = useI18n();
useEffect(() => {
setTempValue(parsedValue);
}, [parsedValue]);
const [open, setOpen] = useState(false);
const onClose = useCallback(() => {
setOpen(false);
onChange(tempValue);
}, [onChange, tempValue]);
return (
<>
<PropertyValue
className={styles.numberPropertyValueContainer}
isEmpty={!parsedValue}
onClick={() => {
setOpen(true);
}}
>
<div className={styles.mobileNumberPropertyValueInput}>
{value ||
t['com.affine.page-properties.property-value-placeholder']()}
</div>
</PropertyValue>
<ConfigModal
open={open}
variant="popup"
onDone={onClose}
onOpenChange={setOpen}
title={
<>
<NumberIcon className={styles.numberIcon} />
{propertyInfo?.name}
</>
}
>
<input
className={styles.mobileNumberPropertyValueInput}
type="number"
inputMode="decimal"
value={tempValue || ''}
onChange={handleOnChange}
onBlur={handleBlur}
data-empty={!tempValue}
placeholder={t[
'com.affine.page-properties.property-value-placeholder'
]()}
/>
</ConfigModal>
</>
);
};
export const NumberValue = BUILD_CONFIG.isMobileEdition
? MobileNumberValue
: DesktopNumberValue;

View File

@@ -83,13 +83,15 @@ export const ConfigModal = ({
)} )}
{children} {children}
{variant === 'popup' && onDone ? ( {variant === 'popup' && onDone ? (
<Button <div className={styles.bottomDoneButtonContainer}>
variant="primary" <Button
className={styles.bottomDoneButton} variant="primary"
onClick={onDone} className={styles.bottomDoneButton}
> onClick={onDone}
{t['Done']()} >
</Button> {t['Done']()}
</Button>
</div>
) : null} ) : null}
</div> </div>
</Modal> </Modal>

View File

@@ -11,7 +11,9 @@ export const pageModalContent = style({
backgroundColor: cssVarV2('layer/background/secondary'), backgroundColor: cssVarV2('layer/background/secondary'),
}); });
export const popupModalContent = style({}); export const popupModalContent = style({
padding: '12px',
});
export const pageTitle = style([ export const pageTitle = style([
bodyEmphasized, bodyEmphasized,
@@ -30,6 +32,8 @@ export const popupTitle = style([
alignItems: 'center', alignItems: 'center',
gap: 8, gap: 8,
color: cssVarV2('text/primary'), color: cssVarV2('text/primary'),
padding: '0 8px',
height: 44,
}, },
]); ]);
@@ -43,7 +47,7 @@ export const pageContent = style({
export const popupContent = style({ export const popupContent = style({
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
gap: 16, gap: 24,
}); });
export const doneButton = style([ export const doneButton = style([
@@ -53,8 +57,15 @@ export const doneButton = style([
}, },
]); ]);
export const bottomDoneButtonContainer = style({
padding: '4px',
});
export const bottomDoneButton = style({ export const bottomDoneButton = style({
width: '100%', width: '100%',
height: 44,
fontSize: 17,
alignSelf: 'center',
}); });
export const group = style({ export const group = style({

View File

@@ -0,0 +1,8 @@
import { cssVarV2 } from '@toeverything/theme/v2';
import { style } from '@vanilla-extract/css';
export const progressIcon = style({
color: cssVarV2('icon/primary'),
width: 20,
height: 20,
});

View File

@@ -6,6 +6,7 @@ import { useLiveData } from '@toeverything/infra';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import type { DatabaseCellRendererProps } from '../../../types'; import type { DatabaseCellRendererProps } from '../../../types';
import * as styles from './progress.css';
const DesktopProgressCell = ({ const DesktopProgressCell = ({
cell, cell,
@@ -14,15 +15,14 @@ const DesktopProgressCell = ({
onChange, onChange,
}: DatabaseCellRendererProps) => { }: DatabaseCellRendererProps) => {
const value = useLiveData(cell.value$ as LiveData<number>); const value = useLiveData(cell.value$ as LiveData<number>);
const isEmpty = value === undefined; const [localValue, setLocalValue] = useState(value || 0);
const [localValue, setLocalValue] = useState(value);
useEffect(() => { useEffect(() => {
setLocalValue(value); setLocalValue(value || 0);
}, [value]); }, [value]);
return ( return (
<PropertyValue isEmpty={isEmpty} hoverable={false}> <PropertyValue hoverable={false}>
<Progress <Progress
value={localValue} value={localValue}
onChange={v => { onChange={v => {
@@ -44,11 +44,10 @@ const MobileProgressCell = ({
onChange, onChange,
}: DatabaseCellRendererProps) => { }: DatabaseCellRendererProps) => {
const value = useLiveData(cell.value$ as LiveData<number>); const value = useLiveData(cell.value$ as LiveData<number>);
const isEmpty = value === undefined; const [localValue, setLocalValue] = useState(value || 0);
const [localValue, setLocalValue] = useState(value);
useEffect(() => { useEffect(() => {
setLocalValue(value); setLocalValue(value || 0);
}, [value]); }, [value]);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
@@ -62,12 +61,8 @@ const MobileProgressCell = ({
return ( return (
<> <>
<PropertyValue <PropertyValue hoverable={false} onClick={() => setOpen(true)}>
isEmpty={isEmpty} <Progress value={value || 0} />
hoverable={false}
onClick={() => setOpen(true)}
>
<Progress value={value} />
</PropertyValue> </PropertyValue>
<ConfigModal <ConfigModal
@@ -77,7 +72,7 @@ const MobileProgressCell = ({
onDone={commitChange} onDone={commitChange}
title={ title={
<> <>
<ProgressIcon /> <ProgressIcon className={styles.progressIcon} />
{name} {name}
</> </>
} }

View File

@@ -268,6 +268,7 @@ export type ErrorDataUnion =
| DocAccessDeniedDataType | DocAccessDeniedDataType
| DocHistoryNotFoundDataType | DocHistoryNotFoundDataType
| DocNotFoundDataType | DocNotFoundDataType
| InvalidEmailDataType
| InvalidHistoryTimestampDataType | InvalidHistoryTimestampDataType
| InvalidPasswordLengthDataType | InvalidPasswordLengthDataType
| InvalidRuntimeConfigTypeDataType | InvalidRuntimeConfigTypeDataType
@@ -387,6 +388,11 @@ export interface HumanReadableQuotaType {
storageQuota: Scalars['String']['output']; storageQuota: Scalars['String']['output'];
} }
export interface InvalidEmailDataType {
__typename?: 'InvalidEmailDataType';
email: Scalars['String']['output'];
}
export interface InvalidHistoryTimestampDataType { export interface InvalidHistoryTimestampDataType {
__typename?: 'InvalidHistoryTimestampDataType'; __typename?: 'InvalidHistoryTimestampDataType';
timestamp: Scalars['String']['output']; timestamp: Scalars['String']['output'];