fix(mobile): progress styles (#9001)
fix AF-1875, fix AF-1878, fix AF-1879
This commit is contained in:
@@ -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({
|
||||||
|
|||||||
@@ -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}>
|
||||||
|
|||||||
@@ -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;
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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({
|
||||||
|
|||||||
@@ -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,
|
||||||
|
});
|
||||||
@@ -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}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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'];
|
||||||
|
|||||||
Reference in New Issue
Block a user