Le tabbed view permettono di organizzare contenuti correlati in schede separate, migliorando la navigazione all’interno di una singola pagina.

ShaTabs e ShaTab #
ShaTabs è il contenitore delle schede, mentre ShaTab rappresenta una singola scheda.
ShaTabs #
Proprietà principali:
| Proprietà | Tipo | Descrizione |
|---|---|---|
| selectedTab | number | Indice della scheda selezionata (0-based) |
| className | string | Classi CSS personalizzate |
Eventi:
- onChangeTab(event): Scatenato al cambio scheda
- event.selectedTab: Nuovo indice selezionato
ShaTab #
Proprietà principali:
| Proprietà | Tipo | Descrizione |
|---|---|---|
| label | string | Etichetta della scheda |
| icon | string | Icona opzionale |
| disabled | boolean | Disabilita la scheda |
| className | string | Classi CSS personalizzate |
Struttura base #
ShaTabs
├── ShaTab (Informazioni)
│ └── contenuto tab 1
├── ShaTab (Documenti)
│ └── contenuto tab 2
└── ShaTab (Storico)
└── contenuto tab 3
Esempio implementazione:
ShaTabs
selectedTab: 0
├── infoTab (ShaTab)
│ label: "Informazioni"
│ icon: "shaicons shaicons-info"
│ └── ShaCard
│ └── form informazioni
│
├── docsTab (ShaTab)
│ label: "Documenti"
│ icon: "shaicons shaicons-file-text"
│ └── ShaCard
│ └── lista documenti
│
└── historyTab (ShaTab)
label: "Storico"
icon: "shaicons shaicons-clock"
└── ShaCard
└── timeline eventi
Gestione cambio tab #
function* tabs_onChangeTab() {
let selectedTab = this.view.tabs.selectedTab;
// Carica dati specifici per la tab
switch(selectedTab) {
case 0: // Informazioni
yield this.loadInfo();
break;
case 1: // Documenti
yield this.loadDocuments();
break;
case 2: // Storico
yield this.loadHistory();
break;
}
}
Pattern comuni #
1. Form multi-step con tabs: #
ShaTabs
selectedTab: 0
├── ShaTab (Step 1: Dati base)
│ └── form step 1 + pulsante "Avanti"
│
├── ShaTab (Step 2: Dettagli)
│ └── form step 2 + pulsanti "Indietro" e "Avanti"
│
└── ShaTab (Step 3: Conferma)
└── riepilogo + pulsante "Salva"
// Avanza alla tab successiva
function* nextButton_onClick() {
let currentTab = this.view.tabs.selectedTab;
this.view.tabs.selectedTab = currentTab + 1;
}
// Torna alla tab precedente
function* prevButton_onClick() {
let currentTab = this.view.tabs.selectedTab;
this.view.tabs.selectedTab = currentTab - 1;
}
2. Lazy loading contenuti: #
function* tabs_onChangeTab() {
let tab = this.view.tabs.selectedTab;
// Carica solo se non già caricato
if (tab === 1 && !this.documentsLoaded) {
this.view.docsSpinner.visible = true;
yield this.view.documentsDM.load();
this.view.docsSpinner.visible = false;
this.documentsLoaded = true;
}
}
3. Validazione prima di cambiare tab: #
function* tabs_onChangeTab() {
let newTab = this.view.tabs.selectedTab;
let oldTab = this.currentTab || 0;
// Se sta lasciando tab 0, valida
if (oldTab === 0) {
let isValid = yield this.validateStep1();
if (!isValid) {
// Torna alla tab precedente
this.view.tabs.selectedTab = oldTab;
yield app.toast("Completa tutti i campi", {
variant: "destructive"
});
return;
}
}
this.currentTab = newTab;
}
4. Badge con contatore su tab: #
ShaTab
label: `Documenti (${documentCount})`
icon: "shaicons shaicons-file-text"
5. Tab disabilitate condizionalmente: #
// Disabilita tab 2 e 3 finché non completi tab 1
function* step1ContinueButton_onClick() {
yield this.saveStep1();
// Abilita tab successiva
this.view.step2Tab.disabled = false;
this.view.tabs.selectedTab = 1;
}
6. Contenuto tab con DataMap: #
// Tab con lista documenti
ShaTab
label: "Documenti"
└── ShaCard
├── ShaCardHeader
│ └── ShaButton (Aggiungi documento)
│
└── ShaCardContent
└── documentRow (template: documentsDM)
├── documentName (ShaLabel)
├── documentDate (ShaLabel)
└── actionsButton (ShaButton)
function* onLoad() {
yield this.view.documentsDM.load();
}
function* documentRow_onClick() {
let doc = this.sender.row;
yield this.openDocument(doc.id);
}
7. Tabs con URL routing (opzionale): #
// Apri view con tab specifica
yield view.push(App.ProjectDetailView, {
title: "Progetto",
projectId: id,
initialTab: 1 // Apri su tab "Documenti"
});
// In ProjectDetailView onLoad
function* onLoad() {
if (this.options.initialTab !== undefined) {
this.view.tabs.selectedTab = this.options.initialTab;
}
}
Stile tabs #
Tabs orizzontali (default) #
ShaTabs
className: "w-full"
├── ShaTab (Tab 1)
├── ShaTab (Tab 2)
└── ShaTab (Tab 3)
Tabs con icone #
ShaTab
label: "Documenti"
icon: "shaicons shaicons-file-text"
Tabs compatte #
ShaTabs
className: "tabs-compact"
Best Practices #
- Numero di tabs: Mantieni 3-7 tabs per pagina (massimo leggibile)
- Label chiare: Usa etichette brevi e descrittive
// ✅ Bene
“Informazioni”, “Documenti”, “Storico”
// ❌ Male
“Info generali del progetto”, “Tutti i documenti”, “Cronologia completa” - Caricamento lazy: Carica contenuti solo quando necessario
- Stato tab: Mantieni traccia della tab corrente in una variabile
- Validazione: Valida prima di permettere cambio tab in wizard
- Feedback visivo: Mostra spinner durante caricamento contenuti tab