Synapse

Components Components

Tabs

Components tabs

Tabbed panels — switch content without navigating.

Markup

Drops in as data-pb-block="tabs".

html
<div data-pb-block="tabs" class="pb-tabs" x-data="{ tab: 'one' }" style="max-width:36rem;">
  <div class="pb-tabs__list" role="tablist" style="display:flex;gap:0.25rem;border-bottom:1px solid #e2e8f0;">
    <button type="button" class="pb-tabs__tab" role="tab" @click="tab = 'one'" :aria-selected="tab === 'one'" :style="tab === 'one' ? 'color:#4f46e5;border-bottom-color:#4f46e5' : 'color:#64748b;border-bottom-color:transparent'" style="padding:0.7rem 1rem;border:0;border-bottom:2px solid transparent;background:transparent;font-weight:600;cursor:pointer;">Tab one</button>
    <button type="button" class="pb-tabs__tab" role="tab" @click="tab = 'two'" :aria-selected="tab === 'two'" :style="tab === 'two' ? 'color:#4f46e5;border-bottom-color:#4f46e5' : 'color:#64748b;border-bottom-color:transparent'" style="padding:0.7rem 1rem;border:0;border-bottom:2px solid transparent;background:transparent;font-weight:600;cursor:pointer;">Tab two</button>
    <button type="button" class="pb-tabs__tab" role="tab" @click="tab = 'three'" :aria-selected="tab === 'three'" :style="tab === 'three' ? 'color:#4f46e5;border-bottom-color:#4f46e5' : 'color:#64748b;border-bottom-color:transparent'" style="padding:0.7rem 1rem;border:0;border-bottom:2px solid transparent;background:transparent;font-weight:600;cursor:pointer;">Tab three</button>
  </div>
  <div class="pb-tabs__panels" style="padding:1.25rem 0;color:#475569;line-height:1.6;">
    <div class="pb-tabs__panel" role="tabpanel" x-show="tab === 'one'"><p style="margin:0;">Content for the first tab.</p></div>
    <div class="pb-tabs__panel" role="tabpanel" x-show="tab === 'two'" x-cloak><p style="margin:0;">Content for the second tab.</p></div>
    <div class="pb-tabs__panel" role="tabpanel" x-show="tab === 'three'" x-cloak><p style="margin:0;">Content for the third tab.</p></div>
  </div>
</div>

Settings

Interactive behaviour is built in; on top of that every block supports:

Bind to State
Drive content reactively from a State with declarative Alpine — x-text, x-show or x-model over $store.app.<stateKey>.
On event → run a Flow
Wire an interaction to a Flow: set data-pb-flow="<slug>" and data-pb-flow-event="click|submit|hover|change|…". The flow's returned actions update the page.
Link to a page
Navigate to another published page on click with data-pb-page="<slug>".
Styles & classes
Edit spacing, colour and layout visually in the GrapesJS editor. The wrapper carries data-pb-block="tabs" so it imports as a labelled, editable component.
Interactive out of the box
Ships with Alpine state baked in (x-data, @click, x-show, x-transition) — open/close, tabs and toggles work with no wiring. These owner-authored blocks are trusted and keep their executable directives.