diff --git a/web/pages/components/message-visiblity-toggle.tsx b/web/pages/components/message-visiblity-toggle.tsx
new file mode 100644
index 0000000000..c202e8d1e0
--- /dev/null
+++ b/web/pages/components/message-visiblity-toggle.tsx
@@ -0,0 +1,83 @@
+// Custom component for AntDesign Button that makes an api call, then displays a confirmation icon upon
+import React, { useState, useEffect } from "react";
+import { Button, Tooltip } from "antd";
+import { EyeOutlined, EyeInvisibleOutlined, CheckCircleFilled, ExclamationCircleFilled } from "@ant-design/icons";
+import { fetchData, UPDATE_CHAT_MESSGAE_VIZ } from "../../utils/apis";
+import { MessageType } from '../../types/chat';
+import { OUTCOME_TIMEOUT } from "../chat";
+import { isEmptyObject } from "../../utils/format";
+
+interface MessageToggleProps {
+ isVisible: boolean;
+ message: MessageType;
+ setMessage: (message: MessageType) => void,
+};
+
+
+export default function MessageVisiblityToggle({ isVisible, message, setMessage }: MessageToggleProps) {
+ if (!message || isEmptyObject(message)) {
+ return null;
+ }
+
+ let outcomeTimeout = null;
+ const [outcome, setOutcome] = useState(0);
+
+ const { id: messageId } = message || {};
+
+ const resetOutcome = () => {
+ outcomeTimeout = setTimeout(() => { setOutcome(0)}, OUTCOME_TIMEOUT);
+ };
+
+ useEffect(() => {
+ return () => {
+ clearTimeout(outcomeTimeout);
+ };
+ });
+
+
+ const updateChatMessage = async () => {
+ clearTimeout(outcomeTimeout);
+ setOutcome(0);
+ const result = await fetchData(UPDATE_CHAT_MESSGAE_VIZ, {
+ auth: true,
+ method: 'POST',
+ data: {
+ visible: !isVisible,
+ idArray: [messageId],
+ },
+ });
+
+ if (result.success && result.message === "changed") {
+ setMessage({ ...message, visible: !isVisible });
+ setOutcome(1);
+ } else {
+ setMessage({ ...message, visible: isVisible });
+ setOutcome(-1);
+ }
+ resetOutcome();
+ }
+
+
+ let outcomeIcon =