Skip to content

Towser Component ​

A full-height slide-in panel component for displaying detailed content alongside the main page. Unlike a Modal which overlays the center of the screen, the Towser slides in from the right edge and occupies the full viewport height — ideal for editing forms, detail views, and data-heavy content that needs more space.


Table of Contents ​


Import ​

ts
import { Towser } from "dolphin-components";
import type { TowserProps, TowserTitle, TowserAction } from "dolphin-components";

Basic Usage ​

vue
<template>
  <button @click="showPanel = true" class="btn btn-primary">Open Panel</button>

  <Towser
    :show="showPanel"
    :title="[{ name: 'User Details' }]"
    :actions="[
      { title: 'Cancel', emit: 'onClose' },
      { title: 'Save', emit: 'onSave', class: 'btn btn-primary' },
    ]"
    @onClose="showPanel = false"
    @onSave="handleSave"
  >
    <p>Panel content goes here.</p>
  </Towser>
</template>

<script setup>
import { ref } from "vue";
import { Towser } from "dolphin-components";

const showPanel = ref(false);
const handleSave = () => {
  console.log("Saving...");
  showPanel.value = false;
};
</script>

Props ​

PropTypeDefaultDescription
showbooleanfalseControls visibility of the panel.
titleTowserTitle[][]Breadcrumb-style title array with optional links.
actionsTowserAction[][]Footer action buttons. Each emits the specified event on click.
doublebooleanfalseEnable a two-column (split-pane) layout inside the panel.
bodyWidthnumber50Width percentage of the first column when double is true.
body2Widthnumber50Width percentage of the second column when double is true.

Events ​

EventPayloadDescription
onClose—Emitted when the panel should be closed.
[custom emit]—Custom events from action buttons. Name comes from the emit property of the action.

Slots ​

Slot NameDescription
defaultMain content area of the panel.
body2Second column content (only used when double is true).

TypeScript Interfaces ​

typescript
interface TowserTitle {
  name: string;     // Display text
  link?: string;    // Optional Vue Router link path
}

interface TowserAction {
  emit: string;     // Event name to emit when clicked
  title: string;    // Button label text
  class?: string;   // CSS class for the button
}

interface TowserProps {
  show: boolean;
  title: TowserTitle[];
  actions?: TowserAction[];
  double?: boolean;
  bodyWidth?: number;
  body2Width?: number;
}

Usage Examples ​

With Breadcrumb Title ​

vue
<Towser
  :show="showPanel"
  :title="[
    { name: 'Users', link: '/users' },
    { name: 'Edit User' },
  ]"
  :actions="[{ title: 'Close', emit: 'onClose' }]"
  @onClose="showPanel = false"
>
  <form>
    <label class="input-label">Name</label>
    <input class="input-text" v-model="userName" />
  </form>
</Towser>

Two-Column (Split-Pane) Layout ​

Use the double prop to create a side-by-side layout, useful for showing a form alongside related data:

vue
<Towser
  :show="showPanel"
  :double="true"
  :bodyWidth="60"
  :body2Width="40"
  :title="[{ name: 'Dashboard' }, { name: 'Product Details' }]"
  :actions="[
    { title: 'Cancel', emit: 'onClose' },
    { title: 'Save', emit: 'onSave', class: 'btn btn-primary' },
  ]"
  @onClose="showPanel = false"
  @onSave="handleSave"
>
  <template #default>
    <h3>Product Form</h3>
    <label class="input-label">Product Name</label>
    <input class="input-text" v-model="product.name" />
    <label class="input-label mt-3">Price</label>
    <input class="input-text" v-model="product.price" type="number" />
  </template>

  <template #body2>
    <h3>Preview</h3>
    <div class="bg-gray-50 p-4 rounded">
      <p class="font-bold">{{ product.name }}</p>
      <p class="text-gray-600">Rs. {{ product.price }}</p>
    </div>
  </template>
</Towser>

With TypeScript ​

vue
<script setup lang="ts">
import { ref } from "vue";
import { Towser, type TowserTitle, type TowserAction } from "dolphin-components";

const showPanel = ref(false);

const title: TowserTitle[] = [
  { name: "Settings", link: "/settings" },
  { name: "Profile" },
];

const actions: TowserAction[] = [
  { title: "Cancel", emit: "onClose" },
  { title: "Update", emit: "onUpdate", class: "btn btn-primary" },
];
</script>

<template>
  <Towser
    :show="showPanel"
    :title="title"
    :actions="actions"
    @onClose="showPanel = false"
    @onUpdate="handleUpdate"
  >
    <p>Profile settings form...</p>
  </Towser>
</template>

Screenshot ​

towser image


Best Practices ​

  1. Use Towser for data-heavy forms — When a Modal feels too cramped, the Towser's full-height design gives more room.
  2. Use breadcrumb titles — Provide navigation context, especially when opened from a list/detail page.
  3. Use the double layout for preview — Show a form on one side and a live preview on the other.
  4. Control from parent — Always set :show="showPanel" and handle @onClose="showPanel = false" in the parent component.

Troubleshooting ​

Panel doesn't open ​

  • Ensure show is bound to a reactive ref variable set to true.
  • Check that no CSS is hiding overflow on the parent container.

Second column not visible ​

  • Set :double="true" to enable the two-column layout.
  • Provide content in the #body2 slot.

Actions not triggering ​

  • Ensure the @ event listener matches the emit value exactly (e.g., emit: 'onSave' → @onSave).

Notes ​

  • The component uses a slide-in transition from the right edge.
  • The header dynamically generates breadcrumb navigation from the title prop.
  • When double is true, the panel creates a split-pane layout with configurable column widths.
  • The Towser uses <Teleport> for proper rendering above other content.