Skip to content

feat(files): add space header extension point#2725

Open
flash7777 wants to merge 3 commits into
opencloud-eu:mainfrom
flash7777:feat/space-header-extension-point
Open

feat(files): add space header extension point#2725
flash7777 wants to merge 3 commits into
opencloud-eu:mainfrom
flash7777:feat/space-header-extension-point

Conversation

@flash7777

Copy link
Copy Markdown

Summary

Add app.files.space-header extension point (type customComponent) that allows extensions to replace the default SpaceHeader on project space frontpages with a custom component.

Motivation

Folder view extensions (e.g. typed folder views, DMS views) need to render their own space header with domain-specific information (icons, metadata, action buttons). Currently the only option is to modify GenericSpace.vue in the core, which creates maintenance burden and tight coupling.

This extension point follows the same pattern as the existing app.files.sidebar.* and app.files.folder-views.* extension points.

Changes

File Change
extensionPoints.ts Add spaceHeaderExtensionPoint definition
GenericSpace.vue Check for registered extension; render CustomComponentTarget if present, otherwise default SpaceHeader

How extensions use it

// In an extension's setup():
extensions: computed(() => [
  {
    id: 'my-extension.space-header',
    type: 'customComponent',
    extensionPointIds: ['app.files.space-header'],
    content: markRaw(MySpaceHeaderComponent),
    componentProps: () => ({ space, resources })
  }
])

Backward compatibility

No breaking changes. When no extension registers at this point, the default SpaceHeader renders exactly as before.

Add `app.files.space-header` extension point that allows extensions
to provide a custom component in place of the default SpaceHeader
on project space frontpages.

When an extension registers at this point, its component is rendered
instead of the built-in SpaceHeader. When no extension is registered,
the default SpaceHeader is shown as before.

This enables folder view extensions to render their own space header
with domain-specific information without modifying the core.
<template v-else>
<space-header v-if="isSpaceFrontpage" :space="space" class="px-4" />
<custom-component-target
v-if="isSpaceFrontpage && hasSpaceHeaderExtension"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather make this extension point a bit more generic by removing the check on isSpaceFrontpage. This way, it would not only go for project spaces, but for all generic spaces. You can then further specify in your extension when it should be displayed.

And then maybe rather name the extension point app.files.generic-space-header.

Comment on lines +38 to +42
<space-header
v-else-if="isSpaceFrontpage"
:space="space"
class="px-4"
/>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't hide this if a generic space header extension was found. There might be extensions were you actually want both.

We don't have a final solution for this yet, but for the time being, you could hide the space header in your custom extension via CSS.

flash added 2 commits June 23, 2026 14:02
…ader

Per review feedback:
- Extension point renamed to app.files.generic-space-header
- Removed isSpaceFrontpage check — extensions decide visibility
- Default SpaceHeader always rendered (not hidden by extension)
- Extensions can hide the default SpaceHeader via CSS if needed
- CustomComponentTarget: track mounted children, show fallback slot
  when no extension renders visible content (Comment nodes skipped)
- GenericSpace: use fallback slot for SpaceHeader — only rendered
  when extension decides not to render its own header
- Ensures extension point works as passthrough: if extension renders
  nothing (v-if="false"), default SpaceHeader appears as fallback
@JammingBen

Copy link
Copy Markdown
Member

This was just missing a format and a rebase (same as your other PR #2726).

The last commit 1e3a9d0 I don't quite like. The approach will become an issue as soon as genericSpaceHeaderExtensionPoint allows multiple extensions (which I think will/should be the case in the future). Because then the fallback might get rendered multiple times.

What were you missing without that commit?

@flash7777

Copy link
Copy Markdown
Author

Thanks for the review! Let me clarify the intent here:

This extension point is specifically a replacement pattern, not an additive one. The use case is: an app provides its own complete space header, replacing the default one entirely. Showing both headers side by side doesn't make sense in this scenario — it would look broken.

The fallback mechanism handles this cleanly: if the extension renders visible content, the default header is hidden. If it doesn't (e.g. the extension decides it's not applicable), the default header shows up as normal. This is more robust than hiding the default header via CSS from the extension side.

Regarding making it more generic (removing the isSpaceFrontpage check): I'm open to that. The extension point name already says "generic-space-header", so scoping it to all spaces rather than just frontpages makes sense. Happy to adjust if you agree on the replacement approach.

@JammingBen

Copy link
Copy Markdown
Member

This extension point is specifically a replacement pattern, not an additive one. The use case is: an app provides its own complete space header, replacing the default one entirely. Showing both headers side by side doesn't make sense in this scenario — it would look broken.

I get your intention, still, development for the extension system always needs a broader view on the ecosystem. The current implementation is good for your use case, when there is exactly extension on that extension point. But it won't work for multiple extensions (e.g. another app wants to display additional content, not replace it). Hence I'd prefer build it in a more generic way that satisfies both use cases.

The only thing missing for you would be a way to hide the existing space header. Doing this via CSS feels quite brittle, I agree. Another, cleaner approach would be to first register the existing space header on the new extension point (this should be done anyways), then, in your app, disable or unregister it via its id.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants