Skip to content

[web component func] Tabs - anchor navigation #5940

@alizedebray

Description

@alizedebray

📝 Description

The Tabs component will be extended with a new navigation mode, triggered automatically when <post-tab-header> contains an <a> element in its light DOM.

  • In this case, the component renders as subnavigation, and consumers handle routing via their framework or plain anchors.
  • The existing panels mode (with <post-tab-panel>) remains unchanged and fully supported.

This change unifies the previously separate Tabs and Subnavigation components.

♿ Accessibility

  • Follows semantic navigation markup:
    • Wrapped in <nav> (with aria-label for context).
    • Each item is an <a> element provided by the consumer.
    • The active link uses aria-current="page".

⚙️ Requirements

  • Panels mode continues to work as it is today.
  • Add a navigation mode with the following requirements:
    • Navigation mode is automatically enabled when <a> is present inside <post-tab-header>.

    • Consumers define the active item using the existing active-panel property, which should be renamed (e.g., active-tab) to work in both modes.

      We should rename the properties on post-tab-header and post-tab-panel so they work for both panels and navigation modes.

      • The post-tab-header will have a name property.
      • The post-tab-panel will reference the corresponding post-tab-header via a for property.

      Finally, it also makes sense to rename post-tab-header to post-tab-item, since in navigation mode the concept of a “header” no longer applies.

    • Tabs remain in place when navigating between pages.

    • <a> elements are rendered in the light DOM to allow consumer routing integration (React Router, Angular Router, etc.).

    • If consumers attempt to mix both modes (anchors + panels), the component must log an error in the console.

🧪 Testing

  • Renders <nav> wrapper correctly.
  • <post-tab-header> sets aria-current="page" on active <a>.
  • Clicking an item triggers navigation via consumer routing.
  • <post-tab-panel> elements are ignored.

💻 Proposed implementation

  • Mode detection
    • <post-tab-header>: detects its own mode and exposes it to <post-tabs> (via data-attribute or internal prop).
    • <post-tabs>: reads children’s modes and decides container type (<div> for panels, <nav> for navigation).
  • Properties
    • Rename active-panelactive-tab to work in both modes.
  • HTML structure (navigation mode):
    <post-tabs active-tab="first">
      <post-tab-header name="first">
        <a href="/first">First page</a>
      </post-tab-header>
      <post-tab-header name="second">
        <a href="/second">Second page</a>
      </post-tab-header>
      <post-tab-header name="third">
        <a href="/third">Third page</a>
      </post-tab-header>
    </post-tabs>

🔗 References

📃 Tasks

  • Implement component functionality
  • Add this new behavior to the Tabs documentation in Storybook
  • Add functional tests
  • Add React integration tests
  • Add Angular integration tests

Metadata

Metadata

Labels

📦 componentsRelated to the @swisspost/design-system-components package

Projects

Status

🆗 Ready

Relationships

None yet

Development

No branches or pull requests

Issue actions