Now.js Framework Documentation

Now.js Framework Documentation

TabsComponent

TH 15 Dec 2025 08:52

TabsComponent

ภาพรวม

TabsComponent คือ component สำหรับ tabs/tab panels ใน Now.js Framework รองรับ ARIA accessibility และ keyboard navigation

ใช้เมื่อ:

  • ต้องการ tab navigation
  • ต้องการ switch between panels
  • ต้องการ tabbed content
  • ต้องการ accessible tabs

ทำไมต้องใช้:

  • ✅ Full ARIA accessibility
  • ✅ Keyboard navigation (Arrow keys, Home, End)
  • ✅ Declarative HTML setup
  • ✅ Animation support
  • ✅ URL hash sync
  • ✅ Events และ callbacks

การใช้งานพื้นฐาน

HTML Declarative

<div data-component="tabs">
  <!-- Tab buttons -->
  <div data-tabs-list>
    <button data-tab-button="home">Home</button>
    <button data-tab-button="profile">Profile</button>
    <button data-tab-button="settings">Settings</button>
  </div>

  <!-- Tab panels -->
  <div data-tab-panel="home">
    <h2>Home Content</h2>
    <p>Welcome to the home tab!</p>
  </div>
  <div data-tab-panel="profile">
    <h2>Profile Content</h2>
    <p>Your profile information.</p>
  </div>
  <div data-tab-panel="settings">
    <h2>Settings Content</h2>
    <p>Application settings.</p>
  </div>
</div>

With Default Tab

<div data-component="tabs" data-default-tab="profile">
  <div data-tabs-list>
    <button data-tab-button="home">Home</button>
    <button data-tab-button="profile">Profile</button>
  </div>
  <div data-tab-panel="home">...</div>
  <div data-tab-panel="profile">...</div>
</div>

JavaScript API

const tabs = TabsComponent.create(element, {
  defaultTab: 'home',
  keyboard: true,
  onTabChange: (tabId) => {
    console.log('Switched to:', tabId);
  }
});

// Switch tab programmatically
tabs.switchTab('profile');

// Get active tab
const activeId = tabs.getActiveTab();

Data Attributes

Attribute Description
data-component="tabs" Initialize tabs container
data-tabs-list Container for tab buttons
data-tab-button="id" Tab button with unique ID
data-tab-panel="id" Tab panel matching button ID
data-default-tab="id" Default active tab
data-keyboard="true/false" Enable keyboard navigation
data-animation="true/false" Enable animations

Options

TabsComponent.create(element, {
  // Default active tab
  defaultTab: null,  // null = first tab

  // Keyboard navigation
  keyboard: true,

  // Animation
  animation: true,
  animationDuration: 200,

  // URL hash sync
  hashNavigation: false,

  // Callbacks
  onTabChange: (tabId, previousId) => {},
  onInit: (instance) => {}
});

API อ้างอิง

TabsComponent.create(element, options)

สร้าง tabs instance

Parameter Type Description
element HTMLElement Tabs container
options object Configuration

Returns: Object - Instance with methods

instance.switchTab(tabId)

เปลี่ยน tab

Parameter Type Description
tabId string Tab ID
tabs.switchTab('settings');

instance.getActiveTab()

รับ active tab ID

Returns: string

instance.refresh()

Refresh tabs (rescan DOM)

instance.destroy()

ทำลาย instance

TabsComponent.getInstance(element)

รับ instance จาก element

Keyboard Navigation

Key Action
/ Next tab
/ Previous tab
Home First tab
End Last tab
Enter / Space Activate focused tab

เหตุการณ์

Event เมื่อเกิด Detail
tabs:change Tab เปลี่ยน {tabId, previousId}
tabs:init Initialize เสร็จ {instance}
element.addEventListener('tabs:change', (e) => {
  console.log(`Changed from ${e.detail.previousId} to ${e.detail.tabId}`);
});

การจัดรูปแบบ CSS

/* Tab list */
[data-tabs-list] {
  display: flex;
  gap: 4px;
  border-bottom: 2px solid #e5e7eb;
}

/* Tab buttons */
[data-tab-button] {
  padding: 12px 24px;
  border: none;
  background: transparent;
  cursor: pointer;
  color: #6b7280;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  transition: all 0.2s;
}

[data-tab-button]:hover {
  color: #3b82f6;
}

[data-tab-button][aria-selected="true"] {
  color: #3b82f6;
  border-bottom-color: #3b82f6;
  font-weight: 500;
}

[data-tab-button]:focus {
  outline: 2px solid #3b82f6;
  outline-offset: 2px;
}

/* Tab panels */
[data-tab-panel] {
  padding: 24px;
}

[data-tab-panel][hidden] {
  display: none;
}

/* Animation */
[data-tab-panel]:not([hidden]) {
  animation: tab-fade-in 0.2s ease-out;
}

@keyframes tab-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

ตัวอย่างการใช้งานจริง

Settings Tabs

<div data-component="tabs" class="settings-tabs">
  <div data-tabs-list>
    <button data-tab-button="general">
      <svg>...</svg> General
    </button>
    <button data-tab-button="security">
      <svg>...</svg> Security
    </button>
    <button data-tab-button="notifications">
      <svg>...</svg> Notifications
    </button>
  </div>

  <div data-tab-panel="general">
    <form>
      <!-- General settings form -->
    </form>
  </div>

  <div data-tab-panel="security">
    <form>
      <!-- Security settings form -->
    </form>
  </div>

  <div data-tab-panel="notifications">
    <form>
      <!-- Notification settings form -->
    </form>
  </div>
</div>

Dynamic Tab Content

<div data-component="tabs" id="product-tabs">
  <div data-tabs-list>
    <button data-tab-button="description">Description</button>
    <button data-tab-button="specs">Specifications</button>
    <button data-tab-button="reviews">Reviews</button>
  </div>

  <div data-tab-panel="description" data-src="/api/products/1/description">
    Loading...
  </div>
  <div data-tab-panel="specs" data-src="/api/products/1/specs">
    Loading...
  </div>
  <div data-tab-panel="reviews" data-src="/api/products/1/reviews">
    Loading...
  </div>
</div>

<script>
const tabs = TabsComponent.getInstance(document.getElementById('product-tabs'));

document.getElementById('product-tabs').addEventListener('tabs:change', async (e) => {
  const panel = document.querySelector(`[data-tab-panel="${e.detail.tabId}"]`);
  const src = panel.dataset.src;

  if (src && !panel.dataset.loaded) {
    const response = await fetch(src);
    panel.innerHTML = await response.text();
    panel.dataset.loaded = 'true';
  }
});
</script>

ข้อควรระวัง

⚠️ 1. Button ID ต้องตรงกับ Panel ID

<!-- ❌ ID ไม่ตรงกัน -->
<button data-tab-button="tab1">Tab 1</button>
<div data-tab-panel="tab-1">...</div>

<!-- ✅ ID ตรงกัน -->
<button data-tab-button="tab1">Tab 1</button>
<div data-tab-panel="tab1">...</div>

⚠️ 2. ต้องมี data-tabs-list

<!-- ❌ ไม่มี data-tabs-list -->
<div data-component="tabs">
  <button data-tab-button="a">A</button>
</div>

<!-- ✅ มี data-tabs-list -->
<div data-component="tabs">
  <div data-tabs-list>
    <button data-tab-button="a">A</button>
  </div>
</div>

เอกสารที่เกี่ยวข้อง