Skip to content

Commit 190b494

Browse files
authored
Merge pull request #1160 from pattern-lab/feature/nav-ui-refactor
Minor Nav Refactor + Fix for Overlapping Dropdown Menus
2 parents ff18eb5 + 7a8b418 commit 190b494

File tree

9 files changed

+252
-188
lines changed

9 files changed

+252
-188
lines changed

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

Lines changed: 30 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -10,161 +10,10 @@ import { BaseComponent } from '../base-component.js';
1010
import Mousetrap from 'mousetrap';
1111
import 'url-search-params-polyfill';
1212

13-
const SubSubList = props => {
14-
const { children, category, elem } = props;
15-
const reorderedChildren = [];
16-
17-
const nonViewAllItems = elem.noViewAll
18-
? children.filter(item => item.patternName !== 'View All')
19-
: children.filter(
20-
item =>
21-
item.patternName !== 'View All' && !item.patternName.includes(' Docs')
22-
);
23-
const viewAllItems = elem.noViewAll
24-
? []
25-
: children.filter(item => item.patternName === 'View All');
26-
27-
reorderedChildren.push(...viewAllItems, ...nonViewAllItems);
28-
29-
return (
30-
<li className={`pl-c-nav__item pl-c-nav__item--${category.toLowerCase()}`}>
31-
{viewAllItems.length > 0 ? (
32-
viewAllItems.map(patternSubtypeItem => (
33-
<div class="pl-c-nav__link--overview-wrapper">
34-
<a
35-
href={`patterns/${patternSubtypeItem.patternPath}`}
36-
className={`pl-c-nav__link pl-c-nav__link--sublink
37-
${
38-
patternSubtypeItem.patternName === 'View All'
39-
? 'pl-c-nav__link--overview pl-js-link-overview'
40-
: 'pl-c-nav__link--subsublink'
41-
}
42-
`}
43-
onClick={e =>
44-
elem.handleClick(e, patternSubtypeItem.patternPartial)
45-
}
46-
data-patternpartial={patternSubtypeItem.patternPartial}
47-
>
48-
{patternSubtypeItem.patternName === 'View All'
49-
? `${category}`
50-
: patternSubtypeItem.patternName}
51-
{patternSubtypeItem.patternState && (
52-
<span
53-
class={`pl-c-pattern-state pl-c-pattern-state--${patternSubtypeItem.patternState}`}
54-
title={patternSubtypeItem.patternState}
55-
/>
56-
)}
57-
</a>
58-
59-
{nonViewAllItems.length >= 1 && (
60-
<SpecialButton
61-
aria-controls={category}
62-
onClick={elem.toggleSpecialNavPanel}
63-
>
64-
{category}
65-
</SpecialButton>
66-
)}
67-
</div>
68-
))
69-
) : (
70-
<Button aria-controls={category} onClick={elem.toggleNavPanel}>
71-
{category}
72-
</Button>
73-
)}
74-
75-
{((viewAllItems.length && nonViewAllItems.length) ||
76-
viewAllItems.length === 0) && (
77-
<ol
78-
id={category}
79-
className={`pl-c-nav__subsublist pl-c-nav__subsublist--dropdown pl-js-acc-panel`}
80-
>
81-
{nonViewAllItems.map(patternSubtypeItem => (
82-
<li class="pl-c-nav__item">
83-
<a
84-
href={`patterns/${patternSubtypeItem.patternPath}`}
85-
className={`pl-c-nav__link pl-c-nav__link--sublink
86-
${
87-
patternSubtypeItem.patternName === 'View All'
88-
? 'pl-c-nav__link--overview'
89-
: 'pl-c-nav__link--subsublink'
90-
}
91-
`}
92-
onClick={e =>
93-
elem.handleClick(e, patternSubtypeItem.patternPartial)
94-
}
95-
data-patternpartial={patternSubtypeItem.patternPartial}
96-
>
97-
{patternSubtypeItem.patternName === 'View All'
98-
? `${category} Overview`
99-
: patternSubtypeItem.patternName}
100-
{patternSubtypeItem.patternState && (
101-
<span
102-
class={`pl-c-pattern-state pl-c-pattern-state--${patternSubtypeItem.patternState}`}
103-
title={patternSubtypeItem.patternState}
104-
/>
105-
)}
106-
</a>
107-
</li>
108-
))}
109-
</ol>
110-
)}
111-
</li>
112-
);
113-
};
114-
115-
const SpecialButton = props => {
116-
return (
117-
<button
118-
className={`pl-c-nav__link pl-c-nav__link--section-dropdown pl-js-acc-handle`}
119-
role="tab"
120-
{...props}
121-
>
122-
{props.children}
123-
<span
124-
class="pl-c-nav__link-icon"
125-
dangerouslySetInnerHTML={{
126-
__html: '<pl-icon name="arrow-down"></pl-icon>',
127-
}}
128-
/>
129-
</button>
130-
);
131-
};
132-
133-
const Button = props => {
134-
return (
135-
<button
136-
className={`pl-c-nav__link pl-c-nav__link--dropdown pl-js-acc-handle`}
137-
role="tab"
138-
{...props}
139-
>
140-
<span className={`pl-c-nav__link-text`}>{props.children}</span>
141-
<span
142-
class="pl-c-nav__link-icon"
143-
dangerouslySetInnerHTML={{
144-
__html: '<pl-icon name="arrow-down"></pl-icon>',
145-
}}
146-
/>
147-
</button>
148-
);
149-
};
150-
151-
const ButtonTitle = props => {
152-
return (
153-
<button
154-
className={`pl-c-nav__link pl-c-nav__link--title pl-js-acc-handle`}
155-
role="tab"
156-
{...props}
157-
>
158-
<span
159-
class="pl-c-nav__link-icon"
160-
dangerouslySetInnerHTML={{
161-
__html: '<pl-icon name="arrow-down"></pl-icon>',
162-
}}
163-
/>
164-
<span className={`pl-c-nav__link-text`}>{props.children}</span>
165-
</button>
166-
);
167-
};
13+
import { NavTitle } from './src/NavTitle';
14+
import { NavList } from './src/NavList';
15+
import { NavLink } from './src/NavLink';
16+
import { NavItem } from './src/NavItem';
16817

16918
@define
17019
class Nav extends BaseComponent {
@@ -370,7 +219,22 @@ class Nav extends BaseComponent {
370219

371220
toggleNavPanel(e) {
372221
const target = e.target;
222+
373223
target.classList.toggle('pl-is-active');
224+
225+
// when the Nav renders as a dropdown menu, only allow one top-level menu item to be open at a time to prevent overlap issues
226+
if (this.layoutMode !== 'vertical' && window.innerWidth > 670) {
227+
this.topLevelTriggers = document.querySelectorAll(
228+
'.pl-c-nav__link--title.pl-is-active'
229+
);
230+
231+
this.topLevelTriggers.forEach(trigger => {
232+
if (trigger !== target) {
233+
trigger.classList.remove('pl-is-active');
234+
trigger.nextSibling.classList.remove('pl-is-active');
235+
}
236+
});
237+
}
374238
}
375239

376240
rendered() {
@@ -393,32 +257,28 @@ class Nav extends BaseComponent {
393257
return (
394258
<ol class="pl-c-nav__list pl-js-pattern-nav-target">
395259
{patternTypes.map((item, i) => {
396-
const classes = classNames({
397-
[`pl-c-nav__item pl-c-nav__item--${item.patternTypeLC}`]: true,
398-
});
399-
400260
const patternItems = item.patternItems;
401261

402262
return (
403-
<li className={classes}>
404-
<ButtonTitle
263+
<NavItem className={`pl-c-nav__item--${item.patternTypeLC}`}>
264+
<NavTitle
405265
aria-controls={item.patternTypeLC}
406266
onClick={this.toggleNavPanel}
407267
>
408268
{item.patternTypeUC}
409-
</ButtonTitle>
269+
</NavTitle>
410270
<ol
411271
id={item.patternSubtypeUC}
412272
className={`pl-c-nav__sublist pl-c-nav__sublist--dropdown pl-js-acc-panel`}
413273
>
414274
{item.patternTypeItems.map((patternSubtype, i) => {
415275
return (
416-
<SubSubList
276+
<NavList
417277
elem={this.elem}
418278
category={patternSubtype.patternSubtypeUC}
419279
>
420280
{patternSubtype.patternSubtypeItems}
421-
</SubSubList>
281+
</NavList>
422282
);
423283
})}
424284

@@ -428,31 +288,13 @@ class Nav extends BaseComponent {
428288
patternItem.patternPartial.includes('viewall') ? (
429289
''
430290
) : (
431-
<li class="pl-c-nav__item">
432-
<a
433-
href={`patterns/${patternItem.patternPath}`}
434-
class="pl-c-nav__link pl-c-nav__link--pattern"
435-
onClick={e =>
436-
this.handleClick(e, patternItem.patternPartial)
437-
}
438-
data-patternpartial={patternItem.patternPartial}
439-
tabindex="0"
440-
>
441-
{patternItem.patternName === 'View All'
442-
? patternItem.patternName + ' ' + item.patternTypeUC
443-
: patternItem.patternName}
444-
{patternItem.patternState && (
445-
<span
446-
class={`pl-c-pattern-state pl-c-pattern-state--${patternItem.patternState}`}
447-
title={patternItem.patternState}
448-
/>
449-
)}
450-
</a>
451-
</li>
291+
<NavItem>
292+
<NavLink item={patternItem} elem={this} />
293+
</NavItem>
452294
);
453295
})}
454296
</ol>
455-
</li>
297+
</NavItem>
456298
);
457299
})}
458300

@@ -461,7 +303,7 @@ class Nav extends BaseComponent {
461303
window.ishControls.ishControlsHide === undefined ||
462304
(window.ishControls.ishControlsHide['views-all'] !== true &&
463305
window.ishControls.ishControlsHide.all !== true)) && (
464-
<li class="pl-c-nav__item">
306+
<NavItem>
465307
<a
466308
onClick={e => this.handleClick(e, 'all')}
467309
href="styleguide/html/styleguide.html"
@@ -471,7 +313,7 @@ class Nav extends BaseComponent {
471313
>
472314
All
473315
</a>
474-
</li>
316+
</NavItem>
475317
)}
476318
</ol>
477319
);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { h } from 'preact';
2+
3+
export const NavButton = props => {
4+
return (
5+
<button
6+
className={`pl-c-nav__link pl-c-nav__link--dropdown pl-js-acc-handle`}
7+
role="tab"
8+
{...props}
9+
>
10+
<span className={`pl-c-nav__link-text`}>{props.children}</span>
11+
<span
12+
class="pl-c-nav__link-icon"
13+
dangerouslySetInnerHTML={{
14+
__html: '<pl-icon name="arrow-down"></pl-icon>',
15+
}}
16+
/>
17+
</button>
18+
);
19+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { h } from 'preact';
2+
import cx from 'classnames';
3+
4+
export const NavItem = props => {
5+
const classes = cx('pl-c-nav__item', props.className);
6+
7+
return <li className={classes}>{props.children}</li>;
8+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { h } from 'preact';
2+
import { PatternState } from './PatternState';
3+
4+
export const NavLink = props => {
5+
return (
6+
<a
7+
href={`patterns/${props.item.patternPath}`}
8+
className={`pl-c-nav__link pl-c-nav__link--sublink
9+
${
10+
props.item.patternName === 'View All'
11+
? 'pl-c-nav__link--overview'
12+
: 'pl-c-nav__link--subsublink'
13+
}
14+
`}
15+
onClick={e => props.elem.handleClick(e, props.item.patternPartial)}
16+
data-patternpartial={props.item.patternPartial}
17+
>
18+
{props.item.patternName === 'View All' && props.category
19+
? `${props.category}`
20+
: props.item.patternName}
21+
{props.item.patternState && (
22+
<PatternState variant={props.item.patternState} />
23+
)}
24+
</a>
25+
);
26+
};

0 commit comments

Comments
 (0)