Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions Source/Common/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ export interface TooltipProps {
content: string;
/** Where the tooltip appears relative to the trigger (default: 'top'). */
position?: TooltipPosition;
/**
* When true, the tooltip is suppressed and never appears on hover (default: false).
* Useful when the trigger has expanded into a submenu/fan-out panel and the hover
* label would otherwise overlap the revealed content.
*/
disabled?: boolean;
/** The element that triggers the tooltip on hover. */
children: React.ReactNode;
}
Expand All @@ -28,17 +34,19 @@ const POSITION_CLASSES: Record<TooltipPosition, string> = {
* A CSS-only hover tooltip wrapper. Wraps any child element and displays
* a styled floating label on hover without relying on native browser tooltips.
*/
export const Tooltip: React.FC<TooltipProps> = ({ content, position = 'top', children }) => (
export const Tooltip: React.FC<TooltipProps> = ({ content, position = 'top', disabled = false, children }) => (
<div className='relative group inline-flex'>
{children}
<div
role='tooltip'
className={`tooltip-bubble pointer-events-none absolute ${POSITION_CLASSES[position]} z-50
text-xs px-2 py-1 rounded
whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity duration-150 delay-200`}
style={{ fontFamily: 'system-ui, sans-serif' }}
>
{content}
</div>
{!disabled && (
<div
role='tooltip'
className={`tooltip-bubble pointer-events-none absolute ${POSITION_CLASSES[position]} z-50
text-xs px-2 py-1 rounded
whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity duration-150 delay-200`}
style={{ fontFamily: 'system-ui, sans-serif' }}
>
{content}
</div>
)}
</div>
);
24 changes: 24 additions & 0 deletions Source/Common/for_Tooltip/when_rendered/and_it_is_disabled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) Cratis. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { Tooltip } from '../../Tooltip';

describe('when Tooltip is rendered and it is disabled', () => {
const html = renderToStaticMarkup(
React.createElement(
Tooltip,
{ content: 'Shapes', disabled: true },
React.createElement('button', null, 'Trigger'),
),
);

it('should not render the tooltip bubble', () => {
html.should.not.include('role="tooltip"');
});

it('should still render the trigger element', () => {
html.should.include('Trigger');
});
});
24 changes: 24 additions & 0 deletions Source/Common/for_Tooltip/when_rendered/and_it_is_not_disabled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) Cratis. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { Tooltip } from '../../Tooltip';

describe('when Tooltip is rendered and it is not disabled', () => {
const html = renderToStaticMarkup(
React.createElement(
Tooltip,
{ content: 'Shapes' },
React.createElement('button', null, 'Trigger'),
),
);

it('should render the tooltip bubble', () => {
html.should.include('role="tooltip"');
});

it('should render the tooltip content', () => {
html.should.include('Shapes');
});
});
2 changes: 1 addition & 1 deletion Source/Toolbar/ToolbarFanOutItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const ToolbarFanOutItem = ({

return (
<div className='toolbar-fanout-item' ref={containerRef}>
<Tooltip content={tooltip} position={tooltipPosition}>
<Tooltip content={tooltip} position={tooltipPosition} disabled={isExpanded}>
<button
type='button'
aria-label={tooltip}
Expand Down
2 changes: 1 addition & 1 deletion Source/Toolbar/ToolbarFolder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const ToolbarFolder = ({
return (
<ToolbarFolderContext.Provider value={mode}>
<div className='toolbar-folder-item' ref={containerRef}>
<Tooltip content={title} position={tooltipPosition}>
<Tooltip content={title} position={tooltipPosition} disabled={isExpanded}>
<button
type='button'
aria-label={title}
Expand Down
Loading