/
Alert.tsx
122 lines (103 loc) · 3 KB
/
Alert.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import React, { forwardRef } from 'react';
import {
DefaultProps,
MantineColor,
Selectors,
MantineNumberSize,
useComponentDefaultProps,
} from '@mantine/styles';
import { useId } from '@mantine/hooks';
import { CloseButton } from '../CloseButton';
import { Box } from '../Box';
import useStyles, { AlertStylesParams } from './Alert.styles';
export type AlertVariant = 'filled' | 'outline' | 'light';
export type AlertStylesNames = Selectors<typeof useStyles>;
export interface AlertProps
extends DefaultProps<AlertStylesNames, AlertStylesParams>,
Omit<React.ComponentPropsWithoutRef<'div'>, 'title'> {
/** Alert title */
title?: React.ReactNode;
/** Controls Alert background, color and border styles, defaults to light */
variant?: AlertVariant;
/** Alert message */
children: React.ReactNode;
/** Color from theme.colors */
color?: MantineColor;
/** Icon displayed next to title */
icon?: React.ReactNode;
/** True to display close button */
withCloseButton?: boolean;
/** Called when close button is clicked */
onClose?(): void;
/** Close button aria-label */
closeButtonLabel?: string;
/** Radius from theme.radius, or number to set border-radius in px, defaults to theme.defaultRadius */
radius?: MantineNumberSize;
}
const defaultProps: Partial<AlertProps> = {
variant: 'light',
};
export const Alert = forwardRef<HTMLDivElement, AlertProps>((props: AlertProps, ref) => {
const {
id,
className,
title,
variant,
children,
color,
classNames,
icon,
styles,
onClose,
radius,
withCloseButton,
closeButtonLabel,
unstyled,
...others
} = useComponentDefaultProps('Alert', defaultProps, props);
const { classes, cx } = useStyles(
{ color, radius, variant },
{ classNames, styles, unstyled, name: 'Alert' }
);
const rootId = useId(id);
const titleId = title && `${rootId}-title`;
const bodyId = `${rootId}-body`;
return (
<Box
id={rootId}
role="alert"
aria-labelledby={titleId}
aria-describedby={bodyId}
className={cx(classes.root, classes[variant], className)}
ref={ref}
{...others}
>
<div className={classes.wrapper}>
{icon && <div className={classes.icon}>{icon}</div>}
<div className={classes.body}>
{title && (
<div className={classes.title} data-with-close-button={withCloseButton || undefined}>
<span id={titleId} className={classes.label}>
{title}
</span>
</div>
)}
{withCloseButton && (
<CloseButton
className={classes.closeButton}
onClick={onClose}
variant="transparent"
size={16}
iconSize={16}
aria-label={closeButtonLabel}
/>
)}
<div id={bodyId} className={classes.message}>
{children}
</div>
</div>
</div>
</Box>
);
});
Alert.displayName = '@mantine/core/Alert';