Skip to content

Commit 88aab49

Browse files
authored
fix(list, list-item, list-item-group): improve drag experience by indenting items (#9169)
**Related Issue:** #8242 #8667 #9058 ## Summary - Properly indents each list-item nested within another list or list-item - Removes transparent bg from handle, not necessary - Updates internal table cell classes to remove padding being set by default browser styles. - Changes borders to use proper css borders instead of a 1px margin and shadow - Sets bg color of foreground 1 on list-item. - Stretch action and handles slotted within a list-item. - Removes padding from empty lists - Remove unnecessary utils from list - Add and improve screenshot tests
1 parent 193bb7d commit 88aab49

File tree

10 files changed

+168
-177
lines changed

10 files changed

+168
-177
lines changed

packages/calcite-components/src/components.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2845,6 +2845,10 @@ export namespace Components {
28452845
* Sets the item as focusable. Only one item should be focusable within a list.
28462846
*/
28472847
"active": boolean;
2848+
/**
2849+
* Sets the item to display a border.
2850+
*/
2851+
"bordered": boolean;
28482852
/**
28492853
* When `true`, a close button is added to the component.
28502854
*/
@@ -10362,6 +10366,10 @@ declare namespace LocalJSX {
1036210366
* Sets the item as focusable. Only one item should be focusable within a list.
1036310367
*/
1036410368
"active"?: boolean;
10369+
/**
10370+
* Sets the item to display a border.
10371+
*/
10372+
"bordered"?: boolean;
1036510373
/**
1036610374
* When `true`, a close button is added to the component.
1036710375
*/

packages/calcite-components/src/components/handle/handle.scss

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
items-center
99
justify-center
1010
self-stretch
11-
border-none
12-
bg-transparent;
11+
border-none;
1312
color: theme("borderColor.color.input");
1413
padding-block: theme("spacing.3");
1514
padding-inline: theme("spacing.1");
Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
:host {
22
@apply flex flex-col bg-foreground-1;
3-
--calcite-list-item-spacing-indent: theme("spacing.4");
43
}
54

65
:host([filter-hidden]) {
@@ -15,20 +14,6 @@
1514

1615
.heading {
1716
@apply p-0;
18-
padding-inline-start: calc(
19-
var(--calcite-list-item-spacing-indent) * var(--calcite-list-item-spacing-indent-multiplier)
20-
);
21-
}
22-
23-
::slotted(calcite-list-item) {
24-
@apply shadow-border-top;
25-
margin-block-start: 1px;
26-
}
27-
28-
// removes shadow for the first item of the group for both filtered and unfiltered items.
29-
::slotted(calcite-list-item:nth-child(1 of :not([hidden]))) {
30-
@apply shadow-none;
31-
margin-block-start: 0px;
3217
}
3318

3419
@include base-component();

packages/calcite-components/src/components/list-item-group/list-item-group.tsx

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,4 @@
1-
import {
2-
Component,
3-
Element,
4-
Event,
5-
EventEmitter,
6-
h,
7-
Host,
8-
Prop,
9-
State,
10-
VNode,
11-
} from "@stencil/core";
1+
import { Component, Element, Event, EventEmitter, h, Host, Prop, VNode } from "@stencil/core";
122
import {
133
connectInteractive,
144
disconnectInteractive,
@@ -17,7 +7,6 @@ import {
177
updateHostInteraction,
188
} from "../../utils/interactive";
199
import { MAX_COLUMNS } from "../list-item/resources";
20-
import { getDepth } from "../list-item/utils";
2110
import { CSS } from "./resources";
2211
/**
2312
* @slot - A slot for adding `calcite-list-item` and `calcite-list-item-group` elements.
@@ -71,8 +60,6 @@ export class ListItemGroup implements InteractiveComponent {
7160
// --------------------------------------------------------------------------
7261

7362
connectedCallback(): void {
74-
const { el } = this;
75-
this.visualLevel = getDepth(el, true);
7663
connectInteractive(this);
7764
}
7865

@@ -92,23 +79,18 @@ export class ListItemGroup implements InteractiveComponent {
9279

9380
@Element() el: HTMLCalciteListItemGroupElement;
9481

95-
@State() visualLevel: number = null;
96-
9782
// --------------------------------------------------------------------------
9883
//
9984
// Render Methods
10085
//
10186
// --------------------------------------------------------------------------
10287

10388
render(): VNode {
104-
const { disabled, heading, visualLevel } = this;
89+
const { disabled, heading } = this;
10590
return (
10691
<Host>
10792
<InteractiveContainer disabled={disabled}>
108-
<tr
109-
class={CSS.container}
110-
style={{ "--calcite-list-item-spacing-indent-multiplier": `${visualLevel}` }}
111-
>
93+
<tr class={CSS.container}>
11294
<td class={CSS.heading} colSpan={MAX_COLUMNS}>
11395
{heading}
11496
</td>

packages/calcite-components/src/components/list-item/list-item.scss

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
11
:host {
2-
@apply flex flex-col;
2+
@apply flex flex-col bg-foreground-1;
33
--calcite-list-item-icon-color: theme("colors.brand");
4-
--calcite-list-item-spacing-indent: theme("spacing.4");
4+
}
5+
6+
:host([filter-hidden]),
7+
:host([closed]) {
8+
@apply hidden;
9+
}
10+
11+
.wrapper--bordered {
12+
border-block-end: 1px solid var(--calcite-color-border-3);
513
}
614

715
@include disabled();
816

17+
.indent {
18+
@apply flex
19+
flex-col
20+
border-solid
21+
border-0
22+
border-color-3;
23+
24+
margin-inline-start: var(--calcite-list-item-spacing-indent, theme("spacing.6"));
25+
}
26+
927
.container {
1028
@apply bg-foreground-1
1129
box-border
@@ -14,9 +32,6 @@
1432
* {
1533
@apply box-border;
1634
}
17-
padding-inline-start: calc(
18-
var(--calcite-list-item-spacing-indent) * var(--calcite-list-item-spacing-indent-multiplier)
19-
);
2035
}
2136

2237
.container--hover:hover {
@@ -47,7 +62,7 @@
4762
}
4863

4964
.nested-container {
50-
@apply bg-foreground-1 flex flex-col;
65+
@apply flex flex-col;
5166
}
5267

5368
.nested-container--hidden {
@@ -122,13 +137,14 @@ td:focus {
122137
.content-start,
123138
.content-end {
124139
@apply flex-auto;
140+
141+
::slotted(calcite-icon) {
142+
@apply self-center mx-3;
143+
}
125144
}
126145

127146
.content-bottom {
128-
@apply bg-foreground-1 flex flex-col;
129-
padding-inline-start: calc(
130-
var(--calcite-list-item-spacing-indent) * var(--calcite-list-item-spacing-indent-multiplier)
131-
);
147+
@apply flex flex-col;
132148
}
133149

134150
.content-container--has-center-content .content-start,
@@ -171,20 +187,18 @@ td:focus {
171187
.drag-container,
172188
.open-container {
173189
@apply flex items-center;
190+
191+
calcite-action,
192+
calcite-handle {
193+
@apply self-stretch;
194+
}
174195
}
175196

176197
.open-container,
177198
.selection-container {
178199
@apply cursor-pointer;
179200
}
180201

181-
.content-start,
182-
.content-end {
183-
::slotted(calcite-icon) {
184-
@apply self-center mx-3;
185-
}
186-
}
187-
188202
.actions-start,
189203
.actions-end {
190204
@apply p-0;
@@ -198,13 +212,8 @@ td:focus {
198212
}
199213
}
200214

201-
::slotted(calcite-list-item),
202-
::slotted(calcite-list) {
203-
@apply border-solid border-0 border-t border-color-3;
204-
}
205-
206215
::slotted(calcite-list:empty) {
207-
@apply py-3;
216+
@apply border-t-0;
208217
}
209218

210219
@include base-component();

packages/calcite-components/src/components/list-item/list-item.tsx

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,13 @@ export class ListItem
9797
}
9898
}
9999

100+
/**
101+
* Sets the item to display a border.
102+
*
103+
* @internal
104+
*/
105+
@Prop() bordered = false;
106+
100107
/** When `true`, a close button is added to the component. */
101108
@Prop({ reflect: true }) closable = false;
102109

@@ -312,8 +319,6 @@ export class ListItem
312319

313320
@State() level: number = null;
314321

315-
@State() visualLevel: number = null;
316-
317322
@State() parentListEl: HTMLCalciteListElement;
318323

319324
@State() openable = false;
@@ -355,7 +360,6 @@ export class ListItem
355360
const { el } = this;
356361
this.parentListEl = el.closest(listSelector);
357362
this.level = getDepth(el) + 1;
358-
this.visualLevel = getDepth(el, true);
359363
this.setSelectionDefaults();
360364
}
361365

@@ -560,13 +564,9 @@ export class ListItem
560564
}
561565

562566
renderContentBottom(): VNode {
563-
const { hasContentBottom, visualLevel } = this;
567+
const { hasContentBottom } = this;
564568
return (
565-
<div
566-
class={CSS.contentBottom}
567-
hidden={!hasContentBottom}
568-
style={{ "--calcite-list-item-spacing-indent-multiplier": `${visualLevel}` }}
569-
>
569+
<div class={CSS.contentBottom} hidden={!hasContentBottom}>
570570
<slot name={SLOTS.contentBottom} onSlotchange={this.handleContentBottomSlotChange} />
571571
</div>
572572
);
@@ -651,8 +651,9 @@ export class ListItem
651651
selectionAppearance,
652652
selectionMode,
653653
closed,
654-
visualLevel,
655654
filterHidden,
655+
bordered,
656+
disabled,
656657
} = this;
657658

658659
const showBorder = selectionMode !== "none" && selectionAppearance === "border";
@@ -661,40 +662,41 @@ export class ListItem
661662

662663
return (
663664
<Host>
664-
<InteractiveContainer disabled={this.disabled}>
665-
<tr
666-
aria-expanded={openable ? toAriaBoolean(open) : null}
667-
aria-label={label}
668-
aria-level={level}
669-
aria-posinset={setPosition}
670-
aria-selected={toAriaBoolean(selected)}
671-
aria-setsize={setSize}
672-
class={{
673-
[CSS.container]: true,
674-
[CSS.containerHover]: true,
675-
[CSS.containerBorder]: showBorder,
676-
[CSS.containerBorderSelected]: borderSelected,
677-
[CSS.containerBorderUnselected]: borderUnselected,
678-
}}
679-
hidden={closed || filterHidden}
680-
onFocus={this.focusCellNull}
681-
onFocusin={this.emitInternalListItemActive}
682-
onKeyDown={this.handleItemKeyDown}
683-
role="row"
684-
style={{ "--calcite-list-item-spacing-indent-multiplier": `${visualLevel}` }}
685-
tabIndex={active ? 0 : -1}
686-
// eslint-disable-next-line react/jsx-sort-props -- ref should be last so node attrs/props are in sync (see https://github.com/Esri/calcite-design-system/pull/6530)
687-
ref={(el) => (this.containerEl = el)}
688-
>
689-
{this.renderDragHandle()}
690-
{this.renderSelected()}
691-
{this.renderOpen()}
692-
{this.renderActionsStart()}
693-
{this.renderContentContainer()}
694-
{this.renderActionsEnd()}
695-
</tr>
696-
{this.renderContentBottom()}
697-
{this.renderDefaultContainer()}
665+
<InteractiveContainer disabled={disabled}>
666+
<div class={{ [CSS.wrapper]: true, [CSS.wrapperBordered]: bordered }}>
667+
<tr
668+
aria-expanded={openable ? toAriaBoolean(open) : null}
669+
aria-label={label}
670+
aria-level={level}
671+
aria-posinset={setPosition}
672+
aria-selected={toAriaBoolean(selected)}
673+
aria-setsize={setSize}
674+
class={{
675+
[CSS.container]: true,
676+
[CSS.containerHover]: true,
677+
[CSS.containerBorder]: showBorder,
678+
[CSS.containerBorderSelected]: borderSelected,
679+
[CSS.containerBorderUnselected]: borderUnselected,
680+
}}
681+
hidden={closed || filterHidden}
682+
onFocus={this.focusCellNull}
683+
onFocusin={this.emitInternalListItemActive}
684+
onKeyDown={this.handleItemKeyDown}
685+
role="row"
686+
tabIndex={active ? 0 : -1}
687+
// eslint-disable-next-line react/jsx-sort-props -- ref should be last so node attrs/props are in sync (see https://github.com/Esri/calcite-design-system/pull/6530)
688+
ref={(el) => (this.containerEl = el)}
689+
>
690+
{this.renderDragHandle()}
691+
{this.renderSelected()}
692+
{this.renderOpen()}
693+
{this.renderActionsStart()}
694+
{this.renderContentContainer()}
695+
{this.renderActionsEnd()}
696+
</tr>
697+
{this.renderContentBottom()}
698+
</div>
699+
<div class={CSS.indent}>{this.renderDefaultContainer()}</div>
698700
</InteractiveContainer>
699701
</Host>
700702
);

packages/calcite-components/src/components/list-item/resources.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
export const CSS = {
2+
wrapper: "wrapper",
3+
wrapperBordered: "wrapper--bordered",
24
container: "container",
5+
indent: "indent",
36
containerHover: "container--hover",
47
containerBorder: "container--border",
58
containerBorderSelected: "container--border-selected",

packages/calcite-components/src/components/list/list.scss

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,6 @@
2828
--calcite-stack-padding-block: 0;
2929
}
3030

31-
::slotted(calcite-list-item:not([filter-hidden], [closed])) {
32-
@apply shadow-border-top;
33-
margin-block-start: 1px;
34-
}
35-
36-
::slotted(calcite-list-item:first-of-type) {
37-
@apply shadow-none;
38-
}
39-
40-
// removes shadow for the first item in filteredItems of the list.
41-
::slotted(calcite-list-item[data-filter]) {
42-
@apply shadow-none;
43-
margin-block-start: 0px;
44-
}
45-
4631
.sticky-pos {
4732
@apply sticky
4833
top-0

0 commit comments

Comments
 (0)