feat(core): adjust property table's style to match design (#10849)

This commit is contained in:
@@ -4,9 +4,9 @@ import { globalStyle, style } from '@vanilla-extract/css';
|
|||||||
|
|
||||||
export const propertyRoot = style({
|
export const propertyRoot = style({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
minHeight: 32,
|
gap: 4,
|
||||||
|
minHeight: 30,
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
padding: '2px 0px 2px 2px',
|
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
selectors: {
|
selectors: {
|
||||||
'&[draggable="true"]': {
|
'&[draggable="true"]': {
|
||||||
@@ -20,7 +20,7 @@ export const propertyRoot = style({
|
|||||||
display: 'block',
|
display: 'block',
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
cursor: 'grab',
|
cursor: 'grab',
|
||||||
top: '50%',
|
top: 15,
|
||||||
left: 0,
|
left: 0,
|
||||||
borderRadius: '2px',
|
borderRadius: '2px',
|
||||||
backgroundColor: cssVarV2('text/placeholder'),
|
backgroundColor: cssVarV2('text/placeholder'),
|
||||||
@@ -36,7 +36,7 @@ export const propertyRoot = style({
|
|||||||
display: 'block',
|
display: 'block',
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
cursor: 'grab',
|
cursor: 'grab',
|
||||||
top: '50%',
|
top: 15,
|
||||||
left: 0,
|
left: 0,
|
||||||
borderRadius: '2px',
|
borderRadius: '2px',
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
@@ -51,6 +51,11 @@ export const propertyRoot = style({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
export const propertyTableContent = style({
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: 8,
|
||||||
|
});
|
||||||
|
|
||||||
export const hide = style({
|
export const hide = style({
|
||||||
// Visually hide the property while maintaining its position in the layout.
|
// Visually hide the property while maintaining its position in the layout.
|
||||||
@@ -61,21 +66,24 @@ export const hide = style({
|
|||||||
padding: '0px',
|
padding: '0px',
|
||||||
visibility: 'hidden',
|
visibility: 'hidden',
|
||||||
pointerEvents: 'none',
|
pointerEvents: 'none',
|
||||||
|
position: 'absolute',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const propertyNameContainer = style({
|
export const propertyNameContainer = style({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
alignSelf: 'flex-start',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
justifyContent: 'start',
|
justifyContent: 'start',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
fontSize: cssVar('fontSm'),
|
fontSize: cssVar('fontSm'),
|
||||||
padding: `6px 6px 6px 4px`,
|
padding: `4px`,
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
lineHeight: '22px',
|
lineHeight: '22px',
|
||||||
userSelect: 'none',
|
userSelect: 'none',
|
||||||
color: cssVarV2('text/secondary'),
|
color: cssVarV2.text.tertiary,
|
||||||
width: '160px',
|
width: '160px',
|
||||||
|
height: 30,
|
||||||
selectors: {
|
selectors: {
|
||||||
'&[data-has-menu="true"]': {
|
'&[data-has-menu="true"]': {
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
@@ -121,7 +129,7 @@ export const propertyValueContainer = style({
|
|||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
fontSize: cssVar('fontSm'),
|
fontSize: cssVar('fontSm'),
|
||||||
lineHeight: '22px',
|
lineHeight: '22px',
|
||||||
padding: `6px`,
|
padding: `4px`,
|
||||||
flex: 1,
|
flex: 1,
|
||||||
':focus-visible': {
|
':focus-visible': {
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@@ -145,9 +153,9 @@ export const propertyValueContainer = style({
|
|||||||
export const tableButton = style({
|
export const tableButton = style({
|
||||||
alignSelf: 'flex-start',
|
alignSelf: 'flex-start',
|
||||||
fontSize: cssVar('fontSm'),
|
fontSize: cssVar('fontSm'),
|
||||||
color: `${cssVarV2('text/secondary')}`,
|
color: `${cssVarV2.text.tertiary}`,
|
||||||
padding: '0 6px',
|
padding: '0 8px 0px 4px',
|
||||||
height: 36,
|
height: 30,
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
gap: 6,
|
gap: 6,
|
||||||
'@media': {
|
'@media': {
|
||||||
@@ -174,14 +182,14 @@ export const sectionHeader = style({
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: 20,
|
gap: 20,
|
||||||
padding: '4px 6px',
|
padding: '4px',
|
||||||
minHeight: 30,
|
minHeight: 30,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const sectionHeaderTrigger = style({
|
export const sectionHeaderTrigger = style({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: 4,
|
gap: 6,
|
||||||
flex: 1,
|
flex: 1,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
});
|
});
|
||||||
@@ -223,7 +231,6 @@ export const sectionContent = style({
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
gap: 4,
|
gap: 4,
|
||||||
marginTop: 4,
|
|
||||||
selectors: {
|
selectors: {
|
||||||
'&[hidden]': {
|
'&[hidden]': {
|
||||||
display: 'none',
|
display: 'none',
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ export const PropertyCollapsibleContent = forwardRef<
|
|||||||
defaultCollapsed,
|
defaultCollapsed,
|
||||||
onCollapseChange,
|
onCollapseChange,
|
||||||
collapseButtonText,
|
collapseButtonText,
|
||||||
|
className,
|
||||||
...props
|
...props
|
||||||
},
|
},
|
||||||
ref
|
ref
|
||||||
@@ -179,6 +180,7 @@ export const PropertyCollapsibleContent = forwardRef<
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
data-property-collapsible={finalCollapsible}
|
data-property-collapsible={finalCollapsible}
|
||||||
data-property-collapsed={!finalShowAllHide}
|
data-property-collapsed={!finalShowAllHide}
|
||||||
|
className={clsx(styles.propertyTableContent, className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<PropertyTableContext.Provider value={contextValue}>
|
<PropertyTableContext.Provider value={contextValue}>
|
||||||
|
|||||||
@@ -121,9 +121,9 @@ export const actionContainer = style({
|
|||||||
|
|
||||||
export const propertyActionButton = style({
|
export const propertyActionButton = style({
|
||||||
fontSize: cssVar('fontSm'),
|
fontSize: cssVar('fontSm'),
|
||||||
color: `${cssVarV2('text/secondary')}`,
|
color: `${cssVarV2.text.tertiary}`,
|
||||||
padding: '0 6px',
|
padding: '0 4px',
|
||||||
height: 34,
|
height: 30,
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
gap: 6,
|
gap: 6,
|
||||||
width: '160px',
|
width: '160px',
|
||||||
|
|||||||
@@ -449,7 +449,9 @@ const DocPropertiesTableInner = ({
|
|||||||
onOpenChange={setExpanded}
|
onOpenChange={setExpanded}
|
||||||
/>
|
/>
|
||||||
<Collapsible.Content>
|
<Collapsible.Content>
|
||||||
<DocIntegrationPropertiesTable />
|
<DocIntegrationPropertiesTable
|
||||||
|
divider={<div className={styles.tableHeaderDivider} />}
|
||||||
|
/>
|
||||||
<DocWorkspacePropertiesTableBody
|
<DocWorkspacePropertiesTableBody
|
||||||
defaultOpen={
|
defaultOpen={
|
||||||
!defaultOpenProperty || defaultOpenProperty.type === 'workspace'
|
!defaultOpenProperty || defaultOpenProperty.type === 'workspace'
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
import {
|
import { notify, PropertyValue, type RadioItem } from '@affine/component';
|
||||||
notify,
|
|
||||||
PropertyValue,
|
|
||||||
RadioGroup,
|
|
||||||
type RadioItem,
|
|
||||||
} from '@affine/component';
|
|
||||||
import { DocService } from '@affine/core/modules/doc';
|
import { DocService } from '@affine/core/modules/doc';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import type { DocMode } from '@blocksuite/affine/model';
|
import type { DocMode } from '@blocksuite/affine/model';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
|
import { DocPropertyRadioGroup } from '../widgets/radio-group';
|
||||||
import * as styles from './doc-primary-mode.css';
|
import * as styles from './doc-primary-mode.css';
|
||||||
import type { PropertyValueProps } from './types';
|
import type { PropertyValueProps } from './types';
|
||||||
|
|
||||||
@@ -59,14 +55,11 @@ export const DocPrimaryModeValue = ({
|
|||||||
hoverable={false}
|
hoverable={false}
|
||||||
readonly={readonly}
|
readonly={readonly}
|
||||||
>
|
>
|
||||||
<RadioGroup
|
<DocPropertyRadioGroup
|
||||||
width={BUILD_CONFIG.isMobileEdition ? '100%' : 194}
|
|
||||||
itemHeight={24}
|
|
||||||
value={primaryMode}
|
value={primaryMode}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
items={DocModeItems}
|
items={DocModeItems}
|
||||||
disabled={readonly}
|
disabled={readonly}
|
||||||
className={styles.radioGroup}
|
|
||||||
/>
|
/>
|
||||||
</PropertyValue>
|
</PropertyValue>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { PropertyValue, RadioGroup, type RadioItem } from '@affine/component';
|
import { PropertyValue, type RadioItem } from '@affine/component';
|
||||||
import { DocService } from '@affine/core/modules/doc';
|
import { DocService } from '@affine/core/modules/doc';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
|
import { DocPropertyRadioGroup } from '../widgets/radio-group';
|
||||||
import * as styles from './edgeless-theme.css';
|
import * as styles from './edgeless-theme.css';
|
||||||
import type { PropertyValueProps } from './types';
|
import type { PropertyValueProps } from './types';
|
||||||
|
|
||||||
@@ -46,9 +47,7 @@ export const EdgelessThemeValue = ({
|
|||||||
hoverable={false}
|
hoverable={false}
|
||||||
readonly={readonly}
|
readonly={readonly}
|
||||||
>
|
>
|
||||||
<RadioGroup
|
<DocPropertyRadioGroup
|
||||||
width={BUILD_CONFIG.isMobileEdition ? '100%' : 194}
|
|
||||||
itemHeight={24}
|
|
||||||
value={edgelessTheme || 'system'}
|
value={edgelessTheme || 'system'}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
items={themeItems}
|
items={themeItems}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { cssVarV2 } from '@toeverything/theme/v2';
|
|||||||
import { style } from '@vanilla-extract/css';
|
import { style } from '@vanilla-extract/css';
|
||||||
|
|
||||||
export const property = style({
|
export const property = style({
|
||||||
padding: 4,
|
padding: '3px 4px',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const root = style({
|
export const root = style({
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { PropertyValue, RadioGroup, type RadioItem } from '@affine/component';
|
import { PropertyValue, type RadioItem } from '@affine/component';
|
||||||
import { DocService } from '@affine/core/modules/doc';
|
import { DocService } from '@affine/core/modules/doc';
|
||||||
import { EditorSettingService } from '@affine/core/modules/editor-setting';
|
import { EditorSettingService } from '@affine/core/modules/editor-setting';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
|
import { DocPropertyRadioGroup } from '../widgets/radio-group';
|
||||||
import { container } from './page-width.css';
|
import { container } from './page-width.css';
|
||||||
import type { PageLayoutMode, PropertyValueProps } from './types';
|
import type { PageLayoutMode, PropertyValueProps } from './types';
|
||||||
|
|
||||||
@@ -50,9 +51,7 @@ export const PageWidthValue = ({ readonly }: PropertyValueProps) => {
|
|||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<PropertyValue className={container} hoverable={false} readonly={readonly}>
|
<PropertyValue className={container} hoverable={false} readonly={readonly}>
|
||||||
<RadioGroup
|
<DocPropertyRadioGroup
|
||||||
width={BUILD_CONFIG.isMobileEdition ? '100%' : 194}
|
|
||||||
itemHeight={24}
|
|
||||||
value={radioValue}
|
value={radioValue}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
items={radioItems}
|
items={radioItems}
|
||||||
|
|||||||
@@ -2,10 +2,6 @@ import { style } from '@vanilla-extract/css';
|
|||||||
|
|
||||||
export const tagInlineEditor = style({
|
export const tagInlineEditor = style({
|
||||||
width: '100%',
|
width: '100%',
|
||||||
minHeight: 34,
|
|
||||||
padding: `6px`,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const container = style({
|
export const container = style({});
|
||||||
padding: '0px !important',
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { style } from '@vanilla-extract/css';
|
||||||
|
|
||||||
|
export const label = style({
|
||||||
|
fontWeight: 400,
|
||||||
|
});
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { RadioGroup, type RadioItem, type RadioProps } from '@affine/component';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
import * as styles from './radio-group.css';
|
||||||
|
|
||||||
|
export const DocPropertyRadioGroup = ({
|
||||||
|
width = 194,
|
||||||
|
items,
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
disabled,
|
||||||
|
}: Pick<RadioProps, 'items' | 'value' | 'onChange' | 'disabled' | 'width'>) => {
|
||||||
|
const finalItems = useMemo(
|
||||||
|
() =>
|
||||||
|
items.map(item => {
|
||||||
|
let finalItem: RadioItem = { value: '' };
|
||||||
|
if (typeof item === 'string') {
|
||||||
|
finalItem.label = item;
|
||||||
|
finalItem.value = item;
|
||||||
|
} else {
|
||||||
|
finalItem = { ...item };
|
||||||
|
finalItem.className = clsx(styles.label, item.className);
|
||||||
|
}
|
||||||
|
return finalItem;
|
||||||
|
}),
|
||||||
|
[items]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RadioGroup
|
||||||
|
width={BUILD_CONFIG.isMobileEdition ? '100%' : width}
|
||||||
|
itemHeight={20}
|
||||||
|
borderRadius={8}
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
items={finalItems}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -6,13 +6,17 @@ import {
|
|||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
import { useMemo } from 'react';
|
import { type ReactNode, useMemo } from 'react';
|
||||||
|
|
||||||
import { IntegrationPropertyService } from '../services/integration-property';
|
import { IntegrationPropertyService } from '../services/integration-property';
|
||||||
import type { IntegrationProperty } from '../type';
|
import type { IntegrationProperty } from '../type';
|
||||||
import { ValueRenderer } from './property-values';
|
import { ValueRenderer } from './property-values';
|
||||||
|
|
||||||
export const DocIntegrationPropertiesTable = () => {
|
export const DocIntegrationPropertiesTable = ({
|
||||||
|
divider,
|
||||||
|
}: {
|
||||||
|
divider?: ReactNode;
|
||||||
|
}) => {
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const integrationPropertyService = useService(IntegrationPropertyService);
|
const integrationPropertyService = useService(IntegrationPropertyService);
|
||||||
|
|
||||||
@@ -36,31 +40,37 @@ export const DocIntegrationPropertiesTable = () => {
|
|||||||
if (!schema || !integrationType) return null;
|
if (!schema || !integrationType) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PropertyCollapsibleSection
|
<>
|
||||||
title={t['com.affine.integration.properties']()}
|
<PropertyCollapsibleSection
|
||||||
>
|
title={t['com.affine.integration.properties']()}
|
||||||
<PropertyCollapsibleContent>
|
>
|
||||||
{properties.map(property => {
|
<PropertyCollapsibleContent>
|
||||||
const Icon = property.icon;
|
{properties.map(property => {
|
||||||
const key = property.key as string;
|
const Icon = property.icon;
|
||||||
const label = property.label;
|
const key = property.key as string;
|
||||||
const displayName =
|
const label = property.label;
|
||||||
typeof label === 'string'
|
const displayName =
|
||||||
? t[label]()
|
typeof label === 'string'
|
||||||
: t.t(label?.i18nKey, label?.options);
|
? t[label]()
|
||||||
|
: t.t(label?.i18nKey, label?.options);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PropertyRoot key={key}>
|
<PropertyRoot key={key}>
|
||||||
<PropertyName name={displayName} icon={Icon ? <Icon /> : null} />
|
<PropertyName
|
||||||
<ValueRenderer
|
name={displayName}
|
||||||
integration={integrationType}
|
icon={Icon ? <Icon /> : null}
|
||||||
type={property.type}
|
/>
|
||||||
propertyKey={key}
|
<ValueRenderer
|
||||||
/>
|
integration={integrationType}
|
||||||
</PropertyRoot>
|
type={property.type}
|
||||||
);
|
propertyKey={key}
|
||||||
})}
|
/>
|
||||||
</PropertyCollapsibleContent>
|
</PropertyRoot>
|
||||||
</PropertyCollapsibleSection>
|
);
|
||||||
|
})}
|
||||||
|
</PropertyCollapsibleContent>
|
||||||
|
</PropertyCollapsibleSection>
|
||||||
|
{divider}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user