diff --git a/fluxer_app/src/features/app/components/layout/sidebar_nav/GuildListItemPresentation.tsx b/fluxer_app/src/features/app/components/layout/sidebar_nav/GuildListItemPresentation.tsx index 39caf87be..ac86d5e85 100644 --- a/fluxer_app/src/features/app/components/layout/sidebar_nav/GuildListItemPresentation.tsx +++ b/fluxer_app/src/features/app/components/layout/sidebar_nav/GuildListItemPresentation.tsx @@ -8,6 +8,7 @@ import type {GuildListIndicatorBarTarget} from '@app/features/app/components/lay import type {GuildListItemDragAndDrop} from '@app/features/app/components/layout/sidebar_nav/UseGuildListItemDragAndDrop'; import {VoiceBadge, type VoiceBadgeActivity} from '@app/features/app/components/layout/sidebar_nav/VoiceBadge'; import {DropPlacement} from '@app/features/app/components/layout/types/DndTypes'; +import {useMergeRefs} from '@app/features/app/hooks/useMergeRefs'; import type {Guild} from '@app/features/guild/models/Guild'; import Guilds from '@app/features/guild/state/Guilds'; import { @@ -27,7 +28,7 @@ import {GuildFeatures} from '@fluxer/constants/src/GuildConstants'; import {ExclamationMarkIcon, PauseIcon} from '@phosphor-icons/react'; import {clsx} from 'clsx'; import type React from 'react'; -import {useMemo} from 'react'; +import {forwardRef, useMemo} from 'react'; import invariant from 'tiny-invariant'; const GuildListItemIcon = createAnimeFlxElement('flx-app-guild-list-item-icon'); @@ -267,42 +268,77 @@ export interface GuildListItemPresentationProps { readonly onLongPress: () => void; } -export function GuildListItemPresentation(props: GuildListItemPresentationProps) { - const rawInitials = getInitialsFromName(props.guild.name); +type GuildListItemPresentationDomProps = Omit< + React.HTMLAttributes, + 'onClick' | 'onContextMenu' | 'onKeyDown' +>; + +export const GuildListItemPresentation = forwardRef< + HTMLElement, + GuildListItemPresentationProps & GuildListItemPresentationDomProps +>(function GuildListItemPresentation( + { + backgroundImage, + canManageGuild, + contextMenuOpen, + dragAndDrop, + focusRingTargetRef, + guild, + guildARIALabel, + hasVoiceActivity, + iconBorderRadius, + indicatorTarget, + isSelected, + isSortingList, + mentionCount, + onClick, + onContextMenu, + onKeyDown, + onLongPress, + showGuildIndicator, + surfaceRef, + voiceBadgeActivity, + ...domProps + }, + forwardedRef, +) { + const rootRef = useMergeRefs([surfaceRef, forwardedRef]); + const rawInitials = getInitialsFromName(guild.name); const initialsLength = resolveInitialsLength(rawInitials); - const dropIndicator = resolveDropIndicator(props.dragAndDrop); + const dropIndicator = resolveDropIndicator(dragAndDrop); const motion = resolveGuildListItemMotion(Accessibility.useReducedMotion); - const draggingCursor = resolveDraggingCursor(props.dragAndDrop); + const draggingCursor = resolveDraggingCursor(dragAndDrop); const guildIconStyle = useMemo( - () => resolveGuildIconStyle(props.backgroundImage, draggingCursor), - [props.backgroundImage, draggingCursor], + () => resolveGuildIconStyle(backgroundImage, draggingCursor), + [backgroundImage, draggingCursor], ); - const guildIconTarget = useMemo(() => ({borderRadius: props.iconBorderRadius}), [props.iconBorderRadius]); + const guildIconTarget = useMemo(() => ({borderRadius: iconBorderRadius}), [iconBorderRadius]); return ( - {!props.isSortingList && props.showGuildIndicator && ( + {!isSortingList && showGuildIndicator && ( - {props.guild.icon == null && ( + {guild.icon == null && ( - {renderCombinePreview(props.guild, props.dragAndDrop, dropIndicator)} + {renderCombinePreview(guild, dragAndDrop, dropIndicator)} ); -} +});