aboutsummaryrefslogtreecommitdiffstats
path: root/apps/web/components/dashboard/lists/ListHeader.tsx
diff options
context:
space:
mode:
authorMohamed Bassem <me@mbassem.com>2025-12-24 15:15:46 +0200
committerGitHub <noreply@github.com>2025-12-24 13:15:46 +0000
commitef27670f5c027be87d279b9b32553e980e55d888 (patch)
treeaa30e49787c17499abbe7a12b7a3353d13dbec7d /apps/web/components/dashboard/lists/ListHeader.tsx
parentf7d3462790652c6e5ecd90ae0d699e05b0320a97 (diff)
downloadkarakeep-ef27670f5c027be87d279b9b32553e980e55d888.tar.zst
feat: show bookmark owner icon in shared lists (#2277)
* feat: Add owner icon to bookmarks in shared lists Display a small icon showing the bookmark owner's name and email on hover when viewing bookmarks from other users in shared lists. The icon appears in the top-right corner of bookmark cards across all layout types (grid, list, compact). Changes: - Add user field to ZBookmark type to include owner name and email - Update bookmark queries to fetch user information via join - Create BookmarkOwnerIcon component with tooltip showing owner details - Integrate owner indicator into BookmarkLayoutAdaptingCard for all layouts - Only show icon for bookmarks not owned by current user * use icons in more places * remove tooltip providers * fix non list context --------- Co-authored-by: Claude <noreply@anthropic.com>
Diffstat (limited to 'apps/web/components/dashboard/lists/ListHeader.tsx')
-rw-r--r--apps/web/components/dashboard/lists/ListHeader.tsx64
1 files changed, 48 insertions, 16 deletions
diff --git a/apps/web/components/dashboard/lists/ListHeader.tsx b/apps/web/components/dashboard/lists/ListHeader.tsx
index 8e014e2a..ecbb6431 100644
--- a/apps/web/components/dashboard/lists/ListHeader.tsx
+++ b/apps/web/components/dashboard/lists/ListHeader.tsx
@@ -6,11 +6,11 @@ import { Button } from "@/components/ui/button";
import {
Tooltip,
TooltipContent,
- TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
+import { UserAvatar } from "@/components/ui/user-avatar";
import { useTranslation } from "@/lib/i18n/client";
-import { MoreHorizontal, SearchIcon, Users } from "lucide-react";
+import { MoreHorizontal, SearchIcon } from "lucide-react";
import { api } from "@karakeep/shared-react/trpc";
import { parseSearchQuery } from "@karakeep/shared/searchQueryParser";
@@ -35,6 +35,16 @@ export default function ListHeader({
},
);
+ const { data: collaboratorsData } = api.lists.getCollaborators.useQuery(
+ {
+ listId: initialData.id,
+ },
+ {
+ refetchOnWindowFocus: false,
+ enabled: list.hasCollaborators,
+ },
+ );
+
const parsedQuery = useMemo(() => {
if (!list.query) {
return null;
@@ -55,22 +65,44 @@ export default function ListHeader({
<span className="text-2xl">
{list.icon} {list.name}
</span>
- {list.hasCollaborators && (
- <TooltipProvider>
- <Tooltip>
- <TooltipTrigger asChild>
- <Users className="size-5 text-primary" />
- </TooltipTrigger>
- <TooltipContent>
- <p>{t("lists.shared")}</p>
- </TooltipContent>
- </Tooltip>
- </TooltipProvider>
+ {list.hasCollaborators && collaboratorsData && (
+ <div className="group flex">
+ {collaboratorsData.owner && (
+ <Tooltip>
+ <TooltipTrigger>
+ <div className="-mr-2 transition-all duration-300 ease-out group-hover:mr-1">
+ <UserAvatar
+ name={collaboratorsData.owner.name}
+ image={collaboratorsData.owner.image}
+ className="size-5 shrink-0 rounded-full ring-2 ring-background"
+ />
+ </div>
+ </TooltipTrigger>
+ <TooltipContent>
+ <p>{collaboratorsData.owner.name}</p>
+ </TooltipContent>
+ </Tooltip>
+ )}
+ {collaboratorsData.collaborators.map((collab) => (
+ <Tooltip key={collab.userId}>
+ <TooltipTrigger>
+ <div className="-mr-2 transition-all duration-300 ease-out group-hover:mr-1">
+ <UserAvatar
+ name={collab.user.name}
+ image={collab.user.image}
+ className="size-5 shrink-0 rounded-full ring-2 ring-background"
+ />
+ </div>
+ </TooltipTrigger>
+ <TooltipContent>
+ <p>{collab.user.name}</p>
+ </TooltipContent>
+ </Tooltip>
+ ))}
+ </div>
)}
{list.description && (
- <span className="text-lg text-gray-400">
- {`(${list.description})`}
- </span>
+ <span className="text-lg text-gray-400">{`(${list.description})`}</span>
)}
</div>
<div className="flex items-center">