Rewrote all the docs - more noob friendly now.
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
+62
-63
@@ -1,50 +1,27 @@
|
||||
# Tabs
|
||||
|
||||
A tabbed interface. One tab panel is visible at a time. The active tab has a highlighted style; all others are hidden. Client-side JS switches panels without a server round-trip.
|
||||
A row of clickable tabs that each reveal different content. Only one tab is visible at a time. Think of it like a filing cabinet with labelled dividers — you flip between sections without leaving the page.
|
||||
|
||||
---
|
||||
|
||||
## HTML structure
|
||||
## Quick example
|
||||
|
||||
```
|
||||
div[id].tabs-root
|
||||
div.tabs-list.flex.gap-1.border-b.mb-4 ← tab button strip
|
||||
button.tabs-trigger[data-tab={tabId}] ← one per tab; ACTIVE/INACTIVE variant
|
||||
{label}
|
||||
div.tabs-panel[data-tab={tabId}] ← one per tab; hidden or visible
|
||||
{content}
|
||||
```csharp
|
||||
new Tabs(
|
||||
id: "settings-tabs",
|
||||
tabs: new[]
|
||||
{
|
||||
("general", "General", "<p>General settings here.</p>"),
|
||||
("security", "Security", "<p>Password and 2FA here.</p>"),
|
||||
("billing", "Billing", "<p>Payment details here.</p>"),
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CSS mechanics
|
||||
|
||||
| Class | Effect |
|
||||
|---|---|
|
||||
| `tabs-trigger` | `px-4 py-2 text-sm font-medium rounded-t-md -mb-px` |
|
||||
| Active trigger | `bg-background border border-b-0 border-border text-foreground` |
|
||||
| Inactive trigger | `text-muted-foreground hover:text-foreground hover:bg-muted/40` |
|
||||
| `tabs-panel[hidden]` | `display: none` via the HTML `hidden` attribute |
|
||||
The first tab is active by default.
|
||||
|
||||
---
|
||||
|
||||
## JavaScript (`initTabs` in `components.js`)
|
||||
|
||||
Runs on `DOMContentLoaded` and `htmx:afterSwap`.
|
||||
|
||||
**Per-instance initialization:**
|
||||
|
||||
1. Guard `_tabsInit` prevents double-binding
|
||||
2. Reads all `.tabs-trigger` and `.tabs-panel` elements within the root
|
||||
3. Activates the first tab on init (removes `hidden`, applies active class)
|
||||
4. On trigger click:
|
||||
- Deactivate all panels (set `hidden`, downgrade trigger class to inactive)
|
||||
- Activate the clicked panel by matching `data-tab` attribute
|
||||
- Apply active class to the clicked trigger
|
||||
|
||||
---
|
||||
|
||||
## Constructor signature
|
||||
## All the options
|
||||
|
||||
```csharp
|
||||
public Tabs(
|
||||
@@ -52,52 +29,74 @@ public Tabs(
|
||||
IEnumerable<(string Id, string Label, string Content)> tabs)
|
||||
```
|
||||
|
||||
| Parameter | Description |
|
||||
| Parameter | What it does |
|
||||
|---|---|
|
||||
| `id` | Root element id — must be unique per page if multiple Tabs are rendered |
|
||||
| `tabs` | List of `(Id, Label, Content)` tuples; `Id` must be unique within this instance |
|
||||
| `id` | A unique identifier for this tabs widget. Required if you have more than one `Tabs` on the same page. |
|
||||
| `tabs` | The list of tabs. Each is a `(Id, Label, Content)` tuple. |
|
||||
|
||||
**Tab tuple fields:**
|
||||
|
||||
| Field | What it does |
|
||||
|---|---|
|
||||
| `Id` | A unique identifier for this tab within the widget. Used internally to link the trigger to the panel. |
|
||||
| `Label` | The text shown on the tab button. |
|
||||
| `Content` | The HTML content shown when this tab is active. |
|
||||
|
||||
---
|
||||
|
||||
## Usage examples
|
||||
## Real-world examples
|
||||
|
||||
### Simple tabbed content
|
||||
### User profile page with tabbed sections
|
||||
|
||||
```csharp
|
||||
new Tabs(
|
||||
id: "settings-tabs",
|
||||
id: "profile-tabs",
|
||||
tabs: new[]
|
||||
{
|
||||
("general", "General", "<p>General settings content here.</p>"),
|
||||
("security", "Security", "<p>Security settings content here.</p>"),
|
||||
("billing", "Billing", "<p>Billing details here.</p>"),
|
||||
("overview", "Overview", $"<p>Joined {user.CreatedAt:MMMM yyyy}</p>"),
|
||||
("activity", "Activity", activityHtml),
|
||||
("settings", "Settings", settingsFormHtml),
|
||||
})
|
||||
```
|
||||
|
||||
### HTML-rich content in a tab
|
||||
### Tab containing a full component
|
||||
|
||||
Pre-render inner components to HTML strings before embedding them:
|
||||
|
||||
```csharp
|
||||
new Tabs(
|
||||
id: "code-tabs",
|
||||
tabs: new[]
|
||||
{
|
||||
("csharp", "C#", "<pre><code>var x = 42;</code></pre>"),
|
||||
("fsharp", "F#", "<pre><code>let x = 42</code></pre>"),
|
||||
("vb", "VB.NET", "<pre><code>Dim x As Integer = 42</code></pre>"),
|
||||
})
|
||||
```
|
||||
|
||||
### Embedding a full component in a tab
|
||||
|
||||
```csharp
|
||||
// Pre-render the inner component to HTML string
|
||||
var buf = new System.Buffers.ArrayBufferWriter<byte>();
|
||||
new Table(headers: cols, rows: data).Render(new HtmxRenderContext(buf));
|
||||
var tableHtml = System.Text.Encoding.UTF8.GetString(buf.WrittenSpan);
|
||||
string Render(IHtmxComponent c)
|
||||
{
|
||||
var buf = new System.Buffers.ArrayBufferWriter<byte>();
|
||||
c.Render(new HtmxRenderContext(buf));
|
||||
return System.Text.Encoding.UTF8.GetString(buf.WrittenSpan);
|
||||
}
|
||||
|
||||
new Tabs(
|
||||
id: "report",
|
||||
tabs: new[]
|
||||
{
|
||||
("table", "Table", Render(new Table(headers: cols, rows: rows))),
|
||||
("summary", "Summary", summaryHtml),
|
||||
})
|
||||
```
|
||||
|
||||
### Code samples in multiple languages
|
||||
|
||||
```csharp
|
||||
new Tabs(
|
||||
id: "code-example",
|
||||
tabs: new[]
|
||||
{
|
||||
("csharp", "C#", "<pre><code>var x = 42;</code></pre>"),
|
||||
("fsharp", "F#", "<pre><code>let x = 42</code></pre>"),
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
All tab panels are present in the HTML on page load. JavaScript in `components.js` hides all but the first using the HTML `hidden` attribute. When a tab button is clicked, its matching panel has `hidden` removed and all others get it added back. No server request is made — this is pure client-side switching.
|
||||
{
|
||||
("summary", "Summary", "<p>High level numbers.</p>"),
|
||||
("detail", "Detail", tableHtml),
|
||||
|
||||
Reference in New Issue
Block a user