refactor(core): new workspace selector and create dialog (#10323)

This commit is contained in:
Cats Juice
2025-02-21 17:16:38 +08:00
committed by GitHub
parent 22e4bd8c20
commit 09cc5c392b
28 changed files with 760 additions and 563 deletions

View File

@@ -97,6 +97,8 @@ export const WorkspaceSelector = ({
...menuContentOptions,
style: {
width: '300px',
maxHeight: 'min(800px, calc(100vh - 200px))',
padding: 0,
...menuContentOptions?.style,
},
}}

View File

@@ -1,23 +1,5 @@
import { cssVar } from '@toeverything/theme';
import { style } from '@vanilla-extract/css';
export const ItemContainer = style({
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-start',
padding: '8px 14px',
gap: '14px',
cursor: 'pointer',
borderRadius: '8px',
transition: 'background-color 0.2s',
fontSize: '24px',
color: cssVar('iconSecondary'),
});
export const ItemText = style({
fontSize: cssVar('fontSm'),
lineHeight: '22px',
color: cssVar('textSecondaryColor'),
fontWeight: 400,
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
export const addServerDividerWrapper = style({
padding: '0px 12px',
});

View File

@@ -1,34 +1,50 @@
import { MenuItem } from '@affine/component/ui/menu';
import { Divider, MenuItem } from '@affine/component';
import { GlobalDialogService } from '@affine/core/modules/dialogs';
import { FeatureFlagService } from '@affine/core/modules/feature-flag';
import { useI18n } from '@affine/i18n';
import { PlusIcon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra';
import { useCallback } from 'react';
import * as styles from './index.css';
import {
ItemContainer,
ItemText,
prefixIcon,
} from '../add-workspace/index.css';
import { addServerDividerWrapper } from './index.css';
export const AddServer = ({ onAddServer }: { onAddServer?: () => void }) => {
export const AddServer = () => {
const t = useI18n();
const globalDialogService = useService(GlobalDialogService);
const featureFlagService = useService(FeatureFlagService);
const enableMultipleServer = useLiveData(
featureFlagService.flags.enable_multiple_cloud_servers.$
);
const onAddServer = useCallback(() => {
globalDialogService.open('sign-in', { step: 'addSelfhosted' });
}, [globalDialogService]);
if (!enableMultipleServer) {
return null;
}
return (
<div>
<>
<div className={addServerDividerWrapper}>
<Divider size="thinner" />
</div>
<MenuItem
block={true}
prefixIcon={<PlusIcon />}
prefixIconClassName={prefixIcon}
onClick={onAddServer}
data-testid="new-server"
className={styles.ItemContainer}
className={ItemContainer}
>
<div className={styles.ItemText}>
<div className={ItemText}>
{t['com.affine.workspaceList.addServer']()}
</div>
</MenuItem>
</div>
</>
);
};

View File

@@ -1,21 +1,28 @@
import { cssVar } from '@toeverything/theme';
import { cssVarV2 } from '@toeverything/theme/v2';
import { style } from '@vanilla-extract/css';
export const ItemContainer = style({
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-start',
padding: '8px 14px',
gap: '14px',
padding: '6px 16px 6px 11px',
gap: '12px',
cursor: 'pointer',
borderRadius: '8px',
transition: 'background-color 0.2s',
fontSize: '24px',
color: cssVar('iconSecondary'),
});
export const prefixIcon = style({
width: 24,
height: 24,
fontSize: 24,
color: cssVarV2.icon.secondary,
});
export const ItemText = style({
fontSize: cssVar('fontSm'),
lineHeight: '22px',
color: cssVar('textSecondaryColor'),
color: cssVarV2.text.secondary,
fontWeight: 400,
whiteSpace: 'nowrap',
overflow: 'hidden',

View File

@@ -20,11 +20,12 @@ export const AddWorkspace = ({
);
return (
<div>
<>
{BUILD_CONFIG.isElectron && (
<MenuItem
block={true}
prefixIcon={<ImportIcon />}
prefixIconClassName={styles.prefixIcon}
onClick={onAddWorkspace}
data-testid="add-workspace"
className={styles.ItemContainer}
@@ -37,6 +38,7 @@ export const AddWorkspace = ({
<MenuItem
block={true}
prefixIcon={<PlusIcon />}
prefixIconClassName={styles.prefixIcon}
onClick={onNewWorkspace}
data-testid="new-workspace"
className={styles.ItemContainer}
@@ -47,6 +49,6 @@ export const AddWorkspace = ({
: t['com.affine.workspaceList.addWorkspace.create-cloud']()}
</div>
</MenuItem>
</div>
</>
);
};

View File

@@ -1,10 +1,26 @@
import { cssVar } from '@toeverything/theme';
import { style } from '@vanilla-extract/css';
export const workspaceListWrapper = style({
export const workspaceScrollArea = style({
display: 'flex',
width: '100%',
flexDirection: 'column',
});
export const workspaceScrollAreaViewport = style({
padding: '10px 8px 0px 8px',
});
export const workspaceFooter = style({
padding: '0px 8px 10px 8px',
});
export const scrollbar = style({
width: 9,
padding: '0px 2px',
':hover': {
padding: 0,
},
});
export const scrollbarThumb = style({
width: 5,
});
export const signInWrapper = style({
display: 'flex',
width: '100%',

View File

@@ -1,3 +1,4 @@
import { ScrollableContainer } from '@affine/component';
import { MenuItem } from '@affine/component/ui/menu';
import { AuthService } from '@affine/core/modules/cloud';
import { GlobalDialogService } from '@affine/core/modules/dialogs';
@@ -9,7 +10,6 @@ import { Logo1Icon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra';
import { useCallback } from 'react';
import { AddServer } from './add-server';
import { AddWorkspace } from './add-workspace';
import * as styles from './index.css';
import { AFFiNEWorkspaceList } from './workspace-list';
@@ -58,7 +58,7 @@ interface UserWithWorkspaceListProps {
showEnableCloudButton?: boolean;
}
const UserWithWorkspaceListInner = ({
export const UserWithWorkspaceList = ({
onEventEnd,
onClickWorkspace,
onCreatedWorkspace,
@@ -109,26 +109,26 @@ const UserWithWorkspaceListInner = ({
onEventEnd?.();
}, [globalDialogService, onCreatedWorkspace, onEventEnd]);
const onAddServer = useCallback(() => {
globalDialogService.open('sign-in', { step: 'addSelfhosted' });
}, [globalDialogService]);
return (
<div className={styles.workspaceListWrapper}>
<AFFiNEWorkspaceList
onEventEnd={onEventEnd}
onClickWorkspace={onClickWorkspace}
showEnableCloudButton={showEnableCloudButton}
/>
<AddWorkspace
onAddWorkspace={onAddWorkspace}
onNewWorkspace={onNewWorkspace}
/>
<AddServer onAddServer={onAddServer} />
</div>
<>
<ScrollableContainer
className={styles.workspaceScrollArea}
viewPortClassName={styles.workspaceScrollAreaViewport}
scrollBarClassName={styles.scrollbar}
scrollThumbClassName={styles.scrollbarThumb}
>
<AFFiNEWorkspaceList
onEventEnd={onEventEnd}
onClickWorkspace={onClickWorkspace}
showEnableCloudButton={showEnableCloudButton}
/>
</ScrollableContainer>
<div className={styles.workspaceFooter}>
<AddWorkspace
onAddWorkspace={onAddWorkspace}
onNewWorkspace={onNewWorkspace}
/>
</div>
</>
);
};
export const UserWithWorkspaceList = (props: UserWithWorkspaceListProps) => {
return <UserWithWorkspaceListInner {...props} />;
};

View File

@@ -1,81 +1,73 @@
import { cssVar } from '@toeverything/theme';
import { cssVarV2 } from '@toeverything/theme/v2';
import { style } from '@vanilla-extract/css';
export const workspaceListsWrapper = style({
display: 'flex',
width: '100%',
flexDirection: 'column',
maxHeight: 'calc(100vh - 300px)',
});
export const workspaceListWrapper = style({
display: 'flex',
width: '100%',
flexDirection: 'column',
gap: 2,
});
export const workspaceServer = style({
display: 'flex',
justifyContent: 'space-between',
gap: 4,
paddingLeft: '12px',
marginBottom: '4px',
alignItems: 'center',
padding: '0px 8px',
gap: 8,
marginBottom: 6,
});
export const workspaceServerIcon = style({
border: `1px solid ${cssVarV2.layer.insideBorder.border}`,
borderRadius: 4,
color: cssVarV2.icon.primary,
fontSize: 18,
width: 30,
height: 30,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
});
export const workspaceServerContent = style({
display: 'flex',
flexDirection: 'column',
color: cssVarV2('text/secondary'),
gap: 4,
width: '100%',
overflow: 'hidden',
});
export const workspaceServerName = style({
display: 'flex',
alignItems: 'center',
gap: 4,
fontWeight: 500,
fontSize: cssVar('fontXs'),
lineHeight: '20px',
const ellipsis = style({
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
});
export const account = style({
fontSize: cssVar('fontXs'),
overflow: 'hidden',
width: '100%',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
});
export const workspaceTypeIcon = style({
color: cssVarV2('icon/primary'),
fontSize: '16px',
});
export const scrollbar = style({
width: '4px',
});
export const workspaceCard = style({
height: '44px',
padding: '0 12px',
export const workspaceServerAccount = style([
ellipsis,
{
fontSize: cssVar('fontXs'),
lineHeight: '20px',
color: cssVarV2.text.secondary,
marginTop: -1.5,
},
]);
export const workspaceServerName = style([
ellipsis,
{
fontSize: cssVar('fontXs'),
lineHeight: '20px',
fontWeight: 500,
color: cssVarV2.text.primary,
selectors: {
[`&:has(~ ${workspaceServerAccount})`]: {
marginBottom: -1.5,
},
},
},
]);
export const workspaceServerSpacer = style({
width: 0,
flexGrow: 1,
});
export const ItemContainer = style({
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-start',
padding: '8px 14px',
gap: '14px',
cursor: 'pointer',
borderRadius: '8px',
transition: 'background-color 0.2s',
fontSize: '24px',
color: cssVarV2('icon/secondary'),
export const workspaceCard = style({
height: 36,
padding: '7px 12px',
});
export const ItemText = style({
fontSize: cssVar('fontSm'),
lineHeight: '22px',
color: cssVarV2('text/secondary'),
fontWeight: 400,
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
export const workspaceCardInfoContainer = style({
gap: 12,
});
export const serverDivider = style({
marginTop: 8,
marginBottom: 12,
});

View File

@@ -1,14 +1,9 @@
import {
IconButton,
Menu,
MenuItem,
ScrollableContainer,
} from '@affine/component';
import { IconButton, Menu, MenuItem } from '@affine/component';
import { Divider } from '@affine/component/ui/divider';
import { useEnableCloud } from '@affine/core/components/hooks/affine/use-enable-cloud';
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
import { useNavigateHelper } from '@affine/core/components/hooks/use-navigate-helper';
import type { Server } from '@affine/core/modules/cloud';
import type { AuthAccountInfo, Server } from '@affine/core/modules/cloud';
import { AuthService, ServersService } from '@affine/core/modules/cloud';
import { GlobalDialogService } from '@affine/core/modules/dialogs';
import { GlobalContextService } from '@affine/core/modules/global-context';
@@ -17,14 +12,15 @@ import {
WorkspaceService,
WorkspacesService,
} from '@affine/core/modules/workspace';
import { ServerDeploymentType } from '@affine/graphql';
import { useI18n } from '@affine/i18n';
import {
AccountIcon,
CloudWorkspaceIcon,
DeleteIcon,
LocalWorkspaceIcon,
MoreHorizontalIcon,
PlusIcon,
TeamWorkspaceIcon,
SelfhostIcon,
SignOutIcon,
} from '@blocksuite/icons/rc';
import {
FrameworkScope,
@@ -35,6 +31,7 @@ import {
import { useCallback, useMemo } from 'react';
import { WorkspaceCard } from '../../workspace-card';
import { AddServer } from '../add-server';
import * as styles from './index.css';
interface WorkspaceModalProps {
@@ -46,6 +43,91 @@ interface WorkspaceModalProps {
onAddWorkspace: () => void;
}
const WorkspaceServerInfo = ({
server,
name,
account,
accountStatus,
onDeleteServer,
onSignOut,
onSignIn,
}: {
server: string;
name: string;
account?: AuthAccountInfo | null;
accountStatus?: 'authenticated' | 'unauthenticated';
onDeleteServer?: () => void;
onSignOut?: () => void;
onSignIn?: () => void;
}) => {
const t = useI18n();
const isCloud = server !== 'local';
const isAffineCloud = server === 'affine-cloud';
const Icon = isAffineCloud
? CloudWorkspaceIcon
: isCloud
? SelfhostIcon
: LocalWorkspaceIcon;
const menuItems = useMemo(
() =>
[
server !== 'affine-cloud' && server !== 'local' && (
<MenuItem
prefixIcon={<DeleteIcon />}
type="danger"
key="delete-server"
onClick={onDeleteServer}
>
{t['com.affine.server.delete']()}
</MenuItem>
),
accountStatus === 'authenticated' && (
<MenuItem
prefixIcon={<SignOutIcon />}
key="sign-out"
onClick={onSignOut}
type="danger"
>
{t['Sign out']()}
</MenuItem>
),
accountStatus === 'unauthenticated' && (
<MenuItem
prefixIcon={<AccountIcon />}
key="sign-in"
onClick={onSignIn}
>
{t['Sign in']()}
</MenuItem>
),
].filter(Boolean),
[accountStatus, onDeleteServer, onSignIn, onSignOut, server, t]
);
return (
<div className={styles.workspaceServer}>
<div className={styles.workspaceServerIcon}>
<Icon />
</div>
<div className={styles.workspaceServerContent}>
<div className={styles.workspaceServerName}>{name}</div>
{isCloud ? (
<div className={styles.workspaceServerAccount}>
{account ? account.email : 'Not signed in'}
</div>
) : null}
</div>
<div className={styles.workspaceServerSpacer} />
{menuItems.length ? (
<Menu items={menuItems}>
<IconButton icon={<MoreHorizontalIcon />} />
</Menu>
) : null}
</div>
);
};
const CloudWorkSpaceList = ({
server,
workspaces,
@@ -57,7 +139,6 @@ const CloudWorkSpaceList = ({
onClickWorkspace: (workspaceMetadata: WorkspaceMetadata) => void;
onClickEnableCloud?: (meta: WorkspaceMetadata) => void;
}) => {
const t = useI18n();
const globalContextService = useService(GlobalContextService);
const globalDialogService = useService(GlobalDialogService);
const serverName = useLiveData(server.config$.selector(c => c.serverName));
@@ -71,8 +152,6 @@ const CloudWorkSpaceList = ({
globalContextService.globalContext.workspaceFlavour.$
);
const serverType = server.config$.value.type;
const handleDeleteServer = useCallback(() => {
serversService.removeServer(server.id);
@@ -100,78 +179,23 @@ const CloudWorkSpaceList = ({
});
}, [globalDialogService, server.baseUrl]);
const onNewWorkspace = useCallback(() => {
globalDialogService.open(
'create-workspace',
{
serverId: server.id,
forcedCloud: true,
},
payload => {
if (payload) {
navigateHelper.openPage(payload.metadata.id, 'all');
}
}
);
}, [globalDialogService, navigateHelper, server.id]);
return (
<div className={styles.workspaceListWrapper}>
<div className={styles.workspaceServer}>
<div className={styles.workspaceServerContent}>
<div className={styles.workspaceServerName}>
{serverType === ServerDeploymentType.Affine ? (
<CloudWorkspaceIcon className={styles.workspaceTypeIcon} />
) : (
<TeamWorkspaceIcon className={styles.workspaceTypeIcon} />
)}
<div className={styles.account}>{serverName}</div>
</div>
<div className={styles.account}>
{account ? account.email : 'Not signed in'}
</div>
</div>
<Menu
items={[
server.id !== 'affine-cloud' && (
<MenuItem key="delete-server" onClick={handleDeleteServer}>
{t['com.affine.server.delete']()}
</MenuItem>
),
accountStatus === 'authenticated' && (
<MenuItem key="sign-out" onClick={handleSignOut}>
{t['Sign out']()}
</MenuItem>
),
accountStatus === 'unauthenticated' && (
<MenuItem key="sign-in" onClick={handleSignIn}>
{t['Sign in']()}
</MenuItem>
),
]}
>
<div>
<IconButton icon={<MoreHorizontalIcon />} />
</div>
</Menu>
</div>
<>
<WorkspaceServerInfo
server={server.id}
name={serverName}
account={account}
accountStatus={accountStatus}
onDeleteServer={handleDeleteServer}
onSignOut={handleSignOut}
onSignIn={handleSignIn}
/>
<WorkspaceList
items={workspaces}
onClick={onClickWorkspace}
onEnableCloudClick={onClickEnableCloud}
/>
<MenuItem
block={true}
prefixIcon={<PlusIcon />}
onClick={onNewWorkspace}
className={styles.ItemContainer}
>
<div className={styles.ItemText}>
{t['com.affine.workspaceList.addWorkspace.create']()}
</div>
</MenuItem>
</div>
</>
);
};
@@ -186,25 +210,18 @@ const LocalWorkspaces = ({
return null;
}
return (
<div className={styles.workspaceListWrapper}>
<div className={styles.workspaceServer}>
<div className={styles.workspaceServerName}>
<LocalWorkspaceIcon
width={14}
height={14}
className={styles.workspaceTypeIcon}
/>
{t['com.affine.workspaceList.workspaceListType.local']()}
</div>
</div>
<>
<WorkspaceServerInfo
server="local"
name={t['com.affine.workspaceList.workspaceListType.local']()}
/>
<WorkspaceList
items={workspaces}
onClick={onClickWorkspace}
onSettingClick={onClickWorkspaceSetting}
onEnableCloudClick={onClickEnableCloud}
/>
<Divider size="thinner" />
</div>
</>
);
};
@@ -224,6 +241,14 @@ export const AFFiNEWorkspaceList = ({
const serversService = useService(ServersService);
const servers = useLiveData(serversService.servers$);
const affineCloudServer = useMemo(
() => servers.find(s => s.id === 'affine-cloud') as Server,
[servers]
);
const selfhostServers = useMemo(
() => servers.filter(s => s.id !== 'affine-cloud'),
[servers]
);
const cloudWorkspaces = useMemo(
() =>
@@ -262,24 +287,26 @@ export const AFFiNEWorkspaceList = ({
);
return (
<ScrollableContainer
className={styles.workspaceListsWrapper}
scrollBarClassName={styles.scrollbar}
>
<div>
{servers.map(server => (
<FrameworkScope key={server.id} scope={server.scope}>
<CloudWorkSpaceList
server={server}
workspaces={cloudWorkspaces.filter(
({ flavour }) => flavour === server.id
)}
onClickWorkspace={handleClickWorkspace}
/>
<Divider size="thinner" />
</FrameworkScope>
<>
{/* 1. affine-cloud */}
<FrameworkScope
key={affineCloudServer.id}
scope={affineCloudServer.scope}
>
<CloudWorkSpaceList
server={affineCloudServer}
workspaces={cloudWorkspaces.filter(
({ flavour }) => flavour === affineCloudServer.id
)}
onClickWorkspace={handleClickWorkspace}
/>
</FrameworkScope>
{localWorkspaces.length > 0 ||
(selfhostServers.length > 0 && (
<Divider size="thinner" className={styles.serverDivider} />
))}
</div>
{/* 2. local */}
<LocalWorkspaces
workspaces={localWorkspaces}
onClickWorkspace={handleClickWorkspace}
@@ -287,7 +314,28 @@ export const AFFiNEWorkspaceList = ({
showEnableCloudButton ? onClickEnableCloud : undefined
}
/>
</ScrollableContainer>
{selfhostServers.length > 0 && (
<Divider size="thinner" className={styles.serverDivider} />
)}
{/* 3. selfhost */}
{selfhostServers.map((server, index) => (
<FrameworkScope key={server.id} scope={server.scope}>
<CloudWorkSpaceList
server={server}
workspaces={cloudWorkspaces.filter(
({ flavour }) => flavour === server.id
)}
onClickWorkspace={handleClickWorkspace}
/>
{index !== selfhostServers.length - 1 && (
<Divider size="thinner" className={styles.serverDivider} />
)}
</FrameworkScope>
))}
<AddServer />
<Divider size="thinner" />
</>
);
};
@@ -317,9 +365,10 @@ const SortableWorkspaceItem = ({
return (
<WorkspaceCard
className={styles.workspaceCard}
infoClassName={styles.workspaceCardInfoContainer}
workspaceMetadata={workspaceMetadata}
onClick={handleClick}
avatarSize={28}
avatarSize={22}
active={currentWorkspace?.id === workspaceMetadata.id}
onClickOpenSettings={onSettingClick}
onClickEnableCloud={onEnableCloudClick}

View File

@@ -249,6 +249,7 @@ export const WorkspaceCard = forwardRef<
hideCollaborationIcon?: boolean;
hideTeamWorkspaceIcon?: boolean;
active?: boolean;
infoClassName?: string;
onClickOpenSettings?: (workspaceMetadata: WorkspaceMetadata) => void;
onClickEnableCloud?: (workspaceMetadata: WorkspaceMetadata) => void;
}
@@ -262,6 +263,7 @@ export const WorkspaceCard = forwardRef<
onClickOpenSettings,
onClickEnableCloud,
className,
infoClassName,
disable,
hideCollaborationIcon,
hideTeamWorkspaceIcon,
@@ -296,7 +298,7 @@ export const WorkspaceCard = forwardRef<
ref={ref}
{...props}
>
<div className={styles.infoContainer}>
<div className={clsx(styles.infoContainer, infoClassName)}>
{information ? (
<WorkspaceAvatar
meta={workspaceMetadata}
@@ -332,34 +334,35 @@ export const WorkspaceCard = forwardRef<
Enable Cloud
</Button>
) : null}
{hideCollaborationIcon || information?.isOwner ? null : (
<Tooltip
content={t['com.affine.settings.workspace.state.joined']()}
>
<CollaborationIcon className={styles.collaborationIcon} />
</Tooltip>
)}
{hideTeamWorkspaceIcon || !information?.isTeam ? null : (
<Tooltip
content={t['com.affine.settings.workspace.state.team']()}
>
<TeamWorkspaceIcon className={styles.collaborationIcon} />
</Tooltip>
)}
{onClickOpenSettings && (
<div className={styles.settingButton} onClick={onOpenSettings}>
<SettingsIcon width={16} height={16} />
</div>
)}
</div>
{showArrowDownIcon && <ArrowDownSmallIcon />}
</div>
{active && (
<div className={styles.activeContainer}>
<DoneIcon className={styles.activeIcon} />
</div>
)}
<div className={styles.suffixIcons}>
{hideCollaborationIcon || information?.isOwner ? null : (
<Tooltip
content={t['com.affine.settings.workspace.state.joined']()}
>
<CollaborationIcon className={styles.collaborationIcon} />
</Tooltip>
)}
{hideTeamWorkspaceIcon || !information?.isTeam ? null : (
<Tooltip content={t['com.affine.settings.workspace.state.team']()}>
<TeamWorkspaceIcon className={styles.collaborationIcon} />
</Tooltip>
)}
{active && (
<div className={styles.activeContainer}>
<DoneIcon className={styles.activeIcon} />
</div>
)}
{showArrowDownIcon && <ArrowDownSmallIcon />}
</div>
</div>
);
}

View File

@@ -19,6 +19,7 @@ export const container = style({
width: '100%',
maxWidth: 500,
color: cssVarV2('text/primary'),
overflow: 'hidden',
':hover': {
cursor: 'pointer',
background: cssVar('hoverColor'),
@@ -34,6 +35,7 @@ export const infoContainer = style({
});
export const activeContainer = style({
flexShrink: 0,
lineHeight: 0,
});
export const disable = style({
@@ -187,6 +189,9 @@ export const showOnCardHover = style({
[`.${container}:hover &`]: {
position: 'relative',
},
'&:empty': {
display: 'none',
},
},
});
@@ -194,3 +199,14 @@ export const activeIcon = style({
fontSize: 14,
color: cssVarV2('icon/activated'),
});
export const suffixIcons = style({
display: 'flex',
gap: 8,
alignItems: 'center',
selectors: {
'&:empty': {
display: 'none',
},
},
});