From dff3e7aabc27cd1a3667e129344f33a92de06d0c Mon Sep 17 00:00:00 2001 From: 2427021 <s.a.vink@students.uu.nl> Date: Tue, 5 Mar 2024 14:02:37 +0100 Subject: [PATCH] fix(addTooltipToActionButtons): added tooltips --- .../lib/components/color-mode/index.tsx | 7 +- libs/shared/lib/components/tooltip/index.tsx | 67 ++++---- .../lib/querybuilder/panel/querybuilder.tsx | 147 ++++++++++-------- libs/shared/lib/schema/panel/schema.tsx | 53 ++++--- libs/shared/lib/vis/visualizationPanel.tsx | 43 ++--- 5 files changed, 178 insertions(+), 139 deletions(-) diff --git a/libs/shared/lib/components/color-mode/index.tsx b/libs/shared/lib/components/color-mode/index.tsx index 5ee1198ff..18ffc7c8f 100644 --- a/libs/shared/lib/components/color-mode/index.tsx +++ b/libs/shared/lib/components/color-mode/index.tsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from 'react'; import { Button } from '../buttons'; // Adjust the import path according to your project structure import { DarkMode, LightMode } from '@mui/icons-material'; +import Tooltip from '@graphpolaris/shared/lib/components/tooltip'; const ColorMode = () => { // Initialize theme state without setting a default yet @@ -40,7 +41,11 @@ const ColorMode = () => { }; const iconComponent = theme === 'dark-mode' ? <DarkMode /> : <LightMode />; - return <Button variant="ghost" iconComponent={iconComponent} onClick={toggleTheme} />; + return ( + <Tooltip tooltip={`Switch to ${theme === 'dark-mode' ? 'light' : 'dark'}-mode`}> + <Button variant="ghost" iconComponent={iconComponent} onClick={toggleTheme} /> + </Tooltip> + ); }; export default ColorMode; diff --git a/libs/shared/lib/components/tooltip/index.tsx b/libs/shared/lib/components/tooltip/index.tsx index 060cb73ea..51b3591fc 100644 --- a/libs/shared/lib/components/tooltip/index.tsx +++ b/libs/shared/lib/components/tooltip/index.tsx @@ -18,40 +18,45 @@ export type TooltipProps = { position?: 'top' | 'bottom' | 'left' | 'right'; children: ReactNode; tooltip: string; + disabled?: boolean; }; -export default function Tooltip({ position = 'bottom', children, tooltip }: TooltipProps) { +export default function Tooltip({ position = 'bottom', children, tooltip, disabled = false }: TooltipProps) { return ( - <div className="group relative cursor-pointer"> - <div className="mx-2 my-2">{children}</div> - <span - className={`absolute hidden group-hover:inline-block bg-neutral-900 text-white text-xs p-2 whitespace-nowrap rounded ${ - position === 'top' ? 'left-1/2 -translate-x-1/2 bottom-[calc(100%+5px)]' : '' - } ${position === 'bottom' ? 'left-1/2 -translate-x-1/2 top-[calc(100%+5px)]' : ''} ${ - position === 'left' ? 'top-1/2 -translate-y-1/2 right-[calc(100%+5px)]' : '' - } ${position === 'right' ? 'top-1/2 -translate-y-1/2 left-[calc(100%+5px)]' : ''} `} - > - {tooltip} - </span> - <span - className={`absolute hidden group-hover:inline-block border-[6px] ${ - position === 'top' - ? 'left-1/2 -translate-x-1/2 bottom-full border-l-transparent border-r-transparent border-b-0 border-t-neutral-900' - : '' - } ${ - position === 'bottom' - ? 'left-1/2 -translate-x-1/2 top-full border-l-transparent border-r-transparent border-t-0 border-b-neutral-900' - : '' - } ${ - position === 'left' - ? 'top-1/2 -translate-y-1/2 right-full border-t-transparent border-b-transparent border-r-0 border-l-neutral-900' - : '' - } ${ - position === 'right' - ? 'top-1/2 -translate-y-1/2 left-full border-t-transparent border-b-transparent border-l-0 border-r-neutral-900' - : '' - } `} - ></span> + <div className="group relative cursor-pointer z-50"> + <div className="">{children}</div> + {!disabled && ( + <> + <span + className={`absolute hidden group-hover:inline-block bg-neutral-900 text-white text-xs p-2 whitespace-nowrap rounded ${ + position === 'top' ? 'left-1/2 -translate-x-1/2 bottom-[calc(100%+5px)]' : '' + } ${position === 'bottom' ? 'left-1/2 -translate-x-1/2 top-[calc(100%+5px)]' : ''} ${ + position === 'left' ? 'top-1/2 -translate-y-1/2 right-[calc(100%+5px)]' : '' + } ${position === 'right' ? 'top-1/2 -translate-y-1/2 left-[calc(100%+5px)]' : ''} `} + > + {tooltip} + </span> + <span + className={`absolute hidden group-hover:inline-block border-[6px] ${ + position === 'top' + ? 'left-1/2 -translate-x-1/2 bottom-full border-l-transparent border-r-transparent border-b-0 border-t-neutral-900' + : '' + } ${ + position === 'bottom' + ? 'left-1/2 -translate-x-1/2 top-full border-l-transparent border-r-transparent border-t-0 border-b-neutral-900' + : '' + } ${ + position === 'left' + ? 'top-1/2 -translate-y-1/2 right-full border-t-transparent border-b-transparent border-r-0 border-l-neutral-900' + : '' + } ${ + position === 'right' + ? 'top-1/2 -translate-y-1/2 left-full border-t-transparent border-b-transparent border-l-0 border-r-neutral-900' + : '' + } `} + ></span> + </> + )} </div> ); } diff --git a/libs/shared/lib/querybuilder/panel/querybuilder.tsx b/libs/shared/lib/querybuilder/panel/querybuilder.tsx index c2621af5d..019850fd5 100644 --- a/libs/shared/lib/querybuilder/panel/querybuilder.tsx +++ b/libs/shared/lib/querybuilder/panel/querybuilder.tsx @@ -41,6 +41,7 @@ import { QueryMLDialog } from './querysidepanel/queryMLDialog'; import { QuerySettingsDialog } from './querysidepanel/querySettingsDialog'; import { ConnectingNodeDataI } from './utils/connectorDrop'; import { CameraAlt, Cached, Difference, ImportExport, Lightbulb, Settings, Fullscreen, Delete } from '@mui/icons-material'; +import Tooltip from '../../components/tooltip'; export type QueryBuilderProps = { onRunQuery?: () => void; @@ -440,71 +441,87 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => { <div className="relative flex items-center justify-between z-[2] py-0 px-2 bg-secondary-100 border-b border-secondary-200"> <h1 className="text-xs font-semibold text-secondary-800">Query builder</h1> <ControlContainer> - <Button type="secondary" variant="ghost" size="xs" iconComponent={<Fullscreen />} onClick={fitView} /> - <Button type="secondary" variant="ghost" size="xs" iconComponent={<Delete />} onClick={() => clearAllNodes()} /> - <Button - type="secondary" - variant="ghost" - size="xs" - iconComponent={<CameraAlt />} - onClick={(event) => { - event.stopPropagation(); - }} - /> - <Button - type="secondary" - variant="ghost" - size="xs" - iconComponent={<ImportExport />} - onClick={(event) => { - event.stopPropagation(); - applyLayout(); - }} - /> - <Button - type="secondary" - variant="ghost" - size="xs" - iconComponent={<Settings />} - additionalClasses="query-settings" - onClick={(event) => { - event.stopPropagation(); - if (toggleSettings === 'settings') setToggleSettings(undefined); - else setToggleSettings('settings'); - }} - /> - <Button - type="secondary" - variant="ghost" - size="xs" - iconComponent={<Cached />} - onClick={(event) => { - event.stopPropagation(); - if (props.onRunQuery) props.onRunQuery(); - }} - /> - <Button - type="secondary" - variant="ghost" - size="xs" - iconComponent={<Difference />} - onClick={(event) => { - event.stopPropagation(); - if (toggleSettings === 'logic') setToggleSettings(undefined); - else setToggleSettings('logic'); - }} - /> - <Button - type="secondary" - variant="ghost" - size="xs" - iconComponent={<Lightbulb />} - onClick={(event) => { - event.stopPropagation(); - if (toggleSettings === 'ml') setToggleSettings(undefined); - else setToggleSettings('ml'); - }} - /> + <Tooltip tooltip="Fit to screen"> + <Button type="secondary" variant="ghost" size="xs" iconComponent={<Fullscreen />} onClick={fitView} /> + </Tooltip> + <Tooltip tooltip="Clear query panel"> + <Button type="secondary" variant="ghost" size="xs" iconComponent={<Delete />} onClick={() => clearAllNodes()} /> + </Tooltip> + <Tooltip tooltip="Capture screen"> + <Button + type="secondary" + variant="ghost" + size="xs" + iconComponent={<CameraAlt />} + onClick={(event) => { + event.stopPropagation(); + }} + /> + </Tooltip> + <Tooltip tooltip="Layouts"> + <Button + type="secondary" + variant="ghost" + size="xs" + iconComponent={<ImportExport />} + onClick={(event) => { + event.stopPropagation(); + applyLayout(); + }} + /> + </Tooltip> + <Tooltip tooltip="Query builder settings" disabled={toggleSettings === 'settings'}> + <Button + type="secondary" + variant="ghost" + size="xs" + iconComponent={<Settings />} + additionalClasses="query-settings" + onClick={(event) => { + event.stopPropagation(); + if (toggleSettings === 'settings') setToggleSettings(undefined); + else setToggleSettings('settings'); + }} + /> + </Tooltip> + <Tooltip tooltip="Rerun query"> + <Button + type="secondary" + variant="ghost" + size="xs" + iconComponent={<Cached />} + onClick={(event) => { + event.stopPropagation(); + if (props.onRunQuery) props.onRunQuery(); + }} + /> + </Tooltip> + <Tooltip tooltip="Logic settings" disabled={toggleSettings === 'logic'}> + <Button + type="secondary" + variant="ghost" + size="xs" + iconComponent={<Difference />} + onClick={(event) => { + event.stopPropagation(); + if (toggleSettings === 'logic') setToggleSettings(undefined); + else setToggleSettings('logic'); + }} + /> + </Tooltip> + <Tooltip tooltip="Machine learning" disabled={toggleSettings === 'ml'}> + <Button + type="secondary" + variant="ghost" + size="xs" + iconComponent={<Lightbulb />} + onClick={(event) => { + event.stopPropagation(); + if (toggleSettings === 'ml') setToggleSettings(undefined); + else setToggleSettings('ml'); + }} + /> + </Tooltip> </ControlContainer> </div> diff --git a/libs/shared/lib/schema/panel/schema.tsx b/libs/shared/lib/schema/panel/schema.tsx index a70b190d1..c8e2f7cc2 100644 --- a/libs/shared/lib/schema/panel/schema.tsx +++ b/libs/shared/lib/schema/panel/schema.tsx @@ -20,6 +20,7 @@ import { EntityNode } from '../pills/nodes/entity/entity-node'; import { RelationNode } from '../pills/nodes/relation/relation-node'; import { SchemaDialog } from './schemaDialog'; import { Fullscreen, Cached, Settings } from '@mui/icons-material'; +import Tooltip from '../../components/tooltip'; interface Props { content?: string; @@ -114,29 +115,35 @@ export const Schema = (props: Props) => { <div className="relative flex items-center justify-between z-[2] py-0 px-2 bg-secondary-100 border-b border-secondary-200"> <h1 className="text-xs font-semibold text-secondary-800">Schema</h1> <ControlContainer> - <Button type="secondary" variant="ghost" size="xs" iconComponent={<Fullscreen />} onClick={fitView} /> - <Button - type="secondary" - variant="ghost" - size="xs" - iconComponent={<Cached />} - onClick={(e) => { - e.stopPropagation(); - if (session.currentSaveState) wsSchemaRequest(session.currentSaveState); - else wsGetStates(); - }} - /> - <Button - type="secondary" - variant="ghost" - size="xs" - iconComponent={<Settings />} - additionalClasses="schema-settings" - onClick={(e) => { - e.stopPropagation(); - setToggleSchemaSettings(!toggleSchemaSettings); - }} - /> + <Tooltip tooltip="Fit to screen"> + <Button type="secondary" variant="ghost" size="xs" iconComponent={<Fullscreen />} onClick={fitView} /> + </Tooltip> + <Tooltip tooltip="Refresh schema"> + <Button + type="secondary" + variant="ghost" + size="xs" + iconComponent={<Cached />} + onClick={(e) => { + e.stopPropagation(); + if (session.currentSaveState) wsSchemaRequest(session.currentSaveState); + else wsGetStates(); + }} + /> + </Tooltip> + <Tooltip tooltip="Schema settings"> + <Button + type="secondary" + variant="ghost" + size="xs" + iconComponent={<Settings />} + additionalClasses="schema-settings" + onClick={(e) => { + e.stopPropagation(); + setToggleSchemaSettings(!toggleSchemaSettings); + }} + /> + </Tooltip> </ControlContainer> </div> {nodes.length === 0 ? ( diff --git a/libs/shared/lib/vis/visualizationPanel.tsx b/libs/shared/lib/vis/visualizationPanel.tsx index 0cb6f554c..42cdf0cc1 100644 --- a/libs/shared/lib/vis/visualizationPanel.tsx +++ b/libs/shared/lib/vis/visualizationPanel.tsx @@ -15,6 +15,7 @@ import { Button } from '@graphpolaris/shared/lib/components/buttons'; import { VisualizationDialog } from './configuration'; import { Settings as SettingsIcon, Apps as AppsIcon } from '@mui/icons-material'; import { VisualizationManager, Visualizations } from './visualizationManager'; +import Tooltip from '../components/tooltip'; export const VisualizationPanel = () => { const graphQueryResult = useGraphQueryResult(); @@ -43,25 +44,29 @@ export const VisualizationPanel = () => { <div className="sticky top-0 flex items-center justify-between z-[2] py-0 px-2 bg-secondary-100 border-b border-secondary-200"> <h1 className="text-xs font-semibold text-secondary-800">{vis.activeVisualization} visualization</h1> <ControlContainer> - <Button - type="secondary" - variant="ghost" - size="xs" - iconComponent={<SettingsIcon />} - onClick={() => { - // TODO - // setShowVisSettings(!showVisSettings); - }} - /> - <Button - type="secondary" - variant="ghost" - size="xs" - iconComponent={<AppsIcon />} - onClick={() => { - setVisDropdownOpen(!visDropdownOpen); - }} - /> + <Tooltip tooltip="Visualization settings" disabled={showVisSettings}> + <Button + type="secondary" + variant="ghost" + size="xs" + iconComponent={<SettingsIcon />} + onClick={() => { + // TODO + // setShowVisSettings(!showVisSettings); + }} + /> + </Tooltip> + <Tooltip tooltip="Change visualization" disabled={visDropdownOpen}> + <Button + type="secondary" + variant="ghost" + size="xs" + iconComponent={<AppsIcon />} + onClick={() => { + setVisDropdownOpen(!visDropdownOpen); + }} + /> + </Tooltip> {visDropdownOpen && ( <div ref={visDropdownRef}> <DropdownItemContainer align="top-6 right-6"> -- GitLab