Skip to content

Commit

Permalink
✨ feat: Add exrta to Alert
Browse files Browse the repository at this point in the history
  • Loading branch information
canisminor1990 committed Nov 17, 2023
1 parent 1c70635 commit 7c21f47
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 38 deletions.
28 changes: 28 additions & 0 deletions src/Alert/demos/Extra.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Alert, Highlighter } from '@lobehub/ui';

const demoError = {
details: {
exception: 'Validation filter failed',
msgId: 'Id-f5aab7304f6c754804f70000',
},
reasons: [
{
language: 'en',
message: 'Validation filter failed',
},
],
};
export default () => {
return (
<Alert
extra={
<Highlighter copyButtonSize={'small'} language={'json'} type={'pure'}>
{JSON.stringify(demoError, null, 2)}
</Highlighter>
}
message={'Quest error'}
showIcon
type={'error'}
/>
);
};
4 changes: 4 additions & 0 deletions src/Alert/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ title: Alert

<code src="./demos/index.tsx" nopadding></code>

## Extra

<code src="./demos/Extra.tsx" center></code>

## APIs

<API></API>
91 changes: 80 additions & 11 deletions src/Alert/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
import { type AlertProps as AntAlertProps, Alert as AntdAlert } from 'antd';
import { type AlertProps as AntAlertProps, Alert as AntdAlert, message } from 'antd';
import { camelCase } from 'lodash-es';
import { AlertTriangle, CheckCircle, Info, X, XCircle } from 'lucide-react';
import { memo } from 'react';
import {
AlertTriangle,
CheckCircle,
ChevronDown,
ChevronRight,
Info,
X,
XCircle,
} from 'lucide-react';
import { type ReactNode, memo, useState } from 'react';
import { Flexbox } from 'react-layout-kit';

import ActionIcon from '@/ActionIcon';
import Icon from '@/Icon';

import { useStyles } from './style';

export interface AlertProps extends AntAlertProps {
classNames?: {
alert?: string;
container?: string;
};
colorfulText?: boolean;
styleType?: 'block' | 'ghost' | 'pure';
extra?: ReactNode;
text?: {
detail?: string;
};
variant?: 'default' | 'block' | 'ghost' | 'pure';
}

const typeIcons = {
Expand All @@ -26,30 +43,37 @@ const colors = (theme: any, type: string = 'info', ...keys: string[]) =>
const Alert = memo<AlertProps>(
({
closeIcon,
closable,
closable = false,
description,
showIcon,
showIcon = true,
type = 'info',
styleType,
variant,
icon,
colorfulText = true,
style,
extra,
classNames,
text,
...rest
}) => {
const [expand, setExpand] = useState(true);
const { theme, styles, cx } = useStyles({
closable: !!closable,
hasTitle: !!description,
showIcon: !!showIcon,
});

return (
const alert = (
<AntdAlert
className={cx(
styles.container,
colorfulText && styles.colorfulText,
styleType === 'block' && styles.styleBlock,
styleType === 'ghost' && styles.styleGhost,
styleType === 'pure' && styles.stylePure,
!!extra && styles.hasExtra,
variant === 'block' && styles.variantBlock,
variant === 'ghost' && styles.variantGhost,
variant === 'pure' && styles.variantPure,
classNames?.alert,
!extra && styles.container,
)}
closable={closable}
closeIcon={closeIcon || <ActionIcon color={colors(theme, type)} icon={X} size={'small'} />}
Expand All @@ -61,6 +85,51 @@ const Alert = memo<AlertProps>(
{...rest}
/>
);

if (!extra) return alert;

return (
<Flexbox className={classNames?.container}>
{alert}
<Flexbox
className={cx(
styles.extra,
variant === 'block' && styles.variantBlock,
variant === 'ghost' && styles.variantGhost,
variant === 'pure' && styles.variantPure,
)}
style={{
background: colors(theme, type, 'bg'),
borderColor: colors(theme, type, 'border'),
color: colors(theme, type),
fontSize: description ? 14 : 12,
}}
>
<Flexbox
align={'center'}
className={cx(styles.extraHeader, variant === 'pure' && styles.variantPureExtraHeader)}
gap={message ? 6 : 10}
horizontal
style={{
borderColor: colors(theme, type, 'border'),
}}
>
<ActionIcon
color={colorfulText ? colors(theme, type) : undefined}
icon={expand ? ChevronDown : ChevronRight}
onClick={() => setExpand(!expand)}
size={{ blockSize: 24, fontSize: 18 }}
/>
<div>{text?.detail || 'Show Details'}</div>
</Flexbox>
{expand && (
<div className={cx(styles.extraBody, variant === 'pure' && styles.variantPure)}>
{extra}
</div>
)}
</Flexbox>
</Flexbox>
);
},
);

Expand Down
47 changes: 41 additions & 6 deletions src/Alert/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createStyles } from 'antd-style';

export const useStyles = createStyles(
(
{ cx, css, prefixCls },
{ cx, token, css, prefixCls },
{
closable,
hasTitle,
Expand All @@ -19,11 +19,14 @@ export const useStyles = createStyles(
`,
container: cx(
css`
position: relative;
display: flex;
flex-direction: row;
gap: ${hasTitle ? 12 : 8}px;
align-items: flex-start;
max-width: 100%;
padding-right: ${closable ? baseInlinePadding : baseInlinePadding * 1.5}px;
padding-left: ${showIcon ? baseInlinePadding : baseInlinePadding * 1.5}px;
padding-block: ${baseBlockPadding}px;
Expand Down Expand Up @@ -55,17 +58,49 @@ export const useStyles = createStyles(
}
`,
),
styleBlock: css`
extra: css`
position: relative;
overflow: hidden;
max-width: 100%;
border: 1px solid;
border-top: none;
border-bottom-right-radius: ${token.borderRadiusLG}px;
border-bottom-left-radius: ${token.borderRadiusLG}px;
`,
extraBody: css`
overflow-x: auto;
width: 100%;
padding-block: ${baseBlockPadding}px;
padding-inline: ${baseInlinePadding}px;
`,
extraHeader: css`
padding-block: ${baseBlockPadding * 0.75}px;
padding-inline: ${baseInlinePadding * 0.75}px;
border-top: 1px dashed;
`,
hasExtra: css`
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
`,
variantBlock: css`
border: none;
`,
styleGhost: css`
background: transparent;
variantGhost: css`
background: transparent !important;
`,
stylePure: css`
variantPure: css`
padding: 0 !important;
background: transparent;
background: transparent !important;
border: none;
`,
variantPureExtraHeader: css`
margin-top: ${baseBlockPadding}px;
margin-left: ${-baseInlinePadding * 0.25}px;
padding-inline: 0;
`,
};
},
);
5 changes: 2 additions & 3 deletions src/ChatItem/components/ErrorContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ const ErrorContent = memo<ErrorContentProps>(({ message, error, placement }) =>
const { styles } = useStyles({ placement });

return (
<Flexbox className={styles.errorContent} gap={8}>
<Alert closable={false} showIcon type={'error'} {...error} />
{message}
<Flexbox className={styles.errorContainer}>
<Alert closable={false} extra={message} showIcon type={'error'} {...error} />
</Flexbox>
);
});
Expand Down
33 changes: 31 additions & 2 deletions src/ChatItem/demos/Alert.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
import { ChatItem, ChatItemProps, StoryBook, useControls, useCreateStore } from '@lobehub/ui';
import {
ChatItem,
ChatItemProps,
Highlighter,
StoryBook,
useControls,
useCreateStore,
} from '@lobehub/ui';

import { avatar } from './data';

const demoError = {
details: {
exception:
'Validation filter failedId-f5aab7304f6c754804f70000Id-f5aab7304f6c754804f70000Id-f5aab7304f6c754804f70000Id-f5aab7304f6c754804f70000Id-f5aab7304f6c754804f70000Id-f5aab7304f6c754804f70000',
msgId:
'Id-f5aab7304f6c754804f70000Id-f5aab7304f6c754804f70000Id-f5aab7304f6c754804f70000Id-f5aab7304f6c754804f70000Id-f5aab7304f6c754804f70000',
},
reasons: [
{
language: 'en',
message: 'Validation filter failed',
},
],
};
export default () => {
const store = useCreateStore();
const control: ChatItemProps['error'] | any = useControls(
Expand All @@ -18,7 +39,15 @@ export default () => {

return (
<StoryBook levaStore={store}>
<ChatItem avatar={avatar} error={control} />
<ChatItem
avatar={avatar}
error={control}
errorMessage={
<Highlighter copyButtonSize={'small'} language={'json'} type={'pure'}>
{JSON.stringify(demoError, null, 2)}
</Highlighter>
}
/>
</StoryBook>
);
};
20 changes: 13 additions & 7 deletions src/ChatItem/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const useStyles = createStyles(
return {
actions: cx(
css`
flex: none;
align-self: ${type === 'block'
? 'flex-end'
: placement === 'left'
Expand All @@ -80,9 +81,12 @@ export const useStyles = createStyles(
type === 'pure' && pureContainerStylish,
css`
position: relative;
overflow: hidden;
width: 100%;
max-width: 100vw;
padding: 12px 16px;
padding: 16px;
time {
display: inline-block;
Expand Down Expand Up @@ -133,11 +137,12 @@ export const useStyles = createStyles(
editingInput: css`
width: 100%;
`,
errorContent: css`
${responsive.mobile} {
width: 100%;
}
errorContainer: css`
position: relative;
overflow: hidden;
width: 100%;
`,

loading: css`
position: absolute;
right: ${placement === 'left' ? '-4px' : 'unset'};
Expand All @@ -162,10 +167,11 @@ export const useStyles = createStyles(
editingStylish,
css`
position: relative;
overflow: hidden;
max-width: 100%;
${responsive.mobile} {
overflow-x: auto;
max-width: 100%;
}
`,
),
Expand All @@ -174,10 +180,10 @@ export const useStyles = createStyles(
css`
position: relative;
overflow-x: hidden;
max-width: 100%;
${responsive.mobile} {
flex-direction: column !important;
width: 100%;
}
`,
),
Expand Down
Loading

0 comments on commit 7c21f47

Please sign in to comment.