ui icon indicating copy to clipboard operation
ui copied to clipboard

[Table] Allow to collapse a row cells vertically on a breakpoint

Open DarkGhostHunter opened this issue 2 years ago • 1 comments

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

Currently, tables work like normal HTML tables. This means that on small screens the width will mostly/always exceed the device width, leaving the user to scroll down through the results.

Describe the solution you'd like

Instead of letting the user scrolling and hide the information from other columns due to the device width, I think a good solution would be to collapse the cells vertically:

  • Headers would be kept as-is, allowing the user to scroll through the header columns.
  • The rest of the Table functionality would be kept intact.

Describe alternatives you've considered

Creating my own table with using table CSS properties is cumbersome and using HTML's <table> doesn't leave space for creativity.

Also, since it's not a Nuxt UI Table, all functionality is lost and must be made from scratch (or forked).

Additional context

The other approach is to create a new Data element called List that would work as table-like, but use <div> internally, use CSS to be presented as table-like, offer the same features (sorting, pagination, etc.) , and configure a breakpoint to transform the list into a grid.

DarkGhostHunter avatar Aug 11 '23 21:08 DarkGhostHunter

From my perspective, as a short-term "workaround," it would be good if there was a way to apply classes to the data columns directly, e.g., rowClass property, from the columns list. This would allow us to be easily be able to use media queries to hide/show/"combine" data where appropriate.

columns
{ [key: string]: any; key: string; sortable?: boolean; sort?: (a: any, b: any, direction: "asc" | "desc") => number; direction?: "asc" | "desc";
class?: string; rowClass?: string }[]

These classes would then be applied to the columns to hide/display them to improve visibility for smaller screens, as it heavily depends on the data if it can be hidden on smaller screens or combined with other columns.

const columns = [
   {
        key: 'test1',
        label: 'Big Screen',
        class: 'hidden lg:block',
        rowClass: 'hidden lg:block',
    },
   {
        key: 'test2',
        label: 'Mobile only',
        class: 'block lg:hidden',
        rowClass: 'block lg:hidden',
    },
];
<table>
  <thead>
    <tr class="hidden lg:block">
      Big Screen
    </tr>
    <tr class="block lg:hidden">
      Mobile only
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="hidden lg:block">Big Screen</td>
      <td class="block lg:hidden">Mobile only</td>
    </tr>
  </tbody>
</table>

I have used hidden lg:block, and so on to hide specific data or display it in another column as a "block of data" in tables. In the code below, I would hide/combine the dateofbirth and occupation columns into the name column in a nice-looking block like this:

            <template #name-data="{ row }">
                <div class="inline-flex items-center">
                    <UAvatar
                        :url="row.avatar"
                        alt="Avatar"
                        size="sm"
                    />

                    <span>{{ row.name }}</span>
                    <span class="lg:hidden"> ({{ row.dateofbirth }}) </span>
                </div>

                <dl class="lg:hidden">
                    <dt class="sr-only">Occupation</dt>
                    <dd class="truncate">{{ row.occupation }}</dd>
                </dl>
            </template>

Results more or less in something looking like this on smaller screens:

<td
  class="whitespace-nowrap px-1.5 py-1.5 text-gray-500 dark:text-gray-400 text-sm"
>
  <div class="inline-flex items-center gap-1">
    <span
      class="relative inline-flex items-center justify-center flex-shrink-0 bg-gray-100 dark:bg-gray-800 rounded-full h-8 w-8 text-sm"
      ><span
        class="font-medium leading-none text-gray-900 dark:text-white truncate"
        >AT</span
      ><!--v-if--></span
    ><span>Alexander T.</span><span class="lg:hidden"> (01.01.1970) </span>
  </div>
  <!--v-if-->
  <dl class="font-normal lg:hidden">
    <dt class="sr-only">Occupation</dt>
    <dd class="mt-1 truncate">IT Engineer</dd>
  </dl>
</td>

image

I can modify the rows list to add a class property, as is written in the docs, but I would prefer not to have to modify the list from the API call that I pass to the table :D ~~I haven't figured out if something like rowClass is already available that would hide the column;~~ that's why the occupation is seen after the name block in the screenshot (the table header disappears as expected though).

Any thoughts on this approach for table data?

galexrt avatar Apr 07 '24 11:04 galexrt