refactor: ♻️ Refactor Avatar usage into a single component

This commit is contained in:
Jesse Wierzbinski 2024-12-03 14:07:00 +01:00
parent caf4759d74
commit a7c8477efe
No known key found for this signature in database
9 changed files with 52 additions and 46 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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 {

View 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>

View file

@ -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>

View file

@ -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"

View file

@ -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();

View file

@ -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: [