πŸš€Β Β Astro β€” Tabs bar + panels


A tabs bar + panels component which works entirely without JS. Supports height equalization and automatic vertical scroll bar for tabs bar.

Keywords:

  • astro
  • astro-component
  • tabs
  • ui
  • no-js
  • native
  • interactive
  • vanilla
  • css
  • html

Component live demo

WITH "tallest" panel equalization

Use panel-<n>-tallest.

Panel 1

Hello world

Panel 2

Panel 3

Heya


WITHOUT "tallest" equalization

The content below this component will reflow depending on panel content height.

Panel 1

Hello world

Panel 2

Panel 3

HΓ© HΓ΄

HΓ© HΓ΄

HΓ© HΓ΄

Unstyled

Panel 1

Panel 2

Panel 3

πŸš€Β Β Astro β€” Tabs bar + panels

NPM Downloads ISC License PRs Welcome
Astro TypeScript Prettier EditorConfig ESLint

A tabs bar + panels component which works entirely without JS.
Supports height equalization and automatic vertical scroll bar for tabs bar.

Note: It uses the :has() CSS selector under the hood.



πŸ“¦Β Β Installation

pnpm i astro-tabs

πŸ› Β Β Usage

WITHOUT "tallest" equalization

---
import { Tabs } from 'astro-tabs';
// ...
---

<Tabs class="pass-your-own-class" class:list={['pass-your-class-list']}>
  <Fragment slot="tab-1">Tab 1</Fragment>
  <Fragment slot="tab-2">Tab 2</Fragment>
  <Fragment slot="tab-3">Tab 3</Fragment>

  <Fragment slot="panel-1">
    <h2>Panel 1</h2>
    <p>Hello world</p>
  </Fragment>

  <Fragment slot="panel-2">
    <h2>Panel 2</h2>

    <img
      height="400"
      src="https://res.cloudinary.com/dzfylx93l/image/upload/v1664340439/astro-takeoff-1_ecdfxf.gif"
    />
  </Fragment>

  <Fragment slot="panel-3">
    <h2>Panel 3</h2>
  </Fragment>
</Tabs>

WITH "tallest" panel equalization, use panel-<n>-tallest

<Tabs>
  <Fragment slot="tab-1">Tab 1</Fragment>
  <Fragment slot="tab-2">Tab 2</Fragment>
  <Fragment slot="tab-3">Tab 3</Fragment>

  <Fragment slot="panel-1">
    <h2>Panel 1</h2>
    <p>Hello world</p>
  </Fragment>

  <!-- vβ€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” This is the tallest panel -->
  <Fragment slot="panel-2-tallest">
    <h2>Panel 2</h2>
    <img
      height="400"
      src="https://res.cloudinary.com/dzfylx93l/image/upload/v1664340439/astro-takeoff-1_ecdfxf.gif"
    />
  </Fragment>

  <Fragment slot="panel-3">
    <h2>Panel 3</h2>
    <p>Heya</p>
  </Fragment>
</Tabs>

Styling

.tab {
  color: white;
  padding: 1rem;
  background-color: teal;
  border: 1px solid cyan;

  &:hover {
    color: black;
    background-color: cyan;
  }
}

.tab-selector:checked ~ .tab {
  color: black;
  background: turquoise;
}

.panel {
  padding: 1rem;
  background-color: lightcyan;
  border: 3px solid darkcyan;
}

Or use :global(.tab),… in scoped styles.

πŸŽ‰Β Β Result

<div class="_tabs_1754q_15 tabs pass-your-class-list pass-your-own-class">
  <style>
    ._tabs_1754q_15:has(._radio_1754q_29-1:checked) ._panel_1754q_7-1 {
      visibility: visible;
      display: inline-block;
    }
    ._tabs_1754q_15:has(._radio_1754q_29-2:checked) ._panel_1754q_7-2 {
      visibility: visible;
      display: inline-block;
    }
    ._tabs_1754q_15:has(._radio_1754q_29-3:checked) ._panel_1754q_7-3 {
      visibility: visible;
      display: inline-block;
    }
  </style>

  <nav class="_tab-bar_1754q_3">
    <div class="tab-wrapper tab-1">
      <input
        class="_radio_1754q_29 _radio_1754q_29-1 radio"
        type="radio"
        name="i8ZgJykDTKrqj1xg_epJe"
        checked="true"
        id="i8ZgJykDTKrqj1xg_epJe-1"
      />
      <label class="tab _tab_1754q_3" for="i8ZgJykDTKrqj1xg_epJe-1">
        <div>Tab 1</div>
      </label>
    </div>
    <div class="tab-wrapper tab-2">
      <input
        class="_radio_1754q_29 _radio_1754q_29-2 radio"
        type="radio"
        name="i8ZgJykDTKrqj1xg_epJe"
        id="i8ZgJykDTKrqj1xg_epJe-2"
      />
      <label class="tab _tab_1754q_3" for="i8ZgJykDTKrqj1xg_epJe-2">
        <div>Tab 2</div>
      </label>
    </div>
    <div class="tab-wrapper tab-3">
      <input
        class="_radio_1754q_29 _radio_1754q_29-3 radio"
        type="radio"
        name="i8ZgJykDTKrqj1xg_epJe"
        id="i8ZgJykDTKrqj1xg_epJe-3"
      />
      <label class="tab _tab_1754q_3" for="i8ZgJykDTKrqj1xg_epJe-3">
        <div>Tab 3</div>
      </label>
    </div>
  </nav>

  <div class="_panels_1754q_7">
    <div class="_panel_1754q_7 _panel_1754q_7-1 panel">
      <h2>Panel 1</h2>
      <p>Hello world</p>
    </div>
    <div class="_panel_1754q_7 _tallest_1754q_15 _panel_1754q_7-2 panel">
      <h2>Panel 2</h2>
      <img
        height="400"
        src="https://res.cloudinary.com/dzfylx93l/image/upload/v1664340439/astro-takeoff-1_ecdfxf.gif"
      />
    </div>
    <div class="_panel_1754q_7 _panel_1754q_7-3 panel">
      <h2>Panel 3</h2>
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque deserunt
        quibusdam praesentium. Nobis consectetur, minima laboriosam doloremque.
      </p>
      <p>
        enim perferendis fugit a porro. Corporis quis, tenetur maiores explicabo
        ex nulla quo?
      </p>
    </div>
  </div>
</div>

Changelog

Change Log

All notable changes to this project will be documented in this file. See Conventional Commits for commit guidelines.

0.1.3 (2022-10-17)

Bug Fixes

  • import path, disable og image, tabs props (cf4d2f5)

0.1.2 (2022-10-17)

Bug Fixes

  • remove package prefix, simplify import method (73bd31b)

0.1.1 (2022-10-15)

Note: Version bump only for package astro-tabs

0.1.0 (2022-10-13)

Features

Bug Fixes

  • update video url in docs (cdacac6)
...

⚠️  Having an issue? / πŸ—£   Wanna share feedback or suggestion?

✍️  Open an Issue or a Pull Request   on GitHub -or-   Contact me   on my Website.