diff --git a/packages/frontend/component/src/ui/loading/loading.tsx b/packages/frontend/component/src/ui/loading/loading.tsx index 237f5c5fa1..ec0ebeaff7 100644 --- a/packages/frontend/component/src/ui/loading/loading.tsx +++ b/packages/frontend/component/src/ui/loading/loading.tsx @@ -1,3 +1,4 @@ +import { cssVarV2 } from '@toeverything/theme/v2'; import { assignInlineVars } from '@vanilla-extract/dynamic'; import clsx from 'clsx'; @@ -9,19 +10,23 @@ export interface LoadingProps { speed?: number; progress?: number; strokeColor?: string; + strokeWidth?: number; + className?: string; } export const Loading = ({ size, speed = 1.2, progress = 0.2, + strokeWidth = 4, strokeColor, + className, }: LoadingProps) => { // allow `string` such as `16px` | `100%` | `1em` const sizeWithUnit = size ? withUnit(size, 'px') : '16px'; return ( ; case 'workspace:license': return ; + case 'workspace:integrations': + return ; default: return null; } @@ -58,6 +63,11 @@ export const useWorkspaceSettingList = (): SettingSidebarItem[] => { const workspaceService = useService(WorkspaceService); const information = useWorkspaceInfo(workspaceService.workspace); const serverService = useService(ServerService); + const featureFlagService = useService(FeatureFlagService); + + const enableIntegration = useLiveData( + featureFlagService.flags.enable_integration.$ + ); const isSelfhosted = useLiveData( serverService.server.config$.selector( @@ -90,6 +100,12 @@ export const useWorkspaceSettingList = (): SettingSidebarItem[] => { icon: , testId: 'workspace-setting:members', }, + enableIntegration && { + key: 'workspace:integrations', + title: t['com.affine.integration.integrations'](), + icon: , + testId: 'workspace-setting:integrations', + }, { key: 'workspace:storage', title: t['Storage'](), @@ -109,7 +125,7 @@ export const useWorkspaceSettingList = (): SettingSidebarItem[] => { testId: 'workspace-setting:license', }, ].filter((item): item is SettingSidebarItem => !!item); - }, [showBilling, showLicense, t]); + }, [enableIntegration, showBilling, showLicense, t]); return items; }; diff --git a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/card.css.ts b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/card.css.ts new file mode 100644 index 0000000000..38df092106 --- /dev/null +++ b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/card.css.ts @@ -0,0 +1,71 @@ +import { cssVar } from '@toeverything/theme'; +import { cssVarV2 } from '@toeverything/theme/v2'; +import { style } from '@vanilla-extract/css'; + +import { spaceY } from './index.css'; + +export const card = style({ + padding: '8px 12px 12px 12px', + borderRadius: 8, + border: '1px solid ' + cssVarV2.layer.insideBorder.border, + height: 186, + display: 'flex', + flexDirection: 'column', + background: cssVarV2.layer.background.overlayPanel, +}); +export const cardHeader = style({ + display: 'flex', + alignItems: 'center', + gap: 8, + height: 42, + marginBottom: 4, +}); +export const cardIcon = style({ + width: 32, + height: 32, + borderRadius: 4, + background: cssVarV2.integrations.background.iconSolid, + boxShadow: cssVar('buttonShadow'), + border: `0.5px solid ${cssVarV2.layer.insideBorder.border}`, + fontSize: 24, + padding: 4, + lineHeight: 0, +}); +export const cardContent = style([ + spaceY, + { + display: 'flex', + flexDirection: 'column', + gap: 2, + }, +]); +export const cardTitle = style({ + fontSize: 14, + fontWeight: 500, + lineHeight: '22px', + color: cssVarV2.text.primary, +}); +export const cardDesc = style([ + spaceY, + { + fontSize: 12, + lineHeight: '20px', + fontWeight: 400, + color: cssVarV2.text.secondary, + }, +]); +export const cardFooter = style({ + display: 'flex', + alignItems: 'center', + gap: 8, + justifyContent: 'space-between', + selectors: { + '&:not(:empty)': { + marginTop: 8, + height: 28, + }, + }, +}); +export const settingIcon = style({ + color: cssVarV2.icon.secondary, +}); diff --git a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/card.tsx b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/card.tsx new file mode 100644 index 0000000000..1aa83adb5a --- /dev/null +++ b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/card.tsx @@ -0,0 +1,86 @@ +import { IconButton, type IconButtonProps } from '@affine/component'; +import { SettingsIcon } from '@blocksuite/icons/rc'; +import clsx from 'clsx'; +import type { HTMLAttributes, ReactNode } from 'react'; + +import { + card, + cardContent, + cardDesc, + cardFooter, + cardHeader, + cardIcon, + cardTitle, + settingIcon, +} from './card.css'; +import { spaceX } from './index.css'; + +export const IntegrationCard = ({ + className, + ...props +}: HTMLAttributes) => { + return
  • ; +}; + +export const IntegrationCardIcon = ({ + className, + ...props +}: HTMLAttributes) => { + return
    ; +}; + +export const IntegrationSettingIcon = ({ + className, + ...props +}: IconButtonProps) => { + return ( + } + variant="plain" + {...props} + /> + ); +}; + +export const IntegrationCardHeader = ({ + className, + icon, + onSettingClick, + ...props +}: HTMLAttributes & { + onSettingClick?: () => void; + icon?: ReactNode; +}) => { + return ( +
    + {icon} +
    + +
    + ); +}; + +export const IntegrationCardContent = ({ + className, + title, + desc, + ...props +}: HTMLAttributes & { + title?: string; + desc?: string; +}) => { + return ( +
    +
    {title}
    +
    {desc}
    +
    + ); +}; + +export const IntegrationCardFooter = ({ + className, + ...props +}: HTMLAttributes) => { + return