refactor(component): refactor the implementation of Button and IconButton (#7716)

## Button
- Remove props withoutHoverStyle
   refactor hover impl with independent layer, so that hover-color won't affect the background even if is overridden outside
- Update `type` (renamed to `variant`):
  - remove `processing` and `warning`
  - rename `default` with `secondary`
- Remove `shape` props
- Remove `icon` and `iconPosition`, replaced with `prefix: ReactNode` and `suffix: ReactNode`
- Integrate tooltip for more convenient usage
- New Storybook document
- Focus style

## IconButton
- A Wrapper base on `<Button />`
- Override Button size and variant
  - size: `'12' | '14' | '16' | '20' | '24' | number`
     These presets size are referenced from the design system.
  - variant:  `'plain' | 'solid' | 'danger' | 'custom'`
- Inset icon via Button 's prefix

## Fix
- fix some button related issues
- close AF-1159, AF-1160, AF-1161, AF-1162, AF-1163, AF-1158, AF-1157

## Storybook

![CleanShot 2024-08-03 at 14.57.20@2x.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/LakojjjzZNf6ogjOVwKE/f5a76110-35d0-4082-a940-efc12bed87b0.png)
This commit is contained in:
CatsJuice
2024-08-05 02:57:23 +00:00
parent 10deed94e3
commit 3d855647c7
159 changed files with 1384 additions and 1539 deletions

View File

@@ -32,7 +32,7 @@ export const AdminPanelHeader = ({
</div>
<div>
<Button
type="primary"
variant="primary"
disabled={modifiedValues.length === 0}
onClick={() => {
openConfirmModal({
@@ -41,7 +41,7 @@ export const AdminPanelHeader = ({
'Are you sure you want to save the following changes?',
confirmText: 'Save',
confirmButtonOptions: {
type: 'primary',
variant: 'primary',
},
onConfirm: onConfirm,
children:

View File

@@ -81,7 +81,7 @@ export const ErrorDetail: FC<ErrorDetailProps> = props => {
))}
<div className={styles.errorFooter}>
<Button
type="primary"
variant="primary"
onClick={onBtnClick}
loading={isBtnLoading}
size="extraLarge"

View File

@@ -21,7 +21,6 @@ export const thumbContent = style({
});
export const actionButton = style({
fontWeight: 500,
fontSize: cssVar('fontSm'),
lineHeight: '22px',
});

View File

@@ -103,7 +103,7 @@ export const AIOnboardingEdgeless = () => {
notify.dismiss(id);
toggleEdgelessAIOnboarding(false);
}}
type="plain"
variant="plain"
className={styles.actionButton}
>
<span className={styles.getStartedButtonText}>
@@ -113,7 +113,7 @@ export const AIOnboardingEdgeless = () => {
{aiSubscription ? null : (
<Button
className={styles.actionButton}
type="plain"
variant="plain"
onClick={() => {
goToPricingPlans();
notify.dismiss(id);

View File

@@ -114,17 +114,3 @@ export const subscribeActions = style({
gap: 12,
alignItems: 'center',
});
export const baseActionButton = style({
fontSize: cssVar('fontBase'),
selectors: {
'&.large': {
fontWeight: 500,
},
},
});
export const transparentActionButton = style([
baseActionButton,
{
backgroundColor: 'transparent',
},
]);

View File

@@ -243,36 +243,26 @@ export const AIOnboardingGeneral = () => {
>
{isLast ? (
<>
<IconButton
size="default"
icon={<ArrowLeftSmallIcon width={20} height={20} />}
onClick={onPrev}
type="plain"
className={styles.baseActionButton}
/>
<IconButton size="20" onClick={onPrev}>
<ArrowLeftSmallIcon />
</IconButton>
{aiSubscription ? (
<Button
className={styles.baseActionButton}
size="large"
onClick={closeAndDismiss}
type="primary"
variant="primary"
>
{t['com.affine.ai-onboarding.general.get-started']()}
</Button>
) : (
<div className={styles.subscribeActions}>
<Button
className={styles.baseActionButton}
size="large"
onClick={goToPricingPlans}
>
<Button size="large" onClick={goToPricingPlans}>
{t['com.affine.ai-onboarding.general.purchase']()}
</Button>
<Button
className={styles.baseActionButton}
size="large"
onClick={closeAndDismiss}
type="primary"
variant="primary"
>
{t['com.affine.ai-onboarding.general.try-for-free']()}
</Button>
@@ -282,21 +272,15 @@ export const AIOnboardingGeneral = () => {
) : (
<>
{isFirst ? (
<Button
className={styles.transparentActionButton}
onClick={remindLater}
size="large"
type="default"
>
<Button onClick={remindLater} size="large">
{t['com.affine.ai-onboarding.general.skip']()}
</Button>
) : (
<Button
icon={<ArrowLeftSmallIcon />}
className={styles.baseActionButton}
prefix={<ArrowLeftSmallIcon />}
onClick={onPrev}
type="plain"
size="large"
variant="plain"
>
{t['com.affine.ai-onboarding.general.prev']()}
</Button>
@@ -305,12 +289,7 @@ export const AIOnboardingGeneral = () => {
<div>
{index + 1} / {list.length}
</div>
<Button
className={styles.baseActionButton}
size="large"
type="primary"
onClick={onNext}
>
<Button size="large" variant="primary" onClick={onNext}>
{t['com.affine.ai-onboarding.general.next']()}
</Button>
</div>

View File

@@ -41,7 +41,7 @@ const FooterActions = ({ onDismiss }: { onDismiss: () => void }) => {
<a href="https://ai.affine.pro" target="_blank" rel="noreferrer">
<Button
className={styles.actionButton}
type="plain"
variant="plain"
onClick={onDismiss}
>
{t['com.affine.ai-onboarding.local.action-learn-more']()}
@@ -50,7 +50,7 @@ const FooterActions = ({ onDismiss }: { onDismiss: () => void }) => {
{loggedIn ? null : (
<Button
className={styles.actionButton}
type="plain"
variant="plain"
onClick={() => {
onDismiss();
jumpToSignIn('', RouteLogic.REPLACE, {}, { initCloud: 'true' });

View File

@@ -99,7 +99,7 @@ export const AfterSignInSendEmail = ({
<Button
style={!verifyToken ? { cursor: 'not-allowed' } : {}}
disabled={!verifyToken || isSending}
type="plain"
variant="plain"
size="large"
onClick={onResendClick}
>

View File

@@ -91,7 +91,7 @@ export const AfterSignUpSendEmail: FC<AuthPanelProps> = ({
<Button
style={!verifyToken ? { cursor: 'not-allowed' } : {}}
disabled={!verifyToken || isSending}
type="plain"
variant="plain"
size="large"
onClick={onResendClick}
>

View File

@@ -27,7 +27,7 @@ export const AiLoginRequiredModal = () => {
},
confirmText: t['com.affine.ai.login-required.dialog-confirm'](),
confirmButtonOptions: {
type: 'primary',
variant: 'primary',
},
cancelText: t['com.affine.ai.login-required.dialog-cancel'](),
onOpenChange: setOpen,

View File

@@ -82,11 +82,11 @@ function OAuthProvider({
return (
<Button
key={provider}
type="primary"
variant="primary"
block
size="extraLarge"
style={{ marginTop: 30 }}
icon={icon}
style={{ marginTop: 30, width: '100%' }}
prefix={icon}
onClick={onClick}
>
Continue with {provider}

View File

@@ -203,7 +203,7 @@ export const SendEmail = ({
</Wrapper>
<Button
type="primary"
variant="primary"
size="extraLarge"
style={{ width: '100%' }}
disabled={hasSentEmail}

View File

@@ -129,7 +129,7 @@ export const SignInWithPassword: FC<AuthPanelProps> = ({
</div>
<Button
data-testid="sign-in-button"
type="primary"
variant="primary"
size="extraLarge"
style={{ width: '100%' }}
disabled={isLoading}

View File

@@ -5,8 +5,9 @@ import { authAtom } from '@affine/core/atoms';
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { mixpanel } from '@affine/core/mixpanel';
import { Trans, useI18n } from '@affine/i18n';
import { ArrowDownBigIcon } from '@blocksuite/icons/rc';
import { ArrowRightBigIcon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra';
import { cssVar } from '@toeverything/theme';
import { useAtomValue } from 'jotai';
import type { FC } from 'react';
import { useCallback, useEffect, useState } from 'react';
@@ -149,21 +150,13 @@ export const SignIn: FC<AuthPanelProps> = ({
{verifyToken ? (
<Button
style={{ width: '100%' }}
size="extraLarge"
data-testid="continue-login-button"
block
loading={isMutating}
icon={
<ArrowDownBigIcon
width={20}
height={20}
style={{
transform: 'rotate(-90deg)',
color: 'var(--affine-blue)',
}}
/>
}
iconPosition="end"
suffix={<ArrowRightBigIcon />}
suffixStyle={{ width: 20, height: 20, color: cssVar('blue') }}
onClick={onContinue}
>
{t['com.affine.auth.sign.email.continue']()}

View File

@@ -106,7 +106,7 @@ const NameWorkspaceContent = ({
cancelText={t['com.affine.nameWorkspace.button.cancel']()}
confirmText={t['com.affine.nameWorkspace.button.create']()}
confirmButtonOptions={{
type: 'primary',
variant: 'primary',
disabled: !workspaceName || loading,
['data-testid' as string]: 'create-workspace-create-button',
}}

View File

@@ -28,7 +28,7 @@ export const HistoryTipsModal = () => {
description={t['com.affine.history-vision.tips-modal.description']()}
cancelText={t['com.affine.history-vision.tips-modal.cancel']()}
confirmButtonOptions={{
type: 'primary',
variant: 'primary',
}}
onConfirm={handleConfirm}
confirmText={t['com.affine.history-vision.tips-modal.confirm']()}

View File

@@ -27,7 +27,7 @@ export const IssueFeedbackModal = () => {
to={`${runtimeConfig.githubUrl}/issues/new/choose`}
confirmText={t['com.affine.issue-feedback.confirm']()}
confirmButtonOptions={{
type: 'primary',
variant: 'primary',
}}
external
/>

View File

@@ -19,7 +19,7 @@ export const AnimateInTooltip = ({
</div>
<div className={styles.next}>
{visible ? (
<Button type="primary" size="extraLarge" onClick={onNext}>
<Button variant="primary" size="extraLarge" onClick={onNext}>
Next
</Button>
) : null}

View File

@@ -235,7 +235,7 @@ export const EdgelessSwitch = ({
onSwitchToPageMode={onSwitchToPageMode}
onSwitchToEdgelessMode={onSwitchToEdgelessMode}
/>
<Button size="extraLarge" type="primary" onClick={onNextClick}>
<Button size="extraLarge" variant="primary" onClick={onNextClick}>
Next
</Button>
</header>
@@ -263,7 +263,7 @@ export const EdgelessSwitch = ({
<Button
className={styles.wellDoneEnterAnim}
onClick={onNextClick}
type="primary"
variant="primary"
size="extraLarge"
style={{ marginTop: 40 }}
>

View File

@@ -251,11 +251,9 @@ const PlanPrompt = () => {
: '' /* TODO(@catsjuice): loading UI */
}
<IconButton
size="small"
icon={<CloseIcon />}
onClick={closeFreePlanPrompt}
/>
<IconButton onClick={closeFreePlanPrompt}>
<CloseIcon />
</IconButton>
</div>
);
}, [closeFreePlanPrompt, isProWorkspace, t]);
@@ -393,7 +391,7 @@ const PageHistoryList = ({
})}
{onLoadMore ? (
<Button
type="plain"
variant="plain"
loading={loadingMore}
disabled={loadingMore}
className={styles.historyItemLoadMore}
@@ -480,7 +478,7 @@ const PageHistoryManager = ({
},
confirmText: t['com.affine.history.confirm-restore-modal.restore'](),
confirmButtonOptions: {
type: 'primary',
variant: 'primary',
['data-testid' as string]: 'confirm-restore-history-button',
},
onConfirm: handleRestore,
@@ -520,12 +518,12 @@ const PageHistoryManager = ({
) : null}
<div className={styles.historyFooter}>
<Button type="plain" onClick={onClose}>
<Button onClick={onClose}>
{t['com.affine.history.back-to-page']()}
</Button>
<div className={styles.spacer} />
<Button
type="primary"
variant="primary"
onClick={onConfirmRestore}
disabled={isMutating || !activeVersion}
>

View File

@@ -50,7 +50,7 @@ export const ConfirmDeletePropertyModal = ({
onClick: onCancel,
}}
confirmButtonOptions={{
type: 'error',
variant: 'error',
}}
/>
);

View File

@@ -117,22 +117,14 @@ export const tableBodySortable = style({
});
export const addPropertyButton = style({
display: 'flex',
alignItems: 'center',
alignSelf: 'flex-start',
fontSize: cssVar('fontSm'),
color: `${cssVar('textSecondaryColor')} !important`,
color: `${cssVar('textSecondaryColor')}`,
padding: '0 4px',
height: 36,
cursor: 'pointer',
':hover': {
color: cssVar('textPrimaryColor'),
backgroundColor: cssVar('hoverColor'),
},
gap: 2,
fontWeight: 400,
gap: 6,
});
globalStyle(`${addPropertyButton} svg`, {
fontSize: 16,
color: cssVar('iconSecondary'),

View File

@@ -703,11 +703,9 @@ export const PagePropertiesTableHeader = ({
</div>
{properties.length === 0 || manager.readonly ? null : (
<PagePropertiesSettingsPopup>
<IconButton
data-testid="page-info-show-more"
type="plain"
icon={<MoreHorizontalIcon />}
/>
<IconButton data-testid="page-info-show-more" size="20">
<MoreHorizontalIcon />
</IconButton>
</PagePropertiesSettingsPopup>
)}
<Collapsible.Trigger asChild role="button" onClick={handleCollapse}>
@@ -715,15 +713,12 @@ export const PagePropertiesTableHeader = ({
className={styles.tableHeaderCollapseButtonWrapper}
data-testid="page-info-collapse"
>
<IconButton
type="plain"
icon={
<ToggleExpandIcon
className={styles.collapsedIcon}
data-collapsed={!open}
/>
}
/>
<IconButton size="20">
<ToggleExpandIcon
className={styles.collapsedIcon}
data-collapsed={!open}
/>
</IconButton>
</div>
</Collapsible.Trigger>
</div>
@@ -1056,8 +1051,8 @@ export const PagePropertiesAddProperty = () => {
return (
<Menu {...menuOptions}>
<Button
type="plain"
icon={<PlusIcon />}
variant="plain"
prefix={<PlusIcon />}
className={styles.addPropertyButton}
>
{t['com.affine.page-properties.add-property']()}

View File

@@ -405,11 +405,9 @@ export const TagsEditor = ({ pageId, readonly }: TagsEditorProps) => {
<TagItem maxWidth="100%" tag={tag} mode="inline" />
<div className={styles.spacer} />
<EditTagMenu tagId={tag.id} onTagDelete={onTagDelete}>
<IconButton
className={styles.tagEditIcon}
type="plain"
icon={<MoreHorizontalIcon />}
/>
<IconButton className={styles.tagEditIcon}>
<MoreHorizontalIcon />
</IconButton>
</EditTagMenu>
</div>
);

View File

@@ -112,7 +112,7 @@ export const CloudQuotaModal = () => {
isFreePlanOwner ? t['com.affine.payment.upgrade']() : t['Got it']()
}
confirmButtonOptions={{
type: 'primary',
variant: 'primary',
}}
/>
);

View File

@@ -37,7 +37,7 @@ export const LocalQuotaModal = () => {
onConfirm={onConfirm}
confirmText={t['Got it']()}
confirmButtonOptions={{
type: 'primary',
variant: 'primary',
}}
/>
);

View File

@@ -132,7 +132,7 @@ export const AIUsagePanel = () => {
</div>
{hasPaymentFeature && (
<AISubscribe type="primary" className={styles.storageButton}>
<AISubscribe variant="primary">
{t['com.affine.payment.ai.usage.purchase-button-label']()}
</AISubscribe>
)}

View File

@@ -142,7 +142,6 @@ export const AvatarAndName = () => {
<Button
data-testid="save-user-name"
onClick={handleUpdateUserName}
className={styles.button}
style={{
marginLeft: '12px',
}}
@@ -234,7 +233,7 @@ export const AccountSetting: FC = () => {
/>
<AvatarAndName />
<SettingRow name={t['com.affine.settings.email']()} desc={account.email}>
<Button onClick={onChangeEmail} className={styles.button}>
<Button onClick={onChangeEmail}>
{account.info?.emailVerified
? t['com.affine.settings.email.action.change']()
: t['com.affine.settings.email.action.verify']()}
@@ -244,7 +243,7 @@ export const AccountSetting: FC = () => {
name={t['com.affine.settings.password']()}
desc={t['com.affine.settings.password.message']()}
>
<Button onClick={onPasswordButtonClick} className={styles.button}>
<Button onClick={onPasswordButtonClick}>
{account.info?.hasPassword
? t['com.affine.settings.password.action.change']()
: t['com.affine.settings.password.action.set']()}

View File

@@ -28,6 +28,3 @@ globalStyle(`${storageProgressWrapper} .storage-progress-bar-wrapper`, {
export const storageProgressBar = style({
height: '100%',
});
export const storageButton = style({
padding: '4px 12px',
});

View File

@@ -18,7 +18,7 @@ export interface StorageProgressProgress {
enum ButtonType {
Primary = 'primary',
Default = 'default',
Default = 'secondary',
}
export const StorageProgress = ({ onUpgrade }: StorageProgressProgress) => {
@@ -101,11 +101,7 @@ export const StorageProgress = ({ onUpgrade }: StorageProgressProgress) => {
}
>
<span tabIndex={0}>
<Button
type={buttonType}
onClick={onUpgrade}
className={styles.storageButton}
>
<Button variant={buttonType} onClick={onUpgrade}>
{isFreeUser
? t['com.affine.storage.upgrade']()
: t['com.affine.storage.change-plan']()}

View File

@@ -39,6 +39,3 @@ globalStyle(`${avatarWrapper} .camera-icon-wrapper`, {
color: cssVar('white'),
fontSize: cssVar('fontH4'),
});
export const button = style({
padding: '4px 12px',
});

View File

@@ -299,9 +299,7 @@ const TypeFormLink = () => {
desc={t['com.affine.payment.billing-type-form.description']()}
>
<a target="_blank" href={link} rel="noreferrer">
<Button style={{ padding: '4px 12px' }}>
{t['com.affine.payment.billing-type-form.go']()}
</Button>
<Button>{t['com.affine.payment.billing-type-form.go']()}</Button>
</a>
</SettingRow>
);
@@ -435,7 +433,7 @@ const PlanAction = ({
return (
<Button
className={styles.planAction}
type="primary"
variant="primary"
onClick={gotoPlansSetting}
>
{plan === SubscriptionPlan.Pro
@@ -460,12 +458,7 @@ const PaymentMethodUpdater = () => {
}, [trigger]);
return (
<Button
className={styles.button}
onClick={update}
loading={isMutating}
disabled={isMutating}
>
<Button onClick={update} loading={isMutating} disabled={isMutating}>
{t['com.affine.payment.billing-setting.update']()}
</Button>
);
@@ -492,7 +485,7 @@ const ResumeSubscription = () => {
return (
<ResumeAction open={open} onOpenChange={setOpen}>
<Button className={styles.button} onClick={handleClick}>
<Button onClick={handleClick}>
{t['com.affine.payment.billing-setting.resume-subscription']()}
</Button>
</ResumeAction>
@@ -503,10 +496,11 @@ const CancelSubscription = ({ loading }: { loading?: boolean }) => {
return (
<IconButton
style={{ pointerEvents: 'none' }}
icon={<ArrowRightSmallIcon />}
disabled={loading}
loading={loading}
/>
>
<ArrowRightSmallIcon />
</IconButton>
);
};
@@ -583,7 +577,7 @@ const InvoiceLine = ({
: ''
} $${invoice.amount / 100} - ${planText}`}
>
<Button className={styles.button} onClick={open}>
<Button onClick={open}>
{t['com.affine.payment.billing-setting.view-invoice']()}
</Button>
</SettingRow>

View File

@@ -46,9 +46,6 @@ export const currentPlanName = style({
color: cssVar('textEmphasisColor'),
cursor: 'pointer',
});
export const button = style({
padding: '4px 12px',
});
export const subscriptionSettingSkeleton = style({
display: 'flex',
flexDirection: 'column',

View File

@@ -63,7 +63,7 @@ const ExperimentalFeaturesPrompt = ({
<Button
disabled={!checked}
onClick={onConfirm}
type="primary"
variant="primary"
data-testid="experimental-confirm-button"
>
{t[

View File

@@ -43,12 +43,12 @@ export const AICancel = ({ module, ...btnProps }: AICancelProps) => {
confirmText:
t['com.affine.payment.ai.action.cancel.confirm.confirm-text'](),
confirmButtonOptions: {
type: 'default',
variant: 'secondary',
},
cancelText:
t['com.affine.payment.ai.action.cancel.confirm.cancel-text'](),
cancelButtonOptions: {
type: 'primary',
variant: 'primary',
},
onConfirm: async () => {
try {
@@ -92,7 +92,12 @@ export const AICancel = ({ module, ...btnProps }: AICancelProps) => {
]);
return (
<Button onClick={cancel} loading={isMutating} type="primary" {...btnProps}>
<Button
onClick={cancel}
loading={isMutating}
variant="primary"
{...btnProps}
>
{t['com.affine.payment.ai.action.cancel.button-label']()}
</Button>
);

View File

@@ -16,7 +16,7 @@ export const AILogin = (btnProps: ButtonProps) => {
}, [setOpen]);
return (
<Button onClick={onClickSignIn} type="primary" {...btnProps}>
<Button onClick={onClickSignIn} variant="primary" {...btnProps}>
{t['com.affine.payment.ai.action.login.button-label']()}
</Button>
);

View File

@@ -48,7 +48,7 @@ export const AIResume = ({ module, ...btnProps }: AIResumeProps) => {
confirmText:
t['com.affine.payment.ai.action.resume.confirm.confirm-text'](),
confirmButtonOptions: {
type: 'primary',
variant: 'primary',
},
cancelText:
t['com.affine.payment.ai.action.resume.confirm.cancel-text'](),
@@ -79,7 +79,12 @@ export const AIResume = ({ module, ...btnProps }: AIResumeProps) => {
}, [subscription, openConfirmModal, t, module, idempotencyKey]);
return (
<Button loading={isMutating} onClick={resume} type="primary" {...btnProps}>
<Button
loading={isMutating}
onClick={resume}
variant="primary"
{...btnProps}
>
{t['com.affine.payment.ai.action.resume.button-label']()}
</Button>
);

View File

@@ -102,7 +102,7 @@ export const AISubscribe = ({
<Button
loading={isMutating}
onClick={subscribe}
type="primary"
variant="primary"
{...btnProps}
>
{btnProps.children ?? `${priceReadable} / ${priceFrequency}`}

View File

@@ -46,6 +46,7 @@ export const allPlansLink = style({
export const collapsibleHeader = style({
display: 'flex',
alignItems: 'start',
marginBottom: 8,
});
export const collapsibleHeaderContent = style({

View File

@@ -58,7 +58,7 @@ export const PricingCollapsible = ({
<div className={styles.collapsibleHeaderTitle}>{title}</div>
<div className={styles.collapsibleHeaderCaption}>{caption}</div>
</div>
<IconButton onClick={toggle}>
<IconButton onClick={toggle} size="20">
<ArrowUpSmallIcon
style={{
transform: open ? 'rotate(0deg)' : 'rotate(180deg)',
@@ -163,7 +163,7 @@ export const PlanLayout = ({ cloud, ai, cloudTip }: PlanLayoutProps) => {
</div>
<Button
onClick={() => scrollToAnchor('cloudPricingPlan')}
type="primary"
variant="primary"
>
{t['com.affine.ai-scroll-tip.view']()}
</Button>

View File

@@ -48,7 +48,7 @@ export const ConfirmLoadingModal = ({
cancelText={cancelText}
confirmText={confirmText}
confirmButtonOptions={{
type: 'primary',
variant: 'primary',
loading,
}}
open={open}
@@ -120,7 +120,7 @@ export const DowngradeModal = ({
<Button
disabled={loading}
onClick={() => onOpenChange?.(false)}
type="primary"
variant="primary"
>
{t['com.affine.payment.modal.downgrade.confirm']()}
</Button>

View File

@@ -1,4 +1,4 @@
import { Button } from '@affine/component/ui/button';
import { Button, type ButtonProps } from '@affine/component/ui/button';
import { Tooltip } from '@affine/component/ui/tooltip';
import { generateSubscriptionCallbackLink } from '@affine/core/hooks/affine/use-subscription-notify';
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
@@ -10,10 +10,11 @@ import { SubscriptionPlan, SubscriptionStatus } from '@affine/graphql';
import { Trans, useI18n } from '@affine/i18n';
import { DoneIcon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import clsx from 'clsx';
import { useSetAtom } from 'jotai';
import { nanoid } from 'nanoid';
import type { HTMLAttributes, PropsWithChildren } from 'react';
import type { PropsWithChildren } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { authAtom } from '../../../../../atoms/index';
@@ -194,7 +195,7 @@ const Downgrade = ({ disabled }: { disabled?: boolean }) => {
<div className={styles.planAction}>
<Button
className={styles.planAction}
type="primary"
variant="primary"
onClick={handleClick}
disabled={disabled}
>
@@ -232,7 +233,7 @@ const BookDemo = ({ plan }: { plan: SubscriptionPlan }) => {
});
}}
>
<Button className={styles.planAction} type="primary">
<Button className={styles.planAction} variant="primary">
{t['com.affine.payment.tell-us-use-case']()}
</Button>
</a>
@@ -243,8 +244,8 @@ export const Upgrade = ({
className,
recurring,
children,
...attrs
}: HTMLAttributes<HTMLButtonElement> & {
...btnProps
}: ButtonProps & {
recurring: SubscriptionRecurring;
}) => {
const [isMutating, setMutating] = useState(false);
@@ -307,11 +308,11 @@ export const Upgrade = ({
return (
<Button
className={clsx(styles.planAction, className)}
type="primary"
variant="primary"
onClick={upgrade}
disabled={isMutating}
loading={isMutating}
{...attrs}
{...btnProps}
>
{children ?? t['com.affine.payment.upgrade']()}
</Button>
@@ -371,7 +372,7 @@ const ChangeRecurring = ({
<>
<Button
className={styles.planAction}
type="primary"
variant="primary"
onClick={onStartChange}
disabled={disabled || isMutating}
loading={isMutating}
@@ -405,7 +406,7 @@ const SignUpAction = ({ children }: PropsWithChildren) => {
<Button
onClick={onClickSignIn}
className={styles.planAction}
type="primary"
variant="primary"
>
{children}
</Button>
@@ -415,7 +416,6 @@ const SignUpAction = ({ children }: PropsWithChildren) => {
const ResumeButton = () => {
const t = useI18n();
const [open, setOpen] = useState(false);
const [hovered, setHovered] = useState(false);
const subscription = useService(SubscriptionService).subscription;
const handleClick = useCallback(() => {
@@ -435,14 +435,14 @@ const ResumeButton = () => {
return (
<ResumeAction open={open} onOpenChange={setOpen}>
<Button
className={styles.planAction}
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
className={styles.resumeAction}
onClick={handleClick}
style={assignInlineVars({
'--default-content': t['com.affine.payment.current-plan'](),
'--hover-content': t['com.affine.payment.resume-renewal'](),
})}
>
{hovered
? t['com.affine.payment.resume-renewal']()
: t['com.affine.payment.current-plan']()}
<span className={styles.resumeActionContent} />
</Button>
</ResumeAction>
);

View File

@@ -177,7 +177,17 @@ export const planPriceDesc = style({
});
export const planAction = style({
width: '100%',
fontWeight: 500,
});
export const resumeAction = style([planAction, {}]);
export const resumeActionContent = style({
':after': {
content: 'var(--default-content)',
},
selectors: {
[`${resumeAction}:hover &:after`]: {
content: 'var(--hover-content)',
},
},
});
export const planBenefits = style({
fontSize: cssVar('fontXs'),

View File

@@ -38,7 +38,7 @@ export const WorkspaceDeleteModal = ({
cancelText={t['com.affine.workspaceDelete.button.cancel']()}
confirmText={t['com.affine.workspaceDelete.button.delete']()}
confirmButtonOptions={{
type: 'error',
variant: 'error',
disabled: !allowDelete,
['data-testid' as string]: 'delete-workspace-confirm-button',
}}

View File

@@ -136,7 +136,7 @@ export const DeleteLeaveWorkspace = () => {
description={t['com.affine.deleteLeaveWorkspace.leaveDescription']()}
confirmText={t['Leave']()}
confirmButtonOptions={{
type: 'warning',
variant: 'error',
}}
/>
)}

View File

@@ -56,7 +56,7 @@ export const EnableCloudPanel = () => {
>
<Button
data-testid="publish-enable-affine-cloud-button"
type="primary"
variant="primary"
onClick={confirmEnableCloudAndClose}
style={{ marginTop: '12px' }}
>

View File

@@ -63,7 +63,7 @@ const MembersPanelLocal = () => {
<Tooltip content={t['com.affine.settings.member-tooltip']()}>
<div className={style.fakeWrapper}>
<SettingRow name={`${t['Members']()} (0)`} desc={t['Members hint']()}>
<Button size="large">{t['Invite Members']()}</Button>
<Button>{t['Invite Members']()}</Button>
</SettingRow>
</div>
</Tooltip>
@@ -393,7 +393,6 @@ const MemberItem = ({
>
<IconButton
disabled={!operationButtonInfo.show}
type="plain"
style={{
visibility: operationButtonInfo.show ? 'visible' : 'hidden',
flexShrink: 0,

View File

@@ -173,11 +173,9 @@ const EditPropertyButton = ({
}}
items={editing ? editMenuItems : defaultMenuItems}
>
<IconButton
onClick={() => setOpen(true)}
type="plain"
icon={<MoreHorizontalIcon />}
/>
<IconButton onClick={() => setOpen(true)} size="20">
<MoreHorizontalIcon />
</IconButton>
</Menu>
<ConfirmDeletePropertyModal
onConfirm={() => {
@@ -350,7 +348,7 @@ const WorkspaceSettingPropertiesMain = () => {
<div className={styles.listHeader}>
{properties.length > 0 ? (
<Menu items={filterMenuItems}>
<Button type="default" icon={<FilterIcon />}>
<Button prefix={<FilterIcon />}>
{filterMode === 'all'
? t['com.affine.filter']()
: t[`com.affine.settings.workspace.properties.${filterMode}`]()}
@@ -365,7 +363,7 @@ const WorkspaceSettingPropertiesMain = () => {
/>
}
>
<Button type="primary">
<Button variant="primary">
{t['com.affine.settings.workspace.properties.add_property']()}
</Button>
</Menu>

View File

@@ -55,7 +55,7 @@ const DefaultShareButton = forwardRef(function DefaultShareButton(
}, [shareService]);
return (
<Button ref={ref} className={styles.shareButton} type="primary">
<Button ref={ref} className={styles.shareButton} variant="primary">
{shared
? t['com.affine.share-menu.sharedButton']()
: t['com.affine.share-menu.shareButton']()}

View File

@@ -40,7 +40,7 @@ export const LocalSharePage = (props: ShareMenuProps) => {
<div>
<Button
onClick={props.onEnableAffineCloud}
type="primary"
variant="primary"
data-testid="share-menu-enable-affine-cloud-button"
>
{t['Enable AFFiNE Cloud']()}
@@ -256,7 +256,7 @@ export const AffineSharePage = (props: ShareMenuProps) => {
) : (
<Button
onClick={onClickCreateLink}
type="primary"
variant="primary"
data-testid="share-menu-create-link-button"
style={{ padding: '4px 12px', whiteSpace: 'nowrap' }}
>

View File

@@ -32,7 +32,7 @@ export const SignOutModal = ({ ...props }: ConfirmModalProps) => {
cancelText={cancelText ?? defaultTexts.cancelText}
confirmText={confirmText ?? defaultTexts.children}
confirmButtonOptions={{
type: 'error',
variant: 'error',
['data-testid' as string]: 'confirm-sign-out-button',
}}
contentOptions={{

View File

@@ -26,7 +26,7 @@ export const StarAFFiNEModal = () => {
cancelText={t['com.affine.star-affine.cancel']()}
to={runtimeConfig.githubUrl}
confirmButtonOptions={{
type: 'primary',
variant: 'primary',
}}
confirmText={t['com.affine.star-affine.confirm']()}
external

View File

@@ -48,7 +48,7 @@ const UpgradeSuccessLayout = ({
return (
<AuthPageContainer title={title} subtitle={subtitle}>
<Button type="primary" size="extraLarge" onClick={openAffine}>
<Button variant="primary" size="extraLarge" onClick={openAffine}>
{t['com.affine.other-page.nav.open-affine']()}
</Button>
</AuthPageContainer>

View File

@@ -32,7 +32,7 @@ const SubscriptionChangedNotifyFooter = ({
className={clsx(actionButton, cancelButton)}
size={'default'}
onClick={onCancel}
type="plain"
variant="plain"
>
{cancelText}
</Button>
@@ -40,7 +40,7 @@ const SubscriptionChangedNotifyFooter = ({
<Button
onClick={onConfirm}
className={clsx(actionButton, confirmButton)}
type="plain"
variant="plain"
>
{okText}
</Button>

View File

@@ -6,11 +6,7 @@ export const root = style({
height: 32,
borderRadius: 8,
boxShadow: '0px 1px 2px 0px rgba(0, 0, 0, 0.15)',
border: `1px solid ${cssVarV2('layer/border')}`,
borderWidth: 1,
borderColor: cssVarV2('layer/border'),
background: cssVarV2('button/siderbarPrimary/background'),
});
export const icon = style({
color: cssVarV2('icon/primary'),
fontSize: 20,
display: 'block',
});

View File

@@ -1,4 +1,4 @@
import { Button, Tooltip } from '@affine/component';
import { IconButton } from '@affine/component';
import { useI18n } from '@affine/i18n';
import { PlusIcon } from '@blocksuite/icons/rc';
import clsx from 'clsx';
@@ -12,6 +12,7 @@ interface AddPageButtonProps {
style?: React.CSSProperties;
}
const sideBottom = { side: 'bottom' as const };
export function AddPageButton({
onClick,
className,
@@ -20,15 +21,15 @@ export function AddPageButton({
const t = useI18n();
return (
<Tooltip content={t['New Page']()} side="bottom">
<Button
data-testid="sidebar-new-page-button"
style={style}
className={clsx([styles.root, className])}
onClick={onClick}
>
<PlusIcon className={styles.icon} />
</Button>
</Tooltip>
<IconButton
tooltip={t['New Page']()}
tooltipOptions={sideBottom}
data-testid="sidebar-new-page-button"
style={style}
className={clsx([styles.root, className])}
onClick={onClick}
>
<PlusIcon />
</IconButton>
);
}

View File

@@ -34,25 +34,20 @@ export const label = style({
lineHeight: '20px',
flexGrow: '0',
display: 'flex',
gap: 2,
alignItems: 'center',
justifyContent: 'start',
cursor: 'pointer',
});
export const collapseButton = style({
selectors: {
[`${label} > &`]: {
color: cssVarV2('icon/tertiary'),
transform: 'translateY(1px)',
},
},
});
export const collapseIcon = style({
transform: 'rotate(90deg)',
vars: { '--y': '1px', '--r': '90deg' },
color: cssVarV2('icon/tertiary'),
transform: 'translateY(var(--y)) rotate(var(--r))',
transition: 'transform 0.2s',
selectors: {
[`${root}[data-collapsed="true"] &`]: {
transform: 'rotate(0deg)',
vars: { '--r': '0deg' },
},
},
});

View File

@@ -1,4 +1,3 @@
import { IconButton } from '@affine/component';
import { ToggleCollapseIcon } from '@blocksuite/icons/rc';
import clsx from 'clsx';
import { type ForwardedRef, forwardRef, type PropsWithChildren } from 'react';
@@ -42,14 +41,12 @@ export const CategoryDivider = forwardRef(
<div className={styles.label}>
{label}
{collapsible ? (
<IconButton
withoutHoverStyle
className={styles.collapseButton}
size="small"
<ToggleCollapseIcon
width={16}
height={16}
data-testid="category-divider-collapse-button"
>
<ToggleCollapseIcon className={styles.collapseIcon} />
</IconButton>
className={styles.collapseIcon}
/>
) : null}
</div>
<div className={styles.actions} onClick={e => e.stopPropagation()}>

View File

@@ -1,23 +1,18 @@
import { style } from '@vanilla-extract/css';
export const sidebarSwitch = style({
opacity: 0,
display: 'inline-flex',
export const sidebarSwitchClip = style({
flexShrink: 0,
overflow: 'hidden',
pointerEvents: 'none',
transition: 'max-width 0.2s ease-in-out, margin 0.3s ease-in-out',
transition:
'max-width 0.2s ease-in-out, margin 0.3s ease-in-out, opacity 0.3s ease',
selectors: {
'&[data-show=true]': {
maxWidth: '32px',
opacity: 1,
width: '32px',
flexShrink: 0,
fontSize: '24px',
pointerEvents: 'auto',
maxWidth: '60px',
},
'&[data-show=false]': {
opacity: 0,
maxWidth: 0,
margin: '0 !important',
},
},
});

View File

@@ -1,7 +1,6 @@
import { IconButton, Tooltip } from '@affine/component';
import { IconButton } from '@affine/component';
import { useI18n } from '@affine/i18n';
import { SidebarIcon } from '@blocksuite/icons/rc';
import clsx from 'clsx';
import { useAtom } from 'jotai';
import { appSidebarOpenAtom } from '../index.jotai';
@@ -19,19 +18,21 @@ export const SidebarSwitch = ({
const tooltipContent = open
? t['com.affine.sidebarSwitch.collapse']()
: t['com.affine.sidebarSwitch.expand']();
// TODO(@CatsJuice): Tooltip shortcut style
const collapseKeyboardShortcuts =
environment.isBrowser && environment.isMacOs ? ' ⌘+/' : ' Ctrl+/';
return (
<Tooltip
content={tooltipContent + ' ' + collapseKeyboardShortcuts}
side={open ? 'bottom' : 'right'}
<div
data-show={show}
className={styles.sidebarSwitchClip}
data-testid={`app-sidebar-arrow-button-${open ? 'collapse' : 'expand'}`}
>
<IconButton
className={clsx(styles.sidebarSwitch, className)}
data-show={show}
size="large"
data-testid={`app-sidebar-arrow-button-${open ? 'collapse' : 'expand'}`}
tooltip={tooltipContent + ' ' + collapseKeyboardShortcuts}
tooltipOptions={{ side: open ? 'bottom' : 'right' }}
className={className}
size="24"
style={{
zIndex: 1,
}}
@@ -39,6 +40,6 @@ export const SidebarSwitch = ({
>
<SidebarIcon />
</IconButton>
</Tooltip>
</div>
);
};

View File

@@ -134,7 +134,7 @@ export function patchNotificationService(
description: toReactNode(message),
confirmText,
confirmButtonOptions: {
type: 'primary',
variant: 'primary',
},
cancelText,
onConfirm: () => {
@@ -177,7 +177,7 @@ export function patchNotificationService(
description: description,
confirmText: confirmText ?? 'Confirm',
confirmButtonOptions: {
type: 'primary',
variant: 'primary',
},
cancelText: cancelText ?? 'Cancel',
onConfirm: () => {

View File

@@ -1,4 +1,4 @@
import { IconButton, Tooltip } from '@affine/component';
import { IconButton } from '@affine/component';
import { openInfoModalAtom } from '@affine/core/atoms';
import { useI18n } from '@affine/i18n';
import { InformationIcon } from '@blocksuite/icons/rc';
@@ -11,12 +11,13 @@ export const InfoButton = () => {
setOpenInfoModal(true);
};
return (
<Tooltip content={t['com.affine.page-properties.page-info.view']()}>
<IconButton
data-testid="header-info-button"
onClick={onOpenInfoModal}
icon={<InformationIcon />}
/>
</Tooltip>
<IconButton
size="20"
tooltip={t['com.affine.page-properties.page-info.view']()}
data-testid="header-info-button"
onClick={onOpenInfoModal}
>
<InformationIcon />
</IconButton>
);
};

View File

@@ -9,9 +9,10 @@ export const DetailPageHeaderPresentButton = () => {
return (
<IconButton
style={{ flexShrink: 0 }}
size={'large'}
icon={<PresentationIcon />}
size="24"
onClick={() => handlePresent(!isPresent)}
></IconButton>
>
<PresentationIcon />
</IconButton>
);
};

View File

@@ -11,11 +11,10 @@ export const PresentButton = () => {
return (
<Button
icon={<PresentationIcon />}
prefix={<PresentationIcon />}
className={styles.presentButton}
onClick={() => handlePresent()}
disabled={isPresent}
withoutHoverStyle
>
{t['com.affine.share-page.header.present']()}
</Button>

View File

@@ -46,7 +46,6 @@ export const headerDivider = style({
});
export const presentButton = style({
gap: '4px',
background: cssVar('black'),
color: cssVar('white'),
borderColor: cssVar('pureBlack10'),

View File

@@ -1,7 +1,8 @@
import type { IconButtonProps } from '@affine/component';
import { IconButton, Tooltip } from '@affine/component';
import { IconButton } from '@affine/component';
import { useI18n } from '@affine/i18n';
import { FavoritedIcon, FavoriteIcon } from '@blocksuite/icons/rc';
import { cssVar } from '@toeverything/theme';
import Lottie from 'lottie-react';
import { forwardRef, useCallback, useState } from 'react';
@@ -25,24 +26,32 @@ export const FavoriteTag = forwardRef<
[active, onClick]
);
return (
<Tooltip content={active ? t['Favorited']() : t['Favorite']()} side="top">
<IconButton ref={ref} active={active} onClick={handleClick} {...props}>
{active ? (
playAnimation ? (
<Lottie
loop={false}
animationData={favoritedAnimation}
onComplete={() => setPlayAnimation(false)}
style={{ width: '20px', height: '20px' }}
/>
) : (
<FavoritedIcon data-testid="favorited-icon" />
)
<IconButton
tooltip={active ? t['Favorited']() : t['Favorite']()}
tooltipOptions={{ side: 'top' }}
ref={ref}
onClick={handleClick}
size="20"
{...props}
>
{active ? (
playAnimation ? (
<Lottie
loop={false}
animationData={favoritedAnimation}
onComplete={() => setPlayAnimation(false)}
style={{ width: '20px', height: '20px' }}
/>
) : (
<FavoriteIcon />
)}
</IconButton>
</Tooltip>
<FavoritedIcon
color={cssVar('primaryColor')}
data-testid="favorited-icon"
/>
)
) : (
<FavoriteIcon />
)}
</IconButton>
);
});
FavoriteTag.displayName = 'FavoriteTag';

View File

@@ -5,12 +5,6 @@ export const menu = style({
minWidth: '220px',
});
export const arrowDownSmallIcon = style({
width: '16px',
height: '16px',
color: cssVar('iconColor'),
});
export const headerDisplayButton = style({
marginLeft: '16px',
['WebkitAppRegion' as string]: 'no-drag',

View File

@@ -167,8 +167,7 @@ export const PageDisplayMenu = () => {
}}
>
<Button
iconPosition="end"
icon={<ArrowDownSmallIcon className={styles.arrowDownSmallIcon} />}
suffix={<ArrowDownSmallIcon />}
className={styles.headerDisplayButton}
data-testid="page-display-menu-button"
>

View File

@@ -27,14 +27,6 @@ export const titleIcon = style({
export const titleCollectionName = style({
color: cssVar('textPrimaryColor'),
});
export const addPageButton = style({
padding: '6px 10px',
borderRadius: '8px',
background: cssVar('backgroundPrimaryColor'),
fontSize: cssVar('fontXs'),
fontWeight: 500,
height: '28px',
});
export const tagSticky = style({
display: 'flex',
alignItems: 'center',

View File

@@ -125,7 +125,7 @@ export const CollectionPageListHeader = ({
cancelText: t['Cancel'](),
confirmText: t['Confirm'](),
confirmButtonOptions: {
type: 'primary',
variant: 'primary',
},
onConfirm: () => createAndAddDocument(createDocumentFn),
});
@@ -156,9 +156,7 @@ export const CollectionPageListHeader = ({
<div className={styles.titleCollectionName}>{collection.name}</div>
</div>
<div className={styles.rightButtonGroup}>
<Button className={styles.addPageButton} onClick={handleEdit}>
{t['Edit']()}
</Button>
<Button onClick={handleEdit}>{t['Edit']()}</Button>
<PageListNewPageButton
size="small"
testId="new-page-button-trigger"
@@ -253,7 +251,7 @@ export const TagPageListHeader = ({
</div>
</Menu>
</div>
<Button className={styles.addPageButton} onClick={handleClick}>
<Button onClick={handleClick}>
{t['com.affine.editCollection.saveCollection']()}
</Button>
</div>

View File

@@ -59,15 +59,11 @@ export const FilterList = ({
}
>
{value.length === 0 ? (
<Button
icon={<PlusIcon style={{ color: 'var(--affine-icon-color)' }} />}
iconPosition="end"
style={{ fontSize: 'var(--affine-font-xs)', padding: '0 8px' }}
>
<Button suffix={<PlusIcon />}>
{t['com.affine.filterList.button.add']()}
</Button>
) : (
<IconButton size="small">
<IconButton size="16">
<PlusIcon />
</IconButton>
)}

View File

@@ -84,12 +84,16 @@ export const editTagWrapper = style({
},
});
export const deleteIcon = style({
export const deleteButton = style({
color: cssVar('iconColor'),
':hover': {
background: cssVar('backgroundErrorColor'),
},
});
export const deleteIcon = style({
selectors: {
'&:not(.without-hover):hover': {
[`${deleteButton}:hover &`]: {
color: cssVar('errorColor'),
background: cssVar('backgroundErrorColor'),
},
},
});

View File

@@ -4,7 +4,6 @@ import {
MenuIcon,
MenuItem,
toast,
Tooltip,
useConfirmModal,
} from '@affine/component';
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
@@ -53,6 +52,9 @@ import type { TagMeta } from './types';
import { ColWrapper, stopPropagationWithoutPrevent } from './utils';
import { useEditCollection, useEditCollectionName } from './view';
const tooltipSideTop = { side: 'top' as const };
const tooltipSideTopAlignEnd = { side: 'top' as const, align: 'end' as const };
export interface PageOperationCellProps {
page: DocMeta;
isInAllowList?: boolean;
@@ -238,7 +240,7 @@ export const PageOperationCell = ({
align: 'end',
}}
>
<IconButton type="plain" data-testid="page-list-operation-button">
<IconButton data-testid="page-list-operation-button" size="20">
<MoreVerticalIcon />
</IconButton>
</Menu>
@@ -278,7 +280,7 @@ export const TrashOperationCell = ({
cancelText: t['Cancel'](),
confirmText: t['com.affine.trashOperation.delete'](),
confirmButtonOptions: {
type: 'error',
variant: 'error',
},
onConfirm: onPermanentlyDeletePage,
});
@@ -286,30 +288,29 @@ export const TrashOperationCell = ({
return (
<ColWrapper flex={1}>
<Tooltip content={t['com.affine.trashOperation.restoreIt']()} side="top">
<IconButton
data-testid="restore-page-button"
style={{ marginRight: '12px' }}
onClick={() => {
onRestorePage();
}}
>
<ResetIcon />
</IconButton>
</Tooltip>
<Tooltip
content={t['com.affine.trashOperation.deletePermanently']()}
side="top"
align="end"
<IconButton
tooltip={t['com.affine.trashOperation.restoreIt']()}
tooltipOptions={tooltipSideTop}
data-testid="restore-page-button"
style={{ marginRight: '12px' }}
onClick={() => {
onRestorePage();
}}
size="20"
>
<IconButton
data-testid="delete-page-button"
onClick={onConfirmPermanentlyDelete}
className={styles.deleteIcon}
>
<DeletePermanentlyIcon />
</IconButton>
</Tooltip>
<ResetIcon />
</IconButton>
<IconButton
tooltip={t['com.affine.trashOperation.deletePermanently']()}
tooltipOptions={tooltipSideTopAlignEnd}
data-testid="delete-page-button"
onClick={onConfirmPermanentlyDelete}
className={styles.deleteButton}
iconClassName={styles.deleteIcon}
size="20"
>
<DeletePermanentlyIcon />
</IconButton>
</ColWrapper>
);
};
@@ -393,7 +394,7 @@ export const CollectionOperationCell = ({
cancelText: t['Cancel'](),
confirmText: t['Confirm'](),
confirmButtonOptions: {
type: 'primary',
variant: 'primary',
},
onConfirm: createAndAddDocument,
});
@@ -411,16 +412,20 @@ export const CollectionOperationCell = ({
>
<FavoriteTag onClick={onToggleFavoriteCollection} active={favourite} />
</ColWrapper>
<Tooltip content={t['com.affine.collection.menu.rename']()} side="top">
<IconButton onClick={handleEditName}>
<EditIcon />
</IconButton>
</Tooltip>
<Tooltip content={t['com.affine.collection.menu.edit']()} side="top">
<IconButton onClick={handleEdit}>
<FilterIcon />
</IconButton>
</Tooltip>
<IconButton
onClick={handleEditName}
tooltip={t['com.affine.collection.menu.rename']()}
tooltipOptions={tooltipSideTop}
>
<EditIcon />
</IconButton>
<IconButton
onClick={handleEdit}
tooltip={t['com.affine.collection.menu.edit']()}
tooltipOptions={tooltipSideTop}
>
<FilterIcon />
</IconButton>
<ColWrapper alignment="start">
<Menu
items={
@@ -470,7 +475,7 @@ export const CollectionOperationCell = ({
align: 'end',
}}
>
<IconButton type="plain">
<IconButton>
<MoreVerticalIcon />
</IconButton>
</Menu>
@@ -521,11 +526,13 @@ export const TagOperationCell = ({
</div>
</div>
<Tooltip content={t['Rename']()} side="top">
<IconButton onClick={() => setOpen(true)}>
<EditIcon />
</IconButton>
</Tooltip>
<IconButton
tooltip={t['Rename']()}
tooltipOptions={tooltipSideTop}
onClick={() => setOpen(true)}
>
<EditIcon />
</IconButton>
<ColWrapper alignment="start">
<Menu
@@ -546,7 +553,7 @@ export const TagOperationCell = ({
align: 'end',
}}
>
<IconButton type="plain">
<IconButton>
<MoreVerticalIcon />
</IconButton>
</Menu>

View File

@@ -49,7 +49,7 @@ const MoveToTrashConfirm = ({
confirmText={t.Delete()}
confirmButtonOptions={{
['data-testid' as string]: 'confirm-delete-page',
type: 'error',
variant: 'error',
}}
{...confirmModalProps}
/>

View File

@@ -61,7 +61,11 @@ export const SelectorLayout = ({
<span>{t['com.affine.selectPage.selected']()}</span>
<span className={styles.selectedNum}>{selectedCount ?? 0}</span>
</div>
<Button type="plain" className={styles.clearButton} onClick={onClear}>
<Button
variant="plain"
className={styles.clearButton}
onClick={onClear}
>
{t['com.affine.editCollection.pages.clear']()}
</Button>
</div>
@@ -75,7 +79,7 @@ export const SelectorLayout = ({
<Button
onClick={onConfirm}
className={styles.actionButton}
type="primary"
variant="primary"
>
{t['Confirm']()}
</Button>

View File

@@ -158,7 +158,7 @@ export const CreateOrEditTag = ({
<Button className={styles.cancelBtn} onClick={onClose}>
{t['Cancel']()}
</Button>
<Button type="primary" onClick={onConfirm} disabled={!tagName}>
<Button variant="primary" onClick={onConfirm} disabled={!tagName}>
{tagMeta ? t['Save']() : t['Create']()}
</Button>
</div>

View File

@@ -35,9 +35,6 @@ export const viewOption = style({
});
export const filterMenuTrigger = style({
padding: '6px 8px',
':hover': {
backgroundColor: cssVar('hoverColor'),
},
selectors: {
[`&[data-is-hidden="true"]`]: {
display: 'none',

View File

@@ -30,8 +30,7 @@ export const AllPageListOperationsMenu = ({
>
<Button
className={styles.filterMenuTrigger}
type="default"
icon={<FilterIcon />}
prefix={<FilterIcon />}
data-testid="create-first-filter"
>
{t['com.affine.filter']()}

View File

@@ -115,7 +115,7 @@ export const CreateCollection = ({
<Button
size="large"
data-testid="save-collection"
type="primary"
variant="primary"
disabled={isNameEmpty}
onClick={save}
>

View File

@@ -146,21 +146,13 @@ export const rulesTitleHighlight = style({
fontStyle: 'italic',
fontWeight: 800,
});
export const icon = style({
color: cssVar('iconColor'),
});
export const button = style({
userSelect: 'none',
borderRadius: 4,
cursor: 'pointer',
':hover': {
backgroundColor: cssVar('hoverColor'),
},
});
export const bottomButton = style({
padding: '4px 12px',
borderRadius: 8,
});
export const actionButton = style({
minWidth: 80,
});
export const previewActive = style({
backgroundColor: cssVar('hoverColorFilled'),
});

View File

@@ -119,13 +119,13 @@ export const EditCollection = ({
const buttons = useMemo(
() => (
<>
<Button size="large" onClick={onCancel}>
<Button onClick={onCancel} className={styles.actionButton}>
{t['com.affine.editCollection.button.cancel']()}
</Button>
<Button
size="large"
className={styles.actionButton}
data-testid="save-collection"
type="primary"
variant="primary"
disabled={isNameEmpty}
onClick={onSaveCollection}
>
@@ -183,7 +183,7 @@ export const EditCollection = ({
reset={reset}
updateCollection={onChange}
buttons={buttons}
></RulesMode>
/>
)}
</div>
);

View File

@@ -1,4 +1,4 @@
import { Tooltip } from '@affine/component';
import { Button, IconButton, Tooltip } from '@affine/component';
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
import type { Collection } from '@affine/env/filter';
import { Trans, useI18n } from '@affine/i18n';
@@ -125,14 +125,12 @@ export const RulesMode = ({
<div className={styles.rulesContainerLeftContentInclude}>
{collection.allowList.length > 0 ? (
<div className={styles.includeTitle}>
<ToggleCollapseIcon
<IconButton
onClick={() => setExpandInclude(!expandInclude)}
className={styles.button}
width={24}
height={24}
style={{
iconStyle={{
transform: expandInclude ? 'rotate(90deg)' : undefined,
}}
icon={<ToggleCollapseIcon />}
/>
<div style={{ color: cssVar('textSecondaryColor') }}>
{t['com.affine.editCollection.rules.include.title']()}
@@ -181,8 +179,9 @@ export const RulesMode = ({
{page?.title || t['Untitled']()}
</div>
</div>
<CloseIcon
className={styles.button}
<IconButton
size="14"
icon={<CloseIcon />}
onClick={() => {
updateCollection({
...collection,
@@ -191,7 +190,7 @@ export const RulesMode = ({
),
});
}}
></CloseIcon>
/>
</div>
);
})}
@@ -240,24 +239,16 @@ export const RulesMode = ({
</div>
<div className={styles.rulesBottom}>
<div className={styles.bottomLeft}>
<div
className={clsx(
styles.button,
styles.bottomButton,
showPreview && styles.previewActive
)}
<Button
onClick={() => {
setShowPreview(!showPreview);
}}
>
{t['com.affine.editCollection.rules.preview']()}
</div>
<div
className={clsx(styles.button, styles.bottomButton)}
onClick={reset}
>
</Button>
<Button variant="plain" onClick={reset}>
{t['com.affine.editCollection.rules.reset']()}
</div>
</Button>
<div className={styles.previewCountTips}>
<Trans
i18nKey="com.affine.editCollection.rules.countTips"
@@ -273,7 +264,9 @@ export const RulesMode = ({
</Trans>
</div>
</div>
<div style={{ display: 'flex', alignItems: 'center' }}>{buttons}</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 20 }}>
{buttons}
</div>
</div>
</>
);

View File

@@ -1,4 +1,4 @@
import { Menu, toast } from '@affine/component';
import { IconButton, Menu, toast } from '@affine/component';
import { useBlockSuiteDocMeta } from '@affine/core/hooks/use-block-suite-page-meta';
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
import { ShareDocsService } from '@affine/core/modules/share-doc';
@@ -12,7 +12,6 @@ import {
useServices,
WorkspaceService,
} from '@toeverything/infra';
import clsx from 'clsx';
import { type ReactNode, useCallback, useEffect, useState } from 'react';
import { FavoriteTag } from '../../components/favorite-tag';
@@ -185,22 +184,10 @@ export const SelectPage = ({
/>
}
>
<div>
<FilterIcon
className={clsx(styles.icon, styles.button)}
onClick={clickFilter}
width={24}
height={24}
></FilterIcon>
</div>
<IconButton icon={<FilterIcon />} onClick={clickFilter} />
</Menu>
) : (
<FilterIcon
className={clsx(styles.icon, styles.button)}
onClick={clickFilter}
width={24}
height={24}
></FilterIcon>
<IconButton icon={<FilterIcon />} onClick={clickFilter} />
)}
</div>
{showFilter ? (

View File

@@ -35,7 +35,7 @@ export const SaveAsCollectionButton = ({
<Button
onClick={handleClick}
data-testid="save-as-collection"
icon={<SaveIcon />}
prefix={<SaveIcon />}
className={styles.button}
>
{t['com.affine.editCollection.saveCollection']()}

View File

@@ -75,7 +75,7 @@ export const VirtualizedTrashList = () => {
cancelText: t['Cancel'](),
confirmText: t['com.affine.trashOperation.delete'](),
confirmButtonOptions: {
type: 'error',
variant: 'error',
},
onConfirm: handleMultiDelete,
});

View File

@@ -15,8 +15,6 @@ export const HeaderDropDownButton = forwardRef<
{...props}
data-testid="header-dropDownButton"
className={headerMenuTrigger}
withoutHoverStyle={true}
type="plain"
>
<MoreHorizontalIcon />
</IconButton>

View File

@@ -2,7 +2,7 @@ import { cssVar } from '@toeverything/theme';
import { style } from '@vanilla-extract/css';
export const headerMenuTrigger = style({
selectors: {
'&[data-state=open], &:hover': {
'&[data-state=open]': {
backgroundColor: cssVar('hoverColor'),
},
},

View File

@@ -1,6 +1,5 @@
import { Button } from '@affine/component/ui/button';
import { ConfirmModal } from '@affine/component/ui/modal';
import { Tooltip } from '@affine/component/ui/tooltip';
import { useI18n } from '@affine/i18n';
import { DeleteIcon, ResetIcon } from '@blocksuite/icons/rc';
import { DocService, useService, WorkspaceService } from '@toeverything/infra';
@@ -50,30 +49,23 @@ export const TrashPageFooter = () => {
>
<div className={styles.deleteHintText}>{hintText}</div>
<div className={styles.group}>
<Tooltip content={t['com.affine.trashOperation.restoreIt']()}>
<Button
data-testid="page-restore-button"
type="primary"
onClick={onRestore}
className={styles.buttonContainer}
>
<div className={styles.icon}>
<ResetIcon />
</div>
</Button>
</Tooltip>
<Tooltip content={t['com.affine.trashOperation.deletePermanently']()}>
<Button
type="error"
onClick={onDelete}
style={{ color: 'var(--affine-pure-white)' }}
className={styles.buttonContainer}
>
<div className={styles.icon}>
<DeleteIcon />
</div>
</Button>
</Tooltip>
<Button
tooltip={t['com.affine.trashOperation.restoreIt']()}
data-testid="page-restore-button"
variant="primary"
onClick={onRestore}
className={styles.buttonContainer}
prefix={<ResetIcon />}
prefixClassName={styles.icon}
/>
<Button
tooltip={t['com.affine.trashOperation.deletePermanently']()}
variant="error"
onClick={onDelete}
className={styles.buttonContainer}
prefix={<DeleteIcon />}
prefixClassName={styles.icon}
/>
</div>
<ConfirmModal
title={t['com.affine.trashOperation.delete.title']()}
@@ -81,7 +73,7 @@ export const TrashPageFooter = () => {
description={t['com.affine.trashOperation.delete.description']()}
confirmText={t['com.affine.trashOperation.delete']()}
confirmButtonOptions={{
type: 'error',
variant: 'error',
}}
open={open}
onConfirm={onConfirmDelete}

View File

@@ -28,12 +28,10 @@ export const deleteHintText = style({
overflow: 'hidden',
});
export const buttonContainer = style({
color: cssVar('pureWhite'),
padding: '8px 18px',
fontSize: '20px',
height: '36px',
});
export const icon = style({
display: 'flex',
alignContent: 'center',
width: 20,
height: 20,
});

View File

@@ -24,18 +24,6 @@ export const workspaceWrapper = style({
flex: 1,
});
export const userInfoWrapper = style({
flexShrink: 0,
width: 'auto',
height: 'auto',
padding: '4px 0',
});
// TODO(@catsjuice):
globalStyle(`button.${userInfoWrapper} > span`, {
lineHeight: 0,
});
export const operationMenu = style({
display: 'flex',
flexDirection: 'column',

View File

@@ -44,7 +44,7 @@ export const TrashButton = () => {
),
confirmText: t.Delete(),
confirmButtonOptions: {
type: 'error',
variant: 'error',
},
onConfirm() {
docRecord.moveToTrash();

View File

@@ -1,8 +1,8 @@
import {
Avatar,
Button,
Divider,
ErrorMessage,
IconButton,
Menu,
MenuIcon,
MenuItem,
@@ -52,13 +52,9 @@ const menuContentOptions: MenuProps['contentOptions'] = {
const AuthorizedUserInfo = ({ account }: { account: AuthAccountInfo }) => {
return (
<Menu items={<OperationMenu />} contentOptions={menuContentOptions}>
<Button
data-testid="sidebar-user-avatar"
type="plain"
className={styles.userInfoWrapper}
>
<IconButton data-testid="sidebar-user-avatar" variant="plain" size="24">
<Avatar size={24} name={account.label} url={account.avatar} />
</Button>
</IconButton>
</Menu>
);
};
@@ -71,14 +67,14 @@ const UnauthorizedUserInfo = () => {
}, [setOpen]);
return (
<Button
<IconButton
onClick={openSignInModal}
data-testid="sidebar-user-avatar"
type="plain"
className={styles.userInfoWrapper}
variant="plain"
size="24"
>
<UnknownUserIcon width={24} height={24} />
</Button>
<UnknownUserIcon />
</IconButton>
);
};

View File

@@ -1,5 +1,5 @@
import { cssVar } from '@toeverything/theme';
import { keyframes, style } from '@vanilla-extract/css';
import { style } from '@vanilla-extract/css';
export const layout = style({
margin: '80px auto',
maxWidth: '536px',
@@ -19,17 +19,3 @@ export const upgradeTips = style({
lineHeight: '20px',
textAlign: 'center',
});
const rotate = keyframes({
'0%': {
transform: 'rotate(0deg)',
},
'50%': {
transform: 'rotate(180deg)',
},
'100%': {
transform: 'rotate(360deg)',
},
});
export const loadingIcon = style({
animation: `${rotate} 1.2s infinite linear`,
});

View File

@@ -54,16 +54,9 @@ export const WorkspaceUpgrade = function WorkspaceUpgrade() {
data-testid="upgrade-workspace-button"
onClick={onButtonClick}
size="extraLarge"
icon={
error ? (
<HeartBreakIcon />
) : (
<ArrowCircleIcon
className={upgrading ? styles.loadingIcon : undefined}
/>
)
}
type={error ? 'error' : 'default'}
loading={upgrading}
prefix={error ? <HeartBreakIcon /> : <ArrowCircleIcon />}
variant={error ? 'error' : 'secondary'}
>
{error
? t['com.affine.upgrade.button-text.error']()

View File

@@ -89,7 +89,7 @@ export const useEnableCloud = () => {
? t['Enable']()
: t['Sign in and Enable'](),
confirmButtonOptions: {
type: 'primary',
variant: 'primary',
['data-testid' as string]: 'confirm-enable-affine-cloud-button',
},
onConfirm: async () =>

View File

@@ -362,11 +362,15 @@ export const AppTabsHeader = ({
ref={spacerDropTargetRef}
data-dragged-over={draggedOver}
>
<IconButton onClick={onAddTab} data-testid="add-tab-view-button">
<PlusIcon />
</IconButton>
<IconButton
size={22.86}
onClick={onAddTab}
data-testid="add-tab-view-button"
style={{ width: 32, height: 32 }}
icon={<PlusIcon />}
/>
</div>
<IconButton size="large" onClick={onToggleRightSidebar}>
<IconButton size="24" onClick={onToggleRightSidebar}>
<RightSidebarIcon />
</IconButton>
{environment.isDesktop && environment.isWindows ? (

View File

@@ -95,7 +95,7 @@ export const useExplorerCollectionNodeOperations = (
cancelText: t['Cancel'](),
confirmText: t['Confirm'](),
confirmButtonOptions: {
type: 'primary',
variant: 'primary',
},
onConfirm: createAndAddDocument,
});
@@ -129,11 +129,7 @@ export const useExplorerCollectionNodeOperations = (
index: 0,
inline: true,
view: (
<IconButton
size="small"
type="plain"
onClick={handleAddDocToCollection}
>
<IconButton size="16" onClick={handleAddDocToCollection}>
<PlusIcon />
</IconButton>
),

View File

@@ -61,7 +61,7 @@ export const useExplorerDocNodeOperations = (
confirmText: t['com.affine.moveToTrash.confirmModal.confirm'](),
cancelText: t['com.affine.moveToTrash.confirmModal.cancel'](),
confirmButtonOptions: {
type: 'error',
variant: 'error',
},
onConfirm() {
docRecord.moveToTrash();

View File

@@ -633,7 +633,7 @@ export const ExplorerFolderNodeFolder = ({
index: 0,
inline: true,
view: (
<IconButton size="small" type="plain" onClick={handleNewDoc}>
<IconButton size="16" onClick={handleNewDoc}>
<PlusIcon />
</IconButton>
),

View File

@@ -103,7 +103,7 @@ export const useExplorerTagNodeOperations = (
index: 0,
inline: true,
view: (
<IconButton size="small" type="plain" onClick={handleNewDoc}>
<IconButton size="16" onClick={handleNewDoc}>
<PlusIcon />
</IconButton>
),

Some files were not shown because too many files have changed in this diff Show More