Skip to content

[Meta] Contribute generic components from @conduction/nextcloud-vue for the Tables app (NcTable, NcPagination, NcTabs, …) #9126

Open

Description

@remko48

Is your feature request related to a problem? Please describe.

We as Conduction are currently working with Nextcloud on the Tables app. For that, we want to add some more components that we use ourselves from our own library @conduction/nextcloud-vue, as we discussed in Berlin. We would like to contribute them here, so that they can be reused.

The designs are based on the Nextcloud components. For example, the pagination component uses NcButton, and the tabs use Nextcloud's CSS styling and look like the tabs of the right sidebar.

Describe the solution you'd like

We'd like to contribute them as generic components, without anything Conduction-specific. Each one is ready with styleguide docs and tests.

New components:

  • NcPagination: page buttons with ellipses, page size selector, pages as links
  • NcTable: the Files app table as a component: sorting, row selection, row actions, loading and empty states
  • NcPageHeader: heading with icon, description and actions at the top of a page
  • NcStatsBlock: a single statistic for a dashboard
  • NcTabs: tabs in the app content, styled like the sidebar tabs
  • NcCard: a card for grids of items, optionally one big link
  • NcQuickFilterBar: a row of filter pills above a list
  • NcLockIndicator and NcLockedBanner: show that an item is locked, and by whom

Extensions:

  • NcChip: a small size, an info variant and a light style, for status labels
  • NcBreadcrumbs: pass the crumbs as data instead of as child components

Every component also has optional CSS custom properties based on the format of the NL Design System tokens, so government organisations can apply their own house style. They're not set by default, so nothing changes visually. They're in separate commits, so we can also move them to separate PRs.

Describe alternatives you've considered

  • NcAppSidebarTab only works in the sidebar, so there is nothing for tabs in the app content.
  • A status label is just a smaller chip, so we extended NcChip instead of adding a new component.
  • Keeping everything in our own library works for us, but not for other apps.

Additional context

We'll open one PR per component (the two lock components together), a few at a time, each linking back here. We start with NcPagination, NcTable and NcChip, together with a small fix for the styleguide: Markdown tables in the docs currently break the props tables below them, and all three PRs document their CSS variables in such a table. A second small fix, for a pending update left behind in useFormatRelativeTime, will follow later. The other components follow after that.

Some questions about this approach:

  1. Do you want these, or are there any you'd rather not have?
  2. Does one PR per component work for you?
  3. Should the NL Design System properties stay in, or go to separate PRs?
  4. Are the names okay?
  5. Do you want the NcChip and NcBreadcrumbs changes backported to stable8, or is main enough?

Activity

  1. self-assigned this
    on Oct 27, 2026
  2. added
    enhancementNew feature or request
    componentComponent discussion and/or suggestion
    discussionNeed advices, opinions or ideas on this topic
    on Oct 27, 2026
  3. ShGKme commented on Oct 27, 2026

    @ShGKme
    Contributor
    1. Does one PR per component work for you?

    Yes, 1 PR per component is the best to keep discussion isolated. And with 1 PR per component, one can be merged while another is still on discussion or blocked.

  4. ShGKme commented on Oct 27, 2026

    @ShGKme
    Contributor
    1. Do you want the NcChip and NcBreadcrumbs changes backported to stable8, or is main enough?

    Yes, currently we keep stable8 and main in sync in features and bug fixes until we stop supporting Vue 2 (hopefully very soon).

    Exceptions are bundle/tooling related changes and internal refactoring.

  5. ShGKme commented on Oct 27, 2026

    @ShGKme
    Contributor

    Should the NL Design System properties stay in, or go to separate PRs?

    In general, @nextcloud/vue should not depend on NL Design System properties.

    The question is: should components have many CSS variable params for overrides and/or customizations.

    IMO, there are 2 different cases.

    First - customization.

    For example, we have a button with 4 variants. But there is a specific place in an app where a button must have a different, custom color. Having a CSS variable param instead of deep styles overrides definitely makes sense. But keeping in mind, that then more customization options we introduce, then more we promise to maintain.

    Also, IMO we don't need a CSS variable param to override something that is already inherited CSS property. For example, to make a specific button text-transform: capitalize, we don't need a param. We can use a general CSS property that this button inherits.

    Second - theming.

    For example, --chip-error-color. Here the use-case isn't clear for me. Fonts, named (themed) colors, spacing -- all of it comes from Nextcloud Theming and should be consistent across different apps on Nextcloud instance or a page. primary color should be different on different parts of the page. An app should never have font-family: serif while entire page sans-serif and etc.

    Large amount of such params providing detailed theming fine-tuning is hard to maintain.
    We need to make sure that after refactoring or extending a component, all of them still have the same effect.

    For instance, we had several Tabs design changes (example). Between different designs meaning of "tab's background" or effect of properties change can be very different.

    With Nextcloud theming we also making sure that the colors are accessible with different theming configurations.

    Additionally, CSS variables (unlike component names, props, evens) live in a global scope.
    If we introduce --table-background-color, the name is blocked page-wise for all concurrently supported versions.

  6. ShGKme commented on Oct 27, 2026

    @ShGKme
    Contributor

    Do you want these, or are there any you'd rather not have?

    I'll respond per component below for simplicity. And the next comments will be mostly my opinion, other developers and/or designers may have different opinion.

  7. ShGKme commented on Oct 27, 2026

    @ShGKme
    Contributor

    NcPagination

    Image

    Makes sense. As with every new component, good to coordinate with @nextcloud-libraries/designers

  8. ShGKme commented on Oct 27, 2026

    @ShGKme
    Contributor

    NcTable

    Image

    This is a complex one. It makes sense. On the other hand, tables are one of the most complicated UI component when implemented with:

    • Wide extensibility and customization
    • Accessibility (really painful in tables)
    • Performance, virtual scrolling support
    • Features beyond UI - data-processing like sorting, filters, pagination

    I'd say, let's see if we can split it into more generic UI components and more powerful data tables.

  9. ShGKme commented on Oct 27, 2026

    @ShGKme
    Contributor

    NcPageHeader

    Image

    Currently I don't see how it can be applied in apps with this design.

    It might makes sense to have something like NcAppHeader, which would be inline with navigation and sidebar, preserve space for toggle buttons etc. But the NcPageHeader doesn't fit it.

  10. ShGKme commented on Oct 27, 2026

    @ShGKme
    Contributor

    NcStatsBlock

    Image

    I'm unsure it is something useful for general apps and would ask for @nextcloud-libraries/designers opinion.

  11. ShGKme commented on Oct 27, 2026

    @ShGKme
    Contributor

    NcTabs

    Definitely a missing component.

    Though it isn't as complicated as tables, I'd still see if we can split it into a base component and more specific component (that we already have for NcAppSidebar tabs internally).

    NcTabs sounds very generic, and it would be unfortune if it only supports sidebar style tabs, and we need a new component that will be more generic but with more complex name.

  12. ShGKme commented on Oct 27, 2026

    @ShGKme
    Contributor

    NcCard

    I think, it makes sense as a generic UI container, like a paper/pane. A purely UI block with title, content, maybe actions. But in https://nextcloud-vue.conduction.nl/docs/components/cn-card/ it is not very generic:

    • Has stats props that are very specific for stats cards, not a generic container
    • prop-driven

    I'd consider splitting it into a pure generic container and more specific Conduction app component which is Conduction data driven with additional props and modes like stats.

  13. ShGKme commented on Oct 27, 2026

    @ShGKme
    Contributor

    NcQuickFilterBar

    Image

    It is a data-driven form generator, but specifically for search.
    I'm unsure it makes sense before we have designed generated forms.

  14. ShGKme commented on Oct 27, 2026

    @ShGKme
    Contributor

    NcBreadcrumbs: pass the crumbs as data instead of as child components

    In my opinion - yes, but the best to coordinate with the Files team (cc @skjnldsv @susnux)

  15. remko48 commented on Oct 27, 2026

    @remko48
    Author

    Alright thanks!
    I will respond tomorrow with more detail.
    The short answer is that we will remove the CSS variables (NL Design System) from all PRs.

  16. pinned this issue on Oct 27, 2026
  17. unpinned this issue on Oct 27, 2026
  18. susnux commented on Oct 27, 2026

    @susnux
    Contributor

    NcBreadcrumbs: pass the crumbs as data instead of as child components

    Agree!

  19. remko48 commented on Oct 29, 2026

    @remko48
    Author

    Backport to stable8

    We will make sure that we backport the NcChip and NcBreadcrumbs changes to stable8. Should the new components be backported as well, or not?

    CSS variables

    I have removed all the CSS variables from #9127, #9128 and #9129. These were meant for theming, but are now removed so the components only use the Nextcloud styling.

    NcPagination (#9127)

    Alright, thanks! We will wait for the designers' input.

    NcTable (#9128)

    For a better picture of what is in the PR: NcTable only displays the rows it gets. It doesn't sort, filter, paginate or load data itself. A sortable header only emits which column was clicked, so the app can sort or fetch the rows itself to pass them back to the table. It also renders every row it gets, so there is no virtual scrolling.

    What it does:

    • Rendering: columns with width, align and an optional description, cell-<key> slots, a rowActions column, loading and empty states, and a required (hidden) caption
    • Sorting UI: sortable headers are buttons with aria-sort, bound with v-model:sort
    • Selection: checkboxes with select-all and an indeterminate state, bound with v-model:selected; each checkbox is labelled with the name of its row
    • Row click: a rowClick event for mouse users that ignores clicks on controls and text selections
    • Horizontal scroll: the table only becomes a keyboard stop when it actually overflows

    If you think this is too much for one component, we could:

    1. Remove the selection and row click from this PR
    2. Split it into building blocks, the same way NcRadioGroup / NcRadioGroupButton share their state. NcTable keeps the caption, scroll, styling and the sort and selection state, and the app writes its own rows and cells.

    Which do you prefer?

    NcPageHeader

    We had added the NcPageHeader component, but after some further research we found that the Tables app does not actually use it. So we suggest not opening a PR for it, unless you would like a component for an app header.

    Image

    NcStatsBlock

    Thanks, we will wait for the designers' opinion.

    Image

    NcTabs

    Agreed. The name NcTabs should then go to the generic base, and the sidebar style becomes one of its variants, so we don't end up needing a new component with a longer name later.

    Our NcTabs only has one style at the moment: the sidebar style, with an icon above the label and an optional counter, the same as the NcAppSidebar tabs.
    Image

    In our apps we also use two other tab styles, which are now built separately in the apps themselves:

    • Text-only underline tabs, for example in the BuildIQ store
    Image
    • Pills, for switching between versions or views (mock with only Nextcloud variables)
    Image

    We would suggest one NcTabs base that handles the tablist behaviour (v-model, arrow keys, roving tabindex, aria-controls, etc.) with a variant prop for these three styles, and NcAppSidebar could then use it internally with the sidebar variant. The alternative is a base component with separate styled components on top of it.

    Would you prefer a variant prop, or separate components?

    NcCard

    Image Image

    The CnCard in our docs is our own component with stats. The NcCard we want to contribute is already a generic container without stats: a title, a description, an optional icon, a slot for the content, actions and a footer, and optionally one big link.

    NcQuickFilterBar

    Image

    Makes sense, we will wait until generated forms are designed.

    NcBreadcrumbs

    Great, then we will make the PR soon.

    NcLockedBanner and NcLockIndicator

    You didn't mention these yet. Do you have an opinion on them?

    Image Image
  20. Antreesy commented on Oct 30, 2026

    @Antreesy
    Contributor

    NcLockedBanner and NcLockIndicator
    You didn't mention these yet. Do you have an opinion on them?

    First one is almost identical to NcNoteCard, apart from missing 'locked/grey' theme variant, and dedicated actions slot. Maybe we can extend the existing component instead?

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

Metadata

Metadata

Assignees

Labels

componentComponent discussion and/or suggestiondiscussionNeed advices, opinions or ideas on this topicenhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions