Skip to content

Commit 80d1fe8

Browse files
committed
refactor: update Tools Menu to use new <pl-button> and <pl-icon> components + switch to rendering using lit-html
1 parent 9d602fe commit 80d1fe8

File tree

2 files changed

+152
-126
lines changed

2 files changed

+152
-126
lines changed

packages/uikit-workshop/src/scripts/components/pl-tools-menu/pl-tools-menu.js

Lines changed: 132 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -5,111 +5,175 @@ import { BaseComponent } from '../base-component.js';
55
import { urlHandler, patternName } from '../../utils';
66
import { store } from '../../store'; // redux store
77

8-
import NewTabIcon from '../../../icons/new-tab.svg';
9-
import HelpIcon from '../../../icons/help.svg';
10-
import SettingsIcon from '../../../icons/settings.svg';
8+
let listeningForBodyClicks = false;
9+
10+
import { html } from 'lit-html';
11+
import { BaseLitComponent } from '../base-component.js';
1112

1213
@define
13-
class ToolsMenu extends BaseComponent {
14+
class ToolsMenu extends BaseLitComponent {
1415
static is = 'pl-tools-menu';
1516

17+
static props = {
18+
isOpen: props.boolean,
19+
layoutMode: props.string,
20+
};
21+
1622
_stateChanged(state) {
17-
this.currentUrl =
18-
state.app.currentUrl || urlHandler.getFileName(patternName);
23+
if (this.currentUrl !== state.app.currentUrl) {
24+
this.currentUrl =
25+
state.app.currentUrl || urlHandler.getFileName(patternName);
26+
}
27+
28+
if (this.layoutMode !== state.app.layoutMode) {
29+
this.layoutMode = state.app.layoutMode || 'vertical';
30+
}
1931
}
2032

2133
constructor(self) {
2234
self = super(self);
2335
self.handleClick = self.handleClick.bind(self);
36+
self.receiveIframeMessage = self.receiveIframeMessage.bind(self);
37+
self.handleExternalClicks = self.handleExternalClicks.bind(self);
2438
self.useShadow = false;
2539
return self;
2640
}
2741

2842
connecting() {
43+
super.connecting && super.connecting();
2944
const state = store.getState();
3045
const { ishControlsHide } = window.ishControls;
3146
this.currentUrl =
3247
state.app.currentUrl || urlHandler.getFileName(patternName);
3348
this.ishControlsHide = ishControlsHide;
49+
50+
window.addEventListener('message', this.receiveIframeMessage, false);
51+
document.addEventListener('click', this.handleExternalClicks);
52+
}
53+
54+
disconnecting() {
55+
super.disconnecting && super.disconnecting();
56+
document.removeEventListener('click', this.handleExternalClicks);
57+
window.removeEventListener('message', this.receiveIframeMessage);
58+
}
59+
60+
handleExternalClicks(e) {
61+
if (window.innerWidth >= 670 && this.layoutMode === 'vertical') {
62+
return;
63+
}
64+
65+
if (!this.contains(e.target) && this.isOpen === true) {
66+
this.isOpen = false;
67+
}
68+
}
69+
70+
close() {
71+
this.isOpen = false;
72+
}
73+
74+
toggle() {
75+
if (this.isOpen) {
76+
this.close();
77+
} else {
78+
this.open();
79+
}
80+
}
81+
82+
open() {
83+
this.isOpen = true;
3484
}
3585

3686
handleClick(e) {
37-
const elem = e.target.closest('.pl-js-acc-handle');
38-
const panel = elem.nextSibling;
87+
if (window.innerWidth >= 670 && this.layoutMode === 'vertical') {
88+
return;
89+
}
90+
91+
e.preventDefault();
92+
e.stopPropagation();
93+
94+
this.toggle();
95+
}
96+
97+
receiveIframeMessage(event) {
98+
const self = this;
99+
// does the origin sending the message match the current host? if not dev/null the request
100+
if (
101+
window.location.protocol !== 'file:' &&
102+
event.origin !== window.location.protocol + '//' + window.location.host
103+
) {
104+
return;
105+
}
106+
107+
let data = {};
108+
try {
109+
data =
110+
typeof event.data !== 'string' ? event.data : JSON.parse(event.data);
111+
} catch (e) {
112+
// @todo: how do we want to handle exceptions here?
113+
}
39114

40-
// Activate selected panel
41-
elem.classList.toggle('pl-is-active');
42-
panel.classList.toggle('pl-is-active');
115+
if (data.event !== undefined && data.event === 'patternLab.pageClick') {
116+
try {
117+
console.log('patternLab.pageClick');
118+
self.isOpen = false;
119+
} catch (error) {
120+
console.log(error);
121+
}
122+
}
43123
}
44124

45125
render() {
46-
return (
126+
if (window.innerWidth >= 670 && this.layoutMode === 'vertical') {
127+
this.isOpen = true;
128+
}
129+
130+
return html`
47131
<div class="pl-c-tools">
48-
<button
49-
class="pl-c-tools__toggle pl-js-acc-handle"
50-
title="Tools"
51-
onClick={this.handleClick}
132+
<pl-button
133+
icon-only
134+
@click="${this.handleClick}"
135+
class="pl-c-tools__toggle"
136+
>
137+
<pl-icon name="settings" slot="after"></pl-icon>
138+
</pl-button>
139+
<ul
140+
class="pl-c-tools__list pl-js-acc-panel ${this.isOpen
141+
? 'is-open'
142+
: ''}"
52143
>
53-
<SettingsIcon
54-
width={18}
55-
height={18}
56-
viewBox="0 0 24 24"
57-
className="pl-c-tools__toggle-icon"
58-
fill="currentColor"
59-
/>
60-
</button>
61-
<ul class="pl-c-tools__list pl-js-acc-panel">
62144
<li class="pl-c-tools__item">
63-
<pl-toggle-info />
145+
<pl-toggle-info></pl-toggle-info>
64146
</li>
147+
65148
<li class="pl-c-tools__item">
66-
<pl-toggle-layout text="Switch Layout" />
149+
<pl-toggle-layout text="Switch Layout"></pl-toggle-layout>
67150
</li>
68151
<li class="pl-c-tools__item">
69-
<pl-toggle-theme />
152+
<pl-toggle-theme></pl-toggle-theme>
70153
</li>
71154
72-
{!this.ishControlsHide['views-new'] && (
73-
<li class="pl-c-tools__item">
74-
<a
75-
href={this.currentUrl}
76-
class="pl-c-tools__action pl-js-open-new-window"
77-
target="_blank"
78-
>
79-
<span class="pl-c-tools__action-text">Open In New Tab</span>
80-
<span class="pl-c-tools__action-icon">
81-
<NewTabIcon
82-
height={20}
83-
width={20}
84-
viewBox="0 0 24 24"
85-
fill="currentColor"
86-
/>
87-
</span>
88-
</a>
89-
</li>
90-
)}
91-
92-
{!this.ishControlsHide['tools-docs'] && (
93-
<li class="pl-c-tools__item">
94-
<a
95-
href="http://patternlab.io/docs/"
96-
class="pl-c-tools__action"
97-
target="_blank"
98-
>
99-
<span class="pl-c-tools__action-text">Pattern Lab Docs</span>
100-
<span class="pl-c-tools__action-icon">
101-
<HelpIcon
102-
height={20}
103-
width={20}
104-
viewBox="0 0 24 24"
105-
fill="currentColor"
106-
/>
107-
</span>
108-
</a>
109-
</li>
110-
)}
155+
${!this.ishControlsHide['views-new']
156+
? html`
157+
<li class="pl-c-tools__item">
158+
<pl-button href="${this.currentUrl}" target="_blank">
159+
Open In New Tab
160+
<pl-icon name="new-tab" slot="after"></pl-icon>
161+
</pl-button>
162+
</li>
163+
`
164+
: ''}
165+
${!this.ishControlsHide['tools-docs']
166+
? html`
167+
<li class="pl-c-tools__item">
168+
<pl-button href="http://patternlab.io/docs/" target="_blank">
169+
Pattern Lab Docs
170+
<pl-icon name="help" slot="after"></pl-icon>
171+
</pl-button>
172+
</li>
173+
`
174+
: ''}
111175
</ul>
112176
</div>
113-
);
177+
`;
114178
}
115179
}

packages/uikit-workshop/src/scripts/components/pl-tools-menu/pl-tools-menu.scss

Lines changed: 20 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -19,47 +19,34 @@ pl-tools-menu {
1919
display: flex;
2020
}
2121

22-
/**
23-
* Tools menu button
24-
* 1) This is the button that contains the toggle and
25-
* triggers the tools dropdown list
26-
*/
27-
.pl-c-tools__toggle {
28-
@include linkStyle();
29-
margin: 0;
30-
display: inline-flex;
31-
align-items: center;
32-
justify-content: center;
33-
position: relative;
34-
min-width: 30px;
35-
}
36-
37-
/**
38-
* Tools Toggle SVG icon
39-
* 1) Cog icon
40-
* 2) Set the width and height of the icon to be the same height of font
41-
*/
42-
.pl-c-tools__toggle-icon {
43-
transition: inherit; // inherit transition styles from parent toggle
44-
// pointer-events: none;
45-
}
46-
4722
/**
4823
* Tools dropdown list
4924
*/
5025
.pl-c-tools__list {
5126
@include listReset();
52-
@include accordionPanel();
5327
transform: translateY(-10px);
5428
position: absolute;
55-
right: 3px;
29+
right: 4px;
5630
z-index: 10; // make sure context dropdown z-index is higher than nav dropdown z-index
5731
width: 12rem;
5832
border-radius: 6px;
59-
top: calc(100% + 4px);
60-
box-shadow: 0 0 5px rgba(0, 0, 0, .1);
33+
top: calc(100% - 2px);
34+
box-shadow: 0 0 5px rgba(0, 0, 0, .2);
6135
background-color: $pl-color-gray-87;
6236
background-color: var(--theme-primary, $pl-color-gray-87);
37+
transform: translateY(-4rem);
38+
opacity: 0;
39+
max-height: 0;
40+
visibility: hidden;
41+
pointer-events: none;
42+
43+
&.is-open {
44+
opacity: 1;
45+
max-height: 9999px;
46+
visibility: visible;
47+
pointer-events: auto;
48+
transform: translateY(0);
49+
}
6350

6451
.pl-c-body--theme-light & {
6552
background-color: $pl-color-white;
@@ -73,10 +60,11 @@ pl-tools-menu {
7360
transform: none;
7461
border-radius: 0;
7562
background-color: transparent;
63+
right: 0;
7664
}
7765
}
7866

79-
&.pl-is-active {
67+
&.is-active {
8068
overflow: visible;
8169
}
8270

@@ -91,8 +79,6 @@ pl-tools-menu {
9179
top: -10px;
9280
transform: translateY(50%) translateX(-50%) rotate(45deg);
9381
transition: opacity 0.1s ease-out;
94-
opacity: 0;
95-
visibility: hidden;
9682
box-shadow: 0 0 5px rgba(0, 0, 0, .1);
9783

9884
.pl-c-body--theme-sidebar & {
@@ -102,7 +88,7 @@ pl-tools-menu {
10288
}
10389
}
10490

105-
&.pl-is-active:before {
91+
&.is-active:before {
10692
opacity: 1;
10793
visibility: visible;
10894
}
@@ -111,6 +97,7 @@ pl-tools-menu {
11197
.pl-c-tools__item {
11298
position: relative;
11399
overflow: hidden;
100+
background-color: inherit;
114101

115102
// crop list item when hover
116103
&:first-child {
@@ -136,28 +123,3 @@ pl-tools-menu {
136123
}
137124
}
138125

139-
140-
/**
141-
* Tools dropdown actions
142-
* 1) Links and buttons inside of the tools dropdown
143-
*/
144-
.pl-c-tools__action {
145-
@include linkStyle();
146-
padding-top: 0.4rem;
147-
padding-bottom: 0.4rem;
148-
display: flex;
149-
align-items: center;
150-
width: 100%;
151-
margin: 0;
152-
flex-direction: row-reverse;
153-
justify-content: flex-end;
154-
}
155-
156-
// Make sure the text and icon align to the opposite ends
157-
.pl-c-tools__action-icon {
158-
margin-right: 0.5rem;
159-
160-
&:first-child:last-child {
161-
margin-right: 0;
162-
}
163-
}

0 commit comments

Comments
 (0)