diff --git a/src/pages/rules.tsx b/src/pages/rules.tsx
index 60f6853446ca832815d3c6fb951a62cd9bd8478b..72f54fbfb544dacafd898647fc9592e4a8f5f1a7 100644
--- a/src/pages/rules.tsx
+++ b/src/pages/rules.tsx
@@ -1,71 +1,45 @@
 import { useState } from "react";
-import {
-  Box,
-  Button,
-  Grid,
-  Slide,
-  Snackbar,
-  TextField,
-  Typography,
-} from "@mui/material";
+import { Box, Button, TextField, Typography } from "@mui/material";
 import { importProfile } from "../services/command";
+import useNotice from "../utils/use-notice";
 
 const RulesPage = () => {
   const [url, setUrl] = useState("");
-  const [message, setMessage] = useState("");
   const [disabled, setDisabled] = useState(false);
 
+  const [notice, noticeElement] = useNotice();
+
   const onClick = () => {
     if (!url) return;
     setUrl("");
     setDisabled(true);
     importProfile(url)
-      .then(() => setMessage("Successfully import profile."))
-      .catch(() => setMessage("Failed to import profile."))
+      .then(() => notice.success("Successfully import profile."))
+      .catch(() => notice.error("Failed to import profile."))
       .finally(() => setDisabled(false));
   };
 
   return (
     <Box sx={{ width: 0.9, maxWidth: "850px", mx: "auto", mb: 2 }}>
-      <Typography variant="h4" component="h1" sx={{ py: 2 }}>
+      <Typography variant="h4" component="h1" sx={{ py: 2, mb: 1 }}>
         Rules
       </Typography>
 
-      <Grid
-        container
-        spacing={2}
-        justifyContent="space-between"
-        alignItems="center"
-      >
-        <Grid item xs={9}>
-          <TextField
-            label="Profile Url"
-            size="medium"
-            fullWidth
-            value={url}
-            onChange={(e) => setUrl(e.target.value)}
-          />
-        </Grid>
-        <Grid item>
-          <Button
-            disabled={disabled}
-            size="large"
-            variant="contained"
-            onClick={onClick}
-          >
-            Import
-          </Button>
-        </Grid>
-      </Grid>
+      <Box sx={{ display: "flex" }}>
+        <TextField
+          label="Profile URL"
+          size="small"
+          fullWidth
+          value={url}
+          onChange={(e) => setUrl(e.target.value)}
+          sx={{ mr: 4 }}
+        />
+        <Button disabled={disabled} variant="contained" onClick={onClick}>
+          Import
+        </Button>
+      </Box>
 
-      <Snackbar
-        open={!!message}
-        anchorOrigin={{ vertical: "top", horizontal: "right" }}
-        autoHideDuration={3000}
-        onClose={() => setMessage("")}
-        message={message}
-        TransitionComponent={(p) => <Slide {...p} direction="left" />}
-      />
+      {noticeElement}
     </Box>
   );
 };
diff --git a/src/utils/use-notice.tsx b/src/utils/use-notice.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..4999f0547162d5c2daea822a8abec7e4ca714baa
--- /dev/null
+++ b/src/utils/use-notice.tsx
@@ -0,0 +1,55 @@
+import { useMemo, useState } from "react";
+import { IconButton, Slide, Snackbar } from "@mui/material";
+import { Close } from "@mui/icons-material";
+
+interface NoticeInstance {
+  info: (msg: string) => void;
+  error: (msg: string) => void;
+  success: (msg: string) => void;
+}
+
+const useNotice = () => {
+  const [message, setMessage] = useState("");
+  const [level, setLevel] = useState<"info" | "error" | "success">("info");
+
+  const handleClose = (_e: any, reason: string) => {
+    if (reason !== "clickaway") setMessage("");
+  };
+
+  const element = useMemo(
+    () => (
+      <Snackbar
+        open={!!message}
+        anchorOrigin={{ vertical: "top", horizontal: "right" }}
+        autoHideDuration={3000}
+        onClose={handleClose}
+        message={message}
+        TransitionComponent={(p) => <Slide {...p} direction="left" />}
+        action={
+          <IconButton
+            size="small"
+            color="inherit"
+            onClick={() => setMessage("")}
+          >
+            <Close fontSize="small" />
+          </IconButton>
+        }
+      />
+    ),
+    [message]
+  );
+
+  const instance = (Object.fromEntries(
+    (["info", "error", "success"] as const).map((item) => [
+      item,
+      (msg: string) => {
+        setLevel(item);
+        setMessage(msg);
+      },
+    ])
+  ) as unknown) as NoticeInstance;
+
+  return [instance, element] as const;
+};
+
+export default useNotice;