Skip to content

Commit

Permalink
feat: use own anchor root for DialogAnchor
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinCupela committed Sep 5, 2024
1 parent eb6ab99 commit 143555b
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 94 deletions.
8 changes: 6 additions & 2 deletions src/components/Dialog/DialogAnchor.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import clsx from 'clsx';
import { Placement } from '@popperjs/core';
import React, { ComponentProps, PropsWithChildren, useEffect, useRef } from 'react';
import { usePopper } from 'react-popper';
Expand Down Expand Up @@ -48,14 +49,15 @@ export function useDialogAnchor<T extends HTMLElement>({

type DialogAnchorProps = PropsWithChildren<Partial<DialogAnchorOptions>> & {
id: string;
} & ComponentProps<'div' | 'span'>;
} & ComponentProps<'div'>;

export const DialogAnchor = ({
children,
className,
id,
placement = 'auto',
referenceElement = null,
...restDivProps
}: DialogAnchorProps) => {
const open = useDialogIsOpen(id);
const { attributes, popperElementRef, styles } = useDialogAnchor<HTMLDivElement>({
Expand All @@ -67,8 +69,10 @@ export const DialogAnchor = ({
return (
<DialogPortalEntry dialogId={id}>
<div
{...restDivProps}
{...attributes.popper}
className={className}
className={clsx('str-chat__dialog-contents', className)}
data-testid='str-chat__dialog-contents'
ref={popperElementRef}
style={styles.popper}
>
Expand Down
27 changes: 11 additions & 16 deletions src/components/Dialog/DialogPortal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,17 @@ export const DialogPortalDestination = () => {
);

return (
<>
<div
className='str-chat__dialog-overlay'
onClick={() => dialogsManager.closeAll()}
style={{
height: '100%',
inset: '0',
overflow: 'hidden',
position: 'absolute',
width: '100%',
zIndex: shouldRender ? '2' : '-1',
}}
>
<div data-str-chat__portal-id={dialogsManager.id} />
</div>
</>
<div
className='str-chat__dialog-overlay'
data-str-chat__portal-id={dialogsManager.id}
data-testid='str-chat__dialog-overlay'
onClick={() => dialogsManager.closeAll()}
style={
{
'--str-chat__dialog-overlay-height': shouldRender ? '100%' : '0',
} as React.CSSProperties
}
></div>
);
};

Expand Down
5 changes: 2 additions & 3 deletions src/components/MessageActions/MessageActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,6 @@ export const MessageActions = <
toggleOpen={dialog?.toggleSingle}
>
<DialogAnchor
className={clsx('str-chat__message-actions-box', {
'str-chat__message-actions-box--open': dialogIsOpen,
})}
id={dialogId}
placement={isMine ? 'top-end' : 'top-start'}
referenceElement={actionsBoxButtonRef.current}
Expand All @@ -162,6 +159,8 @@ export const MessageActions = <
handleMute={handleMute}
handlePin={handlePin}
isUserMuted={isMuted}
mine={isMine}
open={dialogIsOpen}
/>
</DialogAnchor>
<button
Expand Down
163 changes: 90 additions & 73 deletions src/components/MessageActions/MessageActionsBox.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import clsx from 'clsx';
import React, { ComponentProps } from 'react';

import { MESSAGE_ACTIONS } from '../Message/utils';

Expand Down Expand Up @@ -27,14 +28,17 @@ export type MessageActionsBoxProps<
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
> = Pick<MessageContextValue<StreamChatGenerics>, PropsDrilledToMessageActionsBox> & {
isUserMuted: () => boolean;
};
mine: boolean;
open: boolean;
} & ComponentProps<'div'>;

const UnMemoizedMessageActionsBox = <
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
>(
props: MessageActionsBoxProps<StreamChatGenerics>,
) => {
const {
className,
getMessageActions,
handleDelete,
handleEdit,
Expand All @@ -43,6 +47,8 @@ const UnMemoizedMessageActionsBox = <
handleMute,
handlePin,
isUserMuted,
open,
...restDivProps
} = props;

const {
Expand Down Expand Up @@ -70,81 +76,92 @@ const UnMemoizedMessageActionsBox = <
}
};

const rootClassName = clsx('str-chat__message-actions-box', className, {
'str-chat__message-actions-box--open': open,
});

const buttonClassName =
'str-chat__message-actions-list-item str-chat__message-actions-list-item-button';

return (
<div
aria-label={t('aria/Message Options')}
className='str-chat__message-actions-list'
role='listbox'
>
<CustomMessageActionsList customMessageActions={customMessageActions} message={message} />
{messageActions.indexOf(MESSAGE_ACTIONS.quote) > -1 && (
<button
aria-selected='false'
className={buttonClassName}
onClick={handleQuote}
role='option'
>
{t<string>('Reply')}
</button>
)}
{messageActions.indexOf(MESSAGE_ACTIONS.pin) > -1 && !message.parent_id && (
<button aria-selected='false' className={buttonClassName} onClick={handlePin} role='option'>
{!message.pinned ? t<string>('Pin') : t<string>('Unpin')}
</button>
)}
{messageActions.indexOf(MESSAGE_ACTIONS.markUnread) > -1 && !threadList && !!message.id && (
<button
aria-selected='false'
className={buttonClassName}
onClick={handleMarkUnread}
role='option'
>
{t<string>('Mark as unread')}
</button>
)}
{messageActions.indexOf(MESSAGE_ACTIONS.flag) > -1 && (
<button
aria-selected='false'
className={buttonClassName}
onClick={handleFlag}
role='option'
>
{t<string>('Flag')}
</button>
)}
{messageActions.indexOf(MESSAGE_ACTIONS.mute) > -1 && (
<button
aria-selected='false'
className={buttonClassName}
onClick={handleMute}
role='option'
>
{isUserMuted() ? t<string>('Unmute') : t<string>('Mute')}
</button>
)}
{messageActions.indexOf(MESSAGE_ACTIONS.edit) > -1 && (
<button
aria-selected='false'
className={buttonClassName}
onClick={handleEdit}
role='option'
>
{t<string>('Edit Message')}
</button>
)}
{messageActions.indexOf(MESSAGE_ACTIONS.delete) > -1 && (
<button
aria-selected='false'
className={buttonClassName}
onClick={handleDelete}
role='option'
>
{t<string>('Delete')}
</button>
)}
<div {...restDivProps} className={rootClassName} data-testid='message-actions-box'>
<div
aria-label={t('aria/Message Options')}
className='str-chat__message-actions-list'
role='listbox'
>
<CustomMessageActionsList customMessageActions={customMessageActions} message={message} />
{messageActions.indexOf(MESSAGE_ACTIONS.quote) > -1 && (
<button
aria-selected='false'
className={buttonClassName}
onClick={handleQuote}
role='option'
>
{t<string>('Reply')}
</button>
)}
{messageActions.indexOf(MESSAGE_ACTIONS.pin) > -1 && !message.parent_id && (
<button
aria-selected='false'
className={buttonClassName}
onClick={handlePin}
role='option'
>
{!message.pinned ? t<string>('Pin') : t<string>('Unpin')}
</button>
)}
{messageActions.indexOf(MESSAGE_ACTIONS.markUnread) > -1 && !threadList && !!message.id && (
<button
aria-selected='false'
className={buttonClassName}
onClick={handleMarkUnread}
role='option'
>
{t<string>('Mark as unread')}
</button>
)}
{messageActions.indexOf(MESSAGE_ACTIONS.flag) > -1 && (
<button
aria-selected='false'
className={buttonClassName}
onClick={handleFlag}
role='option'
>
{t<string>('Flag')}
</button>
)}
{messageActions.indexOf(MESSAGE_ACTIONS.mute) > -1 && (
<button
aria-selected='false'
className={buttonClassName}
onClick={handleMute}
role='option'
>
{isUserMuted() ? t<string>('Unmute') : t<string>('Mute')}
</button>
)}
{messageActions.indexOf(MESSAGE_ACTIONS.edit) > -1 && (
<button
aria-selected='false'
className={buttonClassName}
onClick={handleEdit}
role='option'
>
{t<string>('Edit Message')}
</button>
)}
{messageActions.indexOf(MESSAGE_ACTIONS.delete) > -1 && (
<button
aria-selected='false'
className={buttonClassName}
onClick={handleDelete}
role='option'
>
{t<string>('Delete')}
</button>
)}
</div>
</div>
);
};
Expand Down

0 comments on commit 143555b

Please sign in to comment.