Skip to content

Commit 0a284db

Browse files
committed
docs(drag-to-reorder): add an example to validate horizontal dragging works
currently we don't have any components that can be used for testing this
1 parent c73725c commit 0a284db

File tree

3 files changed

+202
-0
lines changed

3 files changed

+202
-0
lines changed

src/components/drag-handle/drag-handle.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { OpenDirection } from '../menu/menu.types';
2323
* :::
2424
*
2525
* @exampleComponent limel-example-drag-handle-basic
26+
* @exampleComponent limel-example-drag-handle-horizontal
2627
*
2728
* @private
2829
*/
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
@use '../../../style/mixins.scss';
2+
3+
:host {
4+
display: block;
5+
}
6+
7+
div {
8+
max-width: 100%;
9+
display: grid;
10+
grid-template-columns: 1fr 1fr 1fr;
11+
gap: 1rem;
12+
13+
&.has-an-item-which-is-being-dragged {
14+
limel-card {
15+
&:not(.is-being-dragged) {
16+
opacity: 0.5;
17+
}
18+
}
19+
}
20+
}
21+
22+
limel-drag-handle {
23+
margin-left: auto;
24+
}
25+
26+
limel-card {
27+
@include mixins.is-draggable-item(
28+
$border-radius-while-being-dragged: 0.95rem
29+
);
30+
}
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
import { Component, h, Host, State } from '@stencil/core';
2+
import {
3+
dragToReorder,
4+
DragToReorderController,
5+
DragToReorderFinalizeDetail,
6+
DragToReorderPreviewDetail,
7+
} from '../../../util/drag-to-reorder';
8+
9+
interface KittenCard {
10+
id: string;
11+
image: {
12+
src: string;
13+
alt: string;
14+
};
15+
subheading: string;
16+
}
17+
/**
18+
* Horizontal drag handle
19+
* This example shows how to use the drag handle component
20+
* along with the drag-to-reorder utility function,
21+
* in a horizontal drag-and-drop setup.
22+
*/
23+
@Component({
24+
shadow: true,
25+
tag: 'limel-example-drag-handle-horizontal',
26+
styleUrl: 'drag-handle-horizontal.scss',
27+
})
28+
export class DragHandleHorizontalExample {
29+
@State()
30+
private kittens: KittenCard[] = [
31+
{
32+
id: 'kitten-1',
33+
image: {
34+
src: 'https://images.unsplash.com/photo-1621238224334-20222c044b84?q=80&w=600&h=400&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
35+
alt: 'Photo by https://unsplash.com/@paracetamol',
36+
},
37+
subheading: "@paracetamol's kitten",
38+
},
39+
{
40+
id: 'kitten-2',
41+
image: {
42+
src: 'https://images.unsplash.com/photo-1558674378-e4334d4fecc2?q=80&w=600&h=400&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
43+
alt: 'Photo by https://unsplash.com/@bliss1002',
44+
},
45+
subheading: "@bliss1002's kitten",
46+
},
47+
{
48+
id: 'kitten-3',
49+
image: {
50+
src: 'https://images.unsplash.com/photo-1692962063951-0b5c81887f3d?q=80&w=600&h=400&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
51+
alt: 'Photo by https://unsplash.com/@kmly',
52+
},
53+
subheading: "@kmly's kitten",
54+
},
55+
];
56+
57+
private container?: HTMLDivElement;
58+
private dragController?: DragToReorderController;
59+
private snapshot?: KittenCard[];
60+
61+
public render() {
62+
return (
63+
<Host>
64+
<h4>Drag & sort these kittens</h4>
65+
<p>More cute → Less cute</p>
66+
<div class="kitten-list" ref={this.setContainer}>
67+
{this.kittens.map((kitten) => (
68+
<limel-card
69+
class="kitten-card"
70+
key={kitten.id}
71+
clickable={true}
72+
image={kitten.image}
73+
subheading={kitten.subheading}
74+
onClick={this.handleClick}
75+
data-reorder-id={kitten.id}
76+
>
77+
<limel-drag-handle
78+
dragDirection="horizontal"
79+
slot="component"
80+
/>
81+
</limel-card>
82+
))}
83+
</div>
84+
</Host>
85+
);
86+
}
87+
88+
private handleClick = () => {
89+
console.log('Card clicked');
90+
};
91+
92+
private setContainer = (element?: HTMLDivElement) => {
93+
if (this.container === element) {
94+
return;
95+
}
96+
97+
this.teardownDragController();
98+
this.container = element ?? undefined;
99+
this.setupDragController();
100+
};
101+
102+
private setupDragController() {
103+
if (!this.container || this.dragController) {
104+
return;
105+
}
106+
107+
this.dragController = dragToReorder({
108+
container: this.container,
109+
itemSelector: 'limel-card.kitten-card',
110+
dragHandleSelector: '[data-drag-handle]',
111+
orientation: 'horizontal',
112+
onStart: this.handleDragStart,
113+
onPreview: this.handleDragPreview,
114+
onFinalize: this.handleDragFinalize,
115+
});
116+
}
117+
118+
private teardownDragController() {
119+
this.dragController?.destroy();
120+
this.dragController = undefined;
121+
}
122+
123+
private handleDragStart = () => {
124+
this.snapshot = [...this.kittens];
125+
};
126+
127+
private handleDragPreview = ({
128+
fromIndex,
129+
toIndex,
130+
}: DragToReorderPreviewDetail) => {
131+
if (fromIndex === toIndex) {
132+
return;
133+
}
134+
135+
this.kittens = this.moveKitten(this.kittens, fromIndex, toIndex);
136+
};
137+
138+
private handleDragFinalize = ({
139+
cancelled,
140+
}: DragToReorderFinalizeDetail) => {
141+
if (cancelled && this.snapshot) {
142+
this.kittens = [...this.snapshot];
143+
}
144+
145+
this.snapshot = undefined;
146+
};
147+
148+
private moveKitten(
149+
list: KittenCard[],
150+
fromIndex: number,
151+
toIndex: number
152+
): KittenCard[] {
153+
if (fromIndex === toIndex) {
154+
return list;
155+
}
156+
157+
const updated = [...list];
158+
const [moved] = updated.splice(fromIndex, 1);
159+
160+
if (!moved) {
161+
return list;
162+
}
163+
164+
updated.splice(toIndex, 0, moved);
165+
return updated;
166+
}
167+
168+
public disconnectedCallback() {
169+
this.teardownDragController();
170+
}
171+
}

0 commit comments

Comments
 (0)