Skip to content

[Task](context): clean up and refactor Tabs and Tabs naming #1986

Description

@franzheidl

Task Description

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
  • Cleaning up now, before the new filter tabs / secondary tabs ( [Task](ui): implement [predefined filters / secondary tabs] #1991 ) land, will avoid a third branch of naming confusion on top of the existing two

Proposal

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

Removal (next major release):

  • Remove all five components and their directories
  • Remove associated stories and tests

Known usages that will need to migrate:

  • apps/greenhouse/src/components/admin/ClusterDetail/index.tsx
  • apps/greenhouse/src/components/admin/PluginInstanceDetail/index.tsx
  • apps/greenhouse/src/components/admin/PluginPresetDetail/index.tsx
  • apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/index.tsx
  • apps/supernova/src/components/alerts/AlertDetail.tsx
  • apps/example/src/components/pages/AlertsPage.tsx

2. Rename TabNavigation to TabBar

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentationui-componentsAll tasks related to juno-ui-components library

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions