Now.js Framework Documentation
TabsComponent
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>เอกสารที่เกี่ยวข้อง
- ComponentManager - Component system
- AnimationManager - Animations