Skip to content

Commit 179d5be

Browse files
authored
Merge pull request #1072 from Trendyol/feat/table-no-data
feat(table): add table no data content area
2 parents 472576f + 9a5aa39 commit 179d5be

File tree

10 files changed

+227
-8
lines changed

10 files changed

+227
-8
lines changed

src/components/table/bl-table.stories.mdx

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,37 @@ export const TableWithPaginationTemplate = (args, {id}) => {
129129
`;
130130
}
131131

132+
export const NoDataTableTemplate = (args) => {
133+
const { headers, noDataContent } = args;
134+
135+
return html`
136+
<div style="height: 400px;">
137+
<bl-table>
138+
<bl-table-header sticky>
139+
<bl-table-row>
140+
${headers.map((header) =>
141+
html`<bl-table-header-cell
142+
style="${header.width ? '--bl-table-header-cell-width: ' + header.width + ';' : ''} ${header.minWidth ? '--bl-table-header-cell-min-width: ' + header.minWidth + ';' : ''}"
143+
?sortable="${header.sortable || false}"
144+
sort-key="${header.sortKey || ''}"
145+
>
146+
${header.text}
147+
</bl-table-header-cell>`
148+
)}
149+
</bl-table-row>
150+
</bl-table-header>
151+
<bl-table-body>
152+
${noDataContent ? html`
153+
<div slot="no-data">
154+
${noDataContent}
155+
</div>
156+
` : ''}
157+
</bl-table-body>
158+
</bl-table>
159+
</div>
160+
`;
161+
}
162+
132163
# Table Component
133164

134165
<bl-badge icon="check_fill">RTL Supported</bl-badge>
@@ -655,6 +686,55 @@ To enable pagination on the table, use the `bl-pagination` component. The `@bl-c
655686
</Story>
656687
</Canvas>
657688

689+
# No Data Slot
690+
691+
When there are no rows in the table, you can display custom content using the "no-data" slot. This slot appears automatically when no `bl-table-row` elements are present in the table body. If no custom slot is provided, a default no-data message will be displayed.
692+
693+
export const EmptyTableTemplate = (args) => html`
694+
<div style="height: 400px;">
695+
<bl-table>
696+
<bl-table-header sticky>
697+
<bl-table-row>
698+
<bl-table-header-cell>ID</bl-table-header-cell>
699+
<bl-table-header-cell>Name</bl-table-header-cell>
700+
<bl-table-header-cell>Email</bl-table-header-cell>
701+
<bl-table-header-cell>Status</bl-table-header-cell>
702+
</bl-table-row>
703+
</bl-table-header>
704+
<bl-table-body>
705+
${args.showNoDataSlot ? html`
706+
<div slot="no-data">
707+
<div style="display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 200px;">
708+
<bl-icon name="archive" style="font-size: 32px; margin-bottom: var(--bl-size-l); color: var(--bl-color-primary);"></bl-icon>
709+
<p style="margin: 0; font: var(--bl-font-title-2-medium); color: var(--bl-color-neutral-darker);">Custom Empty State</p>
710+
<p style="margin: var(--bl-size-xs) 0 0 0; font: var(--bl-font-body-text-2); color: var(--bl-color-neutral-light);">This is a custom no-data slot implementation.</p>
711+
<bl-button style="margin-top: var(--bl-size-l);">
712+
Add New Item
713+
</bl-button>
714+
</div>
715+
</div>
716+
` : ''}
717+
</bl-table-body>
718+
</bl-table>
719+
</div>
720+
`;
721+
722+
<Canvas>
723+
<Story name="Table with No Data Slot" args={{ showNoDataSlot: true }}>
724+
{EmptyTableTemplate.bind({})}
725+
</Story>
726+
</Canvas>
727+
728+
## Empty Table Without No Data Slot
729+
730+
If no "no-data" slot is provided, the table displays a default no-data message with a standard design.
731+
732+
<Canvas>
733+
<Story name="Empty Table Without Slot" args={{ showNoDataSlot: false }}>
734+
{EmptyTableTemplate.bind({})}
735+
</Story>
736+
</Canvas>
737+
658738
# RTL Support
659739

660740
The table component supports RTL (Right-to-Left) text direction. You can enable RTL mode by setting the `dir` attribute on a parent element or the `html` tag.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,49 @@
11
:host {
22
display: table-row-group;
33
}
4+
5+
.no-data-row {
6+
display: table-row;
7+
}
8+
9+
.no-data-cell {
10+
display: table-cell;
11+
padding: var(--bl-size-2xl);
12+
text-align: center;
13+
vertical-align: middle;
14+
background-color: var(--bl-color-neutral-full);
15+
width: 100%;
16+
min-height: 250px;
17+
position: relative;
18+
}
19+
20+
.no-data-cell ::slotted(*) {
21+
display: block;
22+
width: 100%;
23+
}
24+
25+
.default-no-data {
26+
display: flex;
27+
flex-direction: column;
28+
align-items: center;
29+
justify-content: center;
30+
min-height: 200px;
31+
}
32+
33+
.default-no-data bl-icon {
34+
font-size: 48px;
35+
margin-bottom: var(--bl-size-m);
36+
color: var(--bl-color-neutral-light);
37+
}
38+
39+
.default-no-data .title {
40+
margin: 0;
41+
font: var(--bl-font-title-2-regular);
42+
color: var(--bl-color-neutral-darker);
43+
}
44+
45+
.default-no-data .subtitle {
46+
margin: var(--bl-size-xs) 0 0 0;
47+
font: var(--bl-font-body-text-2);
48+
color: var(--bl-color-neutral-light);
49+
}

src/components/table/table-body/bl-table-body.test.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,35 @@ describe("bl-table-body", () => {
1010
expect(el).instanceOf(BlTableBody);
1111
});
1212

13-
it("should be rendered with default values", async () => {
13+
it("should render simple slot when table rows exist", async () => {
14+
//when
15+
const el = await fixture<BlTableBody>(html`
16+
<bl-table-body>
17+
<bl-table-row></bl-table-row>
18+
</bl-table-body>
19+
`);
20+
21+
//then
22+
expect(el).shadowDom.equal("<slot></slot>");
23+
});
24+
25+
it("should render no-data view when no table rows exist", async () => {
1426
//when
1527
const el = await fixture<BlTableBody>(html`<bl-table-body></bl-table-body>`);
1628

1729
//then
18-
expect(el).shadowDom.equal(
19-
"<slot></slot>"
20-
);
30+
expect(el).shadowDom.equal(`
31+
<tr class="no-data-row">
32+
<td class="no-data-cell" colspan="999">
33+
<slot name="no-data">
34+
<div class="default-no-data">
35+
<bl-icon name="info"></bl-icon>
36+
<p class="title">No data available</p>
37+
<p class="subtitle">There are currently no records to display.</p>
38+
</div>
39+
</slot>
40+
</td>
41+
</tr>
42+
`);
2143
});
2244
});

src/components/table/table-body/bl-table-body.ts

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,66 @@
11
import { html, LitElement, TemplateResult } from "lit";
22
import { customElement } from "lit/decorators.js";
33
import { CSSResultGroup } from "lit/development";
4-
import "element-internals-polyfill";
5-
import { blTableTag } from "../bl-table";
4+
import { msg } from "@lit/localize";
5+
import "../../icon/bl-icon";
66
import type BlTable from "../bl-table";
7+
import { blTableTag } from "../bl-table";
78
import style from "../table-body/bl-table-body.css";
89

910
export const blTableBodyTag = "bl-table-body";
1011

1112
/**
1213
* @tag bl-table-body
1314
* @summary Baklava Table component
15+
*
16+
* @slot no-data - Content to display when no data is available
1417
*/
1518
@customElement(blTableBodyTag)
1619
export default class BlTableBody extends LitElement {
1720
static get styles(): CSSResultGroup {
1821
return [style];
1922
}
23+
24+
private get _table() {
25+
return this.closest<BlTable>(blTableTag);
26+
}
27+
28+
private get hasTableRows() {
29+
return this.querySelector("bl-table-row") !== null;
30+
}
31+
2032
connectedCallback(): void {
2133
super.connectedCallback();
22-
if (!this.closest<BlTable>(blTableTag)) {
34+
if (!this._table) {
2335
console.warn("bl-table-body is designed to be used inside a bl-table", this);
2436
}
2537
}
2638

2739
render(): TemplateResult {
28-
return html` <slot></slot> `;
40+
// If there are table rows, show the normal content
41+
if (this.hasTableRows) {
42+
return html` <slot></slot> `;
43+
}
44+
45+
// If there are no table rows, show the no-data slot or default content
46+
const noDataTitle = msg("No data available", { desc: "bl-table-body: no data title" });
47+
const noDataSubtitle = msg("There are currently no records to display.", {
48+
desc: "bl-table-body: no data subtitle",
49+
});
50+
51+
return html`
52+
<tr class="no-data-row">
53+
<td class="no-data-cell" colspan="999">
54+
<slot name="no-data">
55+
<div class="default-no-data">
56+
<bl-icon name="info"></bl-icon>
57+
<p class="title">${noDataTitle}</p>
58+
<p class="subtitle">${noDataSubtitle}</p>
59+
</div>
60+
</slot>
61+
</td>
62+
</tr>
63+
`;
2964
}
3065
}
3166

src/generated/locales/ar.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
's761665218da1556a': `فتح القائمة المنسدلة`,
1717
's76ddb3a843ed8e06': `مسح البحث`,
1818
's859e1270b0736efc': `إغلاق القائمة المنسدلة`,
19+
's8bf9dd3eac79af25': `لا توجد حاليًا سجلات للعرض.`,
20+
'sa26d7a273074cbf9': `لا توجد بيانات متاحة`,
1921
'sb1ba2131b9a7c7b0': `اذهب إلى`,
2022
'sbaace8219b5f4612': `اختر الكل`,
2123
};

src/generated/locales/ro.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
's761665218da1556a': `Deschide meniul derulant`,
1717
's76ddb3a843ed8e06': `Șterge căutarea`,
1818
's859e1270b0736efc': `Închide meniul derulant`,
19+
's8bf9dd3eac79af25': `În prezent nu există înregistrări de afișat.`,
20+
'sa26d7a273074cbf9': `Nu există date disponibile`,
1921
'sb1ba2131b9a7c7b0': `Mergi la`,
2022
'sbaace8219b5f4612': `Selectează tot`,
2123
};

src/generated/locales/tr.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
's761665218da1556a': `Açılır menüyü aç`,
1717
's76ddb3a843ed8e06': `Aramayı Temizle`,
1818
's859e1270b0736efc': `Açılır menüyü kapat`,
19+
's8bf9dd3eac79af25': `Şu anda görüntülenecek kayıt bulunmamaktadır.`,
20+
'sa26d7a273074cbf9': `Veri bulunamadı`,
1921
'sb1ba2131b9a7c7b0': `Git`,
2022
'sbaace8219b5f4612': `Tümünü Seç`,
2123
};

translations/ar.xlf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@
4747
<target>اختر الكل</target>
4848
<note from="lit-localize">bl-select: select all text</note>
4949
</trans-unit>
50+
<trans-unit id="s8bf9dd3eac79af25">
51+
<source>There are currently no records to display.</source>
52+
<target>لا توجد حاليًا سجلات للعرض.</target>
53+
<note from="lit-localize">bl-table-body: no data subtitle</note>
54+
</trans-unit>
55+
<trans-unit id="sa26d7a273074cbf9">
56+
<source>No data available</source>
57+
<target>لا توجد بيانات متاحة</target>
58+
<note from="lit-localize">bl-table-body: no data title</note>
59+
</trans-unit>
5060
</body>
5161
</file>
5262
</xliff>

translations/ro.xlf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@
4747
<target>Selectează tot</target>
4848
<note from="lit-localize">bl-select: select all text</note>
4949
</trans-unit>
50+
<trans-unit id="s8bf9dd3eac79af25">
51+
<source>There are currently no records to display.</source>
52+
<target>În prezent nu există înregistrări de afișat.</target>
53+
<note from="lit-localize">bl-table-body: no data subtitle</note>
54+
</trans-unit>
55+
<trans-unit id="sa26d7a273074cbf9">
56+
<source>No data available</source>
57+
<target>Nu există date disponibile</target>
58+
<note from="lit-localize">bl-table-body: no data title</note>
59+
</trans-unit>
5060
</body>
5161
</file>
5262
</xliff>

translations/tr.xlf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@
4747
<target>Açılır menüyü aç</target>
4848
<note from="lit-localize">bl-select: open dropdown button</note>
4949
</trans-unit>
50+
<trans-unit id="s8bf9dd3eac79af25">
51+
<source>There are currently no records to display.</source>
52+
<target>Şu anda görüntülenecek kayıt bulunmamaktadır.</target>
53+
<note from="lit-localize">bl-table-body: no data subtitle</note>
54+
</trans-unit>
55+
<trans-unit id="sa26d7a273074cbf9">
56+
<source>No data available</source>
57+
<target>Veri bulunamadı</target>
58+
<note from="lit-localize">bl-table-body: no data title</note>
59+
</trans-unit>
5060
</body>
5161
</file>
5262
</xliff>

0 commit comments

Comments
 (0)