Repository: harness/canary
Pull request #1388: fix pr tabs
Author: login: ankormoreankor
Created: 2025-04-03T10:53:37Z | Merged: 2025-04-18T15:55:04Z

##### Fix for tabs at `Pull Request` page

Used NavLink in PR Tabs for the better accessibility, usability and performance


Diff:
diff --git a/apps/portal/src/content/docs/components/tabs.mdx b/apps/portal/src/content/docs/components/tabs.mdx
index 14efceec94..f3b51892d1 100644
--- a/apps/portal/src/content/docs/components/tabs.mdx
+++ b/apps/portal/src/content/docs/components/tabs.mdx
@@ -87,7 +87,7 @@ The root component for the tabs.
       name: "variant",
       description: "Variant of the tabs",
       required: false,
-      value: "'default' | 'underline' | 'navigation' | 'tabnav'",
+      value: "'pills' | 'underline' | 'tabs'",
     },
     {
       name: "fontSize",
@@ -131,7 +131,7 @@ The list component that contains the tab triggers.
       name: "variant",
       description: "Variant of the tabs",
       required: false,
-      value: "'default' | 'underline' | 'navigation' | 'tabnav'",
+      value: "'pills' | 'underline' | 'tabs'",
     },
     {
       name: "fontSize",
@@ -168,7 +168,7 @@ The trigger component for individual tabs.
       name: "variant",
       description: "Variant of the tabs",
       required: false,
-      value: "'default' | 'underline' | 'navigation' | 'tabnav'",
+      value: "'pills' | 'underline' | 'tabs'",
     },
     {
       name: "value",
@@ -205,7 +205,7 @@ The content component for individual tabs.
       name: "variant",
       description: "Variant of the tabs",
       required: false,
-      value: "'default' | 'underline' | 'navigation' | 'tabnav'",
+      value: "'pills' | 'underline' | 'tabs'",
     },
     {
       name: "value",
diff --git a/packages/ui/src/components/tabnav.tsx b/packages/ui/src/components/tabnav.tsx
index d674a00396..7af9178c70 100644
--- a/packages/ui/src/components/tabnav.tsx
+++ b/packages/ui/src/components/tabnav.tsx
@@ -1,41 +1,81 @@
-import { FC, HTMLAttributes, PropsWithChildren } from 'react'
+import { createContext, HTMLAttributes, PropsWithChildren, useContext } from 'react'
 import { NavLinkProps } from 'react-router-dom'
 
 import { useRouterContext } from '@/context'
 import { cn } from '@utils/cn'
+import { cva, VariantProps } from 'class-variance-authority'
 
-const TabNavRoot: FC<PropsWithChildren<HTMLAttributes<HTMLElement>>> = ({ className, ...props }) => {
+const tabNavRootVariants = cva('flex items-center', {
+  variants: {
+    variant: {
+      underline: 'border-cn-borders-3 h-11 w-full gap-6 border-b px-6',
+      tabs: 'before:border-cn-borders-2 relative w-full before:absolute before:bottom-0 before:left-0 before:w-full before:border-b'
+    }
+  },
+  defaultVariants: {
+    variant: 'underline'
+  }
+})
+
+const makeTabNavTriggerVariants = (isActive?: boolean) =>
+  cva(
+    'text-cn-foreground-2 hover:text-cn-foreground-1 relative flex h-9 place-items-center font-normal duration-150 ease-in-out focus-visible:duration-0',
+    {
+      variants: {
+        variant: {
+          underline: [
+            'text-2 m-0 my-1 whitespace-nowrap px-0 leading-none',
+            // bottom border of active tab
+            'after:pointer-events-none after:absolute after:inset-[-0.25rem_0] after:block after:border-b-2 after:border-solid after:border-b-transparent',
+            ...(isActive ? ['text-cn-foreground-1 after:border-cn-borders-accent'] : [])
+            /*
+             * TODO: Active tab Radial background is hidden until it's adjusted to the light theme
+             */
+            // radial gradient of active tab
+            // 'before:pointer-events-none before:absolute before:left-1/2 before:top-1/2 before:-z-10 before:h-[calc(100%+40px)] before:w-[calc(100%+60px)] before:-translate-x-1/2 before:-translate-y-1/2 before:bg-transparent',
+            // { 'before:[/* the radial gradient was lost during design system update (PR 1462) */]': isActive },
+          ],
+          tabs: [
+            'gap-x-1.5 rounded-t-md border-x border-t border-transparent px-3.5',
+            ...(isActive ? ['border-cn-borders-2 bg-cn-background-1 text-cn-foreground-1'] : [])
+          ]
+        }
+      },
+      defaultVariants: {
+        variant: 'underline'
+      }
+    }
+  )
+
+const TabNavContext = createContext<
+  VariantProps<typeof tabNavRootVariants | ReturnType<typeof makeTabNavTriggerVariants>>
+>({
+  variant: 'underline'
+})
+
+interface TabNavRootProps
+  extends PropsWithChildren<HTMLAttributes<HTMLElement>>,
+    VariantProps<typeof tabNavRootVariants> {}
+
+const TabNavRoot = ({ className, variant, children, ...props }: TabNavRootProps) => {
   return (
-    <nav
-      {...props}
-      className={cn(
-        'flex h-11 w-full items-center gap-6 border-b border-cn-borders-3 px-6 text-cn-foreground-2',
-        className
-      )}
-    />
+    <nav {...props} className={cn(tabNavRootVariants({ variant }), className)}>
+      <TabNavContext.Provider value={{ variant }}>{children}</TabNavContext.Provider>
+    </nav>
   )
 }
 
-const TabNavItem: FC<NavLinkProps> = ({ className, ...props }) => {
+interface TabNavItemProps extends NavLinkProps, VariantProps<ReturnType<typeof makeTabNavTriggerVariants>> {}
+
+const TabNavItem = ({ className, variant, ...props }: TabNavItemProps) => {
   const { NavLink } = useRouterContext()
+  const context = useContext(TabNavContext)
 
   return (
     <NavLink
       role="tab"
       className={({ isActive }) =>
-        cn(
-          'block relative place-content-center whitespace-nowrap m-0 my-1 h-9 px-0 text-2 font-normal leading-none text-cn-foreground-2 focus-visible:duration-0 duration-150 ease-in-out hover:text-cn-foreground-1 disabled:pointer-events-none disabled:opacity-50 ',
-          // bottom border of active tab
-          'after:pointer-events-none after:absolute after:inset-[-0.25rem_0] after:block after:border-b-2 after:border-solid after:border-b-transparent',
-          { 'text-cn-foreground-1 after:border-cn-borders-accent': isActive },
-          /*
-           * TODO: Active tab Radial background is hidden until it's adjusted to the light theme
-           */
-          // radial gradient of active tab
-          // 'before:pointer-events-none before:absolute before:left-1/2 before:top-1/2 before:-z-10 before:h-[calc(100%+40px)] before:w-[calc(100%+60px)] before:-translate-x-1/2 before:-translate-y-1/2 before:bg-transparent',
-          // { 'before:[background-image:var()]': isActive },
-          className
-        )
+        cn(makeTabNavTriggerVariants(isActive)({ variant: context.variant ?? variant }), className)
       }
       {...props}
     />
diff --git a/packages/ui/src/components/tabs.tsx b/packages/ui/src/components/tabs.tsx
index 6708f36a2c..4b1447b5e6 100644
--- a/packages/ui/src/components/tabs.tsx
+++ b/packages/ui/src/components/tabs.tsx
@@ -4,23 +4,12 @@ import * as TabsPrimitive from '@radix-ui/react-tabs'
 import { cn } from '@utils/cn'
 import { cva, type VariantProps } from 'class-variance-authority'
 
-const tabsListVariants = cva('inline-flex items-center text-cn-foreground-2', {
+const tabsListVariants = cva('text-cn-foreground-2 inline-flex items-center', {
   variants: {
     variant: {
-      default: 'h-9 justify-center rounded-lg bg-cn-background-softgray p-1',
+      pills: 'bg-cn-background-softgray h-9 justify-center rounded-lg p-1',
       underline: 'h-11 justify-center gap-4',
-      /**
-       * TODO: Technical Debt - Navigation Variant Removal
-       * This variant needs to be removed after:
-       * 1. Verifying all dependencies in packages/ui || packages/views
-       * 2. Migrating existing usages to TabNav component
-       * 3. Ensuring no breaking changes in the application
-       *
-       * @deprecated Use TabNav component instead
-       */
-      navigation: 'h-[44px] w-full justify-start gap-6 border-b border-cn-borders-3 px-5',
-      tabnav:
-        'before:bg-cn-borders-3 relative flex w-full before:absolute before:bottom-0 before:left-0 before:h-px before:w-full'
+      tabs: 'before:bg-cn-borders-3 relative flex w-full before:absolute before:bottom-0 before:left-0 before:h-px before:w-full'
     },
     fontSize: {
       xs: 'text-1',
@@ -28,68 +17,46 @@ const tabsListVariants = cva('inline-flex items-center text-cn-foreground-2', {
     }
   },
   defaultVariants: {
-    variant: 'default',
+    variant: 'tabs',
     fontSize: 'sm'
   }
 })
 
 const tabsTriggerVariants = cva(
-  'group relative inline-flex items-center justify-center whitespace-nowrap px-3 py-1 font-medium transition-all focus-visible:duration-0 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-cn-foreground-1',
+  'data-[state=active]:text-cn-foreground-1 group relative inline-flex items-center justify-center whitespace-nowrap px-3 py-1 font-medium transition-all focus-visible:duration-0 disabled:pointer-events-none disabled:opacity-50',
   {
     variants: {
       variant: {
-        default: 'rounded-md data-[state=active]:bg-cn-background data-[state=active]:shadow',
+        pills: 'data-[state=active]:bg-cn-background rounded-md data-[state=active]:shadow',
         underline:
-          'm-0 h-11 border-b-2 border-solid border-b-transparent px-0 font-normal data-[state=active]:border-cn-borders-1',
-        /**
-         * TODO: Technical Debt - Navigation Variant Removal
-         * This variant needs to be removed after:
-         * 1. Verifying all dependencies in packages/views
-         * 2. Migrating existing usages to TabNav component
-         * 3. Ensuring no breaking changes in the application
-         *
-         * @deprecated Use TabNav component instead
-         */
-        navigation:
-          'm-0 -mb-px h-[44px] border-b-2 border-solid border-b-transparent px-0 font-normal text-cn-foreground-2 duration-150 ease-in-out hover:text-cn-foreground-1 data-[state=active]:border-cn-borders-9',
-        tabnav:
-          'h-9 rounded-t-md border-x border-t border-transparent px-3.5 font-normal text-cn-foreground-2 hover:text-cn-foreground-1 data-[state=active]:border-cn-borders-2 data-[state=active]:bg-cn-background-1 data-[state=active]:text-cn-foreground-1'
+          'data-[state=active]:border-cn-borders-1 m-0 h-11 border-b-2 border-solid border-b-transparent px-0 font-normal',
+        tabs: 'text-cn-foreground-2 hover:text-cn-foreground-1 data-[state=active]:border-cn-borders-2 data-[state=active]:bg-cn-background-1 data-[state=active]:text-cn-foreground-1 h-9 rounded-t-md border-x border-t border-transparent px-3.5 font-normal'
       }
     },
     defaultVariants: {
-      variant: 'default'
+      variant: 'tabs'
     }
   }
 )
 
 const tabsContentVariants = cva(
-  'ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cn-borders-accent focus-visible:ring-offset-2',
+  'ring-offset-background focus-visible:ring-cn-borders-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2',
   {
     variants: {
       variant: {
-        default: '',
+        pills: '',
         underline: '',
-        /**
-         * TODO: Technical Debt - Navigation Variant Removal
-         * This variant needs to be removed after:
-         * 1. Verifying all dependencies in packages/views
-         * 2. Migrating existing usages to TabNav component
-         * 3. Ensuring no breaking changes in the application
-         *
-         * @deprecated Use TabNav component instead
-         */
-        navigation: '',
-        tabnav: ''
+        tabs: ''
       }
     },
     defaultVariants: {
-      variant: 'default'
+      variant: 'tabs'
     }
   }
 )
 
 const TabsContext = React.createContext<VariantProps<typeof tabsListVariants | typeof tabsTriggerVariants>>({
-  variant: 'default'
+  variant: 'tabs'
 })
 
 interface TabsRootProps
diff --git a/packages/ui/src/views/connectors/connector-details/connector-details-page.tsx b/packages/ui/src/views/connectors/connector-details/connector-details-page.tsx
index b904147766..2e8911c1e3 100644
--- a/packages/ui/src/views/connectors/connector-details/connector-details-page.tsx
+++ b/packages/ui/src/views/connectors/connector-details/connector-details-page.tsx
@@ -47,7 +47,6 @@ const ConnectorDetailsPage: FC<ConnectorDetailsPageProps> = ({
           useTranslationStore={useTranslationStore}
         />
         <Tabs.Root
-          variant="tabnav"
           className="mb-7 px-8"
           defaultValue={ConnectorDetailsTabsKeys.CONFIGURATION}
           value={activeTab}
diff --git a/packages/ui/src/views/execution/step-execution.tsx b/packages/ui/src/views/execution/step-execution.tsx
index c198602136..9eaf271415 100644
--- a/packages/ui/src/views/execution/step-execution.tsx
+++ b/packages/ui/src/views/execution/step-execution.tsx
@@ -26,7 +26,7 @@ const StepExecutionToolbar: FC<
         handleChange={handleInputChange}
         value={query}
       >
-        <div className="absolute inset-y-0 right-1.5 my-auto flex h-5 w-8 items-center justify-center gap-1 rounded border border-cn-borders-2 bg-cn-background-3">
+        <div className="border-cn-borders-2 bg-cn-background-3 absolute inset-y-0 right-1.5 my-auto flex h-5 w-8 items-center justify-center gap-1 rounded border">
           <Icon className="text-icons-3" name="command-symbol" size={10} />
           <span className="text-1 leading-none">F</span>
         </div>
@@ -35,21 +35,21 @@ const StepExecutionToolbar: FC<
         <Button
           variant="outline"
           size="icon"
-          className="rounded-r-none border-r-0 border-cn-borders-2"
+          className="border-cn-borders-2 rounded-r-none border-r-0"
           onClick={onCopy}
         >
-          <Icon name="clone" className="size-4 text-icons-3" />
+          <Icon name="clone" className="text-icons-3 size-4" />
         </Button>
-        <Button variant="outline" size="icon" className="rounded-none border-cn-borders-2" onClick={onEdit}>
-          <Icon name="edit-pen" className="size-4 text-icons-3" />
+        <Button variant="outline" size="icon" className="border-cn-borders-2 rounded-none" onClick={onEdit}>
+          <Icon name="edit-pen" className="text-icons-3 size-4" />
         </Button>
         <Button
           variant="outline"
           size="icon"
-          className="rounded-l-none border-l-0 border-cn-borders-2"
+          className="border-cn-borders-2 rounded-l-none border-l-0"
           onClick={onDownload}
         >
-          <Icon name="download" className="size-4 text-icons-3" />
+          <Icon name="download" className="text-icons-3 size-4" />
         </Button>
       </div>
     </Layout.Horizontal>
@@ -79,10 +79,10 @@ export const StepExecution: FC<StepExecutionProps> = ({ step, logs, onEdit, onDo
   const { isLightTheme } = useTheme()
 
   return (
-    <Tabs.Root defaultValue={StepExecutionTab.LOG} className="size-full">
+    <Tabs.Root variant="pills" defaultValue={StepExecutionTab.LOG} className="size-full">
       <Layout.Vertical className="space-y-0">
         <Layout.Horizontal className="flex justify-between py-2.5 pl-5 pr-3.5">
-          <Tabs.List className="h-8 w-fit gap-x-0.5 border border-cn-borders-2 bg-cn-background-3">
+          <Tabs.List className="border-cn-borders-2 bg-cn-background-3 h-8 w-fit gap-x-0.5 border">
             <TabsTrigger isLightTheme={isLightTheme} value={StepExecutionTab.LOG}>
               Logs
             </TabsTrigger>
diff --git a/packages/ui/src/views/layouts/PullRequestLayout.tsx b/packages/ui/src/views/layouts/PullRequestLayout.tsx
index 25d6e0c419..b972834a7a 100644
--- a/packages/ui/src/views/layouts/PullRequestLayout.tsx
+++ b/packages/ui/src/views/layouts/PullRequestLayout.tsx
@@ -1,26 +1,30 @@
-import { FC, PropsWithChildren, useCallback } from 'react'
-import { NavLink } from 'react-router-dom'
+import { FC, PropsWithChildren, ReactNode } from 'react'
 
-import { Badge, BadgeProps, Icon, IconProps, Tabs, TabsTriggerProps } from '@/components'
+import { Badge, Icon, IconProps, TabNav } from '@/components'
 import { useRouterContext } from '@/context'
-import { cn } from '@/utils'
 import { SandboxLayout } from '@views/layouts/SandboxLayout'
 import { TranslationStore } from '@views/repo'
 import { PullRequestHeader } from '@views/repo/pull-request/components/pull-request-header'
 import { IPullRequestStore } from '@views/repo/pull-request/pull-request.types'
 
-const TabTitleWithIcon = ({ icon, children }: PropsWithChildren<{ icon: IconProps['name'] }>) => (
-  <div className="flex items-center gap-x-1">
-    <Icon className="text-icons-1 group-data-[state=active]:text-icons-2" size={14} name={icon} />
-    {children}
-  </div>
+const TabTitleWithIcon = ({
+  icon,
+  children,
+  badgeContent
+}: PropsWithChildren<{ icon: IconProps['name']; badgeContent?: ReactNode }>) => (
+  <>
+    <div className="flex items-center gap-x-1">
+      <Icon className="text-icons-1 group-[.is-active]:text-icons-2" size={14} name={icon} />
+      {children}
+    </div>
+    {!!badgeContent && (
+      <Badge className="text-foreground-2 font-normal" variant="counter" size="sm">
+        {badgeContent}
+      </Badge>
+    )}
+  </>
 )
 
-const badgeCommonProps: BadgeProps = {
-  variant: 'counter',
-  size: 'sm'
-}
-
 interface PullRequestLayoutProps {
   usePullRequestStore: () => IPullRequestStore
   spaceId?: string
@@ -46,15 +50,6 @@ export const PullRequestLayout: FC<PullRequestLayoutProps> = ({
   const { pullRequest } = usePullRequestStore()
   const { t } = useTranslationStore()
 
-  const getTabProps = useCallback(
-    (tab: PullRequestTabsKeys): TabsTriggerProps => ({
-      value: tab,
-      className: 'group gap-x-1.5',
-      role: 'link'
-    }),
-    []
-  )
-
   return (
     <SandboxLayout.Main fullWidth>
       <SandboxLayout.Content className="mx-auto max-w-[1500px] px-6">
@@ -62,32 +57,28 @@ export const PullRequestLayout: FC<PullRequestLayoutProps> = ({
           <PullRequestHeader className="mb-10" updateTitle={updateTitle} data={{ ...pullRequest, spaceId, repoId }} />
         )}
 
-        <Tabs.Root variant="tabnav" className="mb-7" defaultValue={PullRequestTabsKeys.CONVERSATION}>
-          <Tabs.List className="before:bg-background-9 before:left-1/2 before:w-[calc(100vw-var(--cn-sidebar-width)-var(--cn-inset-layout-indent)*2)] before:min-w-[calc(100%+3rem)] before:-translate-x-1/2">
-            <Tabs.Trigger {...getTabProps(PullRequestTabsKeys.CONVERSATION)} asChild>
-              <NavLink to={PullRequestTabsKeys.CONVERSATION}>
-                <TabTitleWithIcon icon="comments">
-                  {t('views:pullRequests.conversation', 'Conversation')}
-                </TabTitleWithIcon>
-                {pullRequest?.stats?.conversations && (
-                  <Badge {...badgeCommonProps}>{pullRequest.stats.conversations}</Badge>
-                )}
-              </NavLink>
-            </Tabs.Trigger>
-            <Tabs.Trigger {...getTabProps(PullRequestTabsKeys.COMMITS)} asChild>
-              <NavLink to={PullRequestTabsKeys.COMMITS}>
-                <TabTitleWithIcon icon="tube-sign">{t('views:pullRequests.commits', 'Commits')}</TabTitleWithIcon>
-                <Badge {...badgeCommonProps}>{pullRequest?.stats?.commits}</Badge>
-              </NavLink>
-            </Tabs.Trigger>
-            <Tabs.Trigger {...getTabProps(PullRequestTabsKeys.CHANGES)} asChild>
-              <NavLink to={PullRequestTabsKeys.CHANGES}>
-                <TabTitleWithIcon icon="changes">{t('views:pullRequests.changes', 'Changes')}</TabTitleWithIcon>
-                <Badge {...badgeCommonProps}>{pullRequest?.stats?.files_changed}</Badge>
-              </NavLink>
-            </Tabs.Trigger>
-          </Tabs.List>
-        </Tabs.Root>
+        <TabNav.Root variant="tabs" className="mb-7 before:-left-6 before:w-[calc(100%+3rem)]">
+          <TabNav.Item to={PullRequestTabsKeys.CONVERSATION}>
+            <TabTitleWithIcon
+              icon="comments"
+              badgeContent={!!pullRequest?.stats?.conversations && pullRequest?.stats?.conversations}
+            >
+              {t('views:pullRequests.conversation', 'Conversation')}
+            </TabTitleWithIcon>
+          </TabNav.Item>
+
+          <TabNav.Item to={PullRequestTabsKeys.COMMITS}>
+            <TabTitleWithIcon icon="tube-sign" badgeContent={pullRequest?.stats?.commits}>
+              {t('views:pullRequests.commits', 'Commits')}
+            </TabTitleWithIcon>
+          </TabNav.Item>
+
+          <TabNav.Item to={PullRequestTabsKeys.CHANGES}>
+            <TabTitleWithIcon icon="changes" badgeContent={pullRequest?.stats?.files_changed}>
+              {t('views:pullRequests.changes', 'Changes')}
+            </TabTitleWithIcon>
+          </TabNav.Item>
+        </TabNav.Root>
 
         <Outlet />
       </SandboxLayout.Content>
diff --git a/packages/ui/src/views/repo/components/branch-selector-v2/branch-selector-dropdown.tsx b/packages/ui/src/views/repo/components/branch-selector-v2/branch-selector-dropdown.tsx
index ab6846960e..aaefb3d94f 100644
--- a/packages/ui/src/views/repo/components/branch-selector-v2/branch-selector-dropdown.tsx
+++ b/packages/ui/src/views/repo/components/branch-selector-v2/branch-selector-dropdown.tsx
@@ -65,7 +65,6 @@ export const BranchSelectorDropdown: FC<BranchSelectorDropdownProps> = ({
       {!isBranchOnly && (
         <Tabs.Root
           className="mt-2"
-          variant="tabnav"
           value={activeTab}
           onValueChange={value => {
             setActiveTab(value as BranchSelectorTab)
diff --git a/packages/ui/src/views/repo/components/branch-selector/branch-selector-dropdown.tsx b/packages/ui/src/views/repo/components/branch-selector/branch-selector-dropdown.tsx
index ab6846960e..aaefb3d94f 100644
--- a/packages/ui/src/views/repo/components/branch-selector/branch-selector-dropdown.tsx
+++ b/packages/ui/src/views/repo/components/branch-selector/branch-selector-dropdown.tsx
@@ -65,7 +65,6 @@ export const BranchSelectorDropdown: FC<BranchSelectorDropdownProps> = ({
       {!isBranchOnly && (
         <Tabs.Root
           className="mt-2"
-          variant="tabnav"
           value={activeTab}
           onValueChange={value => {
             setActiveTab(value as BranchSelectorTab)
diff --git a/packages/ui/src/views/repo/pull-request/compare/components/pull-request-compare-form.tsx b/packages/ui/src/views/repo/pull-request/compare/components/pull-request-compare-form.tsx
index 4fa32d4b59..3cd8d768cb 100644
--- a/packages/ui/src/views/repo/pull-request/compare/components/pull-request-compare-form.tsx
+++ b/packages/ui/src/views/repo/pull-request/compare/components/pull-request-compare-form.tsx
@@ -123,12 +123,7 @@ const PullRequestCompareForm = forwardRef<HTMLFormElement, PullRequestFormProps>
               // 'border-t': inReplyMode
             })}
           >
-            <Tabs.Root
-              variant="tabnav"
-              defaultValue={TABS_KEYS.WRITE}
-              value={activeTab}
-              onValueChange={handleTabChange}
-            >
+            <Tabs.Root defaultValue={TABS_KEYS.WRITE} value={activeTab} onValueChange={handleTabChange}>
               <Tabs.List className="relative left-1/2 w-[calc(100%+var(--tab-width))] -translate-x-1/2 px-4">
                 <Tabs.Trigger className="data-[state=active]:bg-cn-background-1" value={TABS_KEYS.WRITE}>
                   Write
diff --git a/packages/ui/src/views/repo/pull-request/compare/pull-request-compare-page.tsx b/packages/ui/src/views/repo/pull-request/compare/pull-request-compare-page.tsx
index 1e01dc1853..6389e3781f 100644
--- a/packages/ui/src/views/repo/pull-request/compare/pull-request-compare-page.tsx
+++ b/packages/ui/src/views/repo/pull-request/compare/pull-request-compare-page.tsx
@@ -304,7 +304,7 @@ export const PullRequestComparePage: FC<PullRequestComparePageProps> = ({
         )}
         {isBranchSelected ? (
           <Layout.Vertical className="mt-10">
-            <Tabs.Root variant="tabnav" defaultValue={prBranchCombinationExists ? 'commits' : 'overview'}>
+            <Tabs.Root defaultValue={prBranchCombinationExists ? 'commits' : 'overview'}>
               <Tabs.List className="before:bg-cn-background-2 relative left-1/2 w-[calc(100%+160px)] -translate-x-1/2 px-20">
                 {!prBranchCombinationExists && (
                   <TabTriggerItem
diff --git a/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-comment-box.tsx b/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-comment-box.tsx
index 54fd96b5f1..c865b21705 100644
--- a/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-comment-box.tsx
+++ b/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-comment-box.tsx
@@ -148,7 +148,7 @@ export const PullRequestCommentBox = ({
           'border-t': inReplyMode
         })}
       >
-        <Tabs.Root variant="tabnav" defaultValue={TABS_KEYS.WRITE} value={activeTab} onValueChange={handleTabChange}>
+        <Tabs.Root defaultValue={TABS_KEYS.WRITE} value={activeTab} onValueChange={handleTabChange}>
           <Tabs.List className="relative left-1/2 w-[calc(100%+var(--tab-width))] -translate-x-1/2 px-4">
             <Tabs.Trigger className="data-[state=active]:bg-cn-background-2" value={TABS_KEYS.WRITE}>
               Write
diff --git a/packages/ui/src/views/repo/repo-summary/components/clone-repo-dialog.tsx b/packages/ui/src/views/repo/repo-summary/components/clone-repo-dialog.tsx
index 2e8171a38b..865da77972 100644
--- a/packages/ui/src/views/repo/repo-summary/components/clone-repo-dialog.tsx
+++ b/packages/ui/src/views/repo/repo-summary/components/clone-repo-dialog.tsx
@@ -36,12 +36,7 @@ export const CloneRepoDialog: FC<CloneRepoDialogProps> = ({
         <div className="px-4 pt-4 leading-none">
           <span className="inline-block text-2 font-medium">{t('views:repos.cloneRepo', 'Clone repository')}</span>
         </div>
-        <Tabs.Root
-          className="mt-4"
-          variant="tabnav"
-          value={currentTab}
-          onValueChange={val => setCurrentTab(val as CloneRepoTabs)}
-        >
+        <Tabs.Root className="mt-4" value={currentTab} onValueChange={val => setCurrentTab(val as CloneRepoTabs)}>
           <Tabs.List className="px-4">
             <DropdownMenu.Item
               className="rounded-t-md p-0"


Reviews:
user: login: 3em
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-04T07:13:13Z
user: login: ankormoreankor
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-04T15:44:51Z
user: login: abhinavrastogi-harness
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-04-04T21:19:56Z
user: login: ankormoreankor
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-09T14:54:02Z
user: login: ankormoreankor
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-09T14:54:14Z
user: login: abhinavrastogi-harness
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-18T15:52:21Z

Review comments:
diff_hunk: @@ -65,30 +61,36 @@ export const PullRequestLayout: FC<PullRequestLayoutProps> = ({
           <PullRequestHeader className="mb-10" updateTitle={updateTitle} data={{ ...pullRequest, spaceId, repoId }} />
         )}
 
-        <Tabs.Root variant="tabnav" className="mb-7" defaultValue={PullRequestTabsKeys.CONVERSATION}>
+        <Tabs.Root variant="tabnav" className="mb-7" defaultValue={activeTab}>
           <Tabs.List
             className={cn(
-              'before:w-[calc(100vw-var(--sidebar-width))] before:min-w-[calc(100%+3rem)] before:left-1/2 before:-translate-x-1/2',
-              {
-                'before:w-[calc(100vw-var(--sidebar-width)-6px*2)]': isInset
-              }
+              'before:w-[calc(100vw-var(--sidebar-width))] before:min-w-[calc(100%+3rem)] before:left-1/2 before:-translate-x-1/2 before:bg-border',
path: packages/ui/src/views/layouts/PullRequestLayout.tsx
user: login: 3em
body: we don't have such bg, should use border and border-04 color
created_at: 2025-04-04T07:13:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -65,30 +61,36 @@ export const PullRequestLayout: FC<PullRequestLayoutProps> = ({
           <PullRequestHeader className="mb-10" updateTitle={updateTitle} data={{ ...pullRequest, spaceId, repoId }} />
         )}
 
-        <Tabs.Root variant="tabnav" className="mb-7" defaultValue={PullRequestTabsKeys.CONVERSATION}>
+        <Tabs.Root variant="tabnav" className="mb-7" defaultValue={activeTab}>
           <Tabs.List
             className={cn(
-              'before:w-[calc(100vw-var(--sidebar-width))] before:min-w-[calc(100%+3rem)] before:left-1/2 before:-translate-x-1/2',
-              {
-                'before:w-[calc(100vw-var(--sidebar-width)-6px*2)]': isInset
-              }
+              'before:w-[calc(100vw-var(--sidebar-width))] before:min-w-[calc(100%+3rem)] before:left-1/2 before:-translate-x-1/2 before:bg-border',
path: packages/ui/src/views/layouts/PullRequestLayout.tsx
user: login: ankormoreankor
body: Fixed
created_at: 2025-04-04T15:44:51Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,47 @@
-import { FC, PropsWithChildren, useCallback } from 'react'
+import { FC, PropsWithChildren, ReactNode } from 'react'
+import { NavLinkProps } from 'react-router-dom'
 
-import { Badge, BadgeProps, Icon, IconProps, Tabs, TabsTriggerProps } from '@/components'
+import { Badge, Icon, IconProps } from '@/components'
 import { useRouterContext, useTheme } from '@/context'
 import { cn } from '@/utils'
 import { SandboxLayout } from '@views/layouts/SandboxLayout'
 import { TranslationStore } from '@views/repo'
 import { PullRequestHeader } from '@views/repo/pull-request/components/pull-request-header'
 import { IPullRequestStore } from '@views/repo/pull-request/pull-request.types'
 
-const TabTitleWithIcon = ({ icon, children }: PropsWithChildren<{ icon: IconProps['name'] }>) => (
-  <div className="flex items-center gap-x-1">
-    <Icon className="text-icons-1 group-data-[state=active]:text-icons-2" size={14} name={icon} />
-    {children}
-  </div>
+const TabTitleWithIcon = ({
+  icon,
+  children,
+  badgeContent
+}: PropsWithChildren<{ icon: IconProps['name']; badgeContent?: ReactNode }>) => (
+  <>
+    <div className="flex items-center gap-x-1">
+      <Icon className="text-icons-1 group-[.is-active]:text-icons-2" size={14} name={icon} />
+      {children}
+    </div>
+    {!!badgeContent && (
+      <Badge className="text-foreground-2 font-normal" variant="quaternary" size="xs" borderRadius="base">
+        {badgeContent}
+      </Badge>
+    )}
+  </>
 )
 
-const badgeCommonProps: BadgeProps = {
-  className: 'font-normal text-foreground-2',
-  variant: 'quaternary',
-  size: 'xs',
-  borderRadius: 'base'
+const PullRequestTabItem: FC<NavLinkProps> = ({ className, ...props }) => {
+  const { NavLink } = useRouterContext()
+
+  return (
+    <NavLink
+      className={({ isActive }) =>
+        cn(
+          'group relative z-[1] text-foreground-2 hover:text-foreground-1 inline-flex h-9 items-center justify-center gap-x-1.5 whitespace-nowrap rounded-t-md border-x border-t border-transparent px-3.5 py-1 font-normal transition-all focus-visible:duration-0',
path: packages/ui/src/views/layouts/PullRequestLayout.tsx
user: login: abhinavrastogi-harness
body: can't we move this into the Tab component? 
ideally all tabs across the app will be consistent.. adding so many inline styles is not correct.
created_at: 2025-04-04T21:19:07Z
author_association: COLLABORATOR
diff_hunk: @@ -43,55 +65,85 @@ export const PullRequestLayout: FC<PullRequestLayoutProps> = ({
   repoId,
   updateTitle
 }) => {
-  const { Outlet, navigate } = useRouterContext()
+  const { Outlet } = useRouterContext()
   const { pullRequest } = usePullRequestStore()
   const { t } = useTranslationStore()
   const { isInset } = useTheme()
 
-  const getTabProps = useCallback(
-    (tab: PullRequestTabsKeys): TabsTriggerProps => ({
-      value: tab,
-      onClick: () => navigate(`../${tab}`),
-      className: 'group gap-x-1.5',
-      role: 'link'
-    }),
-    [navigate]
-  )
-
   return (
     <SandboxLayout.Main fullWidth>
       <SandboxLayout.Content className="mx-auto max-w-[1500px] px-6">
         {pullRequest && (
           <PullRequestHeader className="mb-10" updateTitle={updateTitle} data={{ ...pullRequest, spaceId, repoId }} />
         )}
 
-        <Tabs.Root variant="tabnav" className="mb-7" defaultValue={PullRequestTabsKeys.CONVERSATION}>
+        <nav
+          className={cn(
+            'relative before:bottom-0 before:absolute before:w-[calc(100vw-var(--sidebar-width))] before:min-w-[calc(100%+3rem)] before:left-1/2 before:-translate-x-1/2 before:border-b before:border-borders-4',
+            { 'before:w-[calc(100vw-var(--sidebar-width)-6px)]': isInset }
+          )}
+        >
+          <ul className="mb-7 flex items-center">
path: packages/ui/src/views/layouts/PullRequestLayout.tsx
user: login: abhinavrastogi-harness
body: we should be using the TabNav component instead of html elements with custom styles on it
created_at: 2025-04-04T21:19:42Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,47 @@
-import { FC, PropsWithChildren, useCallback } from 'react'
+import { FC, PropsWithChildren, ReactNode } from 'react'
+import { NavLinkProps } from 'react-router-dom'
 
-import { Badge, BadgeProps, Icon, IconProps, Tabs, TabsTriggerProps } from '@/components'
+import { Badge, Icon, IconProps } from '@/components'
 import { useRouterContext, useTheme } from '@/context'
 import { cn } from '@/utils'
 import { SandboxLayout } from '@views/layouts/SandboxLayout'
 import { TranslationStore } from '@views/repo'
 import { PullRequestHeader } from '@views/repo/pull-request/components/pull-request-header'
 import { IPullRequestStore } from '@views/repo/pull-request/pull-request.types'
 
-const TabTitleWithIcon = ({ icon, children }: PropsWithChildren<{ icon: IconProps['name'] }>) => (
-  <div className="flex items-center gap-x-1">
-    <Icon className="text-icons-1 group-data-[state=active]:text-icons-2" size={14} name={icon} />
-    {children}
-  </div>
+const TabTitleWithIcon = ({
+  icon,
+  children,
+  badgeContent
+}: PropsWithChildren<{ icon: IconProps['name']; badgeContent?: ReactNode }>) => (
+  <>
+    <div className="flex items-center gap-x-1">
+      <Icon className="text-icons-1 group-[.is-active]:text-icons-2" size={14} name={icon} />
+      {children}
+    </div>
+    {!!badgeContent && (
+      <Badge className="text-foreground-2 font-normal" variant="quaternary" size="xs" borderRadius="base">
+        {badgeContent}
+      </Badge>
+    )}
+  </>
 )
 
-const badgeCommonProps: BadgeProps = {
-  className: 'font-normal text-foreground-2',
-  variant: 'quaternary',
-  size: 'xs',
-  borderRadius: 'base'
+const PullRequestTabItem: FC<NavLinkProps> = ({ className, ...props }) => {
+  const { NavLink } = useRouterContext()
+
+  return (
+    <NavLink
+      className={({ isActive }) =>
+        cn(
+          'group relative z-[1] text-foreground-2 hover:text-foreground-1 inline-flex h-9 items-center justify-center gap-x-1.5 whitespace-nowrap rounded-t-md border-x border-t border-transparent px-3.5 py-1 font-normal transition-all focus-visible:duration-0',
path: packages/ui/src/views/layouts/PullRequestLayout.tsx
user: login: ankormoreankor
body: Done ✅
created_at: 2025-04-09T14:54:02Z
author_association: COLLABORATOR
diff_hunk: @@ -43,55 +65,85 @@ export const PullRequestLayout: FC<PullRequestLayoutProps> = ({
   repoId,
   updateTitle
 }) => {
-  const { Outlet, navigate } = useRouterContext()
+  const { Outlet } = useRouterContext()
   const { pullRequest } = usePullRequestStore()
   const { t } = useTranslationStore()
   const { isInset } = useTheme()
 
-  const getTabProps = useCallback(
-    (tab: PullRequestTabsKeys): TabsTriggerProps => ({
-      value: tab,
-      onClick: () => navigate(`../${tab}`),
-      className: 'group gap-x-1.5',
-      role: 'link'
-    }),
-    [navigate]
-  )
-
   return (
     <SandboxLayout.Main fullWidth>
       <SandboxLayout.Content className="mx-auto max-w-[1500px] px-6">
         {pullRequest && (
           <PullRequestHeader className="mb-10" updateTitle={updateTitle} data={{ ...pullRequest, spaceId, repoId }} />
         )}
 
-        <Tabs.Root variant="tabnav" className="mb-7" defaultValue={PullRequestTabsKeys.CONVERSATION}>
+        <nav
+          className={cn(
+            'relative before:bottom-0 before:absolute before:w-[calc(100vw-var(--sidebar-width))] before:min-w-[calc(100%+3rem)] before:left-1/2 before:-translate-x-1/2 before:border-b before:border-borders-4',
+            { 'before:w-[calc(100vw-var(--sidebar-width)-6px)]': isInset }
+          )}
+        >
+          <ul className="mb-7 flex items-center">
path: packages/ui/src/views/layouts/PullRequestLayout.tsx
user: login: ankormoreankor
body: Fixed
created_at: 2025-04-09T14:54:14Z
author_association: COLLABORATOR

PR comments:
user: login: CLAassistant
created_at: 2025-04-03T10:53:43Z
body: [![CLA assistant check](https://cla-assistant.io/pull/badge/not_signed)](https://cla-assistant.io/harness/canary?pullRequest=1388) <br/>Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our [Contributor License Agreement](https://cla-assistant.io/harness/canary?pullRequest=1388) before we can accept your contribution.<br/><sub>You have signed the CLA already but the status is still pending? Let us [recheck](https://cla-assistant.io/check/harness/canary?pullRequest=1388) it.</sub>
author_association: NONE
user: login: netlify[bot]
created_at: 2025-04-03T10:54:00Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *harness-xd-review* ready!


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 47399a426c6d3cb861865b8a9c45da81a58265f8 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/harness-xd-review/deploys/67ffd1386ca66b00088d56e1 |
|<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-1388--harness-xd-review.netlify.app](https://deploy-preview-1388--harness-xd-review.netlify.app) |
|<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTEzODgtLWhhcm5lc3MteGQtcmV2aWV3Lm5ldGxpZnkuYXBwIn0.qMTZPiwtpQrVy08NJKlEjh2r5AaopK7365ZVVVClqBY)<br /><br />_Use your smartphone camera to open QR code link._</details> |
---
<!-- [harness-xd-review Preview](https://deploy-preview-1388--harness-xd-review.netlify.app) -->
_To edit notification comments on pull requests, go to your [Netlify site configuration](https://app.netlify.com/sites/harness-xd-review/configuration/notifications#deploy-webhooks)._
author_association: NONE
user: login: netlify[bot]
created_at: 2025-04-03T10:54:08Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *harness-design* ready!


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 47399a426c6d3cb861865b8a9c45da81a58265f8 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/harness-design/deploys/67ffd1388b4c580008007382 |
|<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-1388--harness-design.netlify.app](https://deploy-preview-1388--harness-design.netlify.app) |
|<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTEzODgtLWhhcm5lc3MtZGVzaWduLm5ldGxpZnkuYXBwIn0.1-QnS_o97ZJK7ckKCstCl3tolW3sJyWbMqK4a5R6x3g)<br /><br />_Use your smartphone camera to open QR code link._</details> |
---
<!-- [harness-design Preview](https://deploy-preview-1388--harness-design.netlify.app) -->
_To edit notification comments on pull requests, go to your [Netlify site configuration](https://app.netlify.com/sites/harness-design/configuration/notifications#deploy-webhooks)._
author_association: NONE
user: login: cjlee01
created_at: 2025-04-11T19:03:14Z
body: @ankormoreankor some conflicts now
author_association: CONTRIBUTOR