mirror of
https://github.com/versia-pub/frontend.git
synced 2025-12-06 08:28:20 +01:00
fix: 🐛 Fix broken Note UIs
This commit is contained in:
parent
b6080eff60
commit
ac0a571ecc
|
|
@ -67,7 +67,6 @@
|
|||
<Button variant="ghost" size="icon">
|
||||
<component
|
||||
:is="visibilities[state.visibility].icon"
|
||||
class="!size-5"
|
||||
/>
|
||||
</Button>
|
||||
</SelectTrigger>
|
||||
|
|
|
|||
15
components/notes/action-button.vue
Normal file
15
components/notes/action-button.vue
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<template>
|
||||
<Button variant="ghost" class="max-w-14 w-full">
|
||||
<component :is="icon" class="size-4.5" />
|
||||
<slot />
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { FunctionalComponent } from "vue";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
const { icon } = defineProps<{
|
||||
icon: FunctionalComponent;
|
||||
}>();
|
||||
</script>
|
||||
|
|
@ -1,24 +1,17 @@
|
|||
<template>
|
||||
<div class="flex flex-row w-full gap-x-6 items-stretch justify-start text-sm *:max-w-14 *:w-full *:text-muted-foreground">
|
||||
<Button variant="ghost" @click="emit('reply')" :title="m.drab_tense_turtle_comfort()" :disabled="!identity">
|
||||
<Reply class="size-5 text-primary" />
|
||||
<div class="flex flex-row w-full gap-x-4 items-stretch justify-start">
|
||||
<ActionButton :icon="Reply" @click="emit('reply')" :title="m.drab_tense_turtle_comfort()" :disabled="!identity">
|
||||
{{ numberFormat(replyCount) }}
|
||||
</Button>
|
||||
<Button variant="ghost" @click="liked ? unlike() : like()" :title="liked ? m.vexed_fluffy_clownfish_dance() : m.royal_close_samuel_scold()" :disabled="!identity" :class="liked && '*:fill-red-600 *:text-red-600'">
|
||||
<Heart class="size-5 text-primary" />
|
||||
</ActionButton>
|
||||
<ActionButton :icon="Heart" @click="liked ? unlike() : like()" :title="liked ? m.vexed_fluffy_clownfish_dance() : m.royal_close_samuel_scold()" :disabled="!identity" :class="liked && '*:fill-red-600 *:text-red-600'">
|
||||
{{ numberFormat(likeCount) }}
|
||||
</Button>
|
||||
<Button variant="ghost" @click="reblogged ? unreblog() : reblog()" :title="reblogged ? m.lime_neat_ox_stab() : m.aware_helpful_marlin_drop()" :disabled="!identity" :class="reblogged && '*:text-green-600'">
|
||||
<Repeat class="size-5 text-primary" />
|
||||
</ActionButton>
|
||||
<ActionButton :icon="Repeat" @click="reblogged ? unreblog() : reblog()" :title="reblogged ? m.lime_neat_ox_stab() : m.aware_helpful_marlin_drop()" :disabled="!identity" :class="reblogged && '*:text-green-600'">
|
||||
{{ numberFormat(reblogCount) }}
|
||||
</Button>
|
||||
<Button variant="ghost" @click="emit('quote')" :title="m.true_shy_jackal_drip()" :disabled="!identity">
|
||||
<Quote class="size-5 text-primary" />
|
||||
</Button>
|
||||
</ActionButton>
|
||||
<ActionButton :icon="Quote" @click="emit('quote')" :title="m.true_shy_jackal_drip()" :disabled="!identity" />
|
||||
<Menu :api-note-string="apiNoteString" :url="url" :remote-url="remoteUrl" :is-remote="isRemote" :author-id="authorId" @edit="emit('edit')" :note-id="noteId" @delete="emit('delete')">
|
||||
<Button variant="ghost" :title="m.busy_merry_cowfish_absorb()">
|
||||
<Ellipsis class="size-5 text-primary" />
|
||||
</Button>
|
||||
<ActionButton :icon="Ellipsis" :title="m.busy_merry_cowfish_absorb()" />
|
||||
</Menu>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -26,11 +19,11 @@
|
|||
<script lang="ts" setup>
|
||||
import { Ellipsis, Heart, Quote, Repeat, Reply } from "lucide-vue-next";
|
||||
import { toast } from "vue-sonner";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import { getLocale } from "~/paraglide/runtime";
|
||||
import { SettingIds } from "~/settings";
|
||||
import { confirmModalService } from "../modals/composable";
|
||||
import ActionButton from "./action-button.vue";
|
||||
import Menu from "./menu.vue";
|
||||
|
||||
const { noteId } = defineProps<{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<!-- [&:has(>:last-child:nth-child(1))] means "when this element has 1 child" -->
|
||||
<div class="mt-4 grid gap-4 grid-cols-2 *:max-h-56 [&:has(>:last-child:nth-child(1))]:grid-cols-1 sm:[&:has(>:last-child:nth-child(1))>*]:max-h-72">
|
||||
<div class="grid gap-4 grid-cols-2 *:max-h-56 [&:has(>:last-child:nth-child(1))]:grid-cols-1 sm:[&:has(>:last-child:nth-child(1))>*]:max-h-72">
|
||||
<Attachment v-for="attachment in attachments" :key="attachment.id" :attachment="attachment" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
26
components/notes/content-warning.vue
Normal file
26
components/notes/content-warning.vue
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<template>
|
||||
<Alert layout="button">
|
||||
<TriangleAlert />
|
||||
<AlertTitle class="sr-only">{{ m.livid_tangy_lionfish_clasp() }}</AlertTitle>
|
||||
<AlertDescription>
|
||||
{{ contentWarning || m.sour_seemly_bird_hike() }}
|
||||
</AlertDescription>
|
||||
<Button @click="blurred = !blurred" variant="outline" size="sm">{{ blurred ? m.bald_direct_turtle_win() :
|
||||
m.known_flaky_cockroach_dash() }}</Button>
|
||||
</Alert>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { TriangleAlert } from "lucide-vue-next";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import { Alert, AlertDescription, AlertTitle } from "../ui/alert";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
const { contentWarning } = defineProps<{
|
||||
contentWarning?: string;
|
||||
}>();
|
||||
|
||||
const blurred = defineModel<boolean>({
|
||||
default: true,
|
||||
});
|
||||
</script>
|
||||
|
|
@ -1,34 +1,9 @@
|
|||
<template>
|
||||
<Alert variant="warning" v-if="(sensitive || contentWarning) && showCw.value"
|
||||
class="mb-4 py-2 px-4 grid grid-cols-[auto,1fr,auto] gap-2 items-center [&>svg~*]:pl-0 [&>svg+div]:translate-y-0 [&>svg]:static">
|
||||
<AlertTitle class="sr-only">{{ m.livid_tangy_lionfish_clasp() }}</AlertTitle>
|
||||
<div>
|
||||
<TriangleAlert class="size-4" />
|
||||
</div>
|
||||
<AlertDescription>
|
||||
{{ contentWarning || m.sour_seemly_bird_hike() }}
|
||||
</AlertDescription>
|
||||
<Button @click="blurred = !blurred" variant="outline" size="sm">{{ blurred ? m.bald_direct_turtle_win() : m.known_flaky_cockroach_dash() }}</Button>
|
||||
</Alert>
|
||||
<ContentWarning v-if="(sensitive || contentWarning) && showCw.value" :content-warning="contentWarning" v-model="blurred" />
|
||||
|
||||
<div ref="container" :class="cn('overflow-y-hidden relative duration-200', (blurred && showCw.value) && 'blur-md')" :style="{
|
||||
maxHeight: collapsed ? '18rem' : `${container?.scrollHeight}px`,
|
||||
}">
|
||||
<div :class="[
|
||||
'prose prose-sm block relative dark:prose-invert duration-200 !max-w-full break-words prose-a:no-underline hover:prose-a:underline',
|
||||
$style.content,
|
||||
]" v-html="content" v-render-emojis="emojis"></div>
|
||||
<div v-if="isOverflowing && collapsed"
|
||||
class="absolute inset-x-0 bottom-0 h-36 bg-gradient-to-t from-black/5 to-transparent rounded-b"></div>
|
||||
<Button v-if="isOverflowing" @click="collapsed = !collapsed"
|
||||
class="absolute bottom-2 right-1/2 translate-x-1/2">{{
|
||||
collapsed
|
||||
? `${m.lazy_honest_mammoth_bump()}${plainContent ? ` • ${m.dark_spare_goldfish_charm({
|
||||
count: formattedCharacterCount ?? '0',
|
||||
})}` : "" }`
|
||||
: m.that_misty_mule_arrive()
|
||||
}}</Button>
|
||||
</div>
|
||||
<OverflowGuard :character-count="characterCount" :class="(blurred && showCw.value) && 'blur-md'">
|
||||
<Prose v-html="content" v-render-emojis="emojis"></Prose>
|
||||
</OverflowGuard>
|
||||
|
||||
<Attachments v-if="attachments.length > 0" :attachments="attachments" :class="(blurred && showCw.value) && 'blur-xl'" />
|
||||
|
||||
|
|
@ -38,16 +13,13 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { Attachment, Emoji, Status } from "@versia/client/types";
|
||||
import { TriangleAlert } from "lucide-vue-next";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import { getLocale } from "~/paraglide/runtime";
|
||||
import { type BooleanSetting, SettingIds } from "~/settings";
|
||||
import { Alert, AlertDescription, AlertTitle } from "../ui/alert";
|
||||
import Attachments from "./attachments.vue";
|
||||
import ContentWarning from "./content-warning.vue";
|
||||
import Note from "./note.vue";
|
||||
import OverflowGuard from "./overflow-guard.vue";
|
||||
import Prose from "./prose.vue";
|
||||
|
||||
const { content, plainContent, sensitive, contentWarning } = defineProps<{
|
||||
plainContent?: string;
|
||||
|
|
@ -58,30 +30,9 @@ const { content, plainContent, sensitive, contentWarning } = defineProps<{
|
|||
sensitive: boolean;
|
||||
contentWarning?: string;
|
||||
}>();
|
||||
const container = ref<HTMLDivElement | null>(null);
|
||||
const collapsed = ref(true);
|
||||
|
||||
const blurred = ref(sensitive || !!contentWarning);
|
||||
const showCw = useSetting(SettingIds.ShowContentWarning) as Ref<BooleanSetting>;
|
||||
|
||||
// max-h-72 is 18rem
|
||||
const remToPx = (rem: number) =>
|
||||
rem *
|
||||
Number.parseFloat(
|
||||
getComputedStyle(document.documentElement).fontSize || "16px",
|
||||
);
|
||||
const isOverflowing = computed(() => {
|
||||
if (!container.value) {
|
||||
return false;
|
||||
}
|
||||
return container.value.scrollHeight > remToPx(18);
|
||||
});
|
||||
|
||||
const characterCount = plainContent?.length;
|
||||
const formattedCharacterCount = characterCount
|
||||
? new Intl.NumberFormat(getLocale()).format(characterCount)
|
||||
: undefined;
|
||||
</script>
|
||||
|
||||
<style module>
|
||||
@import url("~/styles/content.css");
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@
|
|||
author.display_name
|
||||
}}</span>
|
||||
<span class="truncate text-sm tracking-tight">
|
||||
<CopyableText :text="author.acct">
|
||||
<span>
|
||||
<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 }}
|
||||
</span>
|
||||
<span class="text-muted-foreground">{{ instance && "@" }}{{ instance }}</span>
|
||||
</CopyableText>
|
||||
</span>
|
||||
·
|
||||
<span class="text-muted-foreground ml-auto tracking-normal" :title="fullTime">{{ timeAgo }}</span>
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<Card as="article" class="relative gap-4 items-stretch">
|
||||
<CardHeader as="header">
|
||||
<CardHeader as="header" class="space-y-2">
|
||||
<ReblogHeader
|
||||
v-if="note.reblog"
|
||||
:avatar="note.account.avatar"
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
<!-- Simply offset by the size of avatar + 0.75rem (the gap) -->
|
||||
<CardContent
|
||||
:class="
|
||||
contentUnderUsername && (smallLayout ? 'ml-11' : 'ml-[4.25rem]')
|
||||
['space-y-4', contentUnderUsername && (smallLayout ? 'ml-11' : 'ml-[4.25rem]')]
|
||||
"
|
||||
>
|
||||
<Content
|
||||
|
|
|
|||
49
components/notes/overflow-guard.vue
Normal file
49
components/notes/overflow-guard.vue
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<template>
|
||||
<div ref="container" class="overflow-y-hidden relative duration-200" :style="{
|
||||
maxHeight: collapsed ? '18rem' : `${container?.scrollHeight}px`,
|
||||
}">
|
||||
<slot />
|
||||
<div v-if="isOverflowing && collapsed"
|
||||
class="absolute inset-x-0 bottom-0 h-36 bg-gradient-to-t from-black/5 to-transparent rounded-b"></div>
|
||||
<Button v-if="isOverflowing" @click="collapsed = !collapsed"
|
||||
class="absolute bottom-2 right-1/2 translate-x-1/2">{{
|
||||
collapsed
|
||||
? `${m.lazy_honest_mammoth_bump()}${formattedCharacterCount ? ` • ${m.dark_spare_goldfish_charm({
|
||||
count: formattedCharacterCount,
|
||||
})}` : ""}`
|
||||
: m.that_misty_mule_arrive()
|
||||
}}</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import { getLocale } from "~/paraglide/runtime";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
const { characterCount = 0 } = defineProps<{
|
||||
characterCount?: number;
|
||||
}>();
|
||||
|
||||
const container = useTemplateRef<HTMLDivElement>("container");
|
||||
const collapsed = ref(true);
|
||||
|
||||
// max-h-72 is 18rem
|
||||
const remToPx = (rem: number) =>
|
||||
rem *
|
||||
Number.parseFloat(
|
||||
getComputedStyle(document.documentElement).fontSize || "16px",
|
||||
);
|
||||
|
||||
const isOverflowing = computed(() => {
|
||||
if (!container.value) {
|
||||
return false;
|
||||
}
|
||||
return container.value.scrollHeight > remToPx(18);
|
||||
});
|
||||
|
||||
const formattedCharacterCount =
|
||||
characterCount > 0
|
||||
? new Intl.NumberFormat(getLocale()).format(characterCount)
|
||||
: undefined;
|
||||
</script>
|
||||
12
components/notes/prose.vue
Normal file
12
components/notes/prose.vue
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<template>
|
||||
<div :class="[
|
||||
'prose prose-sm block relative dark:prose-invert duration-200 !max-w-full break-words prose-a:no-underline hover:prose-a:underline',
|
||||
$style.content,
|
||||
]">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style module>
|
||||
@import "~/styles/content.css";
|
||||
</style>
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
<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 class="size-6 border" :src="avatar" :name="displayName" />
|
||||
<span class="font-semibold" v-render-emojis="emojis">{{ displayName }}</span>
|
||||
{{ m.large_vivid_horse_catch() }}
|
||||
<NuxtLink :href="urlAsPath">
|
||||
<Card class="flex-row px-2 py-1 items-center gap-2 hover:bg-muted duration-100 text-sm">
|
||||
<Repeat class="size-4 text-primary" />
|
||||
<Avatar class="size-6 border" :src="avatar" :name="displayName" />
|
||||
<span class="font-semibold" v-render-emojis="emojis">{{ displayName }}</span>
|
||||
{{ m.large_vivid_horse_catch() }}
|
||||
</Card>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
||||
|
|
@ -12,6 +14,7 @@ import type { Emoji } from "@versia/client/types";
|
|||
import { Repeat } from "lucide-vue-next";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import Avatar from "../profiles/avatar.vue";
|
||||
import { Card } from "../ui/card";
|
||||
|
||||
const { url } = defineProps<{
|
||||
avatar: string;
|
||||
|
|
@ -21,4 +24,4 @@ const { url } = defineProps<{
|
|||
}>();
|
||||
|
||||
const urlAsPath = new URL(url).pathname;
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<Avatar :shape="(shape.value as 'circle' | 'square')" :size="size">
|
||||
<Avatar :class="shape.value === 'square' && 'rounded-md'" :size="size">
|
||||
<AvatarFallback v-if="name">
|
||||
{{ getInitials(name) }}
|
||||
</AvatarFallback>
|
||||
|
|
|
|||
|
|
@ -6,13 +6,14 @@ import { type AlertVariants, alertVariants } from ".";
|
|||
const props = defineProps<{
|
||||
class?: HTMLAttributes["class"];
|
||||
variant?: AlertVariants["variant"];
|
||||
layout?: AlertVariants["layout"];
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
data-slot="alert"
|
||||
:class="cn(alertVariants({ variant }), props.class)"
|
||||
:class="cn(alertVariants({ variant, layout }), props.class)"
|
||||
role="alert"
|
||||
>
|
||||
<slot />
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const props = defineProps<{
|
|||
<template>
|
||||
<div
|
||||
data-slot="alert-description"
|
||||
:class="cn('text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed', props.class)"
|
||||
:class="cn('text-muted-foreground text-sm [&_p]:leading-relaxed', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const props = defineProps<{
|
|||
<template>
|
||||
<div
|
||||
data-slot="alert-title"
|
||||
:class="cn('col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight', props.class)"
|
||||
:class="cn('line-clamp-1 min-h-4 font-medium tracking-tight', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ export { default as AlertDescription } from "./AlertDescription.vue";
|
|||
export { default as AlertTitle } from "./AlertTitle.vue";
|
||||
|
||||
export const alertVariants = cva(
|
||||
"relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
|
||||
"relative w-full rounded-lg border px-4 py-3 grid text-sm [&>svg]:size-4 [&>svg]:text-current",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
|
|
@ -13,9 +13,15 @@ export const alertVariants = cva(
|
|||
destructive:
|
||||
"text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
|
||||
},
|
||||
layout: {
|
||||
default:
|
||||
"has-[>svg]:grid-cols-[1fr_auto] grid-rows-2 gap-x-3 gap-y-1 items-start",
|
||||
button: "grid-cols-[auto_1fr_auto] items-center gap-x-3 gap-y-0.5",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
layout: "default",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const props = defineProps<{
|
|||
|
||||
<template>
|
||||
<div data-slot="card" :class="cn(
|
||||
'bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm',
|
||||
'bg-card text-card-foreground flex flex-col gap-6 rounded-md border py-6 shadow-sm',
|
||||
props.class,
|
||||
)
|
||||
">
|
||||
|
|
|
|||
|
|
@ -13,7 +13,10 @@ import { type HTMLAttributes, computed } from "vue";
|
|||
import DialogOverlay from "./DialogOverlay.vue";
|
||||
|
||||
const props = defineProps<
|
||||
DialogContentProps & { class?: HTMLAttributes["class"] }
|
||||
DialogContentProps & {
|
||||
class?: HTMLAttributes["class"];
|
||||
hideClose?: boolean;
|
||||
}
|
||||
>();
|
||||
const emits = defineEmits<DialogContentEmits>();
|
||||
|
||||
|
|
@ -41,6 +44,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|||
<slot />
|
||||
|
||||
<DialogClose
|
||||
v-if="!hideClose"
|
||||
class="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
||||
>
|
||||
<X />
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ const forwardedProps = useForwardProps(delegatedProps);
|
|||
:data-inset="inset ? '' : undefined"
|
||||
:data-variant="variant"
|
||||
v-bind="forwardedProps"
|
||||
:class="cn(`focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive-foreground data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/40 data-[variant=destructive]:focus:text-destructive-foreground data-[variant=destructive]:*:[svg]:!text-destructive-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`, props.class)"
|
||||
:class="cn(`focus:bg-accent w-full focus:text-accent-foreground data-[variant=destructive]:text-destructive-foreground data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/40 data-[variant=destructive]:focus:text-destructive-foreground data-[variant=destructive]:*:[svg]:!text-destructive-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`, props.class)"
|
||||
>
|
||||
<slot />
|
||||
</DropdownMenuItem>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
:bottom-avatar-bar="true"
|
||||
:content-under-username="true"
|
||||
/>
|
||||
<Note v-if="note" :note="note" :top-avatar-bar="true" />
|
||||
<Note v-if="note" :note="note" :top-avatar-bar="(context?.ancestors.length ?? 0) > 0" />
|
||||
</div>
|
||||
<Note v-for="note of context?.descendants" :note="note" />
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue