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