mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-23 13:02:21 +08:00
refactor(component): migrate design components (#5000)
```[tasklist] ### Tasks - [x] Migrate components from [design](https://github.com/toeverything/design) - [x] Replace all imports from `@toeverything/components` - [x] Clean up `@toeverything/components` dependencies - [x] Storybook ``` ### Influence Here are all the components that are influenced by `@toeverything/components` - `@affine/component` - App update `Button` `Tooltip` - App sidebar header `IconButton`, `Tooltip` - Back `Button` - Auth - Change email page save `Button` - Change password page all `Button`s (Save, Later, Open) - Confirm change email `Button` - Set password page `Button` - Sign in success page `Button` - Sign up page `Button` - Auth `Modal` - Workspace card `Avatar`, `Divider`, `Tooltip`, `IconButton` - Share - Disable shared public link `Modal` - Import page `IconButton`, `Tooltip` - Accept invite page `Avatar`, `Button` - Invite member `Modal` - 404 Page `Avatar`, `Button`, `IconButton`, `Tooltip` - Notification center `IconButton` - Page list - operation cell `IconButton`, `Menu`, `ConfirmModal`, `Tooltip` - tags more `Menu` - favorite `IconButton`, `Tooltip` - new page dropdown `Menu` - filter `Menu`, `Button`, `IconButton` - Page operation `Menu` - export `MenuItem` - move to trash `MenuItem`, `ConfirmModal` - Workspace header filter `Menu`, `Button` - Collection bar `Button`, `Tooltip` (*⚠️ seems not used*) - Collection operation `Menu`, `MenuItem` - Create collection `Modal`, `Button` - Edit collection `Modal`, `Button` - Page mode filter `Menu` - Page mode `Button`, `Menu` - Setting modal - storage usage progress `Button`, `Tooltip` - On boarding tour `Modal` - `@affine/core` - Bookmark `Menu` - Affine error boundary `Button` - After sign in send email `Button` - After sign up send email `Button` - Send email `Button` - Sign in `Button` - Subscription redirect `Loading`, `Button` - Setting `Modal` - User plan button `Tooltip` - Members `Avatar`, `Button`, `IconButton`, `Loading`, `Tooltip`, `Menu` - Profile `Button`, `Avatar` - Workspace - publish panel `Button`, `Tooltip` - export panel `Button` - storage panel `Button`, `Tooltip` - delete `ConfirmModal` - Language `Menu` - Account setting `Avatar`, `Button` - Date format setting `Menu` - Billing `Button`, `IconButton`, `Loading` - Payment plans `Button`, `ConfirmModal`, `Modal`, `Tooltip` - Create workspace `Modal`, `ConfirmModal`, `Button` - Payment disabled `ConfirmModal` - Share/Export `Menu`, `Button`, `Divider` - Sign out `ConfirmModal` - Temp disable affine cloud `Modal` - Page detail operation `Menu` - Blocksuite mode switch `Tooltip` - Login card `Avatar` - Help island `Tooltip` - `plugin` - copilot - hello world - image preview - outline
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
import { CloseIcon } from '@blocksuite/icons';
|
||||
import {
|
||||
type AvatarFallbackProps,
|
||||
type AvatarImageProps,
|
||||
type AvatarProps as RadixAvatarProps,
|
||||
Fallback as AvatarFallback,
|
||||
Image as AvatarImage,
|
||||
Root as AvatarRoot,
|
||||
} from '@radix-ui/react-avatar';
|
||||
import { assignInlineVars } from '@vanilla-extract/dynamic';
|
||||
import clsx from 'clsx';
|
||||
import type { CSSProperties, HTMLAttributes, MouseEvent } from 'react';
|
||||
import { forwardRef, type ReactElement, useMemo, useState } from 'react';
|
||||
|
||||
import { IconButton } from '../button';
|
||||
import { Tooltip, type TooltipProps } from '../tooltip';
|
||||
import { ColorfulFallback } from './colorful-fallback';
|
||||
import * as style from './style.css';
|
||||
import { sizeVar } from './style.css';
|
||||
|
||||
export type AvatarProps = {
|
||||
size?: number;
|
||||
url?: string | null;
|
||||
name?: string;
|
||||
className?: string;
|
||||
style?: CSSProperties;
|
||||
colorfulFallback?: boolean;
|
||||
hoverIcon?: ReactElement;
|
||||
onRemove?: (e: MouseEvent<HTMLButtonElement>) => void;
|
||||
avatarTooltipOptions?: Omit<TooltipProps, 'children'>;
|
||||
removeTooltipOptions?: Omit<TooltipProps, 'children'>;
|
||||
|
||||
fallbackProps?: AvatarFallbackProps;
|
||||
imageProps?: Omit<AvatarImageProps, 'src'>;
|
||||
avatarProps?: RadixAvatarProps;
|
||||
hoverWrapperProps?: HTMLAttributes<HTMLDivElement>;
|
||||
removeButtonProps?: HTMLAttributes<HTMLButtonElement>;
|
||||
} & HTMLAttributes<HTMLSpanElement>;
|
||||
|
||||
export const Avatar = forwardRef<HTMLSpanElement, AvatarProps>(
|
||||
(
|
||||
{
|
||||
size = 20,
|
||||
style: propsStyles = {},
|
||||
url,
|
||||
name,
|
||||
className,
|
||||
colorfulFallback = false,
|
||||
hoverIcon,
|
||||
fallbackProps: { className: fallbackClassName, ...fallbackProps } = {},
|
||||
imageProps,
|
||||
avatarProps,
|
||||
onRemove,
|
||||
hoverWrapperProps: {
|
||||
className: hoverWrapperClassName,
|
||||
...hoverWrapperProps
|
||||
} = {},
|
||||
avatarTooltipOptions,
|
||||
removeTooltipOptions,
|
||||
removeButtonProps: {
|
||||
className: removeButtonClassName,
|
||||
...removeButtonProps
|
||||
} = {},
|
||||
...props
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const firstCharOfName = useMemo(() => {
|
||||
return name?.slice(0, 1) || 'A';
|
||||
}, [name]);
|
||||
const [imageDom, setImageDom] = useState<HTMLDivElement | null>(null);
|
||||
const [removeButtonDom, setRemoveButtonDom] =
|
||||
useState<HTMLButtonElement | null>(null);
|
||||
|
||||
return (
|
||||
<AvatarRoot className={style.avatarRoot} {...avatarProps} ref={ref}>
|
||||
<Tooltip
|
||||
portalOptions={{ container: imageDom }}
|
||||
{...avatarTooltipOptions}
|
||||
>
|
||||
<div
|
||||
ref={setImageDom}
|
||||
className={clsx(style.avatarWrapper, className)}
|
||||
style={{
|
||||
...assignInlineVars({
|
||||
[sizeVar]: size ? `${size}px` : '20px',
|
||||
}),
|
||||
...propsStyles,
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
<AvatarImage
|
||||
className={style.avatarImage}
|
||||
src={url || ''}
|
||||
alt={name}
|
||||
{...imageProps}
|
||||
/>
|
||||
|
||||
<AvatarFallback
|
||||
className={clsx(style.avatarFallback, fallbackClassName)}
|
||||
delayMs={url ? 600 : undefined}
|
||||
{...fallbackProps}
|
||||
>
|
||||
{colorfulFallback ? (
|
||||
<ColorfulFallback char={firstCharOfName} />
|
||||
) : (
|
||||
firstCharOfName
|
||||
)}
|
||||
</AvatarFallback>
|
||||
{hoverIcon ? (
|
||||
<div
|
||||
className={clsx(style.hoverWrapper, hoverWrapperClassName)}
|
||||
{...hoverWrapperProps}
|
||||
>
|
||||
{hoverIcon}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
{onRemove ? (
|
||||
<Tooltip
|
||||
portalOptions={{ container: removeButtonDom }}
|
||||
{...removeTooltipOptions}
|
||||
>
|
||||
<IconButton
|
||||
size="extraSmall"
|
||||
type="default"
|
||||
className={clsx(style.removeButton, removeButtonClassName)}
|
||||
onClick={onRemove}
|
||||
ref={setRemoveButtonDom}
|
||||
{...removeButtonProps}
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
</AvatarRoot>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Avatar.displayName = 'Avatar';
|
||||
Reference in New Issue
Block a user