Skip to content

Commit

Permalink
✨ feat: Add Alert component
Browse files Browse the repository at this point in the history
  • Loading branch information
canisminor1990 committed Nov 17, 2023
1 parent 36ba265 commit acf84e2
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 200 deletions.
39 changes: 39 additions & 0 deletions src/ActionIcon/calcSize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { ActionIconSize } from '@/ActionIcon/index';

export const calcSize = (size?: ActionIconSize) => {
let blockSize: number;
let borderRadius: number;

switch (size) {
case 'large': {
blockSize = 44;
borderRadius = 8;
break;
}
case 'normal': {
blockSize = 36;
borderRadius = 5;
break;
}
case 'small': {
blockSize = 24;
borderRadius = 5;
break;
}
case 'site': {
blockSize = 34;
borderRadius = 5;
break;
}
default: {
blockSize = size?.blockSize || 36;
borderRadius = size?.borderRadius || 5;
break;
}
}

return {
blockSize,
borderRadius,
};
};
133 changes: 43 additions & 90 deletions src/ActionIcon/index.tsx
Original file line number Diff line number Diff line change
@@ -1,64 +1,25 @@
import { Loader2 } from 'lucide-react';
import { forwardRef, useMemo } from 'react';
import { Suspense, forwardRef, lazy, useMemo } from 'react';

import Icon, { type IconProps } from '@/Icon';
import Spotlight from '@/Spotlight';
import Tooltip, { type TooltipProps } from '@/Tooltip';
import { DivProps } from '@/types';
import Icon, { type IconProps, type IconSizeConfig, type IconSizeType } from '@/Icon';
import type { TooltipProps } from '@/Tooltip';

import { calcSize } from './calcSize';
import { useStyles } from './style';

export type ActionIconSize =
| 'large'
| 'normal'
| 'small'
| 'site'
| {
blockSize?: number;
borderRadius?: number;
fontSize?: number;
strokeWidth?: number;
};
const Tooltip = lazy(() => import('@/Tooltip'));
const Spotlight = lazy(() => import('@/Spotlight'));

interface ActionIconSizeConfig extends IconSizeConfig {
blockSize?: number;
borderRadius?: number;
}

type ActionIconSizeType = 'site' | IconSizeType;

export type ActionIconSize = ActionIconSizeType | ActionIconSizeConfig;

const calcSize = (size?: ActionIconSize) => {
let blockSize: number;
let borderRadius: number;

switch (size) {
case 'large': {
blockSize = 44;
borderRadius = 8;
break;
}
case 'normal': {
blockSize = 36;
borderRadius = 5;
break;
}
case 'small': {
blockSize = 24;
borderRadius = 5;
break;
}
case 'site': {
blockSize = 34;
borderRadius = 5;
break;
}
default: {
blockSize = size?.blockSize || 36;
borderRadius = size?.borderRadius || 5;
break;
}
}

return {
blockSize,
borderRadius,
};
};

export interface ActionIconProps extends DivProps {
export interface ActionIconProps extends Omit<IconProps, 'size' | 'icon'> {
/**
* @description Whether the icon is active or not
* @default false
Expand All @@ -69,23 +30,16 @@ export interface ActionIconProps extends DivProps {
* @default false
*/
arrow?: boolean;
color?: IconProps['color'];
fill?: IconProps['fill'];
/**
* @description Glass blur style
* @default 'false'
*/
glass?: boolean;
/**
* @description The icon element to be rendered
* @type LucideIcon
*/
icon?: IconProps['icon'];
/**
* @description Set the loading status of ActionIcon
*/
loading?: boolean;

/**
* @description The position of the tooltip relative to the target
* @enum ["top","left","right","bottom","topLeft","topRight","bottomLeft","bottomRight","leftTop","leftBottom","rightTop","rightBottom"]
Expand Down Expand Up @@ -133,32 +87,28 @@ const ActionIcon = forwardRef<HTMLDivElement, ActionIconProps>(
children,
loading,
tooltipDelay = 0.5,
fillOpacity,
fillRule,
focusable,
...rest
},
ref,
) => {
const { styles, cx } = useStyles({ active: Boolean(active), glass: Boolean(glass) });

const { blockSize, borderRadius } = useMemo(() => calcSize(size), [size]);

const content = (
<>
{icon && (
<Icon
className={styles.icon}
color={color}
fill={fill}
icon={icon}
size={size === 'site' ? 'normal' : size}
/>
)}
{children}
</>
);
const iconProps = {
color,
fill,
fillOpacity,
fillRule,
focusable,
size: size === 'site' ? 'normal' : size,
};

const spin = (
<Icon color={color} icon={Loader2} size={size === 'site' ? 'normal' : size} spin />
);
const content = icon && <Icon className={styles.icon} icon={icon} {...iconProps} />;

const spin = <Icon icon={Loader2} {...iconProps} spin />;

const actionIconBlock = (
<div
Expand All @@ -168,23 +118,26 @@ const ActionIcon = forwardRef<HTMLDivElement, ActionIconProps>(
style={{ borderRadius, height: blockSize, width: blockSize, ...style }}
{...rest}
>
{spotlight && <Spotlight />}
<Suspense fallback={null}>{spotlight && <Spotlight />}</Suspense>
{loading ? spin : content}
{children}
</div>
);

if (!title) return actionIconBlock;

return (
<Tooltip
arrow={arrow}
mouseEnterDelay={tooltipDelay}
overlayStyle={{ pointerEvents: 'none' }}
placement={placement}
title={title}
>
{actionIconBlock}
</Tooltip>
<Suspense fallback={actionIconBlock}>
<Tooltip
arrow={arrow}
mouseEnterDelay={tooltipDelay}
overlayStyle={{ pointerEvents: 'none' }}
placement={placement}
title={title}
>
{actionIconBlock}
</Tooltip>
</Suspense>
);
},
);
Expand Down
10 changes: 5 additions & 5 deletions src/Alert/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useStyles } from './style';

export interface AlertProps extends AntAlertProps {
colorfulText?: boolean;
styleType: 'block' | 'ghost' | 'pure';
styleType?: 'block' | 'ghost' | 'pure';
}

const typeIcons = {
Expand All @@ -37,9 +37,9 @@ const Alert = memo<AlertProps>(
...rest
}) => {
const { theme, styles, cx } = useStyles({
closable,
closable: !!closable,
hasTitle: !!description,
showIcon,
showIcon: !!showIcon,
});

return (
Expand All @@ -54,9 +54,9 @@ const Alert = memo<AlertProps>(
closable={closable}
closeIcon={closeIcon || <ActionIcon color={colors(theme, type)} icon={X} size={'small'} />}
description={description}
icon={<Icon icon={typeIcons[type] || icon} />}
icon={<Icon icon={typeIcons[type] || icon} size={{ fontSize: description ? 24 : 18 }} />}
showIcon={showIcon}
style={{ color: colors(theme, type), ...style }}
style={{ color: colorfulText ? colors(theme, type) : undefined, ...style }}
type={type}
{...rest}
/>
Expand Down
73 changes: 39 additions & 34 deletions src/Alert/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,59 @@ import { createStyles } from 'antd-style';

export const useStyles = createStyles(
(
{ css, prefixCls },
{ cx, css, prefixCls },
{
closable,
hasTitle,
showIcon,
}: { closable?: boolean; hasTitle?: boolean; showIcon?: boolean },
) => {
const basePadding = hasTitle ? 16 : 12;

const baseBlockPadding = hasTitle ? 16 : 8;
const baseInlinePadding = hasTitle ? 16 : 12;
return {
colorfulText: css`
.${prefixCls}-alert-message,.${prefixCls}-alert-description {
color: inherit;
}
`,
container: css`
display: flex;
flex-direction: row;
gap: 12px;
align-items: flex-start;
container: cx(
css`
display: flex;
flex-direction: row;
gap: ${hasTitle ? 12 : 8}px;
align-items: flex-start;
padding-right: ${closable ? basePadding : basePadding * 1.5}px;
padding-left: ${showIcon ? basePadding : basePadding * 1.5}px;
padding-block: ${hasTitle ? 16 : 12}px;
padding-right: ${closable ? baseInlinePadding : baseInlinePadding * 1.5}px;
padding-left: ${showIcon ? baseInlinePadding : baseInlinePadding * 1.5}px;
padding-block: ${baseBlockPadding}px;
.${prefixCls}-alert-message {
font-weight: ${hasTitle ? 600 : 400};
line-height: 24px;
word-break: break-all;
}
.${prefixCls}-alert-description {
line-height: 1.5;
word-break: break-all;
opacity: 0.75;
}
.${prefixCls}-alert-icon {
display: flex;
align-items: center;
height: 24px;
margin: 0;
}
.${prefixCls}-alert-close-icon {
display: flex;
align-items: center;
height: 24px;
margin: 0;
}
`,
.${prefixCls}-alert-message {
font-weight: ${hasTitle ? 600 : 400};
line-height: 24px;
word-break: break-all;
}
.${prefixCls}-alert-icon {
display: flex;
align-items: center;
height: 24px;
margin: 0;
}
.${prefixCls}-alert-close-icon {
display: flex;
align-items: center;
height: 24px;
margin: 0;
}
`,
hasTitle &&
css`
.${prefixCls}-alert-description {
line-height: 1.5;
word-break: break-all;
opacity: 0.75;
}
`,
),
styleBlock: css`
border: none;
`,
Expand Down
4 changes: 2 additions & 2 deletions src/ChatItem/components/ErrorContent.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Alert } from 'antd';
import { memo } from 'react';
import { Flexbox } from 'react-layout-kit';

import Alert from '@/Alert';
import { ChatItemProps } from '@/ChatItem';

import { useStyles } from '../style';
Expand All @@ -17,7 +17,7 @@ const ErrorContent = memo<ErrorContentProps>(({ message, error, placement }) =>

return (
<Flexbox className={styles.errorContent} gap={8}>
<Alert showIcon type={'error'} {...error} />
<Alert closable={false} showIcon type={'error'} {...error} />
{message}
</Flexbox>
);
Expand Down
2 changes: 1 addition & 1 deletion src/ChatItem/type.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AlertProps } from 'antd';
import { ReactNode } from 'react';

import { AlertProps } from '@/Alert';
import { EditableMessageProps } from '@/EditableMessage';
import { DivProps, MetaData } from '@/types';

Expand Down
Loading

0 comments on commit acf84e2

Please sign in to comment.