mirror of
https://github.com/versia-pub/frontend.git
synced 2026-03-13 03:29:16 +01:00
feat: ✨ Implement profile hover cards
This commit is contained in:
parent
b4709dc00f
commit
650d916062
8 changed files with 159 additions and 24 deletions
|
|
@ -1,15 +1,28 @@
|
|||
<template>
|
||||
<div class="rounded flex flex-row items-center gap-3">
|
||||
<NuxtLink :href="urlAsPath" :class="cn('relative size-14', smallLayout && 'size-8')">
|
||||
<Avatar :class="cn('size-14 border border-card', smallLayout && 'size-8')" :src="avatar" :name="displayName" />
|
||||
<Avatar v-if="cornerAvatar" class="size-6 border absolute -bottom-1 -right-1" :src="cornerAvatar" />
|
||||
</NuxtLink>
|
||||
<div :class="cn('flex flex-col gap-0.5 justify-center flex-1 text-left leading-tight', smallLayout && 'text-sm')">
|
||||
<span class="truncate font-semibold" v-render-emojis="emojis">{{
|
||||
displayName
|
||||
}}</span>
|
||||
<HoverCard v-model:open="popupOpen" @update:open="() => {
|
||||
if (!enableHoverCard.value) {
|
||||
popupOpen = false;
|
||||
}
|
||||
}">
|
||||
<HoverCardTrigger :as-child="true">
|
||||
<NuxtLink :href="urlAsPath" :class="cn('relative size-14', smallLayout && 'size-8')">
|
||||
<Avatar :class="cn('size-14 border border-card', smallLayout && 'size-8')" :src="author.avatar"
|
||||
:name="author.display_name" />
|
||||
<Avatar v-if="cornerAvatar" class="size-6 border absolute -bottom-1 -right-1" :src="cornerAvatar" />
|
||||
</NuxtLink>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardContent class="w-96">
|
||||
<SmallCard :account="author" />
|
||||
</HoverCardContent>
|
||||
</HoverCard>
|
||||
<div
|
||||
:class="cn('flex flex-col gap-0.5 justify-center flex-1 text-left leading-tight', smallLayout && 'text-sm')">
|
||||
<span class="truncate font-semibold" v-render-emojis="author.emojis">{{
|
||||
author.display_name
|
||||
}}</span>
|
||||
<span class="truncate text-sm tracking-tight">
|
||||
<CopyableText :text="acct">
|
||||
<CopyableText :text="author.acct">
|
||||
<span
|
||||
class="font-semibold bg-gradient-to-tr from-pink-700 dark:from-indigo-400 via-purple-700 dark:via-purple-400 to-indigo-700 dark:to-indigo-400 text-transparent bg-clip-text">
|
||||
@{{ username }}
|
||||
|
|
@ -21,7 +34,8 @@
|
|||
</span>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1 justify-center items-end" v-if="!smallLayout">
|
||||
<NuxtLink :href="noteUrlAsPath" class="text-xs text-muted-foreground" :title="visibilities[visibility].text">
|
||||
<NuxtLink :href="noteUrlAsPath" class="text-xs text-muted-foreground"
|
||||
:title="visibilities[visibility].text">
|
||||
<component :is="visibilities[visibility].icon" class="size-5" />
|
||||
</NuxtLink>
|
||||
</div>
|
||||
|
|
@ -30,31 +44,35 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { Emoji, StatusVisibility } from "@versia/client/types";
|
||||
import type { Account, StatusVisibility } from "@versia/client/types";
|
||||
import type {
|
||||
UseTimeAgoMessages,
|
||||
UseTimeAgoUnitNamesDefault,
|
||||
} from "@vueuse/core";
|
||||
import { AtSign, Globe, Lock, LockOpen } from "lucide-vue-next";
|
||||
import { SettingIds } from "~/settings";
|
||||
import Avatar from "../profiles/avatar.vue";
|
||||
import SmallCard from "../profiles/small-card.vue";
|
||||
import {
|
||||
HoverCard,
|
||||
HoverCardContent,
|
||||
HoverCardTrigger,
|
||||
} from "../ui/hover-card";
|
||||
import CopyableText from "./copyable-text.vue";
|
||||
|
||||
const { acct, createdAt, url, noteUrl } = defineProps<{
|
||||
avatar: string;
|
||||
const { createdAt, noteUrl, author, authorUrl } = defineProps<{
|
||||
cornerAvatar?: string;
|
||||
acct: string;
|
||||
displayName: string;
|
||||
emojis: Emoji[];
|
||||
visibility: StatusVisibility;
|
||||
url: string;
|
||||
noteUrl: string;
|
||||
createdAt: Date;
|
||||
smallLayout?: boolean;
|
||||
author: Account;
|
||||
authorUrl: string;
|
||||
}>();
|
||||
|
||||
const [username, instance] = acct.split("@");
|
||||
const [username, instance] = author.acct.split("@");
|
||||
const digitRegex = /\d/;
|
||||
const urlAsPath = new URL(url).pathname;
|
||||
const urlAsPath = new URL(authorUrl).pathname;
|
||||
const noteUrlAsPath = new URL(noteUrl).pathname;
|
||||
const timeAgo = useTimeAgo(createdAt, {
|
||||
messages: {
|
||||
|
|
@ -75,6 +93,8 @@ const fullTime = new Intl.DateTimeFormat("en-US", {
|
|||
dateStyle: "medium",
|
||||
timeStyle: "short",
|
||||
}).format(createdAt);
|
||||
const enableHoverCard = useSetting(SettingIds.PopupAvatarHover);
|
||||
const popupOpen = ref(false);
|
||||
|
||||
const visibilities = {
|
||||
public: {
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
<CardHeader class="pb-4" as="header">
|
||||
<ReblogHeader v-if="note.reblog" :avatar="note.account.avatar" :display-name="note.account.display_name"
|
||||
:url="reblogAccountUrl" :emojis="note.account.emojis" />
|
||||
<Header :avatar="noteToUse.account.avatar" :corner-avatar="note.reblog ? note.account.avatar : undefined"
|
||||
:note-url="url" :acct="noteToUse.account.acct" :display-name="noteToUse.account.display_name"
|
||||
:visibility="noteToUse.visibility" :url="accountUrl" :created-at="new Date(noteToUse.created_at)"
|
||||
:small-layout="smallLayout" :emojis="noteToUse.account.emojis" />
|
||||
<Header :author="noteToUse.account" :author-url="accountUrl"
|
||||
:corner-avatar="note.reblog ? note.account.avatar : undefined" :note-url="url"
|
||||
:visibility="noteToUse.visibility" :created-at="new Date(noteToUse.created_at)"
|
||||
:small-layout="smallLayout" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Content :content="noteToUse.content" :quote="note.quote ?? undefined"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue