Skip to content

Commit 864d687

Browse files
committed
feat(data-table): add tableHeaderTranslateWithId prop
The `tableHeaderTranslateWithId` prop on DataTable forwards custom translations to TableHeader for aria-labels on sort icons, enabling localization.
1 parent c4eed4d commit 864d687

File tree

6 files changed

+146
-25
lines changed

6 files changed

+146
-25
lines changed

COMPONENT_INDEX.md

Lines changed: 26 additions & 25 deletions
Large diffs are not rendered by default.

docs/src/COMPONENT_API.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3428,6 +3428,18 @@
34283428
"isRequired": false,
34293429
"constant": false,
34303430
"reactive": false
3431+
},
3432+
{
3433+
"name": "tableHeaderTranslateWithId",
3434+
"kind": "let",
3435+
"description": "Override the default table header translation ids",
3436+
"type": "(id: import(\"./TableHeader.svelte\").TableHeaderTranslationId) => string",
3437+
"value": "undefined",
3438+
"isFunction": false,
3439+
"isFunctionDeclaration": false,
3440+
"isRequired": false,
3441+
"constant": false,
3442+
"reactive": false
34313443
}
34323444
],
34333445
"moduleExports": [],

src/DataTable/DataTable.svelte

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@
181181
/** Set to `number` to set current page */
182182
export let page = 0;
183183
184+
/**
185+
* Override the default table header translation ids
186+
* @type {(id: import("./TableHeader.svelte").TableHeaderTranslationId) => string}
187+
*/
188+
export let tableHeaderTranslateWithId = undefined;
189+
184190
import { createEventDispatcher, setContext } from "svelte";
185191
import { writable } from "svelte/store";
186192
import InlineCheckbox from "../Checkbox/InlineCheckbox.svelte";
@@ -482,6 +488,9 @@
482488
sortable={sortable && header.sort !== false}
483489
sortDirection={sortKey === header.key ? sortDirection : "none"}
484490
active={sortKey === header.key}
491+
{...(tableHeaderTranslateWithId
492+
? { translateWithId: tableHeaderTranslateWithId }
493+
: {})}
485494
on:click={(e) => {
486495
dispatch("click", { header });
487496

tests/DataTable/DataTable.test.svelte

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@
7070
export let expandedRowIds: string[] = [];
7171
export let pageSize = 0;
7272
export let page = 0;
73+
export let tableHeaderTranslateWithId: ((id: string) => string) | undefined =
74+
undefined;
7375
</script>
7476

7577
<DataTable
@@ -93,6 +95,7 @@
9395
{expandedRowIds}
9496
{pageSize}
9597
{page}
98+
{tableHeaderTranslateWithId}
9699
on:click={(e) => {
97100
console.log("click", e.detail);
98101
}}

tests/DataTable/DataTable.test.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,94 @@ describe("DataTable", () => {
11651165
expect(detail).toHaveProperty("row");
11661166
});
11671167

1168+
it("uses default table header translations", async () => {
1169+
render(DataTable, {
1170+
props: {
1171+
sortable: true,
1172+
headers,
1173+
rows,
1174+
},
1175+
});
1176+
1177+
const nameHeader = screen.getByText("Name");
1178+
const headerButton = nameHeader.closest("button");
1179+
assert(headerButton);
1180+
1181+
const sortIcon = headerButton.querySelector(".bx--table-sort__icon");
1182+
assert(sortIcon);
1183+
expect(sortIcon).toHaveAttribute(
1184+
"aria-label",
1185+
"Sort rows by this header in ascending order",
1186+
);
1187+
});
1188+
1189+
it("applies custom table header translations", async () => {
1190+
const customTranslator = (id: string) => {
1191+
const translations: Record<string, string> = {
1192+
columnSortAscending: "Trier par ordre croissant",
1193+
columnSortDescending: "Trier par ordre décroissant",
1194+
};
1195+
return translations[id] || id;
1196+
};
1197+
1198+
render(DataTable, {
1199+
props: {
1200+
sortable: true,
1201+
headers,
1202+
rows,
1203+
tableHeaderTranslateWithId: customTranslator,
1204+
},
1205+
});
1206+
1207+
const nameHeader = screen.getByText("Name");
1208+
const headerButton = nameHeader.closest("button");
1209+
assert(headerButton);
1210+
1211+
const sortIcon = headerButton.querySelector(".bx--table-sort__icon");
1212+
assert(sortIcon);
1213+
expect(sortIcon).toHaveAttribute("aria-label", "Trier par ordre croissant");
1214+
1215+
await user.click(nameHeader);
1216+
expect(sortIcon).toHaveAttribute(
1217+
"aria-label",
1218+
"Trier par ordre décroissant",
1219+
);
1220+
});
1221+
1222+
it("updates aria-label based on sort state", async () => {
1223+
render(DataTable, {
1224+
props: {
1225+
sortable: true,
1226+
headers,
1227+
rows,
1228+
},
1229+
});
1230+
1231+
const nameHeader = screen.getByText("Name");
1232+
const headerButton = nameHeader.closest("button");
1233+
assert(headerButton);
1234+
1235+
const sortIcon = headerButton.querySelector(".bx--table-sort__icon");
1236+
assert(sortIcon);
1237+
1238+
expect(sortIcon).toHaveAttribute(
1239+
"aria-label",
1240+
"Sort rows by this header in ascending order",
1241+
);
1242+
1243+
await user.click(nameHeader);
1244+
expect(sortIcon).toHaveAttribute(
1245+
"aria-label",
1246+
"Sort rows by this header in descending order",
1247+
);
1248+
1249+
await user.click(nameHeader);
1250+
expect(sortIcon).toHaveAttribute(
1251+
"aria-label",
1252+
"Sort rows by this header in ascending order",
1253+
);
1254+
});
1255+
11681256
// Regression test for issue https://github.com/carbon-design-system/carbon-components-svelte/issues/2344
11691257
describe("TypeScript event type definitions", () => {
11701258
it("click:row event type includes target and currentTarget", () => {

types/DataTable/DataTable.svelte.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,14 @@ type $Props<Row> = {
201201
*/
202202
page?: number;
203203

204+
/**
205+
* Override the default table header translation ids
206+
* @default undefined
207+
*/
208+
tableHeaderTranslateWithId?: (
209+
id: import("./TableHeader.svelte").TableHeaderTranslationId,
210+
) => string;
211+
204212
[key: `data-${string}`]: any;
205213
};
206214

0 commit comments

Comments
 (0)