JS Required

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-label describing 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-motion for transitions
  • Count uses tabular-nums for 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');
  }
});