Skip to content

Conversation

@FredrikMWold
Copy link
Contributor

Before:
The onChange function in the Tabs component always received the selected tab’s index.

After:
onChange now receives the tab’s value prop if one is provided. If no value is set, it will fall back to the tab’s index.

Why

Previously, managing tab state often meant:

  • Using “magic numbers” tied to tab order
  • Creating a lookup table to map indexes to meaningful values

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 enhances the Tabs component's onChange callback to receive the tab's value prop when available, instead of always receiving the tab's index. This change makes tab management more semantic by allowing developers to work with meaningful values rather than relying on index-based lookups.

Key Changes

  • Modified onChange callback signature to accept number | string instead of just number
  • Updated tab click handler to pass the tab's value when available, falling back to index
  • Added comprehensive test coverage for the new behavior

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
packages/eds-core-react/src/components/Tabs/Tabs.tsx Updated onChange prop type signature to accept number | string
packages/eds-core-react/src/components/Tabs/Tabs.context.ts Updated context handleChange type to match new signature
packages/eds-core-react/src/components/Tabs/TabList.tsx Modified click handler to pass tab value when available, otherwise index
packages/eds-core-react/src/components/Tabs/Tabs.test.tsx Added test to verify onChange receives value or index appropriately

onClick: () => handleChange($index),
onClick: () =>
handleChange(
controlledActive !== undefined ? controlledActive : $index,
Copy link

Copilot AI Aug 15, 2025

Choose a reason for hiding this comment

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

The logic uses controlledActive which represents the currently active tab, not the clicked tab's value. This will always pass the current active tab instead of the clicked tab's value. Should use the individual tab's value prop or $index for the clicked tab.

Suggested change
controlledActive !== undefined ? controlledActive : $index,
childProps.value !== undefined ? childProps.value : $index,

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

Choose a reason for hiding this comment

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

The naming of controlledActive could be confusing. I believe controlledActive represent the individual tab's value and not the current active tab. Do you agree @FredrikMWold ?

Copy link
Contributor Author

@FredrikMWold FredrikMWold Aug 15, 2025

Choose a reason for hiding this comment

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

Yes, i agree that controlledActive sounds like the currently active tab and not the value of the clicked tab.
The most straight forward name would be value or tabValue

Or to rename childProps to tabProps and just use tabProps.value

…instead of always its index, with index used as a fallback
@FredrikMWold FredrikMWold force-pushed the feat/call-tab-onchange-with-provided-value-if-present branch from f8e5449 to fdd17e4 Compare August 15, 2025 07:48
@torleifhalseth
Copy link
Collaborator

I was wondering if it’s a common practice to have a value on a Tab? In my experience, it’s more common when it comes to inputs.

@FredrikMWold
Copy link
Contributor Author

@torleifhalseth

https://www.radix-ui.com/primitives/docs/components/tabs
https://chakra-ui.com/docs/components/tabs
https://mui.com/material-ui/react-tabs/

Its not uncommen that tabs have a value
Add a few examples. There are some where they have an id, but most use value. Changing it to id would be a breaking change to the functionality of the component. Where as this is just a breaking change to the types.

@torleifhalseth
Copy link
Collaborator

Great. Thank you for the examples, @FredrikMWold. I think this is a great enhancement to the component.

I would prefer one solution to control the active tab, but it is also nice to not break existing solutions ⚖️ Maybe we can simplify another day ✨

Copy link
Collaborator

@torleifhalseth torleifhalseth left a comment

Choose a reason for hiding this comment

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

LGTM 👍 Thanks for the contribution @FredrikMWold!

@torleifhalseth torleifhalseth merged commit 42bb1df into equinor:develop Aug 19, 2025
6 checks passed
activeTab?: number | string
/** The callback function for selecting a tab */
onChange?: (index: number) => void
onChange?: (value: number | string) => void
Copy link
Contributor

Choose a reason for hiding this comment

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

This was a breaking API change. Would be great if this was marked as such in the release note.

magnh pushed a commit that referenced this pull request Oct 13, 2025
…instead of always its index, with index used as a fallback (#3893)
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.

3 participants