Skip to content

Commit 02447b2

Browse files
feat(ui): sync message component with vue (#1522)
* refactor: add gap between icon and text message * feat: add close message functionality * feat: add codeblock for message demo * feat: add serverity for message * feat: add showIcon to show default icon * feat: add example message using showIcon prop * refactor: update message prop to support type react node * refactor: update translations * refactor: update message to sentence case * feat: add usage section and default column in properties table * refactor: update style to align close message to the right * refactor: udpate style to align close icon to the right * refactor: update the color of message * refactor: update the color contrast * refactor: update color * refactor: add translations * refactor: change the background color to make ligher * refactor: add translations for description of props * feat: add support for passing array of messages * refactor: remove width of close message icon * refactor: update translations
1 parent 1debe40 commit 02447b2

6 files changed

Lines changed: 363 additions & 22 deletions

File tree

apps/demo/src/Views/Ui/components/Message.tsx

Lines changed: 162 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,56 @@
11
import { useTranslation } from "@dzangolab/react-i18n";
2-
import { Button, Message, Page } from "@dzangolab/react-ui";
2+
import { Button, Message, Page, TDataTable } from "@dzangolab/react-ui";
33
import { useNavigate } from "react-router-dom";
44

5-
import { Section } from "../../../components/Demo";
5+
import { CodeBlock, Section } from "../../../components/Demo";
66

77
export const MessageDemo = () => {
88
const [t] = useTranslation("ui");
99
const navigate = useNavigate();
1010

11+
const propertiesData = [
12+
{
13+
default: "false",
14+
description: t("message.propertiesDescription.enableClose"),
15+
prop: "enableClose",
16+
type: "boolean",
17+
},
18+
{
19+
default: "-",
20+
description: t("message.propertiesDescription.icon"),
21+
prop: "icon",
22+
type: "string | ReactNode",
23+
},
24+
{
25+
default: "-",
26+
description: t("message.propertiesDescription.message"),
27+
prop: "message",
28+
type: "string | string[] | ReactNode",
29+
},
30+
{
31+
default: "-",
32+
description: t("message.propertiesDescription.onClose"),
33+
prop: "onClose",
34+
type: "() => void",
35+
},
36+
{
37+
default: "info",
38+
description: t("message.propertiesDescription.severity"),
39+
prop: "severity",
40+
type: `"info" | "success" | "warning" | "danger"`,
41+
},
42+
{
43+
default: "true",
44+
description: t("message.propertiesDescription.showIcon"),
45+
prop: "showIcon",
46+
type: "boolean",
47+
},
48+
];
49+
1150
return (
1251
<Page
1352
title={t("message.title")}
53+
subtitle={t("message.subtitle")}
1454
toolbar={
1555
<Button
1656
label={t("buttons.back")}
@@ -20,10 +60,127 @@ export const MessageDemo = () => {
2060
/>
2161
}
2262
>
23-
<Section>
63+
<Section title={t("headers.usage")}>
64+
<p>{t("common.usage", { component: "Message" })}</p>
65+
<CodeBlock exampleCode='import { Message } from "@dzangolab/react-ui"' />
66+
</Section>
67+
68+
<Section title={t("message.usage.basic")}>
69+
<Message message={t("message.contents.content1")} />
70+
<CodeBlock exampleCode='<Message message="Season sale: Up to 50% off selected items!" />' />
71+
</Section>
72+
73+
<Section title={t("message.usage.customMessage")}>
74+
<Message message={<b>{t("message.contents.content1")}</b>} />
75+
<CodeBlock exampleCode="<Message message={<b>Season sale: Up to 50% off selected items!</b>} />" />
76+
</Section>
77+
78+
<Section title={t("message.usage.arrayMessage")}>
79+
<Message
80+
message={[
81+
t("message.contents.content1"),
82+
t("message.contents.content2"),
83+
t("message.contents.content3"),
84+
]}
85+
enableClose={true}
86+
/>
87+
<CodeBlock
88+
exampleCode="<Message
89+
message={
90+
[
91+
'Season Sale: Enjoy massive discounts with up to 50% off on a wide range of selected items — from fashion to electronics, don’t miss out on these limited-time offers!',
92+
'New features just launched! Check them out!',
93+
'New Year, New You: Start fresh with our services!'
94+
]}
95+
enableClose={true}
96+
/>"
97+
/>
98+
</Section>
99+
100+
<Section title={t("message.usage.icons.icon")}>
101+
<Message
102+
message={t("message.contents.content2")}
103+
icon="pi pi-android"
104+
/>
105+
<CodeBlock
106+
exampleCode='<Message
107+
message="New features just launched! Check them out!"
108+
icon="pi pi-android"
109+
/>'
110+
/>
111+
</Section>
112+
113+
<Section title={t("message.usage.icons.customIcon")}>
114+
<Message
115+
message={t("message.contents.content3")}
116+
icon={<i className="pi pi-bell" />}
117+
/>
118+
<CodeBlock
119+
exampleCode='<Message
120+
message="New Year, New You: Start fresh with our services!"
121+
icon={<i className="pi pi-bell" />}
122+
/>'
123+
/>
124+
</Section>
125+
126+
<Section title={t("message.usage.enableClose")}>
24127
<Message
25-
message="This is a very important message."
26-
icon={<i className="pi pi-info-circle" />}
128+
enableClose={true}
129+
icon={<i className="pi pi-bell" />}
130+
message={t("message.contents.content4")}
131+
/>
132+
<CodeBlock
133+
exampleCode='<Message
134+
message="We value your feedback: take our quick survey!"
135+
icon={<i className="pi pi-bell" />}
136+
enableClose={true}
137+
/>'
138+
/>
139+
</Section>
140+
141+
<Section title={t("message.usage.severity")}>
142+
<Message message={t("message.contents.info")} severity="info" />
143+
<Message message={t("message.contents.success")} severity="success" />
144+
<Message message={t("message.contents.warning")} severity="warning" />
145+
<Message message={t("message.contents.danger")} severity="danger" />
146+
147+
<CodeBlock
148+
exampleCode='<Message message="Info message" severity="info" />
149+
<Message message="Success message" severity="success" />
150+
<Message message="Warning message" severity="warning" />
151+
<Message message="Danger message" severity="danger" />'
152+
/>
153+
</Section>
154+
<Section title={t("message.usage.hideIcon")}>
155+
<Message message={t("message.contents.content1")} showIcon={false} />
156+
<CodeBlock exampleCode='<Message message="Season sale: Up to 50% off selected items!" showIcon={false} />' />
157+
</Section>
158+
<Section
159+
title={t("headers.propertiesValue", {
160+
value: "MessageProperties",
161+
})}
162+
>
163+
<TDataTable
164+
columns={[
165+
{
166+
accessorKey: "prop",
167+
header: t("propertiesTable.header.properties"),
168+
},
169+
{
170+
accessorKey: "type",
171+
header: t("propertiesTable.header.type"),
172+
},
173+
{
174+
accessorKey: "default",
175+
header: t("propertiesTable.header.default"),
176+
},
177+
{
178+
accessorKey: "description",
179+
header: t("propertiesTable.header.description"),
180+
},
181+
]}
182+
data={propertiesData}
183+
paginated={false}
27184
/>
28185
</Section>
29186
</Page>

apps/demo/src/locales/en/ui.json

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@
55
"common": {
66
"usage": "To use the {{component}} component, simply import it into your React file:"
77
},
8+
"propertiesTable": {
9+
"header": {
10+
"default": "Default",
11+
"description": "Description",
12+
"properties": "Properties",
13+
"type": "Type"
14+
}
15+
},
816
"headers": {
917
"buttons": "Buttons",
1018
"data": "Data",
@@ -215,7 +223,39 @@
215223
}
216224
},
217225
"message": {
218-
"title": "Message"
226+
"contents": {
227+
"content1": "Season Sale: Enjoy massive discounts with up to 50% off on a wide range of selected items — from fashion to electronics, don’t miss out on these limited-time offers!",
228+
"content2": "New features just launched! Check them out!",
229+
"content3": "New Year, New You: Start fresh with our services!",
230+
"content4": "We value your feedback: take our quick survey!",
231+
"content5": "Warning: Limited time only! Sale ends soon!",
232+
"danger": "Danger message",
233+
"info": "Info message",
234+
"success": "Success message",
235+
"warning": "Warning message"
236+
},
237+
"subtitle": "The Message component displays contextual messages with optional icons and a closable action. It supports custom slots, making it flexible for various use cases.",
238+
"propertiesDescription": {
239+
"enableClose": "Displays a close icon if true, allowing the message to be dismissed.",
240+
"icon": "Icon to display alongside the message.",
241+
"message": "The message text to display in the component.",
242+
"onClose": "Function to be called when the message is closed.",
243+
"severity": "Defines the styling severity of the message. Defaults to 'info'.",
244+
"showIcon": "Show default icon based on severity or custom icon if provided."
245+
},
246+
"title": "Message",
247+
"usage": {
248+
"arrayMessage": "Array of message",
249+
"basic": "Basic",
250+
"customMessage": "Custom message",
251+
"enableClose": "Enable close",
252+
"hideIcon": "Hide default icon",
253+
"icons": {
254+
"customIcon": "Custom icon",
255+
"icon": "Icon"
256+
},
257+
"severity": "Severity"
258+
}
219259
},
220260
"modal": {
221261
"title": "Modal",

apps/demo/src/locales/fr/ui.json

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@
55
"common": {
66
"usage": "To use the {{component}} component, simply import it into your React file (fr):"
77
},
8+
"propertiesTable": {
9+
"header": {
10+
"default": "Default (fr)",
11+
"description": "Description (fr)",
12+
"properties": "Properties (fr)",
13+
"type": "Type (fr)"
14+
}
15+
},
816
"headers": {
917
"buttons": "Buttons (fr)",
1018
"data": "Data (fr)",
@@ -215,7 +223,39 @@
215223
}
216224
},
217225
"message": {
218-
"title": "Message (fr)"
226+
"contents": {
227+
"content1": "Season Sale: Enjoy massive discounts with up to 50% off on a wide range of selected items — from fashion to electronics, don’t miss out on these limited-time offers! (fr)",
228+
"content2": "New features just launched! Check them out! (fr)",
229+
"content3": "New Year, New You: Start fresh with our services! (fr)",
230+
"content4": "We value your feedback: take our quick survey! (fr)",
231+
"content5": "Warning: Limited time only! Sale ends soon! (fr)",
232+
"danger": "Danger message (fr)",
233+
"info": "Info message (fr)",
234+
"success": "Success message (fr)",
235+
"warning": "Warning message (fr)"
236+
},
237+
"subtitle": "The Message component displays contextual messages with optional icons and a closable action. It supports custom slots, making it flexible for various use cases. (fr)",
238+
"propertiesDescription": {
239+
"enableClose": "Displays a close icon if true, allowing the message to be dismissed. (fr)",
240+
"icon": "Icon to display alongside the message. (fr)",
241+
"message": "The message text to display in the component. (fr)",
242+
"onClose": "Function to be called when the message is closed. (fr)",
243+
"severity": "Defines the styling severity of the message. Defaults to 'info'. (fr)",
244+
"showIcon": "Show default icon based on severity or custom icon if provided. (fr)"
245+
},
246+
"title": "Message (fr)",
247+
"usage": {
248+
"arrayMessage": "Array of message (fr)",
249+
"basic": "Basic (fr)",
250+
"customMessage": "Custom message (fr)",
251+
"enableClose": "Enable close (fr)",
252+
"hideIcon": "Hide default icon (fr)",
253+
"icons": {
254+
"customIcon": "Custom icon (fr)",
255+
"icon": "Icon (fr)"
256+
},
257+
"severity": "Severity (fr)"
258+
}
219259
},
220260
"modal": {
221261
"title": "Modal (fr)",

packages/ui/src/Message/index.tsx

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,84 @@
1-
import { ReactNode } from "react";
1+
import { ReactNode, useState } from "react";
22

33
type MessageProperties = {
4-
message: string;
5-
icon?: string | ReactNode;
4+
enableClose?: boolean;
5+
icon?: ReactNode;
6+
message: string[] | ReactNode;
7+
onClose?: () => void;
8+
severity?: "info" | "success" | "warning" | "danger";
9+
showIcon?: boolean;
610
};
711

8-
const Message = ({ message, icon }: MessageProperties) => {
12+
const Message = ({
13+
onClose,
14+
enableClose = false,
15+
message,
16+
icon,
17+
severity = "info",
18+
showIcon = true,
19+
}: MessageProperties) => {
20+
const [showMessage, setShowMessage] = useState(true);
21+
22+
const defaultSeverityIcons = {
23+
info: "pi pi-info-circle",
24+
success: "pi pi-check-circle",
25+
warning: "pi pi-exclamation-triangle",
26+
danger: "pi pi-times-circle",
27+
};
28+
29+
const handleClose = () => {
30+
setShowMessage(false);
31+
32+
if (onClose) {
33+
onClose();
34+
}
35+
};
36+
37+
if (!showMessage) {
38+
return null;
39+
}
40+
941
const renderIcon = () => {
1042
return (
1143
<span className="icon" data-testid="icon">
12-
{typeof icon === "string" ? <i className={icon} /> : icon}
44+
{!icon ? (
45+
<i className={defaultSeverityIcons[severity]} />
46+
) : typeof icon === "string" ? (
47+
<i className={icon} />
48+
) : (
49+
icon
50+
)}
1351
</span>
1452
);
1553
};
1654

55+
const renderMessageContent = () => {
56+
if (typeof message === "string") {
57+
return <span>{message}</span>;
58+
}
59+
60+
if (Array.isArray(message)) {
61+
return (
62+
<ul>
63+
{message.map((message_, index) => (
64+
<li key={index}>{message_}</li>
65+
))}
66+
</ul>
67+
);
68+
}
69+
70+
return message;
71+
};
72+
1773
return (
18-
<div className="message">
19-
{renderIcon()}
20-
<span className="message-content">{message}</span>
74+
<div className={`message ${severity}`}>
75+
{showIcon && renderIcon()}
76+
<div className="message-content">{renderMessageContent()}</div>
77+
{enableClose && (
78+
<span className="close-message" onClick={handleClose}>
79+
<i className="pi pi-times"></i>
80+
</span>
81+
)}
2182
</div>
2283
);
2384
};

0 commit comments

Comments
 (0)