From 1db21d1b00964362ff5c98c45bc44568a9a61706 Mon Sep 17 00:00:00 2001 From: J-Michalek <71264422+J-Michalek@users.noreply.github.com> Date: Mon, 14 Jul 2025 10:56:28 +0200 Subject: [PATCH] feat(Table): add `style` to table and column `meta` (#4513) Co-authored-by: Benjamin Canac --- docs/content/3.components/table.md | 5 + src/runtime/components/Table.vue | 10 + test/components/Table.spec.ts | 10 +- .../__snapshots__/Table-vue.spec.ts.snap | 272 ++++++++++++++++++ .../__snapshots__/Table.spec.ts.snap | 272 ++++++++++++++++++ 5 files changed, 565 insertions(+), 4 deletions(-) diff --git a/docs/content/3.components/table.md b/docs/content/3.components/table.md index d2bb5659..8db8850b 100644 --- a/docs/content/3.components/table.md +++ b/docs/content/3.components/table.md @@ -83,6 +83,9 @@ Use the `columns` prop as an array of [ColumnDef](https://tanstack.com/table/lat - `class`: - `td`: [The classes to apply to the `td` element.]{class="text-muted"} - `th`: [The classes to apply to the `th` element.]{class="text-muted"} + - `style`: + - `td`: [The style to apply to the `td` element.]{class="text-muted"} + - `th`: [The style to apply to the `th` element.]{class="text-muted"} In order to render components or other HTML elements, you will need to use the Vue [`h` function](https://vuejs.org/api/render-function.html#h) inside the `header` and `cell` props. This is different from other components that use slots but allows for more flexibility. @@ -112,6 +115,8 @@ Use the `meta` prop as an object ([TableMeta](https://tanstack.com/table/latest/ - `class`: - `tr`: [The classes to apply to the `tr` element.]{class="text-muted"} +- `style`: + - `tr`: [The style to apply to the `tr` element.]{class="text-muted"} ### Loading diff --git a/src/runtime/components/Table.vue b/src/runtime/components/Table.vue index 88871cb1..082a9878 100644 --- a/src/runtime/components/Table.vue +++ b/src/runtime/components/Table.vue @@ -45,12 +45,19 @@ declare module '@tanstack/table-core' { th?: string | ((cell: Header) => string) td?: string | ((cell: Cell) => string) } + style?: { + th?: string | Record | ((cell: Header) => string | Record) + td?: string | Record | ((cell: Cell) => string | Record) + } } interface TableMeta { class?: { tr?: string | ((row: Row) => string) } + style?: { + tr?: string | Record | ((row: Row) => string | Record) + } } } @@ -432,6 +439,7 @@ defineExpose({ typeof tableApi.options.meta?.class?.tr === 'function' ? tableApi.options.meta.class.tr(row) : tableApi.options.meta?.class?.tr ] })" + :style="typeof tableApi.options.meta?.style?.tr === 'function' ? tableApi.options.meta?.style?.tr(row) : tableApi.options.meta?.style?.tr" @click="onRowSelect($event, row)" @pointerenter="onRowHover($event, row)" @pointerleave="onRowHover($event, null)" @@ -448,6 +456,7 @@ defineExpose({ ], pinned: !!cell.column.getIsPinned() })" + :style="typeof cell.column.columnDef.meta?.style?.td === 'function' ? cell.column.columnDef.meta.style.td(cell) : cell.column.columnDef.meta?.style?.td" > @@ -495,6 +504,7 @@ defineExpose({ ], pinned: !!header.column.getIsPinned() })" + :style="typeof header.column.columnDef.meta?.style?.th === 'function' ? header.column.columnDef.meta.style.th(header) : header.column.columnDef.meta?.style?.th" > diff --git a/test/components/Table.spec.ts b/test/components/Table.spec.ts index a0590c76..ad044bfd 100644 --- a/test/components/Table.spec.ts +++ b/test/components/Table.spec.ts @@ -165,6 +165,8 @@ describe('Table', () => { ['with loading', { props: { ...props, loading: true } }], ...loadingColors.map((loadingColor: string) => [`with loading color ${loadingColor}`, { props: { ...props, loading: true, loadingColor } }]), ...loadingAnimations.map((loadingAnimation: string) => [`with loading animation ${loadingAnimation}`, { props: { ...props, loading: true, loadingAnimation } }]), + ['with meta prop', { props: { ...props, meta: { class: { tr: 'custom-row-class' }, style: { tr: { backgroundColor: 'lightgray' } } } } }], + ['with meta field on columns', { props: { ...props, columns: columns.map(c => ({ ...c, meta: { class: { th: 'custom-heading-class', td: 'custom-cell-class' }, style: { th: { backgroundColor: 'black' }, td: { backgroundColor: 'lightgray' } } } })) } }], ['with as', { props: { ...props, as: 'section' } }], ['with class', { props: { ...props, class: 'absolute' } }], ['with ui', { props: { ...props, ui: { base: 'table-auto' } } }], @@ -194,10 +196,10 @@ describe('Table', () => { }, ...(filter.value === 2 ? [ - { - accessorKey: 'amount', - header: () => h('div', { ['data-test-th']: 'amount' }, 'Amount') - } satisfies TableColumn + { + accessorKey: 'amount', + header: () => h('div', { ['data-test-th']: 'amount' }, 'Amount') + } satisfies TableColumn ] : []) ]) diff --git a/test/components/__snapshots__/Table-vue.spec.ts.snap b/test/components/__snapshots__/Table-vue.spec.ts.snap index cbff99fa..9bdde910 100644 --- a/test/components/__snapshots__/Table-vue.spec.ts.snap +++ b/test/components/__snapshots__/Table-vue.spec.ts.snap @@ -1574,6 +1574,278 @@ exports[`Table > renders with loading slot correctly 1`] = ` " `; +exports[`Table > renders with meta field on columns correctly 1`] = ` +"
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
#DateStatus +
Amount
+
+ +
+
+
+ +
+
#m5gr84i9Invalid Datesuccess +
ken99@yahoo.com
+
+
€316.00
+
+
+ + + +
+
+
+
+ +
+
#3u1reuv4Invalid Datesuccess +
Abe45@gmail.com
+
+
€242.00
+
+
+ + + +
+
+
+
+ +
+
#derv1ws0Invalid Dateprocessing +
Monserrat44@gmail.com
+
+
€837.00
+
+
+ + + +
+
+
+
+ +
+
#5kma53aeInvalid Datesuccess +
Silas22@gmail.com
+
+
€874.00
+
+
+ + + +
+
+
+
+ +
+
#bhqecj4pInvalid Datefailed +
carmella@hotmail.com
+
+
€721.00
+
+
+ + + +
+
+ + + + + + + + + + +
Total: €2,990.00
+
+ +
+
" +`; + +exports[`Table > renders with meta prop correctly 1`] = ` +"
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IdAmountStatusEmail
m5gr84i9316successken99@yahoo.com
3u1reuv4242successAbe45@gmail.com
derv1ws0837processingMonserrat44@gmail.com
5kma53ae874successSilas22@gmail.com
bhqecj4p721failedcarmella@hotmail.com
+
" +`; + exports[`Table > renders with sticky correctly 1`] = ` "
diff --git a/test/components/__snapshots__/Table.spec.ts.snap b/test/components/__snapshots__/Table.spec.ts.snap index ee61ab7a..4c421f18 100644 --- a/test/components/__snapshots__/Table.spec.ts.snap +++ b/test/components/__snapshots__/Table.spec.ts.snap @@ -1574,6 +1574,278 @@ exports[`Table > renders with loading slot correctly 1`] = ` " `; +exports[`Table > renders with meta field on columns correctly 1`] = ` +"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
#DateStatus +
Amount
+
+ +
+
+
+ +
+
#m5gr84i9Invalid Datesuccess +
ken99@yahoo.com
+
+
€316.00
+
+
+ + + +
+
+
+
+ +
+
#3u1reuv4Invalid Datesuccess +
Abe45@gmail.com
+
+
€242.00
+
+
+ + + +
+
+
+
+ +
+
#derv1ws0Invalid Dateprocessing +
Monserrat44@gmail.com
+
+
€837.00
+
+
+ + + +
+
+
+
+ +
+
#5kma53aeInvalid Datesuccess +
Silas22@gmail.com
+
+
€874.00
+
+
+ + + +
+
+
+
+ +
+
#bhqecj4pInvalid Datefailed +
carmella@hotmail.com
+
+
€721.00
+
+
+ + + +
+
+ + + + + + + + + + +
Total: €2,990.00
+
+ +
+
" +`; + +exports[`Table > renders with meta prop correctly 1`] = ` +"
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IdAmountStatusEmail
m5gr84i9316successken99@yahoo.com
3u1reuv4242successAbe45@gmail.com
derv1ws0837processingMonserrat44@gmail.com
5kma53ae874successSilas22@gmail.com
bhqecj4p721failedcarmella@hotmail.com
+
" +`; + exports[`Table > renders with sticky correctly 1`] = ` "