@tour-kit/announcementsHooks
useAnnouncements
useAnnouncements hook: query all announcements, filter by status or variant, and manage the announcement collection state
useAnnouncements
Hook for accessing all announcements and global announcement state. Use this to query, filter, and manage multiple announcements at once.
Why Use This Hook?
Use useAnnouncements when you need to:
- Access all announcements in the provider
- Filter announcements by variant, priority, or dismissal state
- Get counts of visible or dismissed announcements
- Reset multiple announcements at once
- Build announcement management UIs
Basic Usage
import { useAnnouncements } from '@tour-kit/announcements';
function AnnouncementList() {
const { announcements } = useAnnouncements();
return (
<div>
<h2>All Announcements</h2>
<ul>
{announcements.all.map(a => (
<li key={a.id}>{a.config.title}</li>
))}
</ul>
</div>
);
}Return Value
const {
// Collections
announcements,
// State
activeId,
// Arrays
ids,
visible,
dismissed,
// Count
count,
// Methods
getFiltered,
resetAll,
} = useAnnouncements();Properties
Prop
Type
Methods
Prop
Type
Announcements Collection
The announcements object provides different ways to access announcements:
const { announcements } = useAnnouncements();
// Get all announcements
announcements.all // Announcement[]
// Get by ID
announcements.byId['feature-1'] // Announcement | undefined
// Get by variant
announcements.byVariant.modal // Announcement[]
announcements.byVariant.slideout // Announcement[]
announcements.byVariant.banner // Announcement[]
announcements.byVariant.toast // Announcement[]
announcements.byVariant.spotlight // Announcement[]Examples
Display All Announcements
import { useAnnouncements } from '@tour-kit/announcements';
function AnnouncementsDashboard() {
const { announcements, count } = useAnnouncements();
return (
<div>
<h2>Announcements ({count.total})</h2>
<div className="stats">
<p>Visible: {count.visible}</p>
<p>Dismissed: {count.dismissed}</p>
<p>Can show: {count.canShow}</p>
</div>
<ul>
{announcements.all.map(a => (
<li key={a.id}>
<strong>{a.config.title}</strong>
<span>Variant: {a.config.variant}</span>
<span>Priority: {a.config.priority}</span>
<span>Views: {a.state.viewCount}</span>
{a.state.isDismissed && <span>Dismissed</span>}
</li>
))}
</ul>
</div>
);
}Filter by Variant
function ModalAnnouncements() {
const { announcements } = useAnnouncements();
const modals = announcements.byVariant.modal;
return (
<div>
<h2>Modal Announcements</h2>
<ul>
{modals.map(a => (
<li key={a.id}>{a.config.title}</li>
))}
</ul>
</div>
);
}Filter with Custom Criteria
function FilteredAnnouncements() {
const { getFiltered } = useAnnouncements();
// Get high priority announcements that haven't been dismissed
const highPriority = getFiltered({
priority: ['high', 'critical'],
dismissed: false,
});
// Get visible modals
const visibleModals = getFiltered({
variant: ['modal'],
visible: true,
});
// Get announcements with specific IDs
const specific = getFiltered({
ids: ['feature-1', 'feature-2'],
});
return (
<div>
<section>
<h3>High Priority</h3>
{highPriority.map(a => (
<p key={a.id}>{a.config.title}</p>
))}
</section>
<section>
<h3>Visible Modals</h3>
{visibleModals.map(a => (
<p key={a.id}>{a.config.title}</p>
))}
</section>
</div>
);
}Active Announcement
function ActiveAnnouncementIndicator() {
const { activeId, announcements } = useAnnouncements();
if (!activeId) {
return <p>No active announcement</p>;
}
const active = announcements.byId[activeId];
return (
<div className="active-indicator">
<p>Currently showing: {active.config.title}</p>
<p>Variant: {active.config.variant}</p>
</div>
);
}Reset All Announcements
function AnnouncementSettings() {
const { resetAll, count } = useAnnouncements();
const handleReset = () => {
if (confirm('Reset all announcement state? This cannot be undone.')) {
resetAll();
}
};
return (
<div>
<h2>Settings</h2>
<p>You have dismissed {count.dismissed} announcements</p>
<button onClick={handleReset}>
Reset All Announcements
</button>
</div>
);
}Visible/Dismissed Lists
function AnnouncementStatus() {
const { visible, dismissed, announcements } = useAnnouncements();
return (
<div>
<section>
<h3>Visible Announcements ({visible.length})</h3>
<ul>
{visible.map(id => (
<li key={id}>
{announcements.byId[id].config.title}
</li>
))}
</ul>
</section>
<section>
<h3>Dismissed Announcements ({dismissed.length})</h3>
<ul>
{dismissed.map(id => (
<li key={id}>
{announcements.byId[id].config.title}
</li>
))}
</ul>
</section>
</div>
);
}Filter Interface
The getFiltered method accepts this filter interface:
interface AnnouncementsFilter {
ids?: string[];
variant?: AnnouncementVariant[];
priority?: AnnouncementPriority[];
visible?: boolean;
dismissed?: boolean;
canShow?: boolean;
}Filter Examples
const { getFiltered } = useAnnouncements();
// Get all modals and slideouts
const sidePanels = getFiltered({
variant: ['modal', 'slideout'],
});
// Get critical and high priority
const important = getFiltered({
priority: ['critical', 'high'],
});
// Get announcements that can be shown
const available = getFiltered({
canShow: true,
dismissed: false,
});
// Combine filters
const criticalModals = getFiltered({
variant: ['modal'],
priority: ['critical'],
visible: false,
});Count Object
The count object provides quick access to announcement statistics:
const { count } = useAnnouncements();
console.log(count);
// {
// total: 10,
// visible: 2,
// dismissed: 5,
// canShow: 3,
// }Use in UI:
function AnnouncementStats() {
const { count } = useAnnouncements();
return (
<div className="stats-grid">
<div>
<h4>Total</h4>
<p>{count.total}</p>
</div>
<div>
<h4>Visible</h4>
<p>{count.visible}</p>
</div>
<div>
<h4>Dismissed</h4>
<p>{count.dismissed}</p>
</div>
<div>
<h4>Available</h4>
<p>{count.canShow}</p>
</div>
</div>
);
}Advanced Patterns
Conditional Rendering Based on Counts
function ConditionalUI() {
const { count, announcements } = useAnnouncements();
if (count.visible === 0 && count.canShow > 0) {
return (
<button onClick={() => announcements.all[0].show()}>
Show Announcements ({count.canShow})
</button>
);
}
if (count.dismissed === count.total) {
return <p>You've seen all announcements!</p>;
}
return <AnnouncementList />;
}Build Announcement Manager
import { useAnnouncements, useAnnouncement } from '@tour-kit/announcements';
function AnnouncementManager() {
const { announcements, count, resetAll } = useAnnouncements();
return (
<div className="manager">
<header>
<h2>Manage Announcements</h2>
<p>{count.total} total, {count.dismissed} dismissed</p>
<button onClick={resetAll}>Reset All</button>
</header>
<div className="announcement-list">
{announcements.all.map(a => (
<AnnouncementCard key={a.id} id={a.id} />
))}
</div>
</div>
);
}
function AnnouncementCard({ id }: { id: string }) {
const announcement = useAnnouncement(id);
return (
<div className="card">
<h3>{announcement.config.title}</h3>
<p>{announcement.config.description}</p>
<div className="meta">
<span>Variant: {announcement.config.variant}</span>
<span>Priority: {announcement.config.priority}</span>
<span>Views: {announcement.viewCount}</span>
</div>
<div className="actions">
<button onClick={announcement.show} disabled={!announcement.canShow}>
Show
</button>
<button onClick={announcement.hide} disabled={!announcement.isVisible}>
Hide
</button>
<button onClick={() => announcement.dismiss()} disabled={announcement.isDismissed}>
Dismiss
</button>
<button onClick={announcement.reset}>
Reset
</button>
</div>
{announcement.isDismissed && (
<p className="status">Dismissed</p>
)}
</div>
);
}Group by Priority
function PriorityGroupedAnnouncements() {
const { getFiltered } = useAnnouncements();
const critical = getFiltered({ priority: ['critical'] });
const high = getFiltered({ priority: ['high'] });
const normal = getFiltered({ priority: ['normal'] });
const low = getFiltered({ priority: ['low'] });
return (
<div>
{critical.length > 0 && (
<section>
<h3>Critical ({critical.length})</h3>
{critical.map(a => <AnnouncementCard key={a.id} id={a.id} />)}
</section>
)}
{high.length > 0 && (
<section>
<h3>High Priority ({high.length})</h3>
{high.map(a => <AnnouncementCard key={a.id} id={a.id} />)}
</section>
)}
{normal.length > 0 && (
<section>
<h3>Normal ({normal.length})</h3>
{normal.map(a => <AnnouncementCard key={a.id} id={a.id} />)}
</section>
)}
{low.length > 0 && (
<section>
<h3>Low Priority ({low.length})</h3>
{low.map(a => <AnnouncementCard key={a.id} id={a.id} />)}
</section>
)}
</div>
);
}TypeScript
The hook is fully typed:
import { useAnnouncements } from '@tour-kit/announcements';
import type {
Announcement,
AnnouncementsFilter,
AnnouncementCounts,
} from '@tour-kit/announcements';
function TypedComponent() {
const {
announcements,
activeId,
ids,
count,
getFiltered,
} = useAnnouncements();
// All properties are typed
const all: Announcement[] = announcements.all;
const id: string | null = activeId;
const idList: string[] = ids;
const counts: AnnouncementCounts = count;
// Methods are typed
const filter: AnnouncementsFilter = {
variant: ['modal'],
priority: ['high'],
};
const filtered: Announcement[] = getFiltered(filter);
}Performance Considerations
The hook uses memoization to prevent unnecessary re-renders:
// These are memoized and only update when state changes
const { announcements, count, visible, dismissed } = useAnnouncements();The hook automatically subscribes to the announcements context. It will re-render when any announcement state changes.
Related
- useAnnouncement - Control a single announcement
- useAnnouncementQueue - Control the queue
- AnnouncementsProvider - Provider configuration