From 21f07313e8d840663623a5a0511f36c936d7a2a7 Mon Sep 17 00:00:00 2001 From: martincupela Date: Tue, 14 Apr 2026 16:44:39 +0200 Subject: [PATCH 1/2] feat: redesign Tooltip --- .../AppSettings/ActionsMenu/ActionsMenu.tsx | 7 +- .../ActionsMenu/NotificationPromptDialog.tsx | 124 +++++++++++------- examples/vite/src/Sidebar/SidebarToggle.tsx | 43 ++++-- src/components/Tooltip/Tooltip.tsx | 10 +- src/components/Tooltip/styling/Tooltip.scss | 9 +- 5 files changed, 125 insertions(+), 68 deletions(-) diff --git a/examples/vite/src/AppSettings/ActionsMenu/ActionsMenu.tsx b/examples/vite/src/AppSettings/ActionsMenu/ActionsMenu.tsx index a0f0fc8465..50682e18e7 100644 --- a/examples/vite/src/AppSettings/ActionsMenu/ActionsMenu.tsx +++ b/examples/vite/src/AppSettings/ActionsMenu/ActionsMenu.tsx @@ -5,6 +5,7 @@ import { ContextMenu, ContextMenuButton, IconBolt, + Tooltip, useContextMenuContext, useDialogIsOpen, useDialogOnNearestManager, @@ -48,12 +49,12 @@ const ActionsMenuButton = ({ )} {iconOnly && ( - + )} ); diff --git a/examples/vite/src/AppSettings/ActionsMenu/NotificationPromptDialog.tsx b/examples/vite/src/AppSettings/ActionsMenu/NotificationPromptDialog.tsx index a050236c6a..798b438a8b 100644 --- a/examples/vite/src/AppSettings/ActionsMenu/NotificationPromptDialog.tsx +++ b/examples/vite/src/AppSettings/ActionsMenu/NotificationPromptDialog.tsx @@ -16,6 +16,7 @@ import { IconExclamationTriangleFill, IconPlusSmall, NumericInput, + PopperTooltip, Prompt, TextInput, useNotificationApi, @@ -105,54 +106,85 @@ const NotificationChipList = ({ }: { notifications: QueuedNotification[]; removeQueuedNotification: (id: string) => void; -}) => ( -
- {notifications.map((notification) => { - const SeverityIcon = severityIcons[notification.severity]; - const DirectionIcon = directionIcons[notification.entryDirection]; - - return ( -
- {SeverityIcon && ( - - )} - - {notification.message} - - - - - {formatDurationLabel(notification.duration)} - - - - {notification.entryDirection} +}) => { + const [tooltipState, setTooltipState] = useState<{ + referenceElement: HTMLDivElement; + text: string; + } | null>(null); + + return ( +
+ {notifications.map((notification) => { + const SeverityIcon = severityIcons[notification.severity]; + const DirectionIcon = directionIcons[notification.entryDirection]; + + return ( +
{ + if (event.currentTarget.contains(event.relatedTarget as Node | null)) { + return; + } + setTooltipState(null); + }} + onFocusCapture={(event) => + setTooltipState({ + referenceElement: event.currentTarget, + text: notification.message, + }) + } + onMouseEnter={(event) => + setTooltipState({ + referenceElement: event.currentTarget, + text: notification.message, + }) + } + onMouseLeave={() => setTooltipState(null)} + role='listitem' + > + {SeverityIcon && ( + + )} + + {notification.message} - - {notification.targetPanel} + + + + {formatDurationLabel(notification.duration)} + + + + {notification.entryDirection} + + + {notification.targetPanel} + - - -
- ); - })} -
-); + +
+ ); + })} + + {tooltipState?.text ?? ''} + +
+ ); +}; const NotificationDraftForm = ({ draft, diff --git a/examples/vite/src/Sidebar/SidebarToggle.tsx b/examples/vite/src/Sidebar/SidebarToggle.tsx index 25902fc4a7..1b0e7ed507 100644 --- a/examples/vite/src/Sidebar/SidebarToggle.tsx +++ b/examples/vite/src/Sidebar/SidebarToggle.tsx @@ -1,21 +1,40 @@ +import { useState } from 'react'; import { useSidebar } from '../ChatLayout/SidebarContext.tsx'; -import { Button, useTranslationContext } from 'stream-chat-react'; +import { Button, PopperTooltip, useTranslationContext } from 'stream-chat-react'; import { IconSidebar } from '../icons.tsx'; export const SidebarToggle = () => { const { closeSidebar, openSidebar, sidebarOpen } = useSidebar(); const { t } = useTranslationContext(); + const [buttonElement, setButtonElement] = useState(null); + const [tooltipVisible, setTooltipVisible] = useState(false); + const tooltipText = sidebarOpen ? 'Close sidebar' : 'Open sidebar'; + return ( - + <> + + + {tooltipText} + + ); }; diff --git a/src/components/Tooltip/Tooltip.tsx b/src/components/Tooltip/Tooltip.tsx index 79860a585a..d464789f9d 100644 --- a/src/components/Tooltip/Tooltip.tsx +++ b/src/components/Tooltip/Tooltip.tsx @@ -2,9 +2,10 @@ import type { ComponentProps } from 'react'; import React, { useEffect, useState } from 'react'; import type { PopperLikePlacement } from '../Dialog'; import { usePopoverPosition } from '../Dialog/hooks/usePopoverPosition'; +import clsx from 'clsx'; -export const Tooltip = ({ children, ...rest }: ComponentProps<'div'>) => ( -
+export const Tooltip = ({ children, className, ...rest }: ComponentProps<'div'>) => ( +
{children}
); @@ -12,6 +13,8 @@ export const Tooltip = ({ children, ...rest }: ComponentProps<'div'>) => ( export type PopperTooltipProps = React.PropsWithChildren<{ /** Reference element to which the tooltip should attach to */ referenceElement: T | null; + /** Custom class to be merged along the defaults */ + className?: string; /** Popper's modifier (offset) property - [xAxis offset, yAxis offset], default [0, 10] */ offset?: [number, number]; /** Popper's placement property defining default position of the tooltip, default 'top' */ @@ -22,6 +25,7 @@ export type PopperTooltipProps = React.PropsWithChildren< export const PopperTooltip = ({ children, + className, offset = [0, 10], placement = 'top', referenceElement, @@ -51,7 +55,7 @@ export const PopperTooltip = ({ return (
Date: Tue, 14 Apr 2026 17:10:55 +0200 Subject: [PATCH 2/2] fix: remove tooltip after hover away from ChatView buttons --- src/components/ChatView/styling/ChatView.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ChatView/styling/ChatView.scss b/src/components/ChatView/styling/ChatView.scss index fc28c7a0a5..4b447b3c9c 100644 --- a/src/components/ChatView/styling/ChatView.scss +++ b/src/components/ChatView/styling/ChatView.scss @@ -33,7 +33,7 @@ display: flex; position: relative; - &:focus-within .str-chat__chat-view__selector-button-tooltip, + &:focus-visible + .str-chat__chat-view__selector-button-tooltip, &:hover .str-chat__chat-view__selector-button-tooltip { opacity: 1; transform: translate3d(0, -50%, 0);