Skip to content

Commit e56aafb

Browse files
GolodhrosB-T-D
authored andcommitted
chore: tweaks notices icon color, storybook and spacing (amundsen-io#2106)
Signed-off-by: Marcos Iglesias <[email protected]>
1 parent d943152 commit e56aafb

File tree

4 files changed

+190
-10
lines changed

4 files changed

+190
-10
lines changed

frontend/amundsen_application/static/js/components/Alert/alert.story.tsx

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,43 @@ import { NoticeSeverity } from 'config/config-types';
1010
import StorySection from '../StorySection';
1111
import { Alert, AlertList } from '.';
1212

13+
const ALERT_CONTAINER_WIDTH = 425;
14+
1315
export const AlertStory = (): React.ReactNode => (
1416
<>
15-
<StorySection title="Alert">
17+
<StorySection title="Alert" width={ALERT_CONTAINER_WIDTH}>
1618
<Alert
1719
message="Alert text that can be short"
1820
onAction={() => {
1921
alert('action executed!');
2022
}}
2123
/>
2224
</StorySection>
23-
<StorySection title="Alert with long text">
24-
<Alert message="Lorem ipsum dolor sit amet consectetur adipisicing elit. Laboriosam perspiciatis non ipsa officia expedita magnam mollitia, excepturi iste eveniet qui nisi eum illum, quas voluptas, reprehenderit quam molestias cum quisquam!" />
25+
<StorySection title="Alert with long text" width={ALERT_CONTAINER_WIDTH}>
26+
<Alert message="Lorem ipsum dolor sit amet consectetur adipisicing elit. Laboriosam perspiciatis non ipsa officia expedita magnam mollitia, excepturi iste eveniet qui nisi eum illum!" />
27+
</StorySection>
28+
<StorySection
29+
title="Alert with medium long text and action"
30+
width={ALERT_CONTAINER_WIDTH}
31+
>
32+
<Alert
33+
actionText="Action Text"
34+
onAction={() => {
35+
alert('action executed!');
36+
}}
37+
message="Lorem ipsum dolor sit amet consectetur adipisicing elit. Laboriosam perspiciatis"
38+
/>
2539
</StorySection>
26-
<StorySection title="Alert with long text and action">
40+
<StorySection
41+
title="Alert with long text and action"
42+
width={ALERT_CONTAINER_WIDTH}
43+
>
2744
<Alert
2845
actionText="Action Text"
2946
onAction={() => {
3047
alert('action executed!');
3148
}}
32-
message="Lorem ipsum dolor sit amet consectetur adipisicing elit. Laboriosam perspiciatis non ipsa officia expedita magnam mollitia, excepturi iste eveniet qui nisi eum illum, quas voluptas, reprehenderit quam molestias cum quisquam!"
49+
message="Lorem ipsum dolor sit amet consectetur adipisicing elit. Laboriosam perspiciatis non ipsa officia expedita magnam mollitia, excepturi iste eveniet qui nisi eum illum!"
3350
/>
3451
</StorySection>
3552
</>
Lines changed: 161 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,164 @@
11
// Copyright Contributors to the Amundsen project.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
export * from './Alert';
5-
export * from './AlertList';
4+
import * as React from 'react';
5+
import SanitizedHTML from 'react-sanitized-html';
6+
import { Modal } from 'react-bootstrap';
7+
8+
import { IconSizes } from 'interfaces';
9+
import { NoticeSeverity } from 'config/config-types';
10+
import { AlertIcon, InformationIcon } from 'components/SVGIcons';
11+
import { DefinitionList } from 'components/DefinitionList';
12+
13+
import './styles.scss';
14+
15+
const SEVERITY_TO_COLOR_MAP = {
16+
[NoticeSeverity.INFO]: '#3a97d3', // cyan50
17+
[NoticeSeverity.WARNING]: '#FF8D1F', // $amber70
18+
[NoticeSeverity.ALERT]: '#b8072c', // $red70
19+
};
20+
const SEVERITY_TO_SEVERITY_CLASS = {
21+
[NoticeSeverity.INFO]: 'is-info',
22+
[NoticeSeverity.WARNING]: 'is-warning',
23+
[NoticeSeverity.ALERT]: 'is-alert',
24+
};
25+
const OPEN_PAYLOAD_CTA = 'See details';
26+
const PAYLOAD_MODAL_TITLE = 'Summary';
27+
const PAYLOAD_MODAL_CLOSE_BTN = 'Close';
28+
29+
const DEFINITION_WIDTH = 150;
30+
31+
export interface AlertProps {
32+
/** Message to show in the alert */
33+
message: string | React.ReactNode;
34+
/** Severity of the alert (info, warning, or alert) */
35+
severity?: NoticeSeverity;
36+
/** Link passed to set as the action (for routing links) */
37+
actionLink?: React.ReactNode;
38+
/** Text of the link action */
39+
actionText?: string;
40+
/** Href for the link action */
41+
actionHref?: string;
42+
/** Callback to call when the action is clicked */
43+
onAction?: (event: React.MouseEvent<HTMLButtonElement>) => void;
44+
/** Optional extra info to render in a modal */
45+
payload?: Record<string, string>;
46+
}
47+
48+
const Alert: React.FC<AlertProps> = ({
49+
message,
50+
severity = NoticeSeverity.WARNING,
51+
onAction,
52+
actionText,
53+
actionHref,
54+
actionLink,
55+
payload,
56+
}: AlertProps) => {
57+
const [showPayloadModal, setShowPayloadModal] = React.useState(false);
58+
let action: null | React.ReactNode = null;
59+
60+
const handleSeeDetails = (e: React.MouseEvent<HTMLButtonElement>) => {
61+
onAction?.(e);
62+
setShowPayloadModal(true);
63+
};
64+
const handleModalClose = () => {
65+
setShowPayloadModal(false);
66+
};
67+
68+
if (payload) {
69+
action = (
70+
<button
71+
type="button"
72+
className="btn btn-link btn-payload"
73+
onClick={handleSeeDetails}
74+
>
75+
{OPEN_PAYLOAD_CTA}
76+
</button>
77+
);
78+
}
79+
80+
if (actionText && onAction) {
81+
action = (
82+
<button type="button" className="btn btn-link" onClick={onAction}>
83+
{actionText}
84+
</button>
85+
);
86+
}
87+
88+
if (actionText && actionHref) {
89+
action = (
90+
<a className="action-link" href={actionHref}>
91+
{actionText}
92+
</a>
93+
);
94+
}
95+
96+
if (actionLink) {
97+
action = actionLink;
98+
}
99+
100+
let iconComponent: React.ReactNode = null;
101+
102+
if (severity === NoticeSeverity.INFO) {
103+
iconComponent = (
104+
<InformationIcon
105+
fill={SEVERITY_TO_COLOR_MAP[severity]}
106+
size={IconSizes.REGULAR}
107+
/>
108+
);
109+
} else {
110+
iconComponent = (
111+
<AlertIcon
112+
stroke={SEVERITY_TO_COLOR_MAP[severity]}
113+
size={IconSizes.SMALL}
114+
/>
115+
);
116+
}
117+
118+
// If we receive a string, we want to sanitize any html inside
119+
const formattedMessage =
120+
typeof message === 'string' ? <SanitizedHTML html={message} /> : message;
121+
122+
const payloadDefinitions = payload
123+
? Object.keys(payload).map((key) => ({
124+
term: key,
125+
description: payload[key],
126+
}))
127+
: null;
128+
129+
return (
130+
<div className={`alert ${SEVERITY_TO_SEVERITY_CLASS[severity]}`}>
131+
{iconComponent}
132+
<p className="alert-message">{formattedMessage}</p>
133+
{action && <span className="alert-action">{action}</span>}
134+
{payloadDefinitions && (
135+
<Modal
136+
className="alert-payload-modal"
137+
show={showPayloadModal}
138+
onHide={handleModalClose}
139+
>
140+
<Modal.Header closeButton onHide={handleModalClose}>
141+
<Modal.Title>{PAYLOAD_MODAL_TITLE}</Modal.Title>
142+
</Modal.Header>
143+
<Modal.Body>
144+
<DefinitionList
145+
definitions={payloadDefinitions}
146+
termWidth={DEFINITION_WIDTH}
147+
/>
148+
</Modal.Body>
149+
<Modal.Footer>
150+
<button
151+
className="btn btn-primary payload-modal-close"
152+
type="button"
153+
onClick={handleModalClose}
154+
>
155+
{PAYLOAD_MODAL_CLOSE_BTN}
156+
</button>
157+
</Modal.Footer>
158+
</Modal>
159+
)}
160+
</div>
161+
);
162+
};
163+
164+
export default Alert;

frontend/amundsen_application/static/js/components/Alert/styles.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ $alert-alert-background: #ffe4dd;
2121
.alert {
2222
border-radius: $alert-border-radius;
2323
display: flex;
24-
padding: $spacer-1 $spacer-1 * 1.5 $spacer-1 $spacer-2;
24+
padding: $spacer-1 $spacer-1 $spacer-1 $spacer-2;
2525
justify-content: flex-start;
2626
box-shadow: $elevation-level2;
2727
border: none;
@@ -49,7 +49,7 @@ $alert-alert-background: #ffe4dd;
4949
.info-svg-icon {
5050
flex-shrink: 0;
5151
align-self: center;
52-
margin-right: $spacer-1;
52+
margin-right: $spacer-2;
5353
}
5454

5555
.alert-action {

frontend/amundsen_application/static/js/components/StorySection/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,24 @@
33

44
import * as React from 'react';
55

6+
const DEFAULT_WIDTH = 600;
7+
68
export type BlockProps = {
79
children: React.ReactNode;
810
title: string;
911
text?: string | React.ReactNode;
12+
width?: number;
1013
};
1114

1215
const StorySection: React.FC<BlockProps> = ({
1316
children,
1417
text,
1518
title,
19+
width = DEFAULT_WIDTH,
1620
}: BlockProps) => (
1721
<div
1822
className="story-section"
19-
style={{ padding: '2em 2em 1em', maxWidth: 600 }}
23+
style={{ padding: '2em 2em 1em', maxWidth: width }}
2024
>
2125
<h1 className="text-headline-w1">{title}</h1>
2226
{text && <p className="text-body-w1">{text}</p>}

0 commit comments

Comments
 (0)