You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We have a number of [XYZ]-"Tabs" components, these should be cleaned up, their names aligned, and usage clarified.
Task is to
Design a proposal as to what to change to clean up while reducing damage for consumers
Keep including predefined filters/secondary tabs in mind, i.e. reserve a space in the name scheme either way
Discuss and decide
Deprecate Tabs, TabList, Tab, TabPanel, and MainTabs
Remove Tabs, TabList, Tab, TabPanel, and MainTabs (next major release)
Rename TabNavigation to TabBar (and TabNavigationItem to TabBarItem)
Update docs and stories accordingly
Communicate the change
Current Situation
Currently, we have:
Tabs: (react-tabs), manages TabList + Tab + TabPanel together, only used for tabbed in-page content. Supports variant="main|content|codeblocks". Rarely used in practice but holds the primary name.
TabList: The ul holding the individual Tabs
Tab: Individual tab
TabPanel: The element holding the content associated with a tab
MainTabs: === <Tabs variant="main">: A thin wrapper around a variant of Tabs
TabNavigation: nav bar styled like tabs, but for links/onClick handlers — no content panels. Built on the internal Navigation component. Has tabStyle prop that does a similar thing as variant on Tabs: allow for two "flavours", one of which we don't use anywhere curently?
TabNavigationItem: single item inside a TabNavigation.
The Problem(s)
Tabs are squatting the prime name users would look for first for a rarely-used, react-tabs-bound component is actively misleading (most devs reaching for "Tabs" want navigation or filtering, not managed content panels)
TabNavigation conflates two concepts in one word: the visual (tab-shaped) and the functional (navigation, single-select)
Having tabStyle on TabNavigation while Tabs uses variant for the same concept creates an API inconsistency and adds to confusion (normally we reserve variant for semantic variants we would want users to know what possible values are)
MainTabs as a one-prop wrapper adds a component slot to the mental model and docs for what is merely a stylistic variant
1. Deprecate and remove Tabs, TabList, Tab, TabPanel, and MainTabs
After team discussion, the decision is to deprecate the Tabs family first and remove it in the next major release, rather than rename it. The component causes more confusion than it provides value.
Deprecation (this release):
Wrap Tabs, TabList, Tab, TabPanel, and MainTabs with the existing withDeprecationWarning HOC
Add @deprecated JSDoc tags to all five component interfaces
Deprecation warning message should name the component and point consumers to react-tabs directly as the migration path
The new name reflects the current appaerance and use better, it is not necessarily used as a navigation. Rename child components accordingly, rename tabStyle prop to appearance, too, and frees us from style-attibute associations (may be worth it to check across our system).
We could keep the old TabNavigation name / export as an alias for backwards compatibility, but use TabBar exclusively going forward.
3. The New Kid On The Block (NKOTB)
If we want to include the new tab-like elements that were designed primarily with predefined filters in DataGrid in mind as a more universally available and useful component in our system, we could simply add it as a stylistic/visual variant to TabBar.
4. Optional/Later: Restructure TabBar to use Hooks
Ideally, we should resolve the coupling of appearance and functionality. Since TabBar (was TabNavigation) relies on Navigation, we assume and enforce functionality as well:
Right now the Navigation/NavigationItem base leaks assumptions (it's built for link-based nav) that don't hold for filter tabs or handler-only tabs. TabBar as a pure visual container that knows nothing about routing frees us to put anything inside TabBarItem — link, button, toggle, multi-select chip. The cost is a mid-sized refactor; the payoff is that the a new (pre-defined) filter tab variant fits naturally without workarounds.
Navigation models exactly-one-active; filter tabs are fundamentally many-active, or at least could be. Trying to bolt that onto the current NavigationItem base would be a hack. A standalone TabBar that relies e.g. on useSingleSelect / useMultiSelect hooks for functionality would add a great deal of flexibility: We could add any new component at any time, keep visual appearance completely separate from functionality. The base Navigation could use the hooks as well, exposing sinlge- or multi-select functionality as a mode-prop.
Result
The resulting "Tab"-related component landscape would now look like:
TabBar: An all purpose bar of "Tabs" that can be used for navigation or filtering (may support multi-select if we do the hooks-based refactor). IF we decide to make the new tabs universally available, we could expose these as a stylistic variant via an appearance prop as well (see [Task](ui): implement [predefined filters / secondary tabs] #1991 ).
TabBarItem: an item of these
As a result, we will have only one top-level "Tab"-named component family: TabBar / TabBarItem. The Tabs family will be sunset via the standard deprecation → removal cycle.
Task Description
We have a number of [XYZ]-"Tabs" components, these should be cleaned up, their names aligned, and usage clarified.
Task is to
Tabs,TabList,Tab,TabPanel, andMainTabsTabs,TabList,Tab,TabPanel, andMainTabs(next major release)TabNavigationtoTabBar(andTabNavigationItemtoTabBarItem)Current Situation
Currently, we have:
Tabs: (react-tabs), manages TabList + Tab + TabPanel together, only used for tabbed in-page content. Supports variant="main|content|codeblocks". Rarely used in practice but holds the primary name.TabList: Theulholding the individualTabsTab: Individual tabTabPanel: The element holding the content associated with a tabMainTabs: ===<Tabs variant="main">: A thin wrapper around a variant ofTabsTabNavigation: nav bar styled like tabs, but for links/onClick handlers — no content panels. Built on the internalNavigationcomponent. HastabStyleprop that does a similar thing asvariantonTabs: allow for two "flavours", one of which we don't use anywhere curently?TabNavigationItem: single item inside aTabNavigation.The Problem(s)
Tabsare squatting the prime name users would look for first for a rarely-used, react-tabs-bound component is actively misleading (most devs reaching for "Tabs" want navigation or filtering, not managed content panels)TabNavigationconflates two concepts in one word: the visual (tab-shaped) and the functional (navigation, single-select)tabStyleon TabNavigation whileTabsusesvariantfor the same concept creates an API inconsistency and adds to confusion (normally we reservevariantfor semantic variants we would want users to know what possible values are)MainTabsas a one-prop wrapper adds a component slot to the mental model and docs for what is merely a stylistic variantProposal
1. Deprecate and remove
Tabs,TabList,Tab,TabPanel, andMainTabsAfter team discussion, the decision is to deprecate the
Tabsfamily first and remove it in the next major release, rather than rename it. The component causes more confusion than it provides value.Deprecation (this release):
Tabs,TabList,Tab,TabPanel, andMainTabswith the existingwithDeprecationWarningHOC@deprecatedJSDoc tags to all five component interfacesreact-tabsdirectly as the migration pathRemoval (next major release):
Known usages that will need to migrate:
apps/greenhouse/src/components/admin/ClusterDetail/index.tsxapps/greenhouse/src/components/admin/PluginInstanceDetail/index.tsxapps/greenhouse/src/components/admin/PluginPresetDetail/index.tsxapps/heureka/src/components/Service/ImageDetails/ImageIssuesList/index.tsxapps/supernova/src/components/alerts/AlertDetail.tsxapps/example/src/components/pages/AlertsPage.tsx2. Rename
TabNavigationtoTabBarThe new name reflects the current appaerance and use better, it is not necessarily used as a navigation. Rename child components accordingly, rename
tabStyleprop toappearance, too, and frees us fromstyle-attibute associations (may be worth it to check across our system).We could keep the old
TabNavigationname / export as an alias for backwards compatibility, but useTabBarexclusively going forward.3. The New Kid On The Block (NKOTB)
If we want to include the new tab-like elements that were designed primarily with predefined filters in
DataGridin mind as a more universally available and useful component in our system, we could simply add it as a stylistic/visual variant toTabBar.4. Optional/Later: Restructure
TabBarto use HooksIdeally, we should resolve the coupling of appearance and functionality. Since
TabBar(wasTabNavigation) relies onNavigation, we assume and enforce functionality as well:Right now the Navigation/NavigationItem base leaks assumptions (it's built for link-based nav) that don't hold for filter tabs or handler-only tabs. TabBar as a pure visual container that knows nothing about routing frees us to put anything inside TabBarItem — link, button, toggle, multi-select chip. The cost is a mid-sized refactor; the payoff is that the a new (pre-defined) filter tab variant fits naturally without workarounds.
Navigation models exactly-one-active; filter tabs are fundamentally many-active, or at least could be. Trying to bolt that onto the current NavigationItem base would be a hack. A standalone TabBar that relies e.g. on
useSingleSelect/useMultiSelecthooks for functionality would add a great deal of flexibility: We could add any new component at any time, keep visual appearance completely separate from functionality. The baseNavigationcould use the hooks as well, exposing sinlge- or multi-select functionality as amode-prop.Result
The resulting "Tab"-related component landscape would now look like:
TabBar: An all purpose bar of "Tabs" that can be used for navigation or filtering (may support multi-select if we do the hooks-based refactor). IF we decide to make the new tabs universally available, we could expose these as a stylistic variant via anappearanceprop as well (see [Task](ui): implement [predefined filters / secondary tabs] #1991 ).TabBarItem: an item of theseAs a result, we will have only one top-level "Tab"-named component family:
TabBar/TabBarItem. TheTabsfamily will be sunset via the standard deprecation → removal cycle.