Skip to content

Commit 28d47eb

Browse files
committed
feat: refactor Drawer to render via lit-element + massively improve rendering performance
1 parent 5e7b014 commit 28d47eb

File tree

2 files changed

+102
-89
lines changed

2 files changed

+102
-89
lines changed

packages/uikit-workshop/src/scripts/components/pl-drawer/pl-drawer.js

Lines changed: 100 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,50 @@
1-
/* eslint-disable no-unused-vars, no-param-reassign */
2-
import { define, props } from 'skatejs';
3-
import { h } from 'preact';
4-
1+
import { styleMap } from 'lit-html/directives/style-map';
2+
import { classMap } from 'lit-html/directives/class-map';
3+
import { LitElement, html, customElement } from 'lit-element';
54
import { store } from '../../store.js'; // redux store
65
import {
76
updateDrawerState,
87
updateDrawerHeight,
98
updateDrawerAnimationState,
109
} from '../../actions/app.js'; // redux actions needed by this element.
11-
import { css } from '../../utils';
12-
import { BaseComponent } from '../base-component.js';
13-
import AnimateHeight from 'react-animate-height';
14-
import CloseIcon from '../../../icons/close.svg';
15-
16-
@define
17-
class Drawer extends BaseComponent {
18-
static is = 'pl-drawer';
1910

11+
@customElement('pl-drawer')
12+
class Drawer extends LitElement {
2013
constructor(self) {
2114
self = super(self);
2215
self.onMouseDown = self.onMouseDown.bind(self); // fix bindings so "self" works properly
2316
self.onMouseUp = self.onMouseUp.bind(self); // fix bindings so "self" works properly
2417
self.onMouseMove = self.onMouseMove.bind(self); // fix bindings so "this" works properly
25-
self.useShadow = false;
2618
return self;
2719
}
2820

29-
state = {
30-
isMouseDown: false,
31-
isMouseUp: false,
32-
isDragging: false,
33-
hasDragged: false,
34-
panelHeight: '50vh',
35-
};
21+
static get properties() {
22+
return {
23+
drawerOpened: {
24+
attribute: true,
25+
type: Boolean,
26+
},
27+
drawerHeight: {
28+
attribute: true,
29+
type: Number,
30+
},
31+
isViewallPage: {
32+
attribute: true,
33+
type: Boolean,
34+
},
35+
isMouseDown: {
36+
attribute: true,
37+
type: Boolean,
38+
},
39+
};
40+
}
41+
42+
createRenderRoot() {
43+
return this;
44+
}
3645

3746
onMouseDown() {
38-
this.setState({
39-
...this.state,
40-
isMouseDown: true,
41-
});
42-
47+
this.isMouseDown = true;
4348
store.dispatch(updateDrawerAnimationState(true));
4449

4550
document.addEventListener('mousemove', this.onMouseMove);
@@ -53,96 +58,103 @@ class Drawer extends BaseComponent {
5358
: event.clientY;
5459
const panelHeight = window.innerHeight - clientHeight + 7;
5560

56-
store.dispatch(updateDrawerHeight(panelHeight));
57-
58-
this.setState({
59-
...this.state,
60-
isDragging: true,
61-
panelHeight: `${panelHeight}px`,
62-
});
61+
this.drawerHeight = panelHeight;
6362
}
6463

6564
onMouseUp() {
66-
this.setState({
67-
...this.state,
68-
hasDragged: this.state.isDragging,
69-
isDragging: false,
70-
isMouseDown: false,
71-
isMouseUp: true,
72-
});
73-
74-
store.dispatch(updateDrawerAnimationState(false));
75-
65+
this.isMouseDown = false;
7666
document.removeEventListener('mousemove', this.onMouseMove);
7767
document.removeEventListener('mouseup', this.onMouseUp);
78-
}
7968

80-
static props = {
81-
drawerOpened: props.boolean,
82-
};
83-
84-
render({ drawerOpened, drawerHeight, isViewallPage }) {
85-
const classes = css(
86-
'pl-c-drawer',
87-
'pl-js-drawer',
88-
drawerOpened && !isViewallPage ? 'pl-is-active' : ''
89-
);
69+
store.dispatch(updateDrawerHeight(this.drawerHeight));
70+
store.dispatch(updateDrawerAnimationState(false));
71+
}
9072

91-
const height =
92-
drawerOpened && !isViewallPage
93-
? drawerHeight > 20
94-
? drawerHeight
73+
render() {
74+
const classes = {
75+
'pl-c-drawer': true,
76+
'pl-js-drawer': true,
77+
'pl-is-active': this.drawerOpened && !this.isViewallPage,
78+
};
79+
80+
const renderedHeight =
81+
this.drawerOpened && !this.isViewallPage
82+
? this.drawerHeight > 20
83+
? this.drawerHeight
9584
: 300
9685
: 0;
9786

98-
return (
87+
const coverStyles = { display: this.isMouseDown ? 'block' : 'none' };
88+
const drawerStyles = {
89+
height: `${renderedHeight}px`,
90+
transitionDuration: this.isMouseDown ? '0ms' : '300ms',
91+
};
92+
93+
return html`
9994
<div>
100-
<div
101-
class="pl-c-drawer__cover"
102-
style={this.state.isMouseDown ? 'display: block;' : 'display: none;'}
103-
/>
104-
<AnimateHeight
105-
duration={this.state.isMouseDown ? 0 : 300}
106-
height={height}
107-
className="pl-c-drawer__wrapper"
108-
>
109-
<div className={classes}>
95+
<div class="pl-c-drawer__cover" style="${styleMap(coverStyles)}"></div>
96+
<div style="${styleMap(drawerStyles)}" class="pl-c-drawer__wrapper">
97+
<div class="${classMap(classes)}">
11098
<div class="pl-c-drawer__toolbar">
11199
<div
112100
class="pl-c-drawer__resizer"
113-
onMouseDown={this.onMouseDown}
114-
/>
101+
@mousedown="${this.onMouseDown}"
102+
></div>
115103
<div class="pl-c-drawer__toolbar-controls">
116-
{/* <pl-toggle-layout></pl-toggle-layout> */}
104+
<pl-toggle-layout
105+
size="small"
106+
icon-only="true"
107+
></pl-toggle-layout>
117108
118-
<button
119-
class="pl-c-drawer__close-btn"
109+
<pl-button
120110
title="Hide pattern info"
121111
title="Menu"
122-
onClick={_ => store.dispatch(updateDrawerState(false))}
112+
size="small"
113+
icon-only="true"
114+
@click="${_ => store.dispatch(updateDrawerState(false))}"
123115
>
124-
<CloseIcon
125-
width={20}
126-
height={20}
127-
fill="currentColor"
128-
viewBox="0 0 24 24"
129-
className={'pl-c-drawer__close-btn-icon'}
130-
/>
131-
</button>
116+
<pl-icon slot="after" name="close"></pl-icon>
117+
</pl-button>
132118
</div>
133119
</div>
134-
<div class="pl-c-drawer__content pl-js-drawer-content" />
120+
<div class="pl-c-drawer__content pl-js-drawer-content"></div>
135121
</div>
136-
</AnimateHeight>
122+
</div>
137123
</div>
124+
`;
125+
}
126+
127+
connectedCallback() {
128+
if (super.connectedCallback) {
129+
super.connectedCallback();
130+
}
131+
this.__storeUnsubscribe = store.subscribe(() =>
132+
this._stateChanged(store.getState())
138133
);
134+
this._stateChanged(store.getState());
135+
}
136+
137+
disconnectedCallback() {
138+
this.__storeUnsubscribe && this.__storeUnsubscribe();
139+
140+
if (super.disconnectedCallback) {
141+
super.disconnectedCallback();
142+
}
139143
}
140144

141145
_stateChanged(state) {
142-
this.drawerOpened = state.app.drawerOpened;
143-
this.drawerHeight = state.app.drawerHeight;
144-
this.isDragging = state.app.isDragging;
145-
this.isViewallPage = state.app.isViewallPage;
146+
if (this.drawerOpened !== state.app.drawerOpened) {
147+
this.drawerOpened = state.app.drawerOpened;
148+
}
149+
if (this.drawerHeight !== state.app.drawerHeight) {
150+
this.drawerHeight = state.app.drawerHeight;
151+
}
152+
if (this.isDragging !== state.app.isDragging) {
153+
this.isDragging = state.app.isDragging;
154+
}
155+
if (this.isViewallPage !== state.app.isViewallPage) {
156+
this.isViewallPage = state.app.isViewallPage;
157+
}
146158
}
147159
}
148160

packages/uikit-workshop/src/scripts/components/pl-drawer/pl-drawer.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ pl-drawer {
2020
border-top-color: var(--theme-border, $pl-color-gray-20);
2121
}
2222

23-
2423
/**
2524
* 1) The drawer slides up from the bottom of the viewport when
2625
* "show pattern info" is selected on the pattern detail screen.
@@ -61,6 +60,8 @@ pl-drawer {
6160

6261
.pl-c-drawer__wrapper {
6362
transform: translate3d(0, 0, 0);
63+
will-change: height;
64+
overflow: hidden;
6465
}
6566

6667
.pl-c-drawer__wrapper > * {

0 commit comments

Comments
 (0)