Ga naar hoofdinhoud

CnObjectSidebar

Right sidebar for entity detail pages. Provides standardized tabs — Files, Notes, Tags, Tasks, and Audit Trail — that integrate with OpenRegister API endpoints bridging to Nextcloud-native APIs. Each tab is optional and independently overridable via slots.

Wraps: NcAppSidebar, NcAppSidebarTab

Try it

Loading CnObjectSidebar playground…

Tabs

Tab IDLabelContent
filesFilesFile attachments via CnFilesTab
notesNotesNotes list and add form via CnNotesTab
tagsTagsTag management via CnTagsTab
tasksTasksTask list via CnTasksTab
auditTrailAudit TrailChange history via CnAuditTrailTab

Usage

<!-- Basic usage -->
<CnObjectSidebar
object-type="pipelinq_lead"
:object-id="lead.id"
:register="registerConfig.register"
:schema="registerConfig.schema" />

<!-- Hide specific tabs -->
<CnObjectSidebar
object-type="pipelinq_lead"
:object-id="lead.id"
:hidden-tabs="['tasks', 'tags']" />

<!-- Override a tab with custom content -->
<CnObjectSidebar object-type="pipelinq_lead" :object-id="lead.id">
<template #tab-notes="{ objectId }">
<MyCustomNotesComponent :id="objectId" />
</template>
</CnObjectSidebar>

<!-- Add an extra custom tab -->
<CnObjectSidebar object-type="pipelinq_lead" :object-id="lead.id">
<template #extra-tabs>
<NcAppSidebarTab id="relations" name="Relations" :order="6">
<template #icon><LinkVariant :size="20" /></template>
<RelationsList :object-id="lead.id" />
</NcAppSidebarTab>
</template>
</CnObjectSidebar>

Props

PropTypeRequiredDefaultDescription
objectTypeStringEntity type identifier (e.g. 'pipelinq_lead') — used as the sidebar title fallback
objectIdStringObject UUID passed to all tab components
registerString''OpenRegister register ID
schemaString''OpenRegister schema ID
hiddenTabsArray[]Tab IDs to hide: 'files', 'notes', 'tags', 'tasks', 'auditTrail'
openBooleantrueWhether the sidebar is visible
titleString''Sidebar title (defaults to objectType)
subtitleString''Sidebar subtitle
subtitlePropString''Deprecated — use subtitle instead
apiBaseString'/apps/openregister/api'Base URL for OpenRegister API calls
filesLabelString'Files'Files tab label
notesLabelString'Notes'Notes tab label
tagsLabelString'Tags'Tags tab label
tasksLabelString'Tasks'Tasks tab label
auditTrailLabelString'Audit Trail'Audit Trail tab label
tabsArraynullOpen-enum tab definitions [\{ id, label, icon?, widgets?, component?, order? \}]. When set with at least one entry, REPLACES the hard-coded built-in tab set. See Custom tabs below.
customComponentsObjectnullCustom-component registry for tab component names and unknown widget type values. Falls back to the injected cnCustomComponents from a CnAppRoot ancestor.

Events

EventPayloadDescription
update:openbooleanEmitted when the sidebar is closed; use with .sync

Slots

SlotScopeDescription
tab-files{ objectId, objectType }Override the Files tab content
tab-notes{ objectId, objectType }Override the Notes tab content
tab-tags{ objectId, objectType }Override the Tags tab content
tab-tasks{ objectId, objectType }Override the Tasks tab content
tab-audit-trail{ objectId, objectType }Override the Audit Trail tab content
extra-tabsAdditional NcAppSidebarTab elements appended after the built-in tabs

Custom tabs

The tabs prop opens up the closed-enum tab set so apps can drive CnObjectSidebar directly from manifest.json (pages[].config.sidebarProps.tabs). When tabs is set with at least one entry, the built-in tabs (Files / Notes / Tags / Tasks / Audit Trail) do NOT render — the consumer-supplied array drives the UI.

<CnObjectSidebar
object-type="decision"
:object-id="decisionId"
:tabs="[
{ id: 'overview', label: 'Overview', icon: 'eye',
widgets: [
{ type: 'data', props: { schema, objectData } },
{ type: 'metadata', props: { objectData } },
] },
{ id: 'related', label: 'Related', icon: 'link',
component: 'MyRelatedTab' },
]"
:custom-components="{ MyRelatedTab }" />

Tab definition shape

FieldTypeNotes
idStringRequired. Unique within the array; used for active-tab tracking.
labelStringRequired. Display label (i18n key already resolved by the consumer).
iconStringOptional MDI icon name; rendered via CnIcon.
widgetsArrayOptional. List of \{ type, props? \} widget specs (see below).
componentStringOptional. Registry name resolved against customComponents. Mutually exclusive with widgets — when both are set, component wins and a console.warn is logged.
orderNumberOptional. Defaults to array index + 1.

Built-in widget types

Widget typeResolved componentRequired props
dataCnObjectDataWidgetschema, objectData (forward via per-widget props)
metadataCnObjectMetadataWidgetobjectData

Any other type value resolves against the customComponents registry — the explicit customComponents prop wins over the injected cnCustomComponents (mirroring CnPageRenderer's pattern).

Shared object context

Every widget and component mounted inside a custom tab receives the parent CnObjectSidebar's objectId / objectType / register / schema / apiBase as default props (matching the context the built-in tabs receive). Per-widget props win on conflict, so a tab can override objectData, apiBase, etc. without losing the rest of the context.

Backwards compatibility

Apps satisfied with the default tab set make NO changes — leave tabs unset and the hard-coded built-in tabs render exactly as today, including the #tab-files / #tab-notes / #tab-tags / #tab-tasks / #tab-audit-trail / #extra-tabs slot overrides. The tabs prop is purely additive.

Live updates (collaborative editing)

CnObjectSidebar auto-subscribes to live updates for the active object when both objectStore and (objectType + objectId) are provided. This wires useObjectSubscription into the sidebar lifecycle so the cached object stays fresh as remote users edit, and downstream tabs (CnObjectDataWidget, CnAuditTrailTab, etc.) re-render reactively without polling.

PropDefaultBehaviour
subscribetrueWhen false, skips the auto-subscribe (useful for read-only / archive surfaces).
objectStorenullPinia store instance. When omitted, the auto-subscribe is skipped.

The locked-banner UX lives on CnDetailPage for v1 — sidebars host so many editor surfaces (each tab) that the banner would compete with tab content. Consumers needing lock UX inside a sidebar tab should consume useObjectLock directly inside the tab component.

Reference (auto-generated)

The tables below are generated from the SFC source via vue-docgen-cli. They reflect what's actually in CnObjectSidebar.vue and update automatically whenever the component changes.

Props

| Name | Type | Required | Default | Description | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | objectType | string | ✓ | — | The entity type (e.g., "pipelinq_lead", "procest_case") | | objectId | string | ✓ | — | The object UUID | | register | string | | '' | OpenRegister register ID | | schema | string | | '' | OpenRegister schema ID | | hiddenTabs | array | | [] | Array of tab IDs to hide: 'files', 'notes', 'tags', 'tasks', 'auditTrail' | | open | boolean | | true | Whether the sidebar is open | | title | string | | '' | Sidebar title (defaults to objectType) | | subtitle | string | | '' | Sidebar subtitle | | subtitleProp | string | | '' | | | apiBase | string | | '/apps/openregister/api' | Base API URL for OpenRegister | | subscribe | boolean | | true | Whether to auto-subscribe to live updates for the current object. Defaults to true. The sidebar calls objectStore.subscribe(objectType, objectId) on mount and unsubscribes on unmount via tryOnScopeDispose. | | objectStore | union | | null | Optional explicit Pinia store instance. When omitted, the sidebar skips auto-subscribe (Pinia not yet active in the consumer context). | | filesLabel | string | | () =&gt; t('nextcloud-vue', 'Files') | | | notesLabel | string | | () =&gt; t('nextcloud-vue', 'Notes') | | | tagsLabel | string | | () =&gt; t('nextcloud-vue', 'Tags') | | | tasksLabel | string | | () =&gt; t('nextcloud-vue', 'Tasks') | | | auditTrailLabel | string | | () =&gt; t('nextcloud-vue', 'Audit trail') | | | tabs | Array<{ id: string, label: string, icon?: string, widgets?: Array<{ type: string, props?: object }>, component?: string, order?: number }> | null | | null | Open-enum tab definitions. When provided with at least one entry, REPLACES the hard-coded built-in tabs (Files, Notes, Tags, Tasks, Audit Trail). When unset (the default), the built-in tabs render as today. Each entry shape: - id (string, required) — unique tab id, used for active-tab tracking. - label (string, required) — tab display label (caller-resolved i18n). - icon (string, optional) — MDI icon name resolved via CnIcon. - widgets (array, optional) — list of widget specs { type, props? } to render inside the tab. Built-in types: data → CnObjectDataWidget, metadata → CnObjectMetadataWidget. Any other type resolves against the customComponents registry. - component (string, optional) — name resolved against the customComponents registry. Mutually exclusive with widgets (when both are set, component wins and a console.warn is logged). - order (number, optional) — explicit order; defaults to array index + 1. | | customComponents | union | | null | Custom-component registry. Keys are names referenced by tabs[].component and unknown tabs[].widgets[].type values. Falls back to the injected cnCustomComponents from a CnAppRoot ancestor when omitted. |

Events

NamePayloadDescription
update:open

Slots

NameBindingsDescription
tab-filesobject-id, object-type
tab-notesobject-id, object-type
tab-tagsobject-id, object-type
tab-tasksobject-id, object-type
tab-audit-trailobject-id, object-type
extra-tabs