diff --git a/src/lib/components/DetectedUserListItem.stories.tsx b/src/lib/components/DetectedUserListItem.stories.tsx
new file mode 100644
index 0000000..b951c5b
--- /dev/null
+++ b/src/lib/components/DetectedUserListItem.stories.tsx
@@ -0,0 +1,112 @@
+import type { Meta, StoryObj } from "@storybook/react";
+
+import { ACTION_MODE, BSKY_USER_MATCH_TYPE } from "../constants";
+import DetectedUserListItem, { type Props } from "./DetectedUserListItem";
+
+const meta: Meta<typeof DetectedUserListItem> = {
+  title: "Components/DetectedUserListItem",
+  component: DetectedUserListItem,
+};
+export default meta;
+
+type Story = StoryObj<{
+  items: {
+    user: Props["user"];
+    action: Props["clickAction"];
+  }[];
+}>;
+
+const demoUser: Props["user"] = {
+  did: "",
+  handle: "kawamataryo.bsky.social",
+  displayName: "KawamataRyo",
+  description: `
+    Frontend engineer @lapras-inc/ TypeScript / Vue.js / Firebase / ex-FireFighter 🔥
+    Developer of  Sky Follower Bridge.
+
+    Twitter: twitter.com/KawamataRyo
+    GitHub: github.com/kawamataryo
+    Zenn: zenn.dev/ryo_kawamata`,
+  avatar: "https://i.pravatar.cc/150?u=123",
+  matchType: BSKY_USER_MATCH_TYPE.HANDLE,
+  isFollowing: false,
+  followingUri: "",
+  isBlocking: false,
+  blockingUri: "",
+  originalAvatar: "https://i.pravatar.cc/150?u=123",
+  originalHandle: "kawamataryo",
+  originalDisplayName: "KawamataRyo",
+  originalProfileLink: "https://x.com/kawamataryo",
+};
+
+const mockAction: Props["clickAction"] = async () => {
+  await new Promise((resolve) => setTimeout(resolve, 1000));
+};
+
+const CardTemplate = {
+  render: (args: Story["args"]["items"][0]) => (
+    <DetectedUserListItem
+      user={args.user}
+      clickAction={args.action}
+      actionMode={ACTION_MODE.FOLLOW}
+    />
+  ),
+};
+
+const CardsTemplate: Story = {
+  render: (args) => (
+    <div className="divide-y divide-gray-400 border-y border-gray-400">
+      {args.items.map((arg, i) => (
+        <DetectedUserListItem
+          // biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
+          key={i}
+          user={arg.user}
+          clickAction={arg.action}
+          actionMode={ACTION_MODE.FOLLOW}
+        />
+      ))}
+    </div>
+  ),
+};
+
+export const Default = {
+  ...CardTemplate,
+  args: {
+    action: mockAction,
+    user: {
+      ...demoUser,
+      matchType: BSKY_USER_MATCH_TYPE.HANDLE,
+    },
+  },
+};
+
+export const Cards = {
+  ...CardsTemplate,
+  args: {
+    items: [
+      {
+        action: mockAction,
+        user: {
+          ...demoUser,
+          matchType: BSKY_USER_MATCH_TYPE.HANDLE,
+          isFollowing: true,
+        },
+      },
+      {
+        action: mockAction,
+        user: {
+          ...demoUser,
+          matchType: BSKY_USER_MATCH_TYPE.DESCRIPTION,
+        },
+      },
+      {
+        action: mockAction,
+        user: {
+          ...demoUser,
+          matchType: BSKY_USER_MATCH_TYPE.DISPLAY_NAME,
+          inFollowing: true,
+        },
+      },
+    ],
+  },
+};
diff --git a/src/lib/components/DetectedUserListItem.tsx b/src/lib/components/DetectedUserListItem.tsx
new file mode 100644
index 0000000..b5d1c92
--- /dev/null
+++ b/src/lib/components/DetectedUserListItem.tsx
@@ -0,0 +1,99 @@
+import React from "react";
+import { match } from "ts-pattern";
+import type { BskyUser } from "~types";
+import { ACTION_MODE } from "../constants";
+import DetectedUserSource from "./DetectedUserSource";
+import UserCard from "./UserCard";
+export type Props = {
+  user: BskyUser;
+  actionMode: (typeof ACTION_MODE)[keyof typeof ACTION_MODE];
+  clickAction: (user: BskyUser) => Promise<void>;
+};
+
+const DetectedUserListItem = ({ user, actionMode, clickAction }: Props) => {
+  const [isBtnHovered, setIsBtnHovered] = React.useState(false);
+  const [isJustClicked, setIsJustClicked] = React.useState(false);
+  const actionBtnLabelAndClass = React.useMemo(
+    () =>
+      match(actionMode)
+        .with(ACTION_MODE.FOLLOW, ACTION_MODE.IMPORT_LIST, () => {
+          const follow = {
+            label: "Follow on Bluesky",
+            class: "btn-primary",
+          };
+          const following = {
+            label: "Following on Bluesky",
+            class:
+              "btn-outline hover:bg-transparent hover:border hover:bg-transparent hover:text-base-content",
+          };
+          const unfollow = {
+            label: "Unfollow on Bluesky",
+            class:
+              "text-red-500 hover:bg-transparent hover:border hover:border-red-500",
+          };
+          if (!isBtnHovered) {
+            return user.isFollowing ? following : follow;
+          }
+          if (user.isFollowing) {
+            return isJustClicked ? following : unfollow;
+          }
+          return follow;
+        })
+        .with(ACTION_MODE.BLOCK, () => {
+          const block = {
+            label: "Block on Bluesky",
+            class: "btn-primary",
+          };
+          const blocking = {
+            label: "Blocking on Bluesky",
+            class:
+              "btn-outline hover:bg-transparent hover:border hover:bg-transparent hover:text-base-content",
+          };
+          const unblock = {
+            label: "Unblock on Bluesky",
+            class:
+              "text-red-500 hover:bg-transparent hover:border hover:border-red-500",
+          };
+          if (!isBtnHovered) {
+            return user.isBlocking ? blocking : block;
+          }
+          if (user.isBlocking) {
+            return isJustClicked ? blocking : unblock;
+          }
+          return block;
+        })
+        .run(),
+    [
+      user.isFollowing,
+      user.isBlocking,
+      actionMode,
+      isBtnHovered,
+      isJustClicked,
+    ],
+  );
+
+  const [loading, setLoading] = React.useState(false);
+
+  const handleActionButtonClick = async () => {
+    setLoading(true);
+    await clickAction(user);
+    setLoading(false);
+    setIsJustClicked(true);
+  };
+
+  return (
+    <div className="bg-base-100 w-full relative grid grid-cols-[22%_1fr] gap-5">
+      <DetectedUserSource user={user} />
+      <UserCard
+        user={user}
+        loading={loading}
+        actionBtnLabelAndClass={actionBtnLabelAndClass}
+        handleActionButtonClick={handleActionButtonClick}
+        setIsBtnHovered={setIsBtnHovered}
+        setIsJustClicked={setIsJustClicked}
+      />
+    </div>
+  );
+};
+
+export default DetectedUserListItem;
diff --git a/src/lib/components/DetectedUserSource.tsx b/src/lib/components/DetectedUserSource.tsx
new file mode 100644
index 0000000..62121bd
--- /dev/null
+++ b/src/lib/components/DetectedUserSource.tsx
@@ -0,0 +1,50 @@
+import React from "react";
+import type { BskyUser } from "~types";
+import { MATCH_TYPE_LABEL_AND_COLOR } from "../constants";
+import { UserInfo, UserProfile } from "./UserCard";
+
+type DetectedUserSourceProps = {
+  user: BskyUser;
+};
+
+const DetectedUserSource = ({ user }: DetectedUserSourceProps) => (
+  <div className="flex flex-row gap-2 bg-slate-100 dark:bg-slate-800 justify-between pr-2">
+    <div
+      className={`border-l-8 border-${
+        MATCH_TYPE_LABEL_AND_COLOR[user.matchType].color
+      } relative py-3 pl-4 pr-1 grid grid-cols-[50px_1fr]`}
+    >
+      <UserProfile
+        avatar={user.originalAvatar}
+        url={user.originalProfileLink}
+      />
+      <div className="flex flex-col gap-2">
+        <div className="flex justify-between items-center gap-2">
+          <UserInfo
+            handle={user.originalHandle}
+            displayName={user.originalDisplayName}
+            url={user.originalProfileLink}
+          />
+        </div>
+      </div>
+    </div>
+    <div className="flex items-center justify-center">
+      <svg
+        xmlns="http://www.w3.org/2000/svg"
+        fill="none"
+        viewBox="0 0 24 24"
+        strokeWidth={1.5}
+        stroke="currentColor"
+        className="h-7 w-7"
+      >
+        <path
+          strokeLinecap="round"
+          strokeLinejoin="round"
+          d="m8.25 4.5 7.5 7.5-7.5 7.5"
+        />
+      </svg>
+    </div>
+  </div>
+);
+
+export default DetectedUserSource;
diff --git a/src/lib/components/UserCard.stories.tsx b/src/lib/components/UserCard.stories.tsx
index 46433a4..70f3366 100644
--- a/src/lib/components/UserCard.stories.tsx
+++ b/src/lib/components/UserCard.stories.tsx
@@ -1,7 +1,7 @@
 import type { Meta, StoryObj } from "@storybook/react";
 
-import { ACTION_MODE, BSKY_USER_MATCH_TYPE } from "../constants";
-import UserCard, { type Props } from "./UserCard";
+import { BSKY_USER_MATCH_TYPE } from "../constants";
+import UserCard, { type UserCardProps } from "./UserCard";
 
 const meta: Meta<typeof UserCard> = {
   title: "Components/UserCard",
@@ -11,12 +11,11 @@ export default meta;
 
 type Story = StoryObj<{
   items: {
-    user: Props["user"];
-    action: Props["clickAction"];
+    user: UserCardProps["user"];
   }[];
 }>;
 
-const demoUser: Props["user"] = {
+const demoUser: UserCardProps["user"] = {
   did: "",
   handle: "kawamataryo.bsky.social",
   displayName: "KawamataRyo",
@@ -38,17 +37,15 @@ const demoUser: Props["user"] = {
   originalDisplayName: "KawamataRyo",
   originalProfileLink: "https://x.com/kawamataryo",
 };
-
-const mockAction: Props["clickAction"] = async () => {
-  await new Promise((resolve) => setTimeout(resolve, 1000));
-};
-
 const CardTemplate = {
   render: (args: Story["args"]["items"][0]) => (
     <UserCard
       user={args.user}
-      clickAction={args.action}
-      actionMode={ACTION_MODE.FOLLOW}
+      loading={false}
+      actionBtnLabelAndClass={{ label: "Follow", class: "btn-primary" }}
+      handleActionButtonClick={() => {}}
+      setIsBtnHovered={() => {}}
+      setIsJustClicked={() => {}}
     />
   ),
 };
@@ -61,8 +58,11 @@ const CardsTemplate: Story = {
           // biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
           key={i}
           user={arg.user}
-          clickAction={arg.action}
-          actionMode={ACTION_MODE.FOLLOW}
+          loading={false}
+          actionBtnLabelAndClass={{ label: "Follow", class: "btn-primary" }}
+          handleActionButtonClick={() => {}}
+          setIsBtnHovered={() => {}}
+          setIsJustClicked={() => {}}
         />
       ))}
     </div>
@@ -72,41 +72,9 @@ const CardsTemplate: Story = {
 export const Default = {
   ...CardTemplate,
   args: {
-    action: mockAction,
     user: {
       ...demoUser,
       matchType: BSKY_USER_MATCH_TYPE.HANDLE,
     },
   },
 };
-
-export const Cards = {
-  ...CardsTemplate,
-  args: {
-    items: [
-      {
-        action: mockAction,
-        user: {
-          ...demoUser,
-          matchType: BSKY_USER_MATCH_TYPE.HANDLE,
-          isFollowing: true,
-        },
-      },
-      {
-        action: mockAction,
-        user: {
-          ...demoUser,
-          matchType: BSKY_USER_MATCH_TYPE.DESCRIPTION,
-        },
-      },
-      {
-        action: mockAction,
-        user: {
-          ...demoUser,
-          matchType: BSKY_USER_MATCH_TYPE.DISPLAY_NAME,
-          inFollowing: true,
-        },
-      },
-    ],
-  },
-};
diff --git a/src/lib/components/UserCard.tsx b/src/lib/components/UserCard.tsx
index 4e35447..b0a591d 100644
--- a/src/lib/components/UserCard.tsx
+++ b/src/lib/components/UserCard.tsx
@@ -1,7 +1,5 @@
 import React from "react";
-import { match } from "ts-pattern";
 import type { BskyUser } from "~types";
-import { ACTION_MODE, MATCH_TYPE_LABEL_AND_COLOR } from "../constants";
 import AvatarFallbackSvg from "./Icons/AvatarFallbackSvg";
 
 type UserProfileProps = {
@@ -9,7 +7,7 @@ type UserProfileProps = {
   url: string;
 };
 
-const UserProfile = ({ avatar, url }: UserProfileProps) => (
+export const UserProfile = ({ avatar, url }: UserProfileProps) => (
   <div className="avatar">
     <div className="w-10 h-10 rounded-full border border-white">
       <a href={url} target="_blank" rel="noreferrer">
@@ -25,7 +23,7 @@ type UserInfoProps = {
   url: string;
 };
 
-const UserInfo = ({ handle, displayName, url }: UserInfoProps) => (
+export const UserInfo = ({ handle, displayName, url }: UserInfoProps) => (
   <div>
     <h2 className="card-title break-all text-[1.1rem] font-bold">
       <a href={url} target="_blank" rel="noreferrer">
@@ -48,7 +46,7 @@ type ActionButtonProps = {
   setIsJustClicked: (value: boolean) => void;
 };
 
-const ActionButton = ({
+export const ActionButton = ({
   loading,
   actionBtnLabelAndClass,
   handleActionButtonClick,
@@ -71,150 +69,48 @@ const ActionButton = ({
     {loading ? "Processing..." : actionBtnLabelAndClass.label}
   </button>
 );
-
-export type Props = {
+export type UserCardProps = {
   user: BskyUser;
-  actionMode: (typeof ACTION_MODE)[keyof typeof ACTION_MODE];
-  clickAction: (user: BskyUser) => Promise<void>;
+  loading: boolean;
+  actionBtnLabelAndClass: { label: string; class: string };
+  handleActionButtonClick: () => void;
+  setIsBtnHovered: (value: boolean) => void;
+  setIsJustClicked: (value: boolean) => void;
 };
 
-const UserCard = ({ user, actionMode, clickAction }: Props) => {
-  const [isBtnHovered, setIsBtnHovered] = React.useState(false);
-  const [isJustClicked, setIsJustClicked] = React.useState(false);
-  const actionBtnLabelAndClass = React.useMemo(
-    () =>
-      match(actionMode)
-        .with(ACTION_MODE.FOLLOW, ACTION_MODE.IMPORT_LIST, () => {
-          const follow = {
-            label: "Follow on Bluesky",
-            class: "btn-primary",
-          };
-          const following = {
-            label: "Following on Bluesky",
-            class:
-              "btn-outline hover:bg-transparent hover:border hover:bg-transparent hover:text-base-content",
-          };
-          const unfollow = {
-            label: "Unfollow on Bluesky",
-            class:
-              "text-red-500 hover:bg-transparent hover:border hover:border-red-500",
-          };
-          if (!isBtnHovered) {
-            return user.isFollowing ? following : follow;
-          }
-          if (user.isFollowing) {
-            return isJustClicked ? following : unfollow;
-          }
-          return follow;
-        })
-        .with(ACTION_MODE.BLOCK, () => {
-          const block = {
-            label: "Block on Bluesky",
-            class: "btn-primary",
-          };
-          const blocking = {
-            label: "Blocking on Bluesky",
-            class:
-              "btn-outline hover:bg-transparent hover:border hover:bg-transparent hover:text-base-content",
-          };
-          const unblock = {
-            label: "Unblock on Bluesky",
-            class:
-              "text-red-500 hover:bg-transparent hover:border hover:border-red-500",
-          };
-          if (!isBtnHovered) {
-            return user.isBlocking ? blocking : block;
-          }
-          if (user.isBlocking) {
-            return isJustClicked ? blocking : unblock;
-          }
-          return block;
-        })
-        .run(),
-    [
-      user.isFollowing,
-      user.isBlocking,
-      actionMode,
-      isBtnHovered,
-      isJustClicked,
-    ],
-  );
-
-  const [loading, setLoading] = React.useState(false);
-
-  const handleActionButtonClick = async () => {
-    setLoading(true);
-    await clickAction(user);
-    setLoading(false);
-    setIsJustClicked(true);
-  };
-
-  return (
-    <div className="bg-base-100 w-full relative grid grid-cols-[22%_1fr] gap-5">
-      <div className="flex flex-row gap-2 bg-slate-100 dark:bg-slate-800 justify-between pr-2">
-        <div
-          className={`border-l-8 border-${
-            MATCH_TYPE_LABEL_AND_COLOR[user.matchType].color
-          } relative py-3 pl-4 pr-1 grid grid-cols-[50px_1fr]`}
-        >
-          <UserProfile
-            avatar={user.originalAvatar}
-            url={user.originalProfileLink}
-          />
-          <div className="flex flex-col gap-2">
-            <div className="flex justify-between items-center gap-2">
-              <UserInfo
-                handle={user.originalHandle}
-                displayName={user.originalDisplayName}
-                url={user.originalProfileLink}
-              />
-            </div>
-          </div>
-        </div>
-        <div className="flex items-center justify-center">
-          <svg
-            xmlns="http://www.w3.org/2000/svg"
-            fill="none"
-            viewBox="0 0 24 24"
-            strokeWidth={1.5}
-            stroke="currentColor"
-            className="h-7 w-7"
-          >
-            <path
-              strokeLinecap="round"
-              strokeLinejoin="round"
-              d="m8.25 4.5 7.5 7.5-7.5 7.5"
-            />
-          </svg>
-        </div>
-      </div>
-      <div className="relative py-3 pl-0 pr-2 grid grid-cols-[50px_1fr]">
-        <UserProfile
-          avatar={user.avatar}
+const UserCard = ({
+  user,
+  loading,
+  actionBtnLabelAndClass,
+  handleActionButtonClick,
+  setIsBtnHovered,
+  setIsJustClicked,
+}: UserCardProps) => (
+  <div className="relative py-3 pl-0 pr-2 grid grid-cols-[50px_1fr]">
+    <UserProfile
+      avatar={user.avatar}
+      url={`https://bsky.app/profile/${user.handle}`}
+    />
+    <div className="flex flex-col gap-2">
+      <div className="flex justify-between items-center gap-2">
+        <UserInfo
+          handle={user.handle}
+          displayName={user.displayName}
           url={`https://bsky.app/profile/${user.handle}`}
         />
-        <div className="flex flex-col gap-2">
-          <div className="flex justify-between items-center gap-2">
-            <UserInfo
-              handle={user.handle}
-              displayName={user.displayName}
-              url={`https://bsky.app/profile/${user.handle}`}
-            />
-            <div className="card-actions">
-              <ActionButton
-                loading={loading}
-                actionBtnLabelAndClass={actionBtnLabelAndClass}
-                handleActionButtonClick={handleActionButtonClick}
-                setIsBtnHovered={setIsBtnHovered}
-                setIsJustClicked={setIsJustClicked}
-              />
-            </div>
-          </div>
-          <p className="text-sm break-all">{user.description}</p>
+        <div className="card-actions">
+          <ActionButton
+            loading={loading}
+            actionBtnLabelAndClass={actionBtnLabelAndClass}
+            handleActionButtonClick={handleActionButtonClick}
+            setIsBtnHovered={setIsBtnHovered}
+            setIsJustClicked={setIsJustClicked}
+          />
         </div>
       </div>
+      <p className="text-sm break-all">{user.description}</p>
     </div>
-  );
-};
+  </div>
+);
 
 export default UserCard;
diff --git a/src/options.tsx b/src/options.tsx
index 448e32e..e8ad33d 100644
--- a/src/options.tsx
+++ b/src/options.tsx
@@ -1,10 +1,10 @@
-import UserCard from "~lib/components/UserCard";
 import { useBskyUserManager } from "~lib/hooks/useBskyUserManager";
 import "./style.css";
 import { ToastContainer, toast } from "react-toastify";
 import useConfirm from "~lib/components/ConfirmDialog";
 import Sidebar from "~lib/components/Sidebar";
 import "react-toastify/dist/ReactToastify.css";
+import DetectedUserListItem from "~lib/components/DetectedUserListItem";
 
 const Option = () => {
   const {
@@ -121,7 +121,7 @@ const Option = () => {
           <div className="flex flex-col gap-4">
             <div className="divide-y divide-gray-500">
               {filteredUsers.map((user) => (
-                <UserCard
+                <DetectedUserListItem
                   key={user.handle}
                   user={user}
                   clickAction={handleClickAction}