⚡️ feat: create inline notification component
This commit is contained in:
parent
10fae09d15
commit
d1cd144dfc
@ -0,0 +1,78 @@
|
|||||||
|
import { VariantProps, tv } from 'tailwind-variants';
|
||||||
|
|
||||||
|
export const inlineNotificationTheme = tv({
|
||||||
|
slots: {
|
||||||
|
wrapper: ['rounded-xl', 'flex', 'gap-2', 'items-start', 'w-full', 'border'],
|
||||||
|
content: ['flex', 'flex-col', 'gap-1'],
|
||||||
|
title: [],
|
||||||
|
description: [],
|
||||||
|
icon: ['flex', 'items-start'],
|
||||||
|
},
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
info: {
|
||||||
|
wrapper: ['border-border-info-light', 'bg-base-bg-emphasized-info'],
|
||||||
|
title: ['text-elements-on-emphasized-info'],
|
||||||
|
description: ['text-elements-on-emphasized-info'],
|
||||||
|
icon: ['text-elements-info'],
|
||||||
|
},
|
||||||
|
danger: {
|
||||||
|
wrapper: ['border-border-danger-light', 'bg-base-bg-emphasized-danger'],
|
||||||
|
title: ['text-elements-on-emphasized-danger'],
|
||||||
|
description: ['text-elements-on-emphasized-danger'],
|
||||||
|
icon: ['text-elements-danger'],
|
||||||
|
},
|
||||||
|
warning: {
|
||||||
|
wrapper: [
|
||||||
|
'border-border-warning-light',
|
||||||
|
'bg-base-bg-emphasized-warning',
|
||||||
|
],
|
||||||
|
title: ['text-elements-on-emphasized-warning'],
|
||||||
|
description: ['text-elements-on-emphasized-warning'],
|
||||||
|
icon: ['text-elements-warning'],
|
||||||
|
},
|
||||||
|
success: {
|
||||||
|
wrapper: [
|
||||||
|
'border-border-success-light',
|
||||||
|
'bg-base-bg-emphasized-success',
|
||||||
|
],
|
||||||
|
title: ['text-elements-on-emphasized-success'],
|
||||||
|
description: ['text-elements-on-emphasized-success'],
|
||||||
|
icon: ['text-elements-success'],
|
||||||
|
},
|
||||||
|
generic: {
|
||||||
|
wrapper: ['border-border-separator', 'bg-base-bg-emphasized'],
|
||||||
|
title: ['text-elements-high-em'],
|
||||||
|
description: ['text-elements-on-emphasized-info'],
|
||||||
|
icon: ['text-elements-high-em'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
sm: {
|
||||||
|
wrapper: ['px-2', 'py-2'],
|
||||||
|
title: ['leading-4', 'text-xs'],
|
||||||
|
description: ['leading-4', 'text-xs'],
|
||||||
|
icon: ['h-4', 'w-4'],
|
||||||
|
},
|
||||||
|
md: {
|
||||||
|
wrapper: ['px-3', 'py-3'],
|
||||||
|
title: ['leading-5', 'tracking-[-0.006em]', 'text-sm'],
|
||||||
|
description: ['leading-5', 'tracking-[-0.006em]', 'text-sm'],
|
||||||
|
icon: ['h-5', 'w-5'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hasDescription: {
|
||||||
|
true: {
|
||||||
|
title: ['font-medium'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: 'generic',
|
||||||
|
size: 'md',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export type InlineNotificationTheme = VariantProps<
|
||||||
|
typeof inlineNotificationTheme
|
||||||
|
>;
|
@ -0,0 +1,49 @@
|
|||||||
|
import React, { ReactNode, useCallback } from 'react';
|
||||||
|
import { ComponentPropsWithoutRef } from 'react';
|
||||||
|
import {
|
||||||
|
InlineNotificationTheme,
|
||||||
|
inlineNotificationTheme,
|
||||||
|
} from './InlineNotification.theme';
|
||||||
|
import { InfoSquareIcon } from 'components/shared/CustomIcon';
|
||||||
|
import { cloneIcon } from 'utils/cloneIcon';
|
||||||
|
|
||||||
|
export interface InlineNotificationProps
|
||||||
|
extends ComponentPropsWithoutRef<'div'>,
|
||||||
|
InlineNotificationTheme {
|
||||||
|
title: string;
|
||||||
|
description?: string;
|
||||||
|
icon?: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const InlineNotification = ({
|
||||||
|
className,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
size,
|
||||||
|
variant,
|
||||||
|
icon,
|
||||||
|
...props
|
||||||
|
}: InlineNotificationProps) => {
|
||||||
|
const {
|
||||||
|
wrapper,
|
||||||
|
content,
|
||||||
|
title: titleClass,
|
||||||
|
description: descriptionClass,
|
||||||
|
icon: iconClass,
|
||||||
|
} = inlineNotificationTheme({ size, variant, hasDescription: !!description });
|
||||||
|
|
||||||
|
const renderIcon = useCallback(() => {
|
||||||
|
if (!icon) return <InfoSquareIcon className={iconClass()} />;
|
||||||
|
return cloneIcon(icon, { className: iconClass() });
|
||||||
|
}, [icon])();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div {...props} className={wrapper({ className })}>
|
||||||
|
{renderIcon}
|
||||||
|
<div className={content()}>
|
||||||
|
<p className={titleClass()}>{title}</p>
|
||||||
|
{description && <p className={descriptionClass()}>{description}</p>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1 @@
|
|||||||
|
export * from './InlineNotification';
|
Loading…
Reference in New Issue
Block a user