Skip to content

Conversation

@JayashTripathy
Copy link
Member

@JayashTripathy JayashTripathy commented Dec 4, 2025

Description

This PR replaces all the instances of tabs with propel tabs. And removes tabs from the ui package.

Type of Change

  • Improvement (change that would cause existing functionality to not work as expected)
  • Code refactoring

Summary by CodeRabbit

  • Refactor

    • Migrated tab navigation components across analytics, image picker, licensing, and page sections to use an updated component library for improved consistency and maintainability.
  • Style

    • Minor layout adjustments to spacing and alignment in discount badges and progress sections.

✏️ Tip: You can customize this high-level summary in your review settings.

- Replaced instances of Headless UI's Tab component with a new custom Tabs component across various components, including analytics modals, image pickers, and navigation panes.
- Updated tab handling logic to align with the new Tabs API, ensuring consistent behavior and styling.
- Removed unused Tab imports and cleaned up related code for improved maintainability.
- This refactor enhances the overall structure and consistency of tab navigation within the application.
Copilot AI review requested due to automatic review settings December 4, 2025 07:43
@makeplane
Copy link

makeplane bot commented Dec 4, 2025

Linked to Plane Work Item(s)

This comment was auto-generated by Plane

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 4, 2025

Walkthrough

Migrated tab components across the codebase from Headless UI to a new custom Tabs component from @plane/propel/tabs, removed the deprecated tabs module from packages/ui, and applied minor styling adjustments. Old Tabs/TabList implementations deleted from public API.

Changes

Cohort / File(s) Summary
Tabs Migration to @plane/propel
apps/web/core/components/analytics/work-items/modal/content.tsx, apps/web/core/components/core/image-picker-popover.tsx, apps/web/core/components/cycles/analytics-sidebar/progress-stats.tsx, apps/web/core/components/license/modal/card/base-paid-plan-card.tsx, apps/web/core/components/modules/analytics-sidebar/progress-stats.tsx, apps/web/core/components/pages/navigation-pane/root.tsx, apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx, apps/web/core/components/pages/navigation-pane/tabs-list.tsx
Replaced Headless UI Tab components (Tab.Group, Tab.List, Tab, Tab.Panel) with new Tabs, Tabs.List, Tabs.Trigger, Tabs.Content from @plane/propel/tabs. Updated state management from index-based (selectedIndex) to value-based (value/onValueChange). Replaced active state styling from computed logic to data-[selected] attributes. Removed manual tab indicator position calculations.
UI Package Tabs Module Removal
packages/ui/src/index.ts, packages/ui/src/tabs/index.ts, packages/ui/src/tabs/tabs.tsx, packages/ui/src/tabs/tab-list.tsx
Removed deprecated Tabs, TabList, and related types (TabContent, TabItem, TTabsProps) from the public UI package API. Eliminated Headless UI-based tab implementations including local storage persistence, size-based styling, and custom tab configuration logic. Removed re-exports from barrel files.
Styling & Layout Adjustments
apps/web/core/components/license/modal/card/plan-upgrade.tsx, apps/web/core/components/modules/analytics-sidebar/issue-progress.tsx
Updated yearly discount badge layout (added height, line-height, flex centering). Removed horizontal padding from analytics progress container.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Key attention areas:
    • Verify all tab value-to-content bindings are correctly mapped across the refactored components, particularly in image-picker-popover.tsx (image selection behavior and popover closure)
    • Confirm the removal of PAGE_NAVIGATION_PANE_TAB_KEYS constant from public exports doesn't break external consumers
    • Review the deprecated Tabs/TabList removal from packages/ui to ensure no lingering internal dependencies
    • Validate that the new Tabs component from @plane/propel provides equivalent functionality (local storage, default values, event handling)

Possibly related PRs

Suggested reviewers

  • anmolsinghbhatia

Poem

🐰 The tabs did hop from UI's store,
To propel's embrace, oh what a tour!
No more indices, just values so true,
The old ones depart—tab-da-da-zing, we're through!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive The description includes a brief explanation and identifies the change type (Improvement and Code refactoring), but lacks detailed context, test scenarios, and references required by the template. Add more detail about implementation approach, include test scenarios verifying tab functionality across all modified components, and link the related issue (WEB-4921) as a reference.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: replacing all tab instances with propel tabs, which is the primary objective reflected throughout the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/tabs-implementation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/web/core/components/analytics/work-items/modal/content.tsx (1)

3-3: Remove unused Tab import and dependency on Headless UI tabs

Tab from "@headlessui/react" is no longer used in this component, and the PR’s goal is to eliminate tab usage from Headless UI. Clean up this import (and any related dependency if still present elsewhere) to avoid dead code and keep the migration consistent.

Also applies to: 72-77

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 36d4285 and 2acba29.

📒 Files selected for processing (14)
  • apps/web/core/components/analytics/work-items/modal/content.tsx (1 hunks)
  • apps/web/core/components/core/image-picker-popover.tsx (4 hunks)
  • apps/web/core/components/cycles/analytics-sidebar/progress-stats.tsx (3 hunks)
  • apps/web/core/components/license/modal/card/base-paid-plan-card.tsx (3 hunks)
  • apps/web/core/components/license/modal/card/plan-upgrade.tsx (1 hunks)
  • apps/web/core/components/modules/analytics-sidebar/issue-progress.tsx (1 hunks)
  • apps/web/core/components/modules/analytics-sidebar/progress-stats.tsx (3 hunks)
  • apps/web/core/components/pages/navigation-pane/root.tsx (3 hunks)
  • apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx (2 hunks)
  • apps/web/core/components/pages/navigation-pane/tabs-list.tsx (2 hunks)
  • packages/ui/src/index.ts (0 hunks)
  • packages/ui/src/tabs/index.ts (0 hunks)
  • packages/ui/src/tabs/tab-list.tsx (0 hunks)
  • packages/ui/src/tabs/tabs.tsx (0 hunks)
💤 Files with no reviewable changes (4)
  • packages/ui/src/tabs/index.ts
  • packages/ui/src/tabs/tab-list.tsx
  • packages/ui/src/index.ts
  • packages/ui/src/tabs/tabs.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,mts,cts}

📄 CodeRabbit inference engine (.github/instructions/typescript.instructions.md)

**/*.{ts,tsx,mts,cts}: Use const type parameters for more precise literal inference in TypeScript 5.0+
Use the satisfies operator to validate types without widening them
Leverage inferred type predicates to reduce the need for explicit is return types in filter/check functions
Use NoInfer<T> utility to block inference for specific type arguments when they should be determined by other arguments
Utilize narrowing in switch(true) blocks for control flow analysis (TypeScript 5.3+)
Rely on narrowing from direct boolean comparisons for type guards
Trust preserved narrowing in closures when variables aren't modified after the check (TypeScript 5.4+)
Use constant indices to narrow object/array properties (TypeScript 5.5+)
Use standard ECMAScript decorators (Stage 3) instead of legacy experimentalDecorators
Use using declarations for explicit resource management with Disposable pattern instead of manual cleanup (TypeScript 5.2+)
Use with { type: "json" } for import attributes; avoid deprecated assert syntax (TypeScript 5.3/5.8+)
Use import type explicitly when importing types to ensure they are erased during compilation, respecting verbatimModuleSyntax flag
Use .ts, .mts, .cts extensions in import type statements (TypeScript 5.2+)
Use import type { Type } from "mod" with { "resolution-mode": "import" } for specific module resolution contexts (TypeScript 5.3+)
Use new iterator methods (map, filter, etc.) if targeting modern environments (TypeScript 5.6+)
Utilize new Set methods like union, intersection, etc., when available (TypeScript 5.5+)
Use Object.groupBy / Map.groupBy standard methods for grouping instead of external libraries (TypeScript 5.4+)
Use Promise.withResolvers() for creating promises with exposed resolve/reject functions (TypeScript 5.7+)
Use copying array methods (toSorted, toSpliced, with) for immutable array operations (TypeScript 5.2+)
Avoid accessing instance fields via super in classes (TypeScript 5....

Files:

  • apps/web/core/components/license/modal/card/plan-upgrade.tsx
  • apps/web/core/components/analytics/work-items/modal/content.tsx
  • apps/web/core/components/modules/analytics-sidebar/issue-progress.tsx
  • apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx
  • apps/web/core/components/license/modal/card/base-paid-plan-card.tsx
  • apps/web/core/components/cycles/analytics-sidebar/progress-stats.tsx
  • apps/web/core/components/modules/analytics-sidebar/progress-stats.tsx
  • apps/web/core/components/core/image-picker-popover.tsx
  • apps/web/core/components/pages/navigation-pane/tabs-list.tsx
  • apps/web/core/components/pages/navigation-pane/root.tsx
🧠 Learnings (6)
📓 Common learnings
Learnt from: lifeiscontent
Repo: makeplane/plane PR: 7989
File: apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx:45-46
Timestamp: 2025-10-21T17:22:05.204Z
Learning: In the makeplane/plane repository, the refactor from useParams() to params prop is specifically scoped to page.tsx and layout.tsx files in apps/web/app (Next.js App Router pattern). Other components (hooks, regular client components, utilities) should continue using the useParams() hook as that is the correct pattern for non-route components.
📚 Learning: 2025-10-21T17:22:05.204Z
Learnt from: lifeiscontent
Repo: makeplane/plane PR: 7989
File: apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx:45-46
Timestamp: 2025-10-21T17:22:05.204Z
Learning: In the makeplane/plane repository, the refactor from useParams() to params prop is specifically scoped to page.tsx and layout.tsx files in apps/web/app (Next.js App Router pattern). Other components (hooks, regular client components, utilities) should continue using the useParams() hook as that is the correct pattern for non-route components.

Applied to files:

  • apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx
  • apps/web/core/components/license/modal/card/base-paid-plan-card.tsx
  • apps/web/core/components/cycles/analytics-sidebar/progress-stats.tsx
  • apps/web/core/components/modules/analytics-sidebar/progress-stats.tsx
  • apps/web/core/components/core/image-picker-popover.tsx
  • apps/web/core/components/pages/navigation-pane/tabs-list.tsx
  • apps/web/core/components/pages/navigation-pane/root.tsx
📚 Learning: 2025-10-09T20:42:31.843Z
Learnt from: lifeiscontent
Repo: makeplane/plane PR: 7922
File: apps/admin/app/(all)/(dashboard)/ai/form.tsx:19-19
Timestamp: 2025-10-09T20:42:31.843Z
Learning: In the makeplane/plane repository, React types are globally available through TypeScript configuration. Type annotations like React.FC, React.ReactNode, etc. can be used without explicitly importing the React namespace. The codebase uses the modern JSX transform, so React imports are not required for JSX or type references.

Applied to files:

  • apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx
  • apps/web/core/components/license/modal/card/base-paid-plan-card.tsx
  • apps/web/core/components/cycles/analytics-sidebar/progress-stats.tsx
  • apps/web/core/components/modules/analytics-sidebar/progress-stats.tsx
  • apps/web/core/components/core/image-picker-popover.tsx
  • apps/web/core/components/pages/navigation-pane/tabs-list.tsx
  • apps/web/core/components/pages/navigation-pane/root.tsx
📚 Learning: 2025-10-01T15:30:17.605Z
Learnt from: lifeiscontent
Repo: makeplane/plane PR: 7888
File: packages/propel/src/avatar/avatar.stories.tsx:2-3
Timestamp: 2025-10-01T15:30:17.605Z
Learning: In the makeplane/plane repository, avoid suggesting inline type imports (e.g., `import { Avatar, type TAvatarSize }`) due to bundler compatibility issues. Keep type imports and value imports as separate statements.

Applied to files:

  • apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx
  • apps/web/core/components/cycles/analytics-sidebar/progress-stats.tsx
  • apps/web/core/components/modules/analytics-sidebar/progress-stats.tsx
  • apps/web/core/components/pages/navigation-pane/tabs-list.tsx
📚 Learning: 2025-10-09T22:12:26.424Z
Learnt from: lifeiscontent
Repo: makeplane/plane PR: 7922
File: apps/admin/app/(all)/(dashboard)/ai/form.tsx:19-19
Timestamp: 2025-10-09T22:12:26.424Z
Learning: When `types/react` is installed in a TypeScript project (which is standard for React + TypeScript codebases), React types (React.FC, React.ReactNode, React.ComponentProps, etc.) are globally available by design. These type annotations can and should be used without explicitly importing the React namespace. This is a TypeScript/DefinitelyTyped feature, not codebase-specific configuration.

Applied to files:

  • apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx
  • apps/web/core/components/cycles/analytics-sidebar/progress-stats.tsx
  • apps/web/core/components/modules/analytics-sidebar/progress-stats.tsx
📚 Learning: 2025-05-14T13:16:23.323Z
Learnt from: vamsikrishnamathala
Repo: makeplane/plane PR: 7061
File: web/core/components/workspace-notifications/root.tsx:18-18
Timestamp: 2025-05-14T13:16:23.323Z
Learning: In the Plane project codebase, the path alias `@/plane-web` resolves to the `ce` directory, making imports like `@/plane-web/hooks/use-notification-preview` correctly resolve to files in `web/ce/hooks/`.

Applied to files:

  • apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx
🧬 Code graph analysis (6)
apps/web/core/components/license/modal/card/plan-upgrade.tsx (1)
packages/ui/src/billing/subscription.ts (1)
  • getDiscountPillStyle (208-209)
apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx (2)
packages/propel/src/tabs/tabs.tsx (1)
  • Tabs (107-112)
apps/web/core/components/pages/navigation-pane/tab-panels/assets.tsx (1)
  • PageNavigationPaneAssetsTabPanel (104-120)
apps/web/core/components/license/modal/card/base-paid-plan-card.tsx (2)
packages/propel/src/tabs/tabs.tsx (1)
  • Tabs (107-112)
packages/ui/src/billing/subscription.ts (1)
  • getSubscriptionBackgroundColor (35-73)
apps/web/core/components/cycles/analytics-sidebar/progress-stats.tsx (1)
packages/propel/src/tabs/tabs.tsx (1)
  • Tabs (107-112)
apps/web/core/components/modules/analytics-sidebar/progress-stats.tsx (1)
packages/propel/src/tabs/tabs.tsx (1)
  • Tabs (107-112)
apps/web/core/components/pages/navigation-pane/root.tsx (3)
packages/propel/src/tabs/tabs.tsx (1)
  • Tabs (107-112)
apps/web/core/components/pages/navigation-pane/tabs-list.tsx (1)
  • PageNavigationPaneTabsList (7-27)
apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx (1)
  • PageNavigationPaneTabPanelsRoot (21-40)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Agent
  • GitHub Check: CodeQL analysis (javascript-typescript)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Build and lint web apps
🔇 Additional comments (13)
apps/web/core/components/modules/analytics-sidebar/issue-progress.tsx (1)

117-117: CSS spacing adjustment aligns with refactoring goals.

The removal of horizontal padding (px-3) and retention of vertical padding (py-4) appears intentional as part of the broader analytics sidebar layout refinement. The component's disclosure structure and child rendering remain unchanged and functional.

Verify that this CSS adjustment is consistent across other analytics-sidebar components (e.g., progress-stats.tsx) to ensure uniform spacing after the propel tabs migration.

apps/web/core/components/analytics/work-items/modal/content.tsx (1)

72-77: Layout wrapper migration looks correct

Switching from the tab wrapper to a simple <div> while preserving the children and props (peekView={!fullScreen}, isEpic) keeps behavior and data flow intact. No issues from this change alone.

apps/web/core/components/license/modal/card/plan-upgrade.tsx (1)

76-83: LGTM! Styling improvement enhances badge layout.

The addition of flex items-center justify-center properly centers the discount percentage within the badge, and the fixed height h-5 with leading-tight ensures consistent dimensions across different discount values.

apps/web/core/components/cycles/analytics-sidebar/progress-stats.tsx (1)

117-169: LGTM! Clean migration to the new Tabs API.

The refactoring correctly migrates from Headless UI to @plane/propel/tabs:

  • Tab.GroupTabs with value-based control
  • Tab.ListTabs.List
  • TabTabs.Trigger with value prop
  • Tab.PanelTabs.Content with corresponding value

The active state styling correctly uses data-[selected] attributes, and localStorage integration is preserved.

apps/web/core/components/modules/analytics-sidebar/progress-stats.tsx (1)

115-167: LGTM! Consistent migration pattern.

The migration follows the same pattern as the cycles component, correctly adopting the new Tabs API with value-based control and data-[selected] styling.

apps/web/core/components/license/modal/card/base-paid-plan-card.tsx (1)

42-89: LGTM! Controlled tabs implementation is correct.

The migration properly uses controlled state with value and onValueChange, correctly mapping price.recurring as the tab value to link triggers with content panels.

apps/web/core/components/core/image-picker-popover.tsx (3)

215-280: LGTM on Unsplash content structure.

The Unsplash tab content correctly implements search functionality with Controller/Input integration and proper image grid rendering with loading states.


282-298: LGTM on Images tab content.

The static images tab correctly renders the grid with click-to-select behavior.


300-367: LGTM on Upload tab content.

The upload tab correctly preserves the drag-and-drop functionality, file validation, preview, and upload flow with proper error handling.

apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx (1)

25-39: LGTM! Panel structure correctly migrated.

The migration properly replaces Tab.Panels with a fragment wrapper and individual Tabs.Content blocks, correctly using tab.key as the value prop to link with the corresponding triggers.

apps/web/core/components/pages/navigation-pane/tabs-list.tsx (1)

12-26: LGTM! Excellent simplification with Tabs.Indicator.

The migration removes manual active state calculations and positioning logic in favor of Tabs.Indicator, which handles the visual active state automatically. This is cleaner and more maintainable.

apps/web/core/components/pages/navigation-pane/root.tsx (2)

69-80: LGTM! Clean migration to value-based tab control.

The change from index-based to value-based tab handling is more semantic and maintainable. The type cast to TPageNavigationPaneTab is appropriate for ensuring type safety with the query parameter.


107-110: LGTM! Root Tabs structure is correct.

The migration correctly wraps the tabs list and panels in the new Tabs component with proper value and onValueChange handlers.

Comment on lines +201 to +212
<Tabs defaultValue={tabOptions[0].key} className={"h-full overflow-hidden"}>
<Tabs.List className="p-1 w-fit">
{tabOptions.map((tab) => (
<Tab
<Tabs.Trigger
key={tab.key}
className={({ selected }) =>
`rounded px-4 py-1 text-center text-sm outline-none transition-colors ${
selected ? "bg-custom-primary text-white" : "text-custom-text-100"
}`
}
value={tab.key}
className="rounded px-4 py-1 text-center text-sm outline-none transition-colors data-[selected]:bg-custom-primary data-[selected]:text-white text-custom-text-100"
>
{tab.title}
</Tab>
</Tabs.Trigger>
))}
</Tab.List>
<Tab.Panels className="vertical-scrollbar scrollbar-md h-full w-full flex-1 overflow-y-auto overflow-x-hidden">
<Tab.Panel className="mt-4 h-full w-full space-y-4">
{(unsplashImages || !unsplashError) && (
<>
<div className="flex gap-x-2">
<Controller
control={control}
name="search"
render={({ field: { value, ref } }) => (
<Input
id="search"
name="search"
type="text"
onKeyDown={(e) => {
if (e.key === "Enter") {
e.preventDefault();
setSearchParams(formData.search);
}
</Tabs.List>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n apps/web/core/components/core/image-picker-popover.tsx | head -100

Repository: makeplane/plane

Length of output: 3873


🏁 Script executed:

sed -n '190,220p' apps/web/core/components/core/image-picker-popover.tsx

Repository: makeplane/plane

Length of output: 1486


🏁 Script executed:

sed -n '220,280p' apps/web/core/components/core/image-picker-popover.tsx

Repository: makeplane/plane

Length of output: 3067


🏁 Script executed:

sed -n '275,350p' apps/web/core/components/core/image-picker-popover.tsx

Repository: makeplane/plane

Length of output: 3911


🏁 Script executed:

sed -n '360,380p' apps/web/core/components/core/image-picker-popover.tsx

Repository: makeplane/plane

Length of output: 485


Filter disabled tabs and set default to first enabled tab.

The tabOptions array includes an isEnabled field (set on line 68 based on hasUnsplashConfigured), but this is not being used when rendering tabs. All tabs render regardless of enabled state (lines 203-212), and defaultValue always uses tabOptions[0].key ("unsplash" at line 201), which may be disabled.

If hasUnsplashConfigured is false, the Unsplash tab button displays even though it shouldn't be available, and the component attempts to set a disabled tab as the default.

Filter tabs by isEnabled and calculate the default value from the first enabled tab:

-          <Tabs defaultValue={tabOptions[0].key} className={"h-full overflow-hidden"}>
+          <Tabs defaultValue={tabOptions.find(tab => tab.isEnabled)?.key ?? "images"} className={"h-full overflow-hidden"}>
             <Tabs.List className="p-1 w-fit">
-              {tabOptions.map((tab) => (
+              {tabOptions.filter(tab => tab.isEnabled).map((tab) => (
🤖 Prompt for AI Agents
In apps/web/core/components/core/image-picker-popover.tsx around lines 201 to
212, the Tabs are rendered from tabOptions regardless of each tab's isEnabled
flag and defaultValue uses tabOptions[0].key which may be disabled; filter
tabOptions to only include tabs where isEnabled is true when computing the list
to render and when computing the default tab key (use the first enabled tab's
key), and handle the case where no tabs are enabled (e.g., fall back to
undefined or a safe default) so the Tabs component never tries to select a
disabled entry.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates the codebase from using @headlessui/react Tab components to @plane/propel/tabs, and removes the old tabs implementation from the ui package. The migration involves updating all tab component usages to the new propel Tabs API which uses a value-based approach instead of index-based selection.

  • Removed the old Tabs and TabList components from the @plane/ui package
  • Migrated all tab implementations to use the propel Tabs API with value-based selection
  • Updated styling to use data attributes (data-[selected]) instead of render props

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/ui/src/tabs/tabs.tsx Deleted old Tabs component implementation
packages/ui/src/tabs/tab-list.tsx Deleted old TabList component implementation
packages/ui/src/tabs/index.ts Deleted tabs index file
packages/ui/src/index.ts Removed tabs export from ui package
apps/web/core/components/pages/navigation-pane/tabs-list.tsx Migrated to propel Tabs with Tabs.List, Tabs.Trigger, and Tabs.Indicator
apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx Replaced Tab.Panel with Tabs.Content
apps/web/core/components/pages/navigation-pane/root.tsx Migrated Tab.Group to Tabs with value-based selection API
apps/web/core/components/modules/analytics-sidebar/progress-stats.tsx Migrated to propel Tabs with data-[selected] styling pattern
apps/web/core/components/modules/analytics-sidebar/issue-progress.tsx Removed horizontal padding for layout consistency
apps/web/core/components/license/modal/card/plan-upgrade.tsx Updated discount badge styling with improved vertical alignment
apps/web/core/components/license/modal/card/base-paid-plan-card.tsx Migrated pricing tabs to propel Tabs with simplified structure
apps/web/core/components/cycles/analytics-sidebar/progress-stats.tsx Migrated to propel Tabs with value-based API and data attribute styling
apps/web/core/components/core/image-picker-popover.tsx Migrated image picker tabs to propel Tabs with restructured content panels
apps/web/core/components/analytics/work-items/modal/content.tsx Removed unnecessary Tab.Group wrapper

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

onClick={() => setSelectedPlan(price.recurring)}
value={price.recurring}
className={cn(
"w-full rounded text-sm font-medium leading-5 py-2",
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra whitespace detected: There are two spaces between "rounded" and "text-sm". This should be a single space for consistency.

Suggested change
"w-full rounded text-sm font-medium leading-5 py-2",
"w-full rounded text-sm font-medium leading-5 py-2",

Copilot uses AI. Check for mistakes.
>
<Tab.Group>
<Tab.List as="span" className="inline-block rounded bg-custom-background-80 p-1">
<Tabs defaultValue={tabOptions[0].key} className={"h-full overflow-hidden"}>
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary curly braces: The className value is a static string and doesn't need to be wrapped in curly braces. Use className="h-full overflow-hidden" instead of className={"h-full overflow-hidden"}.

Suggested change
<Tabs defaultValue={tabOptions[0].key} className={"h-full overflow-hidden"}>
<Tabs defaultValue={tabOptions[0].key} className="h-full overflow-hidden">

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants