Skip to content

fix(VDataTable/Headers/Header/Row): hide mobile thead when required#22791

Draft
userquin wants to merge 2 commits intomasterfrom
userquin/fix-data-table-mobile-header
Draft

fix(VDataTable/Headers/Header/Row): hide mobile thead when required#22791
userquin wants to merge 2 commits intomasterfrom
userquin/fix-data-table-mobile-header

Conversation

@userquin
Copy link
Copy Markdown
Member

@userquin userquin commented Apr 4, 2026

Description

This PR includes:

  • hide mobile table header when required: added a new computed to avoid adding the thead at VDataTable
  • mobile table header now uses a checkbox button when disableSort (and no sortable columns) and uses the append slot when sort is enabled and there is at least 1 sortable column (changed sortableColumns composable to return empty array when props.disableSort is true)
  • added 5 new entries at dataTable.ariaLabel to include labels or aria-label attributes for row checkbox selection: included in all locales (using Gemini PRO for the translations)
  • table row selection adds the label for the selection depending on its state: added 2 new computed to eval isSelected and isExpanded only once
  • added 3 new browser tests
  • update virtual and server tables: added missing slots props and updated thead logic

Still on draft, I think I forgot to add some transtation at tsx files, I'm reviewing the code: maybe I also need to change the new props at data table, header and row.

Markup:

Playground
<template>
  <v-app>
    <v-container class="pa-0" grid-list-md>
      <v-data-table
        id="id"
        v-model="model"
        :disable-sort="disableSort"
        :headers
        :hide-default-header="hideDefaultHeader"
        :items
        :mobile
        :show-select="showSelect"
        density="comfortable"
      >
        <template #top>
          <v-toolbar :class="contextVisible ? 'bg-green ps-2' : undefined" flat>
            <template v-if="contextVisible" #prepend>
              <v-btn aria-label="Delete rows" density="comfortable" flat icon>
                <v-icon icon="mdi-delete" size="small" />
              </v-btn>
            </template>
            <v-toolbar-title>
              {{ message }}
            </v-toolbar-title>
          </v-toolbar>
          <v-container class="py-0" grid-list-md>
            <v-row>
              <v-switch
                v-model="showSelect"
                :disabled="contextVisible"
                :false-value="false"
                :true-value="true"
                color="primary"
                label="Show Select"
                hide-details
              />
              <v-switch
                v-model="mobile"
                :disabled="contextVisible"
                :false-value="false"
                :true-value="true"
                color="primary"
                label="Mobile"
                hide-details
              />
              <v-switch
                v-model="disableSort"
                :disabled="contextVisible"
                :false-value="false"
                :true-value="true"
                color="primary"
                label="Disable Sort"
                hide-details
              />
            </v-row>
            <v-row
              style="--v-col-gap-y: 0;"
            >
              <v-switch
                v-model="sortable"
                :disabled="contextVisible"
                :false-value="false"
                :true-value="true"
                color="primary"
                label="Sortable Columns"
                hide-details
              />
              <v-switch
                v-model="hideDefaultHeader"
                :disabled="contextVisible"
                :false-value="false"
                :true-value="true"
                color="primary"
                label="Hide Default Header"
                hide-details
              />
            </v-row>
          </v-container>
        </template>
      </v-data-table>
    </v-container>
  </v-app>
</template>

<script setup lang="ts">
  import type { DataTableHeader } from 'vuetify'
  import { VSwitch } from '../src/components/VSwitch/VSwitch'
  import { computed, shallowRef } from 'vue'

  const showSelect = shallowRef(false)
  const mobile = shallowRef(false)
  const disableSort = shallowRef(false)
  const sortable = shallowRef(false)
  const hideDefaultHeader = shallowRef(false)
  const model = shallowRef([])

  const contextVisible = computed(() => !hideDefaultHeader.value && showSelect.value && model.value.length > 0)

  const message = computed(() => {
    return contextVisible.value ? `${model.value.length} row${model.value.length !== 1 ? 's' : ''} selected` : 'A header'
  })

  const headers = computed<DataTableHeader[]>(() => ([
    {
      title: 'Name',
      key: 'id',
      value: 'id',
      sortable: sortable.value,
    },
    {
      title: 'Two',
      key: 'value',
      value: 'value',
      sortable: sortable.value,
    },
  ]))
  const items = Array(3).fill(0).map((_, i) => ({ id: i, name: `Name ${i}`, value: Math.random() > 0.5 ? 'hello' : 'world' }))
</script>

@userquin userquin requested a review from J-Sek April 4, 2026 21:25
return [...v.values()]
})
const selectedItemsCount = computed(() => selected.value.size)
const allItemsCount = computed(() => allItems.value.length)
Copy link
Copy Markdown
Member Author

@userquin userquin Apr 4, 2026

Choose a reason for hiding this comment

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

not sure if this is fine: I need to check the strategies

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.

1 participant