From 0b6213819d3c5839e7dddb0a5f1d5f5573a7d5e8 Mon Sep 17 00:00:00 2001
From: Leonardo Christino <leomilho@gmail.com>
Date: Tue, 19 Mar 2024 17:18:36 +0100
Subject: [PATCH] fix: radix button nesting error

---
 libs/shared/lib/components/buttons/index.tsx  | 177 +++++++++---------
 .../lib/components/color-mode/index.tsx       |   2 +-
 libs/shared/lib/data-access/api/eventBus.tsx  |   6 +-
 .../authorization/dashboardAlerts.tsx         |   2 +-
 .../lib/querybuilder/panel/querybuilder.tsx   |  16 +-
 libs/shared/lib/schema/panel/schema.tsx       |   6 +-
 libs/shared/lib/vis/visualizationPanel.tsx    |   4 +-
 7 files changed, 112 insertions(+), 101 deletions(-)

diff --git a/libs/shared/lib/components/buttons/index.tsx b/libs/shared/lib/components/buttons/index.tsx
index a83936dcc..c98e59fda 100644
--- a/libs/shared/lib/components/buttons/index.tsx
+++ b/libs/shared/lib/components/buttons/index.tsx
@@ -1,6 +1,7 @@
 import React, { ReactElement } from 'react';
 import styles from './buttons.module.scss';
 import Icon, { Sizes } from '../icon';
+import { forwardRef } from 'react';
 
 type ButtonProps = {
   type?: 'primary' | 'secondary' | 'danger';
@@ -18,98 +19,104 @@ type ButtonProps = {
   additionalClasses?: string;
 };
 
-export function Button({
-  type = 'secondary',
-  variant = 'solid',
-  label,
-  size = 'md',
-  rounded = false,
-  disabled = false,
-  onClick,
-  block = false,
-  iconComponent,
-  iconPosition = 'leading',
-  ariaLabel,
-  additionalClasses,
-  children,
-  ...props
-}: ButtonProps & React.HTMLAttributes<HTMLButtonElement>) {
-  let typeClass = '';
-  let variantClass = '';
-  let sizeClass = '';
-  const blockClass = block ? styles['btn-block'] : '';
-  const roundedClass = rounded ? styles['btn-rounded'] : '';
+export const Button = React.forwardRef<HTMLButtonElement, ButtonProps & React.HTMLAttributes<HTMLButtonElement>>(
+  (
+    {
+      type = 'secondary',
+      variant = 'solid',
+      label,
+      size = 'md',
+      rounded = false,
+      disabled = false,
+      onClick,
+      block = false,
+      iconComponent,
+      iconPosition = 'leading',
+      ariaLabel,
+      additionalClasses,
+      children,
+      ...props
+    },
+    forwardRef,
+  ) => {
+    let typeClass = '';
+    let variantClass = '';
+    let sizeClass = '';
+    const blockClass = block ? styles['btn-block'] : '';
+    const roundedClass = rounded ? styles['btn-rounded'] : '';
 
-  switch (type) {
-    case 'primary':
-      typeClass = styles['btn-primary'];
-      break;
-    case 'secondary':
-      typeClass = styles['btn-secondary'];
-      break;
-    case 'danger':
-      typeClass = styles['btn-danger'];
-      break;
-    default:
-      return null;
-  }
+    switch (type) {
+      case 'primary':
+        typeClass = styles['btn-primary'];
+        break;
+      case 'secondary':
+        typeClass = styles['btn-secondary'];
+        break;
+      case 'danger':
+        typeClass = styles['btn-danger'];
+        break;
+      default:
+        return null;
+    }
 
-  switch (variant) {
-    case 'solid':
-      variantClass = styles['btn-solid'];
-      break;
-    case 'outline':
-      variantClass = styles['btn-outline'];
-      break;
-    case 'ghost':
-      variantClass = styles['btn-ghost'];
-      break;
-    default:
-      return null;
-  }
+    switch (variant) {
+      case 'solid':
+        variantClass = styles['btn-solid'];
+        break;
+      case 'outline':
+        variantClass = styles['btn-outline'];
+        break;
+      case 'ghost':
+        variantClass = styles['btn-ghost'];
+        break;
+      default:
+        return null;
+    }
 
-  let iconSize: Sizes = 24;
+    let iconSize: Sizes = 24;
 
-  switch (size) {
-    case 'xs':
-      sizeClass = styles['btn-xs'];
-      iconSize = 16;
-      break;
-    case 'sm':
-      sizeClass = styles['btn-sm'];
-      iconSize = 20;
-      break;
-    case 'md':
-      sizeClass = styles['btn-md'];
-      iconSize = 24;
-      break;
-    case 'lg':
-      sizeClass = styles['btn-lg'];
-      iconSize = 28;
-      break;
-    default:
-      return null;
-  }
+    switch (size) {
+      case 'xs':
+        sizeClass = styles['btn-xs'];
+        iconSize = 16;
+        break;
+      case 'sm':
+        sizeClass = styles['btn-sm'];
+        iconSize = 20;
+        break;
+      case 'md':
+        sizeClass = styles['btn-md'];
+        iconSize = 24;
+        break;
+      case 'lg':
+        sizeClass = styles['btn-lg'];
+        iconSize = 28;
+        break;
+      default:
+        return null;
+    }
 
-  const icon = iconComponent ? <Icon component={iconComponent} size={iconSize} /> : null;
+    const icon = iconComponent ? <Icon component={iconComponent} size={iconSize} /> : null;
 
-  const iconOnlyClass = iconComponent && !label && !children ? styles['btn-icon-only'] : '';
+    const iconOnlyClass = iconComponent && !label && !children ? styles['btn-icon-only'] : '';
 
-  return (
-    <button
-      className={`${styles.btn} ${typeClass} ${variantClass} ${sizeClass} ${blockClass} ${roundedClass} ${iconOnlyClass} ${additionalClasses}`}
-      onClick={onClick}
-      disabled={disabled}
-      aria-label={ariaLabel}
-      {...props}
-    >
-      {iconPosition === 'leading' && icon}
-      {label && <span>{label}</span>}
-      {children && <span>{children}</span>}
-      {iconPosition === 'trailing' && icon}
-    </button>
-  );
-}
+    return (
+      <button
+        className={`${styles.btn} ${typeClass} ${variantClass} ${sizeClass} ${blockClass} ${roundedClass} ${iconOnlyClass} ${additionalClasses}`}
+        onClick={onClick}
+        disabled={disabled}
+        aria-label={ariaLabel}
+        ref={forwardRef}
+        {...props}
+      >
+        {iconPosition === 'leading' && icon}
+        {label && <span>{label}</span>}
+        {children && <span>{children}</span>}
+        {iconPosition === 'trailing' && icon}
+      </button>
+    );
+  },
+);
 
 type ButtonGroupProps = {
   children: React.ReactNode;
diff --git a/libs/shared/lib/components/color-mode/index.tsx b/libs/shared/lib/components/color-mode/index.tsx
index 4376dd0aa..97abb3e04 100644
--- a/libs/shared/lib/components/color-mode/index.tsx
+++ b/libs/shared/lib/components/color-mode/index.tsx
@@ -44,7 +44,7 @@ const ColorMode = () => {
   return (
     <TooltipProvider delayDuration={0}>
       <Tooltip>
-        <TooltipTrigger>
+        <TooltipTrigger asChild>
           <Button variant="ghost" iconComponent={iconComponent} onClick={toggleTheme} />
         </TooltipTrigger>
         <TooltipContent side={'bottom'}>
diff --git a/libs/shared/lib/data-access/api/eventBus.tsx b/libs/shared/lib/data-access/api/eventBus.tsx
index ffd43445d..4f9ea34c2 100644
--- a/libs/shared/lib/data-access/api/eventBus.tsx
+++ b/libs/shared/lib/data-access/api/eventBus.tsx
@@ -43,6 +43,7 @@ import { URLParams, getParam, deleteParam } from './url';
 import { setVisualizationState } from '../store/visualizationSlice';
 import { isEqual } from 'lodash-es';
 import { addSchemaAttributeDimensions } from '../store/schemaSlice';
+import { addError } from '@graphpolaris/shared/lib/data-access/store/configSlice';
 
 export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }) => {
   const { login } = useAuth();
@@ -85,7 +86,10 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
 
     unsubs.push(
       wsTestSaveStateConnectionSubscription((data) => {
-        if (data.status === 'success' && data.saveStateID) dispatch(testedSaveState(data.saveStateID));
+        if (data?.status === 'success' && data.saveStateID) dispatch(testedSaveState(data.saveStateID));
+        else {
+          dispatch(addError('DB connection failed'));
+        }
       }),
     );
 
diff --git a/libs/shared/lib/data-access/authorization/dashboardAlerts.tsx b/libs/shared/lib/data-access/authorization/dashboardAlerts.tsx
index 0a396532c..93839e9c0 100644
--- a/libs/shared/lib/data-access/authorization/dashboardAlerts.tsx
+++ b/libs/shared/lib/data-access/authorization/dashboardAlerts.tsx
@@ -68,7 +68,7 @@ export const DashboardAlerts = (props: { timer?: number }) => {
         {
           message: (
             <>
-              <ErrorOutlineIcon /> Sever Error
+              <ErrorOutlineIcon /> {config.errors?.[config.errors.length - 1] || 'Sever Error'}
             </>
           ),
           className: 'alert-error',
diff --git a/libs/shared/lib/querybuilder/panel/querybuilder.tsx b/libs/shared/lib/querybuilder/panel/querybuilder.tsx
index 5a2d623a3..a594becbc 100644
--- a/libs/shared/lib/querybuilder/panel/querybuilder.tsx
+++ b/libs/shared/lib/querybuilder/panel/querybuilder.tsx
@@ -443,7 +443,7 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => {
         <ControlContainer>
           <TooltipProvider delayDuration={0}>
             <Tooltip>
-              <TooltipTrigger>
+              <TooltipTrigger asChild>
                 <Button type="secondary" variant="ghost" size="xs" iconComponent={<Fullscreen />} onClick={fitView} />
               </TooltipTrigger>
               <TooltipContent side={'bottom'}>
@@ -451,7 +451,7 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => {
               </TooltipContent>
             </Tooltip>
             <Tooltip>
-              <TooltipTrigger>
+              <TooltipTrigger asChild>
                 <Button type="secondary" variant="ghost" size="xs" iconComponent={<Delete />} onClick={() => clearAllNodes()} />
               </TooltipTrigger>
               <TooltipContent side={'bottom'}>
@@ -459,7 +459,7 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => {
               </TooltipContent>
             </Tooltip>
             <Tooltip>
-              <TooltipTrigger>
+              <TooltipTrigger asChild>
                 <Button
                   type="secondary"
                   variant="ghost"
@@ -475,7 +475,7 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => {
               </TooltipContent>
             </Tooltip>
             <Tooltip>
-              <TooltipTrigger>
+              <TooltipTrigger asChild>
                 <Button
                   type="secondary"
                   variant="ghost"
@@ -492,7 +492,7 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => {
               </TooltipContent>
             </Tooltip>
             <Tooltip>
-              <TooltipTrigger>
+              <TooltipTrigger asChild>
                 <Button
                   type="secondary"
                   variant="ghost"
@@ -511,7 +511,7 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => {
               </TooltipContent>
             </Tooltip>
             <Tooltip>
-              <TooltipTrigger>
+              <TooltipTrigger asChild>
                 <Button
                   type="secondary"
                   variant="ghost"
@@ -528,7 +528,7 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => {
               </TooltipContent>
             </Tooltip>
             <Tooltip>
-              <TooltipTrigger>
+              <TooltipTrigger asChild>
                 <Button
                   type="secondary"
                   variant="ghost"
@@ -546,7 +546,7 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => {
               </TooltipContent>
             </Tooltip>
             <Tooltip>
-              <TooltipTrigger>
+              <TooltipTrigger asChild>
                 <Button
                   type="secondary"
                   variant="ghost"
diff --git a/libs/shared/lib/schema/panel/schema.tsx b/libs/shared/lib/schema/panel/schema.tsx
index e9fcbff62..37ed7444c 100644
--- a/libs/shared/lib/schema/panel/schema.tsx
+++ b/libs/shared/lib/schema/panel/schema.tsx
@@ -117,7 +117,7 @@ export const Schema = (props: Props) => {
         <ControlContainer>
           <TooltipProvider delayDuration={0}>
             <Tooltip>
-              <TooltipTrigger>
+              <TooltipTrigger asChild>
                 <Button type="secondary" variant="ghost" size="xs" iconComponent={<Fullscreen />} onClick={fitView} />
               </TooltipTrigger>
               <TooltipContent side={'bottom'}>
@@ -125,7 +125,7 @@ export const Schema = (props: Props) => {
               </TooltipContent>
             </Tooltip>
             <Tooltip>
-              <TooltipTrigger>
+              <TooltipTrigger asChild>
                 <Button
                   type="secondary"
                   variant="ghost"
@@ -143,7 +143,7 @@ export const Schema = (props: Props) => {
               </TooltipContent>
             </Tooltip>
             <Tooltip>
-              <TooltipTrigger>
+              <TooltipTrigger asChild>
                 <Button
                   type="secondary"
                   variant="ghost"
diff --git a/libs/shared/lib/vis/visualizationPanel.tsx b/libs/shared/lib/vis/visualizationPanel.tsx
index 14c2245fe..ab722fc2c 100644
--- a/libs/shared/lib/vis/visualizationPanel.tsx
+++ b/libs/shared/lib/vis/visualizationPanel.tsx
@@ -40,7 +40,7 @@ export const VisualizationPanel = () => {
         <ControlContainer>
           <TooltipProvider delayDuration={0}>
             <Tooltip disabled={showVisSettings}>
-              <TooltipTrigger>
+              <TooltipTrigger asChild>
                 <Button
                   type="secondary"
                   variant="ghost"
@@ -57,7 +57,7 @@ export const VisualizationPanel = () => {
               </TooltipContent>
             </Tooltip>
             <Tooltip>
-              <TooltipTrigger>
+              <TooltipTrigger asChild>
                 <Button
                   type="secondary"
                   variant="ghost"
-- 
GitLab