diff --git a/docs/app/components/content/examples/table/TableResizingExample.vue b/docs/app/components/content/examples/table/TableResizingExample.vue new file mode 100644 index 0000000000..61f900413c --- /dev/null +++ b/docs/app/components/content/examples/table/TableResizingExample.vue @@ -0,0 +1,74 @@ + + + diff --git a/docs/content/3.components/table.md b/docs/content/3.components/table.md index f74e4ed357..d9b6cf162c 100644 --- a/docs/content/3.components/table.md +++ b/docs/content/3.components/table.md @@ -523,6 +523,21 @@ class: '!p-0' --- :: +### With resizable columns + +You can make the columns resizable by setting the `enableColumnResizing` prop. + +Use the `enableResizing` field on the column to allow resizing for specific columns. + +::component-example +--- +prettier: true +collapse: true +name: 'table-resizing-example' +class: '!p-0' +--- +:: + ## API ### Props diff --git a/playground/app/pages/components/table.vue b/playground/app/pages/components/table.vue index 46c3799b8b..3e80dca5c2 100644 --- a/playground/app/pages/components/table.vue +++ b/playground/app/pages/components/table.vue @@ -158,11 +158,13 @@ const columns: TableColumn[] = [{ 'aria-label': 'Select row' }), enableSorting: false, - enableHiding: false + enableHiding: false, + enableResizing: false }, { accessorKey: 'id', header: '#', - cell: ({ row }) => `#${row.getValue('id')}` + cell: ({ row }) => `#${row.getValue('id')}`, + enableResizing: false }, { accessorKey: 'date', header: 'Date', @@ -192,7 +194,8 @@ const columns: TableColumn[] = [{ })[row.getValue('status') as string] return h(UBadge, { class: 'capitalize', variant: 'subtle', color }, () => row.getValue('status')) - } + }, + maxSize: 200 }, { accessorKey: 'email', header: ({ column }) => { @@ -279,6 +282,8 @@ const pagination = ref({ pageSize: 10 }) +const resizeMode = ref<'fit' | 'expand'>('fit') + function addElement() { data.value.unshift({ id: currentID.value.toString(), @@ -318,6 +323,8 @@ onMounted(() => { + + extends TableOptions { * @link [Guide](https://tanstack.com/table/v8/docs/guide/column-faceting) */ facetedOptions?: FacetedOptions + /** + * Whether the table should fit its container's width or expand it when resizing the columns. + * + * @defaultValue 'fit' + */ + resizeMode?: 'fit' | 'expand' onSelect?: (row: TableRow, e?: Event) => void class?: any ui?: Table['slots'] @@ -192,6 +198,7 @@ import { useLocale } from '../composables/useLocale' import { tv } from '../utils/tv' const props = withDefaults(defineProps>(), { + resizeMode: 'expand', watchOptions: () => ({ deep: true }) @@ -209,7 +216,8 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.table || {}) sticky: props.sticky, loading: props.loading, loadingColor: props.loadingColor, - loadingAnimation: props.loadingAnimation + loadingAnimation: props.loadingAnimation, + resizable: props.columnSizingOptions?.enableColumnResizing })) const globalFilterState = defineModel('globalFilter', { default: undefined }) @@ -325,6 +333,34 @@ function handleRowSelect(row: TableRow, e: Event) { props.onSelect(row, e) } +const tableStyle = computed(() => { + return props.columnSizingOptions?.enableColumnResizing && props.resizeMode === 'expand' + ? { + width: `${tableApi.getTotalSize()}px` + } + : undefined +}) + +function getHeaderStyle(header: Header) { + return props.columnSizingOptions?.enableColumnResizing ? { width: `${header.getSize()}px` } : undefined +} + +function getResizeHandleStyle(header: Header) { + return { + transform: props.columnSizingOptions?.columnResizeMode === 'onEnd' + && header.column.getIsResizing() + ? `translateX(${ + (props.columnSizingOptions.columnResizeDirection + === 'rtl' + ? -1 + : 1) + * (tableApi.getState().columnSizingInfo + .deltaOffset ?? 0) + }px)` + : undefined + } +} + watch( () => props.data, () => { data.value = props.data ? [...props.data] : [] @@ -339,7 +375,11 @@ defineExpose({