mirror of
https://github.com/versia-pub/frontend.git
synced 2025-12-06 08:28:20 +01:00
refactor: ♻️ Refactor Avatar usage into a single component
This commit is contained in:
parent
caf4759d74
commit
a7c8477efe
|
|
@ -1,14 +1,8 @@
|
|||
<template>
|
||||
<div class="rounded flex flex-row items-center gap-3">
|
||||
<NuxtLink :href="urlAsPath" :class="cn('relative size-14', smallLayout && 'size-8')">
|
||||
<Avatar shape="square" :class="cn('size-14 border border-card', smallLayout && 'size-8')">
|
||||
<AvatarImage :src="avatar" alt="" />
|
||||
<AvatarFallback class="rounded-lg"> AA </AvatarFallback>
|
||||
</Avatar>
|
||||
<Avatar shape="square" v-if="cornerAvatar" class="size-6 border absolute -bottom-1 -right-1">
|
||||
<AvatarImage :src="cornerAvatar" alt="" />
|
||||
<AvatarFallback class="rounded-lg"> AA </AvatarFallback>
|
||||
</Avatar>
|
||||
<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">{{
|
||||
|
|
@ -43,6 +37,7 @@ import type {
|
|||
} from "@vueuse/core";
|
||||
import { AtSign, Globe, Lock, LockOpen } from "lucide-vue-next";
|
||||
import CopyableText from "./copyable-text.vue";
|
||||
import Avatar from "../profiles/avatar.vue";
|
||||
|
||||
const { acct, createdAt, url, noteUrl } = defineProps<{
|
||||
avatar: string;
|
||||
|
|
|
|||
|
|
@ -1,19 +1,16 @@
|
|||
<template>
|
||||
<NuxtLink :href="urlAsPath" class="rounded border hover:bg-muted duration-100 text-sm flex flex-row items-center gap-2 px-2 py-1 mb-4">
|
||||
<Repeat class="size-4 text-primary" />
|
||||
<Avatar shape="square" class="size-6 border">
|
||||
<AvatarImage :src="avatar" alt="" />
|
||||
<AvatarFallback class="rounded-lg"> AA </AvatarFallback>
|
||||
</Avatar>
|
||||
<Avatar class="size-6 border" :src="avatar" :name="displayName" />
|
||||
<span class="font-semibold" v-render-emojis="emojis">{{ displayName }}</span>
|
||||
reblogged
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import type { Emoji } from "@versia/client/types";
|
||||
import { Repeat } from "lucide-vue-next";
|
||||
import Avatar from "../profiles/avatar.vue";
|
||||
|
||||
const { url } = defineProps<{
|
||||
avatar: string;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<template>
|
||||
<div v-if="relationship?.requested_by !== false" class="flex flex-row items-center gap-3 p-4">
|
||||
<NuxtLink :href="followerUrl" class="relative size-10">
|
||||
<Avatar shape="square" class="size-10 border border-border">
|
||||
<AvatarImage :src="follower.avatar" alt="" />
|
||||
<AvatarFallback class="rounded-lg"> AA </AvatarFallback>
|
||||
</Avatar>
|
||||
<Avatar class="size-10 border border-border" :src="follower.avatar" :name="follower.display_name" />
|
||||
</NuxtLink>
|
||||
<div class="flex flex-col gap-0.5 justify-center flex-1 text-left leading-tight text-sm">
|
||||
<span class="truncate font-semibold" v-render-emojis="follower.emojis">{{
|
||||
|
|
@ -44,8 +41,8 @@ import type { Account } from "@versia/client/types";
|
|||
import { Check, Loader, X } from "lucide-vue-next";
|
||||
import { toast } from "vue-sonner";
|
||||
import CopyableText from "~/components/notes/copyable-text.vue";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import Avatar from "../profiles/avatar.vue";
|
||||
|
||||
const { follower } = defineProps<{
|
||||
follower: Account;
|
||||
|
|
|
|||
|
|
@ -6,10 +6,7 @@
|
|||
<CardHeader v-if="notification.account"
|
||||
class="flex-row items-center gap-2 px-4 py-2 border-b border-border">
|
||||
<component :is="icon" class="size-5 shrink-0" />
|
||||
<Avatar shape="square" class="size-6 border border-card">
|
||||
<AvatarImage :src="notification.account.avatar" alt="" />
|
||||
<AvatarFallback> AA </AvatarFallback>
|
||||
</Avatar>
|
||||
<Avatar class="size-6 border border-card" :src="notification.account.avatar" :name="notification.account.display_name" />
|
||||
<span class="font-semibold" v-render-emojis="notification.account.emojis">{{
|
||||
notification.account.display_name
|
||||
}}</span>
|
||||
|
|
@ -46,7 +43,7 @@ import {
|
|||
UserCheck,
|
||||
UserPlus,
|
||||
} from "lucide-vue-next";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";
|
||||
import Avatar from "../profiles/avatar.vue";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import { Card, CardContent, CardHeader } from "~/components/ui/card";
|
||||
import {
|
||||
|
|
|
|||
31
components/profiles/avatar.vue
Normal file
31
components/profiles/avatar.vue
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<template>
|
||||
<Avatar shape="square">
|
||||
<AvatarFallback v-if="name">
|
||||
{{ getInitials(name) }}
|
||||
</AvatarFallback>
|
||||
<AvatarImage v-if="src" :src="src" />
|
||||
</Avatar>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar";
|
||||
|
||||
const { name } = defineProps<{
|
||||
src?: string;
|
||||
name?: string;
|
||||
}>();
|
||||
|
||||
/**
|
||||
* Gets the initials of any string, even if it's not a name.
|
||||
* If not a name, it will return the first two characters.
|
||||
* @param name
|
||||
*/
|
||||
const getInitials = (name: string): string => {
|
||||
const initials = name.match(/\b\w/g) || [];
|
||||
|
||||
const firstLetter = initials.shift() || name[0] || "";
|
||||
const secondLetter = initials.pop() || name[1] || "";
|
||||
|
||||
return `${firstLetter}${secondLetter}`.toUpperCase();
|
||||
};
|
||||
</script>
|
||||
|
|
@ -6,19 +6,18 @@
|
|||
<div class="absolute bottom-0 w-full h-1/3 bg-gradient-to-b from-black/0 to-black/40"></div>
|
||||
</div>
|
||||
<div class="absolute bottom-0 translate-y-1/3 left-4 flex flex-row items-start gap-2">
|
||||
<Avatar shape="square" size="lg" class="border">
|
||||
<AvatarImage :src="avatar" alt="" />
|
||||
<AvatarFallback>AA</AvatarFallback>
|
||||
</Avatar>
|
||||
<Avatar size="lg" class="border" :src="avatar" :name="displayName" />
|
||||
</div>
|
||||
</CardHeader>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { CardHeader } from "~/components/ui/card";
|
||||
import Avatar from "./avatar.vue";
|
||||
|
||||
defineProps<{
|
||||
header: string;
|
||||
avatar: string;
|
||||
displayName: string;
|
||||
}>();
|
||||
</script>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<Card>
|
||||
<ProfileHeader :header="account.header" :avatar="account.avatar" />
|
||||
<ProfileHeader :header="account.header" :avatar="account.avatar" :display-name="account.display_name" />
|
||||
<CardContent class="pt-3 gap-4 flex flex-col">
|
||||
<div class="flex flex-row justify-end gap-2">
|
||||
<Button variant="secondary" :disabled="isLoading || relationship?.requested" v-if="!isMe"
|
||||
|
|
|
|||
|
|
@ -3,13 +3,8 @@
|
|||
<DropdownMenuTrigger as-child>
|
||||
<SidebarMenuButton size="lg"
|
||||
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground">
|
||||
<Avatar v-if="identity" shape="square" class="size-8">
|
||||
<AvatarImage :src="identity?.account.avatar" alt="" />
|
||||
<AvatarFallback class="rounded-lg"> AA </AvatarFallback>
|
||||
</Avatar>
|
||||
<Avatar v-else shape="square" class="size-8">
|
||||
<AvatarFallback class="rounded-lg"> AB </AvatarFallback>
|
||||
</Avatar>
|
||||
<Avatar v-if="identity" class="size-8" :src="identity.account.avatar" :name="identity.account.display_name" />
|
||||
<Avatar v-else class="size-8" name="AB" />
|
||||
<div class="grid flex-1 text-left text-sm leading-tight">
|
||||
<span class="truncate font-semibold" v-render-emojis="identity?.account.emojis">{{
|
||||
identity?.account.display_name ?? "Not signed in"
|
||||
|
|
@ -23,10 +18,7 @@
|
|||
align="end" :side-offset="4">
|
||||
<DropdownMenuLabel class="p-0 font-normal">
|
||||
<div v-for="identity of identities" class="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
|
||||
<Avatar shape="square" class="size-8">
|
||||
<AvatarImage :src="identity.account.avatar" alt="" />
|
||||
<AvatarFallback class="rounded-lg"> AA </AvatarFallback>
|
||||
</Avatar>
|
||||
<Avatar class="size-8" :src="identity.account.avatar" :name="identity.account.display_name" />
|
||||
<div class="grid flex-1 text-left text-sm leading-tight">
|
||||
<span class="truncate font-semibold" v-render-emojis="identity.account.emojis">{{
|
||||
identity.account.display_name
|
||||
|
|
@ -70,7 +62,6 @@ import {
|
|||
LogIn,
|
||||
} from "lucide-vue-next";
|
||||
import { toast } from "vue-sonner";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
|
|
@ -82,6 +73,7 @@ import {
|
|||
} from "../ui/dropdown-menu";
|
||||
import { SidebarMenuButton } from "../ui/sidebar";
|
||||
import { NuxtLink } from "#components";
|
||||
import Avatar from "../profiles/avatar.vue";
|
||||
|
||||
const appData = useAppData();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,11 +6,9 @@
|
|||
<NuxtLink href="/">
|
||||
<SidebarMenuButton size="lg"
|
||||
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground">
|
||||
<Avatar shape="square" class="size-8">
|
||||
<AvatarImage :src="instance?.thumbnail.url ??
|
||||
'https://cdn.versia.pub/branding/icon.svg'
|
||||
" alt="" />
|
||||
</Avatar>
|
||||
<Avatar class="size-8" :src="instance?.thumbnail.url ??
|
||||
'https://cdn.versia.pub/branding/icon.svg'
|
||||
" :name="instance?.title" />
|
||||
<div class="grid flex-1 text-left text-sm leading-tight">
|
||||
<span class="truncate font-semibold">{{ instance?.title ?? 'Versia Server' }}</span>
|
||||
<span class="truncate text-xs">{{ "A Versia Server instance" }}</span>
|
||||
|
|
@ -104,7 +102,6 @@ import {
|
|||
Pen,
|
||||
Settings2,
|
||||
} from "lucide-vue-next";
|
||||
import { Avatar, AvatarImage } from "~/components/ui/avatar";
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
|
|
@ -128,6 +125,7 @@ import {
|
|||
import { Button } from "../ui/button";
|
||||
import AccountSwitcher from "./account-switcher.vue";
|
||||
import ThemeSwitcher from "./theme-switcher.vue";
|
||||
import Avatar from "../profiles/avatar.vue";
|
||||
|
||||
const data = {
|
||||
navMain: [
|
||||
|
|
|
|||
Loading…
Reference in a new issue