diff --git a/src/app/components/emoji-board/EmojiBoard.tsx b/src/app/components/emoji-board/EmojiBoard.tsx index db371808..273d064b 100644 --- a/src/app/components/emoji-board/EmojiBoard.tsx +++ b/src/app/components/emoji-board/EmojiBoard.tsx @@ -371,6 +371,7 @@ type EmojiBoardProps = { onStickerSelect?: (mxc: string, shortcode: string, label: string) => void; allowTextCustomEmoji?: boolean; addToRecentEmoji?: boolean; + dock?: boolean; }; export function EmojiBoard({ @@ -384,6 +385,7 @@ export function EmojiBoard({ onStickerSelect, allowTextCustomEmoji, addToRecentEmoji = true, + dock, }: EmojiBoardProps) { const mx = useMatrixClient(); const { t } = useTranslation(); @@ -513,6 +515,7 @@ export function EmojiBoard({ }} > {onTabChange && } diff --git a/src/app/components/emoji-board/components/Layout.tsx b/src/app/components/emoji-board/components/Layout.tsx index 392d4a31..ce047045 100644 --- a/src/app/components/emoji-board/components/Layout.tsx +++ b/src/app/components/emoji-board/components/Layout.tsx @@ -9,11 +9,12 @@ export const EmojiBoardLayout = as< header: ReactNode; sidebar?: ReactNode; children: ReactNode; + dock?: boolean; } ->(({ className, header, sidebar, children, ...props }, ref) => ( +>(({ className, header, sidebar, children, dock, ...props }, ref) => ( ( const isOneOnOne = useIsOneOnOne(); const commands = useCommands(mx, room); const emojiBtnRef = useRef(null); + const screenSize = useScreenSizeContext(); + // On native / narrow screens the emoji-sticker board is docked inline at the + // top of the composer instead of floating as a pop-out. + const dockEmojiBoard = mobileOrTablet() || screenSize === ScreenSize.Mobile; + const [emojiBoardTab, setEmojiBoardTab] = useState(undefined); const roomToParents = useAtomValue(roomToParentsAtom); const powerLevels = usePowerLevelsContext(); const creators = useRoomCreators(room); @@ -601,54 +606,62 @@ export const RoomInput = forwardRef( ); - const emojiButton = ( - - {(emojiBoardTab: EmojiBoardTab | undefined, setEmojiBoardTab) => ( - { - setEmojiBoardTab((tab) => { - if (tab) { - if (!mobileOrTablet()) ReactEditor.focus(editor); - return undefined; - } - return tab; - }); - }} - /> - } - > - setEmojiBoardTab(EmojiBoardTab.Emoji)} - variant="SurfaceVariant" - fill="None" - size="300" - radii="300" - > - - - - )} - + const closeEmojiBoard = () => { + setEmojiBoardTab(undefined); + if (!mobileOrTablet()) ReactEditor.focus(editor); + }; + + const emojiBoard = ( + + ); + + const emojiTriggerButton = ( + + dockEmojiBoard + ? setEmojiBoardTab(emojiBoardTab ? undefined : EmojiBoardTab.Emoji) + : setEmojiBoardTab(EmojiBoardTab.Emoji) + } + variant="SurfaceVariant" + fill="None" + size="300" + radii="300" + > + + + ); + + // Native docks the board inline (rendered in the composer's top slot); the + // desktop trigger keeps the floating pop-out anchored to the button. + const emojiButton = dockEmojiBoard ? ( + emojiTriggerButton + ) : ( + + {emojiTriggerButton} + ); const sendButton = ( @@ -785,43 +798,46 @@ export const RoomInput = forwardRef( onKeyUp={handleKeyUp} onPaste={handlePaste} top={ - replyDraft && ( -
- - setReplyDraft(undefined)} - variant="SurfaceVariant" - size="300" - radii="300" + <> + {dockEmojiBoard && emojiBoardTab !== undefined && emojiBoard} + {replyDraft && ( +
+ - - - - {replyDraft.relation?.rel_type === RelationType.Thread && } - - - {getMemberDisplayName(room, replyDraft.userId) ?? - getMxIdLocalPart(replyDraft.userId) ?? - replyDraft.userId} - - - } + setReplyDraft(undefined)} + variant="SurfaceVariant" + size="300" + radii="300" > - - {trimReplyFromBody(replyDraft.body)} - - + + + + {replyDraft.relation?.rel_type === RelationType.Thread && } + + + {getMemberDisplayName(room, replyDraft.userId) ?? + getMxIdLocalPart(replyDraft.userId) ?? + replyDraft.userId} + + + } + > + + {trimReplyFromBody(replyDraft.body)} + + + - -
- ) +
+ )} + } bottom={