Inizia gratis

Documentazione · ShadowUI

Le tabbed view

Documentazione storica, non aggiornata.

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

shadowui design pattern 04 Instant Developer

ShaTabs e ShaTab

ShaTabs è il contenitore delle schede, mentre ShaTab rappresenta una singola scheda.

ShaTabs

Proprietà principali:

ProprietàTipoDescrizione
selectedTabnumberIndice della scheda selezionata (0-based)
classNamestringClassi CSS personalizzate

Eventi:

  • onChangeTab(event): Scatenato al cambio scheda
    • event.selectedTab: Nuovo indice selezionato

ShaTab

Proprietà principali:

ProprietàTipoDescrizione
labelstringEtichetta della scheda
iconstringIcona opzionale
disabledbooleanDisabilita la scheda
classNamestringClassi 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

  1. Numero di tabs: Mantieni 3-7 tabs per pagina (massimo leggibile)
  2. Label chiare: Usa etichette brevi e descrittive
    // ✅ Bene
    “Informazioni”, “Documenti”, “Storico”
    // ❌ Male
    “Info generali del progetto”, “Tutti i documenti”, “Cronologia completa”
  3. Caricamento lazy: Carica contenuti solo quando necessario
  4. Stato tab: Mantieni traccia della tab corrente in una variabile
  5. Validazione: Valida prima di permettere cambio tab in wizard
  6. Feedback visivo: Mostra spinner durante caricamento contenuti tab