mirror of
https://github.com/hunvreus/basecoat.git
synced 2026-11-12 13:18:22 +00:00
167 lines
5.8 KiB
Plaintext
167 lines
5.8 KiB
Plaintext
<script>
|
|
document.addEventListener('alpine:init', () => {
|
|
Alpine.data('tabs', () => ({
|
|
activeTabIndex: 0,
|
|
tabs: [],
|
|
panels: [],
|
|
|
|
init() {
|
|
this.$nextTick(() => {
|
|
this.tabs = Array.from(this.$el.querySelectorAll('[role=tab]:not([disabled])'));
|
|
this.panels = Array.from(this.$el.querySelectorAll('[role=tabpanel]'));
|
|
|
|
if (this.tabs.length > 0) {
|
|
this.selectTab(this.tabs[0], false);
|
|
}
|
|
});
|
|
},
|
|
nextTab() {
|
|
if (this.tabs.length === 0) return;
|
|
let newIndex = (this.activeTabIndex + 1) % this.tabs.length;
|
|
this.selectTab(this.tabs[newIndex]);
|
|
},
|
|
prevTab() {
|
|
if (this.tabs.length === 0) return;
|
|
let newIndex = (this.activeTabIndex - 1 + this.tabs.length) % this.tabs.length;
|
|
this.selectTab(this.tabs[newIndex]);
|
|
},
|
|
selectTab(tab, focus = true) {
|
|
if (!tab || this.tabs.length === 0) return;
|
|
|
|
this.tabs.forEach((t, index) => {
|
|
const isSelected = t === tab;
|
|
t.setAttribute('aria-selected', isSelected);
|
|
t.setAttribute('tabindex', isSelected ? '0' : '-1');
|
|
if (isSelected) {
|
|
this.activeTabIndex = index;
|
|
this.activeTab = t;
|
|
if (focus) {
|
|
t.focus();
|
|
}
|
|
}
|
|
});
|
|
|
|
const panelId = tab.getAttribute('aria-controls');
|
|
if (!panelId) return;
|
|
|
|
this.panels.forEach(panel => {
|
|
panel.hidden = (panel.getAttribute('id') !== panelId);
|
|
});
|
|
},
|
|
|
|
$tablist: {
|
|
['@click'](event) {
|
|
const clickedTab = event.target.closest('[role=tab]');
|
|
if (clickedTab) {
|
|
this.selectTab(clickedTab);
|
|
}
|
|
},
|
|
['@keydown.arrow-right.prevent']() { this.nextTab() },
|
|
['@keydown.arrow-left.prevent']() { this.prevTab() },
|
|
},
|
|
}));
|
|
});
|
|
</script>
|
|
|
|
<section id="tabs" class="w-full rounded-lg border scroll-mt-16">
|
|
<header class="border-b px-4 py-3">
|
|
<h2 class="text-sm font-medium">Tabs</h2>
|
|
</header>
|
|
<div class="p-4">
|
|
<div class="flex flex-col gap-6">
|
|
<div class="tabs flex flex-col gap-2 max-w-[300px]" x-data="tabs">
|
|
<div role="tablist" aria-orientation="horizontal" aria-label="Feature Sections" class="w-full" x-bind="$tablist">
|
|
<button role="tab" id="demo-tab-account" aria-controls="demo-panel-account" aria-selected="true" tabindex="0">
|
|
Account
|
|
</button>
|
|
<button role="tab" id="demo-tab-password" aria-controls="demo-panel-password" aria-selected="false" tabindex="-1">
|
|
Password
|
|
</button>
|
|
</div>
|
|
|
|
<div role="tabpanel" id="demo-panel-account" aria-labelledby="demo-tab-account" tabindex="-1">
|
|
<div class="card">
|
|
<header>
|
|
<h2>Account</h2>
|
|
<p>Make changes to your account here. Click save when you're done.</p>
|
|
</header>
|
|
<section>
|
|
<form class="form grid gap-6">
|
|
<div class="grid gap-3">
|
|
<label for="demo-tabs-account-name">Name</label>
|
|
<input type="text" id="demo-tabs-account-name" value="Pedro Duarte" />
|
|
</div>
|
|
<div class="grid gap-3">
|
|
<label for="demo-tabs-account-username">Username</label>
|
|
<input type="text" id="demo-tabs-account-username" value="@peduarte" />
|
|
</div>
|
|
</form>
|
|
</section>
|
|
<footer>
|
|
<button type="button" class="btn">Save changes</button>
|
|
</footer>
|
|
</div>
|
|
</div>
|
|
|
|
<div role="tabpanel" id="demo-panel-password" aria-labelledby="demo-tab-password" tabindex="-1" hidden>
|
|
<div class="card">
|
|
<header>
|
|
<h2>Password</h2>
|
|
<p>Change your password here. After saving, you'll be logged out.</p>
|
|
</header>
|
|
<section>
|
|
<form class="form grid gap-6">
|
|
<div class="grid gap-3">
|
|
<label for="demo-tabs-password-current">Current password</label>
|
|
<input type="password" id="demo-tabs-password-current" />
|
|
</div>
|
|
<div class="grid gap-3">
|
|
<label for="demo-tabs-password-new">New password</label>
|
|
<input type="password" id="demo-tabs-password-new"/>
|
|
</div>
|
|
</form>
|
|
</section>
|
|
<footer>
|
|
<button type="button" class="btn">Save Password</button>
|
|
</footer>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tabs" x-data="tabs">
|
|
<div role="tablist" aria-orientation="horizontal" aria-label="Feature Sections" x-bind="$tablist">
|
|
<button role="tab" aria-selected="true" tabindex="0">
|
|
Home
|
|
</button>
|
|
<button role="tab" aria-selected="false" tabindex="-1">
|
|
Settings
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tabs" x-data="tabs">
|
|
<div role="tablist" aria-orientation="horizontal" aria-label="Feature Sections" x-bind="$tablist">
|
|
<button role="tab" aria-selected="true" tabindex="0">
|
|
Home
|
|
</button>
|
|
<button role="tab" aria-selected="false" tabindex="-1" disabled>
|
|
Disabled
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tabs" x-data="tabs">
|
|
<div role="tablist" aria-orientation="horizontal" aria-label="Feature Sections" x-bind="$tablist">
|
|
<button role="tab" aria-selected="true" tabindex="0">
|
|
{% lucide 'app-window' %}
|
|
Preview
|
|
</button>
|
|
<button role="tab" aria-selected="false" tabindex="-1">
|
|
{% lucide 'code' %}
|
|
Code
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section> |