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
onCloseEmitted 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.