diff --git a/examples/vite/src/AppSettings/ActionsMenu/ActionsMenu.tsx b/examples/vite/src/AppSettings/ActionsMenu/ActionsMenu.tsx
index a0f0fc846..50682e18e 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 && (
-
Actions
-
+
)}
);
diff --git a/examples/vite/src/AppSettings/ActionsMenu/NotificationPromptDialog.tsx b/examples/vite/src/AppSettings/ActionsMenu/NotificationPromptDialog.tsx
index a050236c6..798b438a8 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 25902fc4a..1b0e7ed50 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/ChatView/styling/ChatView.scss b/src/components/ChatView/styling/ChatView.scss
index fc28c7a0a..4b447b3c9 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);
diff --git a/src/components/Tooltip/Tooltip.tsx b/src/components/Tooltip/Tooltip.tsx
index 79860a585..d464789f9 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 (