Skip to content

Commit a343e29

Browse files
Improve styling to grid body (#2024)
Co-authored-by: Daniëlle Rameau <[email protected]>
1 parent 2e60904 commit a343e29

32 files changed

+386
-240
lines changed

.changeset/purple-pets-fix.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sl-design-system/locales': patch
3+
---
4+
5+
New grid translations

.changeset/sixty-cobras-invite.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sl-design-system/data-source': patch
3+
---
4+
5+
Expand `ListDataSource.setGroupBy` by adding a parameter for the label path

.changeset/tidy-tigers-bow.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@sl-design-system/grid': minor
3+
---
4+
5+
Grid improvements:
6+
- Add "Cancel selection" button to the bulk action toolbar
7+
- Add `column` argument to `GridColumnHeaderRenderer` type
8+
- Fix missing aria-label on a selection column checkbox
9+
- Fix styling so a small button does not expand the header row above 48px
10+
- Fix styling so a row has a height of 40px
11+
- Fix empty `class` attributes
12+
- Fix missing `role="columnheader"` on the header cells

packages/components/data-source/src/list-data-source.spec.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ describe('ListDataSource', () => {
3434
it('should group by after setting one', () => {
3535
ds.setGroupBy('profession');
3636

37-
expect(ds.groupBy).to.deep.equal({ path: 'profession', sorter: undefined, direction: undefined });
37+
expect(ds.groupBy).to.deep.equal({
38+
path: 'profession',
39+
sorter: undefined,
40+
direction: undefined,
41+
labelPath: undefined
42+
});
3843
});
3944

4045
it('should not group by after removing it', () => {

packages/components/data-source/src/list-data-source.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export type ListDataSourceGroupBy<T> = {
55
path: PathKeys<T>;
66
sorter?: DataSourceSortFunction<T>;
77
direction?: DataSourceSortDirection;
8+
labelPath?: PathKeys<T>;
89
};
910

1011
export type ListDataSourceOptions = {
@@ -62,9 +63,15 @@ export abstract class ListDataSource<T = any, U = T> extends DataSource<T, U> {
6263
* @param path Path to group by attribute.
6364
* @param sorter Optional sorter function.
6465
* @param direction Optional sort direction.
66+
* @param labelPath Optional path for the group label.
6567
*/
66-
setGroupBy(path: PathKeys<T>, sorter?: DataSourceSortFunction<T>, direction?: DataSourceSortDirection): void {
67-
this.#groupBy = { path, sorter, direction };
68+
setGroupBy(
69+
path: PathKeys<T>,
70+
sorter?: DataSourceSortFunction<T>,
71+
direction?: DataSourceSortDirection,
72+
labelPath?: PathKeys<T>
73+
): void {
74+
this.#groupBy = { path, sorter, direction, labelPath };
6875
}
6976

7077
/**

packages/components/grid/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"test": "echo \"Error: run tests from monorepo root.\" && exit 1"
4040
},
4141
"dependencies": {
42+
"@sl-design-system/button": "^1.2.3",
4243
"@sl-design-system/checkbox": "^2.1.3",
4344
"@sl-design-system/data-source": "^0.1.3",
4445
"@sl-design-system/ellipsize-text": "^0.0.1",
@@ -50,7 +51,8 @@
5051
"@sl-design-system/shared": "^0.7.1",
5152
"@sl-design-system/skeleton": "^1.0.0",
5253
"@sl-design-system/text-field": "^1.6.3",
53-
"@sl-design-system/tool-bar": "^0.0.8"
54+
"@sl-design-system/tool-bar": "^0.0.8",
55+
"@sl-design-system/tooltip": "^1.1.4"
5456
},
5557
"devDependencies": {
5658
"@lit-labs/virtualizer": "^2.1.0",

packages/components/grid/src/column-group.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ describe('sl-column-group', () => {
3636
});
3737

3838
it('should render column headers', () => {
39-
const columns = Array.from(el.renderRoot.querySelectorAll('th')).map(col => col.textContent);
39+
const columns = Array.from(el.renderRoot.querySelectorAll('th')).map(col => col.textContent?.trim());
4040

4141
expect(columns).to.deep.equal([
4242
'Name',
@@ -86,7 +86,7 @@ describe('sl-column-group', () => {
8686
it('should have the correct width when one is set explicitly', () => {
8787
const cells = Array.from(el.renderRoot.querySelectorAll('th'));
8888
expect(cells.map(cell => Math.floor(parseFloat(getComputedStyle(cell).width)))).to.deep.equal([
89-
281, 724, 214, 212, 197, 186, 195
89+
271, 734, 214, 212, 197, 186, 195
9090
]);
9191
});
9292
});

packages/components/grid/src/column.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ describe('sl-column', () => {
3838
});
3939

4040
it('should render column headers', () => {
41-
const columns = Array.from(el.renderRoot.querySelectorAll('th')).map(col => col.textContent);
41+
const columns = Array.from(el.renderRoot.querySelectorAll('th')).map(col => col.textContent?.trim());
4242

4343
expect(columns).to.deep.equal(['First name', 'Last name', 'Current age']);
4444
});

packages/components/grid/src/column.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
} from '@sl-design-system/shared';
1010
import { type CSSResult, LitElement, type TemplateResult, html, nothing } from 'lit';
1111
import { property, state } from 'lit/decorators.js';
12+
import { ifDefined } from 'lit/directives/if-defined.js';
1213
import { type Grid } from './grid.js';
1314

1415
declare global {
@@ -25,7 +26,8 @@ declare global {
2526
export type GridColumnAlignment = 'start' | 'center' | 'end';
2627

2728
/** Custom renderer type for column headers. */
28-
export type GridColumnHeaderRenderer = () => string | undefined | TemplateResult;
29+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
30+
export type GridColumnHeaderRenderer<T = any> = (column: GridColumn<T>) => string | undefined | TemplateResult;
2931

3032
/** Custom renderer type for column cells. */
3133
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -177,7 +179,30 @@ export class GridColumn<T = any> extends LitElement {
177179
const classes = this.getClasses(),
178180
parts = ['header', ...this.getParts()];
179181

180-
return html`<th class=${classes.join(' ')} part=${parts.join(' ')}>${this.header ?? getNameByPath(this.path)}</th>`;
182+
return html`
183+
<th
184+
class=${ifDefined(classes.length ? classes.join(' ') : undefined)}
185+
part=${parts.join(' ')}
186+
role="columnheader"
187+
>
188+
${this.renderHeaderLabel()}
189+
</th>
190+
`;
191+
}
192+
193+
/**
194+
* This method renders the label for the header. This is used to render the content of the
195+
* `<th>` element. Override this method if you want to customize how a header label is rendered.
196+
* Do not override this if you only want to change the classes, contents or parts of the header.
197+
*/
198+
renderHeaderLabel(): string | undefined | TemplateResult {
199+
if (this.header) {
200+
return typeof this.header === 'string' ? html`<span>${this.header}</span>` : this.header(this);
201+
} else if (this.path) {
202+
return html`<span>${getNameByPath(this.path)}</span>`;
203+
}
204+
205+
return undefined;
181206
}
182207

183208
/**
@@ -193,12 +218,14 @@ export class GridColumn<T = any> extends LitElement {
193218

194219
if (this.ellipsizeText && typeof data === 'string') {
195220
return html`
196-
<td class=${classes.join(' ')} part=${parts.join(' ')}>
221+
<td class=${ifDefined(classes.length ? classes.join(' ') : undefined)} part=${parts.join(' ')}>
197222
<sl-ellipsize-text>${data}</sl-ellipsize-text>
198223
</td>
199224
`;
200225
} else {
201-
return html`<td class=${classes.join(' ')} part=${parts.join(' ')}>${data}</td>`;
226+
return html`
227+
<td class=${ifDefined(classes.length ? classes.join(' ') : undefined)} part=${parts.join(' ')}>${data}</td>
228+
`;
202229
}
203230
}
204231

packages/components/grid/src/drag-handle-column.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export class GridDragHandleColumn<T = any> extends GridColumn<T> {
3434
return nothing;
3535
}
3636

37-
return html`<th part="header drag-handle"></th>`;
37+
return html`<th part="header drag-handle" role="columnheader"></th>`;
3838
}
3939

4040
override renderData(item: T): TemplateResult {

packages/components/grid/src/filter-column.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ declare global {
1313
}
1414
}
1515

16-
export type GridFilterMode = 'select' | 'text';
16+
export type GridFilterMode = 'date' | 'date-range' | 'select' | 'text';
1717

1818
export interface GridFilterOption {
1919
label: string;

packages/components/grid/src/filter.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
gap: var(--sl-size-100);
66
inline-size: 100%;
77
min-inline-size: 0;
8-
padding: var(--sl-size-075) var(--sl-size-200);
8+
padding: var(--sl-size-075) var(--sl-size-150);
99
}
1010

1111
sl-search-field,

0 commit comments

Comments
 (0)