Skip to Content
DocsFrontend DevelopmentOverview

Components

Organized by scope — what each component wraps and where it sits in the page hierarchy. Five layers, from outermost to innermost:

┌──────────────────────────────────────────────────────┐ │ 1. App Shell ─── wraps the whole app │ │ ┌─────────────────────────────────────────────────┐ │ │ │ 2. Page Composer ─── wraps one page.tsx │ │ │ │ ┌────────────────────────────────────────────┐ │ │ │ │ │ 3. Data View ─── renders one dataset │ │ │ │ │ │ ┌───────────────────────────────────────┐ │ │ │ │ │ │ │ 4. Building Blocks ─── inside views │ │ │ │ │ │ │ │ ┌──────────────────────────────────┐ │ │ │ │ │ │ │ │ │ 5. UI Primitives │ │ │ │ │ │ │ │ │ └──────────────────────────────────┘ │ │ │ │ │ │ │ └───────────────────────────────────────┘ │ │ │ │ │ └────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────┘

1. App Shell

Application-wide chrome — the same on every page.

ComponentRole
HeaderTop bar with module switcher, breadcrumbs, search, user menu
SidebarCollapsible nav from current module’s manifest
WorkspaceSwitcherSearchable workspace record picker
BrowsePagesDialogFull-screen page browser

layout/

2. Page Composer

Wraps a single page.tsx in a navigation shell. Not a data view — it composes other views into a unified page-level UI.

ComponentRole
MultiViewTabbed multi-view container with shared header + URL-synced active tab

views/multi-view/

(PageTabs was a former member here; replaced by MultiView. Future page composers — WizardPage, MasterDetailPage, etc. — would join this layer.)

3. Data Views

Render records of a model. Each is a distinct “view kind”.

ComponentRole
ModelTableTabular grid with toolbar, inline edit, side panel, bulk ops
ModelBoardKanban-style column view with drag-drop and per-column “Load more”
ModelCardResponsive card grid with template slots
ModelFormDetail / create / edit form
ModelSideFormMaster-detail (left list + right form)

views/table/ · views/board/ · views/card/ · views/form/ · views/side-form/

All of these accept top-level filters / orders and inherit from MultiView.Tab when nested. See Filter & order precedence for cross-layer rules.

4. Building Blocks

Reusable elements consumed by data views, composers, and pages. Split into three sub-categories by model awareness:

4a. Generic UI widgets (no model awareness)

Plain visual widgets — input is simple data, no modelName / FilterCondition.

ComponentRole
pagination-barPage number / size controls
empty-stateEmpty list placeholder
status-badgeColored status pill
user-avatarUser avatar + name
timelineVertical event timeline
date-picker / datetime-picker / time-pickerDate / time inputs (string in / out, optional triggerWrapper for form adapters)
density-switcherUI density toggle
loading-skeleton / full-screen-loadingLoading states
check-list / option-selectSelection inputs

common/

4b. Model-aware view children (used inside Model* views)

Need modelName and integrate with the Model* view via SidePanelContainerContext or similar — not suitable for use outside a host view.

ComponentUsed in
SideTree / SideCard / SideListSide panel filters inside ModelTable / ModelCard
RecordPickerField / RecordPickerListRelation record pickers used in fields and forms

components/side-panel/ · components/picker/

4c. Model-aware standalones (declared inside views, but stand alone)

Used inside Model* / MultiView declarations as JSX children, but each is a self-contained “thing”:

ComponentRole
FieldColumn / form field declaration; renders read & edit modes
Action / BulkActionPer-record / per-selection operations
Cell renderersBooleanCell / OptionCell / ReferenceCell / etc. used by ModelTable

fields/ · actions/

Sub-category guide

When in doubt where a new component goes:

  • Doesn’t know about models? → 4a (common/)
  • Knows about models AND must live inside a Model* host (publishes to or reads from a host context)? → 4b (views/shared/)
  • Knows about models AND is a self-contained child of a host? → 4c

5. UI Primitives

Low-level UI used by everything above. Mostly third-party adaptations or narrow utilities.

ComponentRole
ui (shadcn)Button / Input / Dialog / Tabs / etc.
TreePanelTree rendering primitive (used by SideTree)
Dialog hostsAction / table action dialog rendering

views/tree/ · views/dialogs/


Choosing the right layer for a new component

Decision tree:

  1. Does it appear on every page (e.g., always-visible nav)? → App Shell
  2. Does it wrap a whole page.tsx and host other views inside? → Page Composer
  3. Does it render records of a single model? → Data View
  4. Is it a piece used inside a view (column, action, side filter)? → Building Block
  5. Is it a low-level UI primitive with no model awareness? → UI Primitive

When in doubt between #2 and #3: page composers don’t fetch data themselves; data views do.

Last updated on