diff --git a/docs/components/content/examples/TableExampleClickable.vue b/docs/components/content/examples/TableExampleClickable.vue new file mode 100644 index 00000000..dad99468 --- /dev/null +++ b/docs/components/content/examples/TableExampleClickable.vue @@ -0,0 +1,54 @@ + + + diff --git a/docs/content/4.data/1.table.md b/docs/content/4.data/1.table.md index 68e97f9a..b7ea61bf 100644 --- a/docs/content/4.data/1.table.md +++ b/docs/content/4.data/1.table.md @@ -327,6 +327,44 @@ const selected = ref([people[1]]) You can use the `by` prop to compare objects by a field instead of comparing object instances. We've replicated the behavior of Headless UI [Combobox](https://headlessui.com/vue/combobox#binding-objects-as-values). :: +### Clickable + +Add a `select` listener on your Table to make the rows clickable. The function will receive the row as the first argument. + +You can use this to navigate to a page, open a modal or even to select the row manually. + +::component-example{class="grid"} +--- +padding: false +overflowClass: 'overflow-x-auto' +--- + +#default +:table-example-clickable{class="flex-1"} + +#code +```vue + + + +``` +:: + ### Searchable You can easily use the [Input](/forms/input) component to filter the rows. diff --git a/src/runtime/app.config.ts b/src/runtime/app.config.ts index 30654233..4aac4c6a 100644 --- a/src/runtime/app.config.ts +++ b/src/runtime/app.config.ts @@ -8,7 +8,8 @@ const table = { tbody: 'divide-y divide-gray-200 dark:divide-gray-800', tr: { base: '', - selected: 'bg-gray-50 dark:bg-gray-800/50' + selected: 'bg-gray-50 dark:bg-gray-800/50', + active: 'hover:bg-gray-50 dark:hover:bg-gray-800/50 cursor-pointer' }, th: { base: 'text-left rtl:text-right', diff --git a/src/runtime/components/data/Table.vue b/src/runtime/components/data/Table.vue index 1b5153cc..7acb1581 100644 --- a/src/runtime/components/data/Table.vue +++ b/src/runtime/components/data/Table.vue @@ -22,9 +22,9 @@ - + - + @@ -69,6 +69,7 @@ import { ref, computed, defineComponent, toRaw } from 'vue' import type { PropType } from 'vue' import { capitalize, orderBy } from 'lodash-es' import { defu } from 'defu' +import { omit } from 'lodash-es' import type { Button } from '../../types/button' import { useAppConfig } from '#imports' // TODO: Remove @@ -92,7 +93,7 @@ export default defineComponent({ default: () => defaultComparator }, rows: { - type: Array as PropType<{ [key: string]: any }[]>, + type: Array as PropType<{ [key: string]: any, click?: Function }[]>, default: () => [] }, columns: { @@ -137,13 +138,13 @@ export default defineComponent({ } }, emits: ['update:modelValue'], - setup (props, { emit }) { + setup (props, { emit, attrs }) { // TODO: Remove const appConfig = useAppConfig() const ui = computed>(() => defu({}, props.ui, appConfig.ui.table)) - const columns = computed(() => props.columns ?? Object.keys(props.rows[0] ?? {}).map((key) => ({ key, label: capitalize(key), sortable: false }))) + const columns = computed(() => props.columns ?? Object.keys(omit(props.rows[0] ?? {}, ['click'])).map((key) => ({ key, label: capitalize(key), sortable: false }))) const sort = ref(defu({}, props.sort, { column: null, direction: 'asc' })) @@ -200,6 +201,15 @@ export default defineComponent({ } } + function onSelect (row) { + if (!attrs.onSelect) { + return + } + + // @ts-ignore + attrs.onSelect(row) + } + return { // eslint-disable-next-line vue/no-dupe-keys ui, @@ -214,7 +224,8 @@ export default defineComponent({ // eslint-disable-next-line vue/no-dupe-keys emptyState, isSelected, - onSort + onSort, + onSelect } } })