From de7df0e4fb38863b830a104a5a38d0e5247679f8 Mon Sep 17 00:00:00 2001
From: crupest <crupest@outlook.com>
Date: Tue, 29 Jun 2021 23:50:55 +0800
Subject: ...

---
 FrontEnd/src/views/common/menu/PopupMenu.tsx | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 FrontEnd/src/views/common/menu/PopupMenu.tsx

(limited to 'FrontEnd/src/views/common/menu/PopupMenu.tsx')

diff --git a/FrontEnd/src/views/common/menu/PopupMenu.tsx b/FrontEnd/src/views/common/menu/PopupMenu.tsx
new file mode 100644
index 00000000..0d447f09
--- /dev/null
+++ b/FrontEnd/src/views/common/menu/PopupMenu.tsx
@@ -0,0 +1,17 @@
+import React from "react";
+
+import Menu, { MenuItems } from "./Menu";
+
+export interface PopupMenuProps {
+  items: MenuItems;
+  children: React.ReactElement;
+}
+
+export const PopupMenu: React.FC<PopupMenuProps> = ({ items, children }) => {
+  const [show, setShow] = React.useState<boolean>(false);
+  const toggle = (): void => setShow(!show);
+
+  // TODO:
+
+  return <Menu items={items} onItemClicked={() => setShow(false)} />;
+};
-- 
cgit v1.2.3


From 6b5d88a6a1a3fe12721f3159a6837d3f41d69022 Mon Sep 17 00:00:00 2001
From: crupest <crupest@outlook.com>
Date: Wed, 30 Jun 2021 00:15:20 +0800
Subject: ...

---
 FrontEnd/package.json                              |  2 +
 FrontEnd/src/views/common/menu/Menu.tsx            | 22 +++++----
 FrontEnd/src/views/common/menu/PopupMenu.css       |  3 ++
 FrontEnd/src/views/common/menu/PopupMenu.tsx       | 56 ++++++++++++++++++++--
 .../timeline-common/TimelinePageCardTemplate.tsx   |  3 +-
 .../src/views/timeline-common/TimelinePostEdit.tsx |  2 +-
 6 files changed, 73 insertions(+), 15 deletions(-)
 create mode 100644 FrontEnd/src/views/common/menu/PopupMenu.css

(limited to 'FrontEnd/src/views/common/menu/PopupMenu.tsx')

diff --git a/FrontEnd/package.json b/FrontEnd/package.json
index 55c7c95f..2c92d6b2 100644
--- a/FrontEnd/package.json
+++ b/FrontEnd/package.json
@@ -7,6 +7,7 @@
   "description": "Timeline app.",
   "dependencies": {
     "@microsoft/signalr": "^5.0.7",
+    "@popperjs/core": "^2.9.2",
     "axios": "^0.21.1",
     "bootstrap": "^5.0.2",
     "bootstrap-icons": "^1.5.0",
@@ -23,6 +24,7 @@
     "react-color": "^2.19.3",
     "react-dom": "^17.0.2",
     "react-i18next": "^11.11.0",
+    "react-popper": "^2.2.5",
     "react-responsive": "^8.2.0",
     "react-router": "^5.2.0",
     "react-router-dom": "^5.2.0",
diff --git a/FrontEnd/src/views/common/menu/Menu.tsx b/FrontEnd/src/views/common/menu/Menu.tsx
index 7523247d..04243fa3 100644
--- a/FrontEnd/src/views/common/menu/Menu.tsx
+++ b/FrontEnd/src/views/common/menu/Menu.tsx
@@ -5,6 +5,8 @@ import { useTranslation } from "react-i18next";
 import { convertI18nText, I18nText } from "@/common";
 import { PaletteColorType } from "@/palette";
 
+import "./Menu.css";
+
 export type MenuItem =
   | {
       type: "divider";
@@ -19,17 +21,23 @@ export type MenuItem =
 
 export type MenuItems = MenuItem[];
 
-export interface MenuProps {
+export type MenuProps = {
   items: MenuItems;
-  className?: string;
   onItemClicked?: () => void;
-}
+  className?: string;
+  style?: React.CSSProperties;
+};
 
-const Menu: React.FC<MenuProps> = ({ items, className, onItemClicked }) => {
+export default function _Menu({
+  items,
+  onItemClicked,
+  className,
+  style,
+}: MenuProps): React.ReactElement | null {
   const { t } = useTranslation();
 
   return (
-    <div className={classnames("cru-menu", className)}>
+    <div className={classnames("cru-menu", className)} style={style}>
       {items.map((item, index) => {
         if (item.type === "divider") {
           return <div key={index} className="cru-menu-divider" />;
@@ -61,6 +69,4 @@ const Menu: React.FC<MenuProps> = ({ items, className, onItemClicked }) => {
       })}
     </div>
   );
-};
-
-export default Menu;
+}
diff --git a/FrontEnd/src/views/common/menu/PopupMenu.css b/FrontEnd/src/views/common/menu/PopupMenu.css
new file mode 100644
index 00000000..8465a1bb
--- /dev/null
+++ b/FrontEnd/src/views/common/menu/PopupMenu.css
@@ -0,0 +1,3 @@
+.cru-popup-menu-menu-container {
+
+}
diff --git a/FrontEnd/src/views/common/menu/PopupMenu.tsx b/FrontEnd/src/views/common/menu/PopupMenu.tsx
index 0d447f09..50f80a91 100644
--- a/FrontEnd/src/views/common/menu/PopupMenu.tsx
+++ b/FrontEnd/src/views/common/menu/PopupMenu.tsx
@@ -1,17 +1,63 @@
+import classNames from "classnames";
 import React from "react";
+import { usePopper } from "react-popper";
 
 import Menu, { MenuItems } from "./Menu";
 
+import "./PopupMenu.css";
+
 export interface PopupMenuProps {
   items: MenuItems;
-  children: React.ReactElement;
+  children?: React.ReactNode;
+  containerClassName?: string;
+  containerStyle?: React.CSSProperties;
 }
 
-export const PopupMenu: React.FC<PopupMenuProps> = ({ items, children }) => {
+const PopupMenu: React.FC<PopupMenuProps> = ({
+  items,
+  children,
+  containerClassName,
+  containerStyle,
+}) => {
   const [show, setShow] = React.useState<boolean>(false);
-  const toggle = (): void => setShow(!show);
 
-  // TODO:
+  const [referenceElement, setReferenceElement] =
+    React.useState<HTMLDivElement | null>(null);
+  const [popperElement, setPopperElement] =
+    React.useState<HTMLDivElement | null>(null);
+  const [arrowElement, setArrowElement] = React.useState<HTMLDivElement | null>(
+    null
+  );
+  const { styles, attributes } = usePopper(referenceElement, popperElement, {
+    modifiers: [{ name: "arrow", options: { element: arrowElement } }],
+  });
 
-  return <Menu items={items} onItemClicked={() => setShow(false)} />;
+  return (
+    <>
+      <div
+        ref={setReferenceElement}
+        className={classNames(
+          "cru-popup-menu-trigger-container",
+          containerClassName
+        )}
+        style={containerStyle}
+        onClick={() => setShow(true)}
+      >
+        {children}
+      </div>
+      {show ? (
+        <div
+          ref={setPopperElement}
+          className="cru-popup-menu-menu-container"
+          style={styles.popper}
+          {...attributes.popper}
+        >
+          <Menu items={items} />
+          <div ref={setArrowElement} style={styles.arrow} />
+        </div>
+      ) : null}
+    </>
+  );
 };
+
+export default PopupMenu;
diff --git a/FrontEnd/src/views/timeline-common/TimelinePageCardTemplate.tsx b/FrontEnd/src/views/timeline-common/TimelinePageCardTemplate.tsx
index 78af1131..75f2d400 100644
--- a/FrontEnd/src/views/timeline-common/TimelinePageCardTemplate.tsx
+++ b/FrontEnd/src/views/timeline-common/TimelinePageCardTemplate.tsx
@@ -17,7 +17,8 @@ import CollapseButton from "./CollapseButton";
 import { TimelineMemberDialog } from "./TimelineMember";
 import TimelinePropertyChangeDialog from "./TimelinePropertyChangeDialog";
 import ConnectionStatusBadge from "./ConnectionStatusBadge";
-import { MenuItems, PopupMenu } from "../common/menu/Menu";
+import { MenuItems } from "../common/menu/Menu";
+import PopupMenu from "../common/menu/PopupMenu";
 import FullPageDialog from "../common/dailog/FullPageDialog";
 import Card from "../common/Card";
 
diff --git a/FrontEnd/src/views/timeline-common/TimelinePostEdit.tsx b/FrontEnd/src/views/timeline-common/TimelinePostEdit.tsx
index 1e6591c0..e2045429 100644
--- a/FrontEnd/src/views/timeline-common/TimelinePostEdit.tsx
+++ b/FrontEnd/src/views/timeline-common/TimelinePostEdit.tsx
@@ -16,7 +16,7 @@ import { base64 } from "@/http/common";
 
 import BlobImage from "../common/BlobImage";
 import LoadingButton from "../common/button/LoadingButton";
-import { PopupMenu } from "../common/menu/Menu";
+import PopupMenu from "../common/menu/PopupMenu";
 import Card from "../common/Card";
 import MarkdownPostEdit from "./MarkdownPostEdit";
 import TimelineLine from "./TimelineLine";
-- 
cgit v1.2.3


From 979ad8556be3576b09e318c9e85ae0138ecf11ec Mon Sep 17 00:00:00 2001
From: crupest <crupest@outlook.com>
Date: Wed, 30 Jun 2021 18:18:04 +0800
Subject: ...

---
 FrontEnd/src/views/common/index.css          |  2 ++
 FrontEnd/src/views/common/menu/PopupMenu.css |  4 +++-
 FrontEnd/src/views/common/menu/PopupMenu.tsx | 32 +++++++++++++++++++++-------
 3 files changed, 29 insertions(+), 9 deletions(-)

(limited to 'FrontEnd/src/views/common/menu/PopupMenu.tsx')

diff --git a/FrontEnd/src/views/common/index.css b/FrontEnd/src/views/common/index.css
index e2769fe4..cb1cccd4 100644
--- a/FrontEnd/src/views/common/index.css
+++ b/FrontEnd/src/views/common/index.css
@@ -1,4 +1,6 @@
 :root {
+  --cru-background-color: #f8f9fa;
+
   --cru-primary-color: rgb(255, 105, 0);
   --cru-primary-l1-color: rgb(255, 120, 26);
   --cru-primary-l2-color: rgb(255, 135, 51);
diff --git a/FrontEnd/src/views/common/menu/PopupMenu.css b/FrontEnd/src/views/common/menu/PopupMenu.css
index 8465a1bb..8f8fd20e 100644
--- a/FrontEnd/src/views/common/menu/PopupMenu.css
+++ b/FrontEnd/src/views/common/menu/PopupMenu.css
@@ -1,3 +1,5 @@
 .cru-popup-menu-menu-container {
-
+  border-radius: 5px;
+  border: var(--cru-primary-color) 1px solid;
+  background-color: var(--cru-background-color);
 }
diff --git a/FrontEnd/src/views/common/menu/PopupMenu.tsx b/FrontEnd/src/views/common/menu/PopupMenu.tsx
index 50f80a91..851f3bee 100644
--- a/FrontEnd/src/views/common/menu/PopupMenu.tsx
+++ b/FrontEnd/src/views/common/menu/PopupMenu.tsx
@@ -25,12 +25,24 @@ const PopupMenu: React.FC<PopupMenuProps> = ({
     React.useState<HTMLDivElement | null>(null);
   const [popperElement, setPopperElement] =
     React.useState<HTMLDivElement | null>(null);
-  const [arrowElement, setArrowElement] = React.useState<HTMLDivElement | null>(
-    null
-  );
-  const { styles, attributes } = usePopper(referenceElement, popperElement, {
-    modifiers: [{ name: "arrow", options: { element: arrowElement } }],
-  });
+  const { styles, attributes } = usePopper(referenceElement, popperElement);
+
+  React.useEffect(() => {
+    const handler = (event: MouseEvent): void => {
+      let element: HTMLElement | null = event.target as HTMLElement;
+      while (element) {
+        if (element == referenceElement || element == popperElement) {
+          return;
+        }
+        element = element.parentElement;
+      }
+      setShow(false);
+    };
+    document.addEventListener("click", handler);
+    return () => {
+      document.removeEventListener("click", handler);
+    };
+  }, [referenceElement, popperElement]);
 
   return (
     <>
@@ -52,8 +64,12 @@ const PopupMenu: React.FC<PopupMenuProps> = ({
           style={styles.popper}
           {...attributes.popper}
         >
-          <Menu items={items} />
-          <div ref={setArrowElement} style={styles.arrow} />
+          <Menu
+            items={items}
+            onItemClicked={() => {
+              setShow(false);
+            }}
+          />
         </div>
       ) : null}
     </>
-- 
cgit v1.2.3


From bb7a017dba4c466eaf167627b3605cf539b1e516 Mon Sep 17 00:00:00 2001
From: crupest <crupest@outlook.com>
Date: Wed, 30 Jun 2021 19:00:13 +0800
Subject: ...

---
 FrontEnd/src/palette.ts                            |  6 +-
 FrontEnd/src/views/common/index.css                | 78 +++++++++++-----------
 FrontEnd/src/views/common/menu/Menu.css            |  2 +-
 FrontEnd/src/views/common/menu/PopupMenu.css       |  1 +
 FrontEnd/src/views/common/menu/PopupMenu.tsx       | 35 +++++-----
 .../timeline-common/TimelinePageCardTemplate.tsx   |  2 +-
 FrontEnd/src/views/timeline/TimelineCard.tsx       | 12 ++--
 FrontEnd/src/views/user/UserCard.tsx               |  8 ++-
 8 files changed, 77 insertions(+), 67 deletions(-)

(limited to 'FrontEnd/src/views/common/menu/PopupMenu.tsx')

diff --git a/FrontEnd/src/palette.ts b/FrontEnd/src/palette.ts
index fb54f042..ca1f76cf 100644
--- a/FrontEnd/src/palette.ts
+++ b/FrontEnd/src/palette.ts
@@ -90,7 +90,7 @@ export function generatePalette(options: {
     primaryEnhance == null
       ? lightenBy(p, 0.3).saturate(0.3)
       : Color(primaryEnhance);
-  const s = secondary == null ? p.rotate(90) : Color(secondary);
+  const s = secondary == null ? Color("gray") : Color(secondary);
 
   return {
     primary: generatePaletteColor(p.toString()),
@@ -130,8 +130,8 @@ export function generatePaletteCSS(palette: Palette): string {
 
 const paletteSubject: BehaviorSubject<Palette | null> =
   new BehaviorSubject<Palette | null>(
-    generatePalette({ primary: "rgb(0, 123, 255)" })
-    // null
+    // generatePalette({ primary: "rgb(0, 123, 255)" })
+    null
   );
 
 export const palette$: Observable<Palette | null> =
diff --git a/FrontEnd/src/views/common/index.css b/FrontEnd/src/views/common/index.css
index d7501f98..4a860e95 100644
--- a/FrontEnd/src/views/common/index.css
+++ b/FrontEnd/src/views/common/index.css
@@ -1,45 +1,45 @@
 :root {
   --cru-background-color: #f8f9fa;
 
-  --cru-primary-color: rgb(255, 105, 0);
-  --cru-primary-l1-color: rgb(255, 120, 26);
-  --cru-primary-l2-color: rgb(255, 135, 51);
-  --cru-primary-l3-color: rgb(255, 150, 77);
-  --cru-primary-d1-color: rgb(230, 95, 0);
-  --cru-primary-d2-color: rgb(204, 84, 0);
-  --cru-primary-d3-color: rgb(179, 74, 0);
-  --cru-primary-f1-color: rgb(230, 95, 0);
-  --cru-primary-f2-color: rgb(204, 84, 0);
-  --cru-primary-f3-color: rgb(179, 74, 0);
-  --cru-primary-r1-color: rgb(255, 120, 26);
-  --cru-primary-r2-color: rgb(255, 135, 51);
-  --cru-primary-r3-color: rgb(255, 150, 77);
-  --cru-primary-enhance-color: rgb(255, 150, 77);
-  --cru-primary-enhance-l1-color: rgb(255, 161, 94);
-  --cru-primary-enhance-l2-color: rgb(255, 171, 112);
-  --cru-primary-enhance-l3-color: rgb(255, 182, 130);
-  --cru-primary-enhance-d1-color: rgb(255, 131, 43);
-  --cru-primary-enhance-d2-color: rgb(255, 111, 10);
-  --cru-primary-enhance-d3-color: rgb(232, 96, 0);
-  --cru-primary-enhance-f1-color: rgb(255, 161, 94);
-  --cru-primary-enhance-f2-color: rgb(255, 171, 112);
-  --cru-primary-enhance-f3-color: rgb(255, 182, 130);
-  --cru-primary-enhance-r1-color: rgb(255, 131, 43);
-  --cru-primary-enhance-r2-color: rgb(255, 111, 10);
-  --cru-primary-enhance-r3-color: rgb(232, 96, 0);
-  --cru-secondary-color: rgb(23, 255, 0);
-  --cru-secondary-l1-color: rgb(46, 255, 26);
-  --cru-secondary-l2-color: rgb(69, 255, 51);
-  --cru-secondary-l3-color: rgb(92, 255, 77);
-  --cru-secondary-d1-color: rgb(20, 230, 0);
-  --cru-secondary-d2-color: rgb(18, 204, 0);
-  --cru-secondary-d3-color: rgb(16, 179, 0);
-  --cru-secondary-f1-color: rgb(20, 230, 0);
-  --cru-secondary-f2-color: rgb(18, 204, 0);
-  --cru-secondary-f3-color: rgb(16, 179, 0);
-  --cru-secondary-r1-color: rgb(46, 255, 26);
-  --cru-secondary-r2-color: rgb(69, 255, 51);
-  --cru-secondary-r3-color: rgb(92, 255, 77);
+  --cru-primary-color: rgb(0, 123, 255);
+  --cru-primary-l1-color: rgb(26, 136, 255);
+  --cru-primary-l2-color: rgb(51, 149, 255);
+  --cru-primary-l3-color: rgb(77, 163, 255);
+  --cru-primary-d1-color: rgb(0, 111, 230);
+  --cru-primary-d2-color: rgb(0, 98, 204);
+  --cru-primary-d3-color: rgb(0, 86, 179);
+  --cru-primary-f1-color: rgb(0, 111, 230);
+  --cru-primary-f2-color: rgb(0, 98, 204);
+  --cru-primary-f3-color: rgb(0, 86, 179);
+  --cru-primary-r1-color: rgb(26, 136, 255);
+  --cru-primary-r2-color: rgb(51, 149, 255);
+  --cru-primary-r3-color: rgb(77, 163, 255);
+  --cru-primary-enhance-color: rgb(77, 163, 255);
+  --cru-primary-enhance-l1-color: rgb(94, 172, 255);
+  --cru-primary-enhance-l2-color: rgb(112, 181, 255);
+  --cru-primary-enhance-l3-color: rgb(130, 190, 255);
+  --cru-primary-enhance-d1-color: rgb(43, 145, 255);
+  --cru-primary-enhance-d2-color: rgb(10, 128, 255);
+  --cru-primary-enhance-d3-color: rgb(0, 112, 232);
+  --cru-primary-enhance-f1-color: rgb(94, 172, 255);
+  --cru-primary-enhance-f2-color: rgb(112, 181, 255);
+  --cru-primary-enhance-f3-color: rgb(130, 190, 255);
+  --cru-primary-enhance-r1-color: rgb(43, 145, 255);
+  --cru-primary-enhance-r2-color: rgb(10, 128, 255);
+  --cru-primary-enhance-r3-color: rgb(0, 112, 232);
+  --cru-secondary-color: rgb(128, 128, 128);
+  --cru-secondary-l1-color: rgb(141, 141, 141);
+  --cru-secondary-l2-color: rgb(153, 153, 153);
+  --cru-secondary-l3-color: rgb(166, 166, 166);
+  --cru-secondary-d1-color: rgb(115, 115, 115);
+  --cru-secondary-d2-color: rgb(102, 102, 102);
+  --cru-secondary-d3-color: rgb(90, 90, 90);
+  --cru-secondary-f1-color: rgb(115, 115, 115);
+  --cru-secondary-f2-color: rgb(102, 102, 102);
+  --cru-secondary-f3-color: rgb(90, 90, 90);
+  --cru-secondary-r1-color: rgb(141, 141, 141);
+  --cru-secondary-r2-color: rgb(153, 153, 153);
+  --cru-secondary-r3-color: rgb(166, 166, 166);
   --cru-text-primary-color: rgb(17, 17, 17);
   --cru-text-primary-l1-color: rgb(41, 41, 41);
   --cru-text-primary-l2-color: rgb(65, 65, 65);
diff --git a/FrontEnd/src/views/common/menu/Menu.css b/FrontEnd/src/views/common/menu/Menu.css
index 0b455baa..e0ea2cad 100644
--- a/FrontEnd/src/views/common/menu/Menu.css
+++ b/FrontEnd/src/views/common/menu/Menu.css
@@ -3,7 +3,7 @@
 }
 
 .cru-menu-item {
-  font-size: 1.2em;
+  font-size: 1em;
   padding: 0.5em 1.5em;
   cursor: pointer;
 }
diff --git a/FrontEnd/src/views/common/menu/PopupMenu.css b/FrontEnd/src/views/common/menu/PopupMenu.css
index 8f8fd20e..658532d3 100644
--- a/FrontEnd/src/views/common/menu/PopupMenu.css
+++ b/FrontEnd/src/views/common/menu/PopupMenu.css
@@ -1,4 +1,5 @@
 .cru-popup-menu-menu-container {
+  z-index: 1040;
   border-radius: 5px;
   border: var(--cru-primary-color) 1px solid;
   background-color: var(--cru-background-color);
diff --git a/FrontEnd/src/views/common/menu/PopupMenu.tsx b/FrontEnd/src/views/common/menu/PopupMenu.tsx
index 851f3bee..d7b81f49 100644
--- a/FrontEnd/src/views/common/menu/PopupMenu.tsx
+++ b/FrontEnd/src/views/common/menu/PopupMenu.tsx
@@ -1,5 +1,6 @@
 import classNames from "classnames";
 import React from "react";
+import { createPortal } from "react-dom";
 import { usePopper } from "react-popper";
 
 import Menu, { MenuItems } from "./Menu";
@@ -57,21 +58,25 @@ const PopupMenu: React.FC<PopupMenuProps> = ({
       >
         {children}
       </div>
-      {show ? (
-        <div
-          ref={setPopperElement}
-          className="cru-popup-menu-menu-container"
-          style={styles.popper}
-          {...attributes.popper}
-        >
-          <Menu
-            items={items}
-            onItemClicked={() => {
-              setShow(false);
-            }}
-          />
-        </div>
-      ) : null}
+      {show
+        ? createPortal(
+            <div
+              ref={setPopperElement}
+              className="cru-popup-menu-menu-container"
+              style={styles.popper}
+              {...attributes.popper}
+            >
+              <Menu
+                items={items}
+                onItemClicked={() => {
+                  setShow(false);
+                }}
+              />
+            </div>,
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+            document.getElementById("portal")!
+          )
+        : null}
     </>
   );
 };
diff --git a/FrontEnd/src/views/timeline-common/TimelinePageCardTemplate.tsx b/FrontEnd/src/views/timeline-common/TimelinePageCardTemplate.tsx
index f57fda2e..4802ca93 100644
--- a/FrontEnd/src/views/timeline-common/TimelinePageCardTemplate.tsx
+++ b/FrontEnd/src/views/timeline-common/TimelinePageCardTemplate.tsx
@@ -23,7 +23,7 @@ import FullPageDialog from "../common/dailog/FullPageDialog";
 import Card from "../common/Card";
 
 export interface TimelineCardTemplateProps extends TimelinePageCardProps {
-  infoArea: React.ReactElement;
+  infoArea: React.ReactNode;
   manageItems?: MenuItems;
   dialog: string | "property" | "member" | null;
   setDialog: (dialog: "property" | "member" | null) => void;
diff --git a/FrontEnd/src/views/timeline/TimelineCard.tsx b/FrontEnd/src/views/timeline/TimelineCard.tsx
index 311aa112..56057560 100644
--- a/FrontEnd/src/views/timeline/TimelineCard.tsx
+++ b/FrontEnd/src/views/timeline/TimelineCard.tsx
@@ -20,16 +20,18 @@ const TimelineCard: React.FC<TimelinePageCardProps> = (props) => {
           <>
             <h3 className="cru-color-primary d-inline-block align-middle">
               {timeline.title}
-              <small className="ms-3 text-secondary">{timeline.name}</small>
+              <small className="ms-3 cru-color-secondary">
+                {timeline.name}
+              </small>
             </h3>
-            <div className="align-middle">
+            <div>
               <UserAvatar
                 username={timeline.owner.username}
-                className="avatar small rounded-circle me-3"
+                className="cru-avatar small cru-round me-3"
               />
               {timeline.owner.nickname}
-              <small className="ms-3 text-secondary">
-                src{timeline.owner.username}
+              <small className="ms-3 cru-color-secondary">
+                @{timeline.owner.username}
               </small>
             </div>
           </>
diff --git a/FrontEnd/src/views/user/UserCard.tsx b/FrontEnd/src/views/user/UserCard.tsx
index 8a532512..739d26ee 100644
--- a/FrontEnd/src/views/user/UserCard.tsx
+++ b/FrontEnd/src/views/user/UserCard.tsx
@@ -16,11 +16,13 @@ const UserCard: React.FC<TimelinePageCardProps> = (props) => {
       <TimelinePageCardTemplate
         infoArea={
           <>
-            <h3 className="cru-color-primary d-inline-block align-middle">
+            <h3 className="cru-color-primary d-inline-block">
               {timeline.title}
-              <small className="ms-3 text-secondary">{timeline.name}</small>
+              <small className="ms-3 cru-color-secondary">
+                {timeline.name}
+              </small>
             </h3>
-            <div className="align-middle">
+            <div>
               <UserAvatar
                 username={timeline.owner.username}
                 className="cru-avatar small cru-round me-3"
-- 
cgit v1.2.3

