Skip to content

Tabs

Tabs split a long form into sections. They only change the layout in the dashboard: the fields on a tab are stored on the entry as if they were defined without tabs, so moving a field to another tab doesn't change your content or queries.

import {Config, Field} from 'alinea'

export const Product = Config.document('Product', {
  fields: {
    ...Field.tabs(
      Field.tab('Content', {
        fields: {
          intro: Field.text('Intro', {multiline: true}),
          body: Field.richText('Body')
        }
      }),
      Field.tab('Pricing', {
        fields: {
          price: Field.number('Price', {width: 0.5}),
          currency: Field.select('Currency', {
            width: 0.5,
            initialValue: 'eur',
            options: {eur: 'EUR', usd: 'USD'}
          })
        }
      })
    )
  }
})

Usage

  • Field.tabs(...tabs) groups tabs. Spread its result into fields, because it adds the fields of every tab to the type.

  • Field.tab(label, {fields, icon}) defines one tab. icon is an optional React component shown before the label.

  • Fields before or after the tabs are shown above or below them, on every tab.

  • Field names must be unique across all tabs of a type: they end up side by side in the same entry.

  • Tabs work in list rows and blocks too, and a tab can contain another set of tabs.

With Config.document, your fields already sit on a "Document" tab next to "Metadata". Tabs you add there appear inside the Document tab.

Entry tabs

Pass tabs to Config.type, Config.document or Config.file to add tabs to the entry editor, next to the tabs alinea shows. A tab holds fields, a view or both: a view is a component, given as a path like with Field.view, that can read the entry with the hooks of alinea/cms.

schema/Program.ts
import {Config, Field} from 'alinea'

export const Program = Config.document('Program', {
  fields: {intro: Field.text('Intro')},
  tabs: {
    planning: Field.tab('Planning', {
      fields: {start: Field.date('Start')}
    }),
    analytics: Field.tab('Analytics', {
      view: '@/views/ProgramAnalytics#ProgramAnalytics'
    })
  }
})
  • Documents show these tabs after their Details tab. Other types show their fields on a Content tab, followed by these tabs. Files show them after the File and Details tabs, and list rows and rich text blocks as sections of their settings sheet.

  • The fields of a tab are stored and queried like the other fields of the type, so their names must be unique across the type.

Reusing tabs

Because Field.tab returns a type, a common set of fields can be shared as a function that creates a new tab each time (fields must be unique, so don't share one instance):

import {Config, Field} from 'alinea'

function settingsTab() {
  return Field.tab('Settings', {
    fields: {
      hideFromNavigation: Field.check('Hide from navigation'),
      noIndex: Field.check('Hide from search engines')
    }
  })
}

export const Page = Config.document('Page', {
  fields: {
    ...Field.tabs(
      Field.tab('Content', {fields: {body: Field.richText('Body')}}),
      settingsTab()
    )
  }
})