Engage
Social engagement component for bookmarks, likes, shares, and comments. Lightweight, accessible, with CSS-defined states and JavaScript for interactivity.
Example
<button class="omni-engage" data-action="like" aria-label="Like this post">
<svg viewBox="0 0 24 24">
<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
</svg>
<span class="omni-engage-count">42</span>
</button>
Action Types
Bookmark
Use data-action="bookmark" for save/bookmark functionality:
<button class="omni-engage" data-action="bookmark" aria-label="Bookmark">
<svg viewBox="0 0 24 24">...</svg>
<span class="omni-engage-text">Save</span>
</button>
<!-- Active state (filled icon) -->
<button class="omni-engage" data-action="bookmark" data-active="true" aria-pressed="true" aria-label="Bookmarked">
<svg viewBox="0 0 24 24">...</svg>
<span class="omni-engage-text">Saved</span>
</button>
Like
Use data-action="like" for like/favorite functionality:
<button class="omni-engage" data-action="like" aria-label="Like">
<svg viewBox="0 0 24 24">...</svg>
<span class="omni-engage-count">42</span>
</button>
<!-- Active state (filled icon) -->
<button class="omni-engage" data-action="like" data-active="true" aria-pressed="true" aria-label="Liked">
<svg viewBox="0 0 24 24">...</svg>
<span class="omni-engage-count">43</span>
</button>
Share
Use data-action="share" for share functionality:
<button class="omni-engage" data-action="share" aria-label="Share">
<svg viewBox="0 0 24 24">...</svg>
<span class="omni-engage-text">Share</span>
</button>
<!-- Success state (after copying link) -->
<button class="omni-engage" data-action="share" data-state="success" aria-label="Link copied">
<svg viewBox="0 0 24 24">...</svg>
<span class="omni-engage-text">Copied!</span>
</button>
Comment
General engagement pattern for comments or other interactions:
Variants
Icon-Only
Use data-type="icon" for compact icon-only buttons. Text is visually hidden but accessible:
Style Variants
Use data-style="solid" for more visual prominence:
States
Active and loading states provide visual feedback:
Active State
Loading State
Real-World Example
Social engagement toolbar for a blog post:
<div style="display: inline-flex; gap: var(--omni-space-2); align-items: center;">
<button class="omni-engage" data-action="like" aria-label="Like this post">
<svg viewBox="0 0 24 24">...</svg>
<span class="omni-engage-count">127</span>
</button>
<button class="omni-engage" aria-label="View 23 comments">
<svg viewBox="0 0 24 24">...</svg>
<span class="omni-engage-count">23</span>
</button>
<button class="omni-engage" data-action="bookmark" data-active="true" aria-pressed="true" aria-label="Bookmarked">
<svg viewBox="0 0 24 24">...</svg>
</button>
<button class="omni-engage" data-action="share" data-style="solid" aria-label="Share this post">
<svg viewBox="0 0 24 24">...</svg>
</button>
</div>
API Reference
| Attribute | Values | Default | Description |
|---|---|---|---|
data-action |
bookmark, like, share | — | Engagement action type (fills icon when active) |
data-active |
true | — | Active/engaged state (use with aria-pressed) |
data-style |
default, solid | default | Visual style (solid has background) |
data-type |
icon | — | Icon-only variant (hides text visually) |
data-state |
loading, success | — | Interactive state feedback |
CSS Classes
| Class | Element | Description |
|---|---|---|
.omni-engage |
<button> or <a> |
Base engagement button |
.omni-engage-text |
<span> |
Optional text label |
.omni-engage-count |
<span> |
Optional count/metric |
Accessibility
- Always include
aria-labeldescribing the action - Use
aria-pressed="true"for toggle states (like, bookmark) - Icon-only buttons hide text visually but keep it accessible
- Loading state prevents duplicate interactions
- Full keyboard navigation support (Tab, Enter, Space)
- Focus visible indicators
- Works with both
<button>and<a>elements - Respects
prefers-reduced-motionfor transitions - Count uses
tabular-numsfor stable layout
JavaScript Enhancement
The engage component requires JavaScript for interactivity:
- Toggle states: Switch between active/inactive on click
- API calls: Send like/bookmark requests to your backend
- Share API: Use native Web Share API with fallback to copy link
- Optimistic updates: Update UI immediately, rollback on error
- Count animations: Animate count changes
// Basic toggle example
const engageBtn = document.querySelector('[data-action="like"]');
engageBtn?.addEventListener('click', async () => {
const isActive = engageBtn.getAttribute('aria-pressed') === 'true';
// Optimistic update
engageBtn.setAttribute('aria-pressed', !isActive);
engageBtn.toggleAttribute('data-active');
// API call
try {
await fetch('/api/like', { method: 'POST' });
} catch (err) {
// Rollback on error
engageBtn.setAttribute('aria-pressed', isActive);
engageBtn.toggleAttribute('data-active');
}
});