TourKit
@tour-kit/announcementsHooks

useAnnouncementQueue

useAnnouncementQueue hook: manage priority-based display ordering and automatic scheduling of queued announcements

useAnnouncementQueue

Hook for accessing and controlling the announcement queue. The queue automatically orders announcements by priority and manages which announcements to show based on queueConfig.

Why Use This Hook?

Use useAnnouncementQueue when you need to:

  • Manually trigger the next announcement in queue
  • Check what announcements are queued
  • Get an announcement's position in the queue
  • Clear the queue
  • Build custom queue management UIs

Basic Usage

import { useAnnouncementQueue } from '@tour-kit/announcements';

function QueueControls() {
  const { queue, showNext } = useAnnouncementQueue();

  return (
    <div>
      <p>{queue.length} announcements in queue</p>
      <button onClick={showNext}>Show Next</button>
    </div>
  );
}

Return Value

const {
  // State
  queue,
  size,
  isEmpty,
  config,

  // Methods
  showNext,
  clear,
  isQueued,
  getPosition,
} = useAnnouncementQueue();

Properties

Prop

Type

Methods

Prop

Type


Queue Order

Announcements are automatically ordered by priority:

Priority order: critical > high > normal > low

// Provider configuration
const announcements = [
  { id: 'low-priority', priority: 'low' },
  { id: 'critical-alert', priority: 'critical' },
  { id: 'high-priority', priority: 'high' },
  { id: 'normal-msg', priority: 'normal' },
];

// Queue will be ordered as:
// ['critical-alert', 'high-priority', 'normal-msg', 'low-priority']

Examples

Show Next Announcement

import { useAnnouncementQueue } from '@tour-kit/announcements';

function NextAnnouncementButton() {
  const { queue, showNext, isEmpty } = useAnnouncementQueue();

  if (isEmpty) {
    return <p>No announcements to show</p>;
  }

  return (
    <button onClick={showNext}>
      Show Next Announcement ({queue.length} remaining)
    </button>
  );
}

Display Queue Status

import { useAnnouncementQueue, useAnnouncements } from '@tour-kit/announcements';

function QueueStatus() {
  const { queue, size, isEmpty } = useAnnouncementQueue();
  const { announcements } = useAnnouncements();

  if (isEmpty) {
    return <p>Queue is empty</p>;
  }

  return (
    <div>
      <h3>Queue ({size})</h3>
      <ol>
        {queue.map((id, index) => {
          const announcement = announcements.byId[id];
          return (
            <li key={id}>
              <strong>{announcement.config.title}</strong>
              <span>Priority: {announcement.config.priority}</span>
              <span>Position: {index + 1}</span>
            </li>
          );
        })}
      </ol>
    </div>
  );
}

Check if Queued

function AnnouncementBadge({ id }: { id: string }) {
  const { isQueued, getPosition } = useAnnouncementQueue();

  if (!isQueued(id)) {
    return null;
  }

  const position = getPosition(id);

  return (
    <span className="badge">
      In queue (#{position + 1})
    </span>
  );
}

Clear Queue

function QueueManager() {
  const { queue, clear, showNext } = useAnnouncementQueue();

  const handleClear = () => {
    if (confirm('Clear all queued announcements?')) {
      clear();
    }
  };

  return (
    <div>
      <h2>Queue Management</h2>
      <p>{queue.length} announcements queued</p>

      <div className="actions">
        <button onClick={showNext} disabled={queue.length === 0}>
          Show Next
        </button>
        <button onClick={handleClear} disabled={queue.length === 0}>
          Clear Queue
        </button>
      </div>
    </div>
  );
}

Queue Configuration

function QueueConfigDisplay() {
  const { config, size } = useAnnouncementQueue();

  return (
    <div>
      <h3>Queue Configuration</h3>
      <dl>
        <dt>Max Concurrent:</dt>
        <dd>{config.maxConcurrent}</dd>

        <dt>Auto Show:</dt>
        <dd>{config.autoShow ? 'Yes' : 'No'}</dd>

        <dt>Delay Between:</dt>
        <dd>{config.delayBetween}ms</dd>

        <dt>Respect Priority:</dt>
        <dd>{config.respectPriority ? 'Yes' : 'No'}</dd>

        <dt>Current Queue Size:</dt>
        <dd>{size}</dd>
      </dl>
    </div>
  );
}

Queue Behavior

Auto-Show

When autoShow is enabled (default), the queue automatically shows the next announcement when the current one is dismissed:

<AnnouncementsProvider
  queueConfig={{
    autoShow: true, // Next announcement shows automatically
  }}
/>

Manual Control

Disable autoShow to manually control when announcements are shown:

<AnnouncementsProvider
  queueConfig={{
    autoShow: false, // Require manual showNext() calls
  }}
/>

function ManualQueue() {
  const { showNext, queue } = useAnnouncementQueue();

  return (
    <button onClick={showNext}>
      Show Next ({queue.length} queued)
    </button>
  );
}

Max Concurrent

Control how many announcements can be visible at once:

<AnnouncementsProvider
  queueConfig={{
    maxConcurrent: 2, // Allow 2 announcements at once
  }}
/>

By default, maxConcurrent is set to 1, meaning only one announcement can be visible at a time.

Delay Between

Add a delay between showing announcements:

<AnnouncementsProvider
  queueConfig={{
    delayBetween: 2000, // Wait 2 seconds between announcements
  }}
/>

Advanced Patterns

Priority-Based Queue Display

import { useAnnouncementQueue, useAnnouncement } from '@tour-kit/announcements';

function PriorityQueue() {
  const { queue } = useAnnouncementQueue();

  const grouped = queue.reduce((acc, id) => {
    const announcement = useAnnouncement(id);
    const priority = announcement.config.priority || 'normal';

    if (!acc[priority]) acc[priority] = [];
    acc[priority].push(announcement);

    return acc;
  }, {} as Record<string, Announcement[]>);

  return (
    <div>
      {grouped.critical?.length > 0 && (
        <section className="critical">
          <h3>Critical ({grouped.critical.length})</h3>
          {/* Render critical announcements */}
        </section>
      )}

      {grouped.high?.length > 0 && (
        <section className="high">
          <h3>High Priority ({grouped.high.length})</h3>
          {/* Render high priority announcements */}
        </section>
      )}
    </div>
  );
}

Queue Progress Indicator

function QueueProgress() {
  const { queue, size } = useAnnouncementQueue();
  const { count } = useAnnouncements();

  const total = count.total;
  const remaining = size;
  const shown = total - remaining;
  const progress = (shown / total) * 100;

  return (
    <div className="progress-bar">
      <div
        className="progress-fill"
        style={{ width: `${progress}%` }}
      />
      <p>{shown} of {total} shown</p>
    </div>
  );
}

Conditional Queue Display

function ConditionalQueue() {
  const { queue, isEmpty, showNext } = useAnnouncementQueue();
  const { announcements } = useAnnouncements();

  if (isEmpty) {
    return <p>All announcements have been shown</p>;
  }

  const nextId = queue[0];
  const next = announcements.byId[nextId];

  return (
    <div className="next-preview">
      <h3>Next Announcement</h3>
      <p>{next.config.title}</p>
      <button onClick={showNext}>
        Show Now
      </button>
    </div>
  );
}

TypeScript

The hook is fully typed:

import { useAnnouncementQueue } from '@tour-kit/announcements';
import type { QueueConfig } from '@tour-kit/announcements';

function TypedComponent() {
  const {
    queue,
    size,
    isEmpty,
    config,
    showNext,
    clear,
    isQueued,
    getPosition,
  } = useAnnouncementQueue();

  // All properties are typed
  const queueIds: string[] = queue;
  const queueSize: number = size;
  const empty: boolean = isEmpty;
  const queueConfig: QueueConfig = config;

  // Methods are typed
  showNext(); // () => void
  clear(); // () => void
  const queued: boolean = isQueued('announcement-id');
  const position: number = getPosition('announcement-id');
}

Common Use Cases

Dashboard Queue Widget

function QueueWidget() {
  const { queue, size, showNext, isEmpty } = useAnnouncementQueue();
  const { announcements } = useAnnouncements();

  if (isEmpty) {
    return (
      <div className="widget">
        <p>No pending announcements</p>
      </div>
    );
  }

  const next = announcements.byId[queue[0]];

  return (
    <div className="widget">
      <h4>Pending Announcements ({size})</h4>
      <div className="next">
        <p className="title">{next.config.title}</p>
        <p className="priority">Priority: {next.config.priority}</p>
      </div>
      <button onClick={showNext} className="primary">
        Show Now
      </button>
    </div>
  );
}

Admin Queue Manager

function AdminQueueManager() {
  const { queue, clear, showNext, getPosition } = useAnnouncementQueue();
  const { announcements } = useAnnouncements();

  return (
    <div className="admin-panel">
      <header>
        <h2>Announcement Queue</h2>
        <div className="actions">
          <button onClick={showNext}>Show Next</button>
          <button onClick={clear} className="danger">
            Clear Queue
          </button>
        </div>
      </header>

      <table>
        <thead>
          <tr>
            <th>Position</th>
            <th>Title</th>
            <th>Variant</th>
            <th>Priority</th>
          </tr>
        </thead>
        <tbody>
          {queue.map((id) => {
            const a = announcements.byId[id];
            const position = getPosition(id);

            return (
              <tr key={id}>
                <td>{position + 1}</td>
                <td>{a.config.title}</td>
                <td>{a.config.variant}</td>
                <td>{a.config.priority}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

On this page