Skip to content

Commit aa52b8f

Browse files
authored
Merge pull request #190 from rackerlabs/surf-726-build-assisted-search
feat(assisted-search): build assisted search styles
2 parents 0c8691b + c58d706 commit aa52b8f

File tree

13 files changed

+316
-19
lines changed

13 files changed

+316
-19
lines changed

docs/_data/nav.json5

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
{ label: '<hx-popover-head>', path: 'hx-popover-head' },
8888
{ label: '<hx-reveal>', path: 'hx-reveal' },
8989
{ label: '<hx-search>', path: 'hx-search' },
90+
{ label: '<hx-search-assistance>', path: 'hx-search-assistance' },
9091
{ label: '<hx-status>', path: 'hx-status' },
9192
{ label: '<hx-tab>', path: 'hx-tab' },
9293
{ label: '<hx-tabcontent>', path: 'hx-tabcontent' },

docs/components/search/index.html

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,14 @@
33
minver: 0.4.0
44
also:
55
elements/hx-search: <hx-search>
6+
elements/hx-search-assistance: <hx-search-assistance>
67
---
78
{% extends 'component.njk' %}
89
{% block content %}
910
<section>
1011
<h2 id="demos">Demos</h2>
1112
<div id="vue-searchDemo" class="hxRow" v-cloak>
12-
<div class="hxCol hxSpan-12-xs hxSpan-9-lg">
13-
<h3>Basic Search Box</h3>
14-
<div class="demo">
15-
<hx-search
16-
:disabled="isDisabled"
17-
:invalid="isInvalid"
18-
:placeholder="placeholder"
19-
:value="searchValue"
20-
@input="onSearchUpdate"
21-
@clear="onSearchUpdate"
22-
></hx-search>
23-
</div>
24-
25-
<pre><code>{% raw %}{{snippet}}{% endraw %}</code></pre>
26-
</div>
27-
<div class="hxCol hxSpan-12-xs hxSpan-3-lg">
13+
<div class="hxCol hxSpan-12-xs hxSpan-3-lg hxOrder-2-lg">
2814
<h3>Options</h3>
2915
<p>
3016
<b>Placeholder:</b><br />
@@ -59,6 +45,65 @@ <h3>Options</h3>
5945
<label>Invalid</label>
6046
</p>
6147
</div>
48+
<div class="hxCol hxSpan-12-xs hxSpan-9-lg hxOrder-1-lg">
49+
<h3>Basic Search Box</h3>
50+
<div class="demo">
51+
<hx-search
52+
:disabled="isDisabled"
53+
:invalid="isInvalid"
54+
:placeholder="placeholder"
55+
:value="searchValue"
56+
@clear="onSearchUpdate"
57+
@input="onSearchUpdate"
58+
></hx-search>
59+
</div>
60+
<pre><code>{% raw %}{{snippet}}{% endraw %}</code></pre>
61+
</div>
62+
</div>
63+
</section>
64+
65+
<section>
66+
<div id="vue-searchAssistanceDemo">
67+
<h3>Search Assistance</h3>
68+
<div class="demo">
69+
<hx-search
70+
id="assisted-hx-search"
71+
:value="searchValue"
72+
@blur="onBlur"
73+
@clear="onUpdate"
74+
@focus="onFocus"
75+
@input="onUpdate"
76+
></hx-search>
77+
<hx-search-assistance relative-to="assisted-hx-search" ref="search">
78+
<header>Search for "<span v-text="searchValue"></span>"</header>
79+
<section v-if="hasValue">
80+
<header>Category Header</header>
81+
<button class="hxSearchSuggestion">Here is a possible <b v-text="searchValue"></b></button>
82+
<button class="hxSearchSuggestion">Here is a possible <b v-text="searchValue"></b></button>
83+
<button class="hxSearchSuggestion">Here is a possible <b v-text="searchValue"></b></button>
84+
</section>
85+
</hx-search-assistance>
86+
</div>
87+
<small>
88+
*Behavior to show/hide search assistance may differ in your app.
89+
</small>
90+
{% code 'html' %}
91+
<hx-search
92+
id="assisted-search"
93+
onblur="hideAssistance()"
94+
onfocus="showAssistance()"
95+
value="item"
96+
></hx-search>
97+
<hx-search-assistance relative-to="assisted-search">
98+
<header>Search for "item"</header>
99+
<section>
100+
<header>Category Header</header>
101+
<button class="hxSearchSuggestion">Here is a possible <b>item</b></button>
102+
<button class="hxSearchSuggestion">Here is a possible <b>item</b></button>
103+
<button class="hxSearchSuggestion">Here is a possible <b>item</b></button>
104+
</section>
105+
</hx-search-assistance>
106+
{% endcode %}
62107
</div>
63108
</section>
64109

docs/components/search/search-demo.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,30 @@ if (document.getElementById('vue-searchDemo')) {
3838
},
3939
},
4040
});
41+
}//vue-searchDemo
42+
43+
if (document.getElementById('vue-searchAssistanceDemo')) {
44+
new Vue({
45+
el: '#vue-searchAssistanceDemo',
46+
data: {
47+
searchValue: '',
48+
},
49+
methods: {
50+
// fires on 'input' and 'clear' events
51+
onUpdate: function (evt) {
52+
this.searchValue = evt.target.value;
53+
},
54+
onFocus: function () {
55+
this.$refs.search.open = true;
56+
},
57+
onBlur: function () {
58+
this.$refs.search.open = false;
59+
},
60+
},
61+
computed: {
62+
hasValue: function () {
63+
return (this.searchValue && this.searchValue !== '');
64+
},
65+
},
66+
});
4167
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
---
2+
title: <hx-search-assistance>
3+
also:
4+
components/search: Search
5+
elements/hx-search: <hx-search>
6+
---
7+
{% extends 'element.njk' %}
8+
{% block content %}
9+
<section>
10+
<p>
11+
The custom <code>{{page.title}}</code> element contains a list of choices
12+
for the user, such as recent or suggested searches depending on their context.
13+
</p>
14+
15+
<hx-dl class="hxBox-md metadata">
16+
<hx-def>
17+
<hx-dt>Permitted Parents</hx-dt>
18+
<hx-dd>any</hx-dd>
19+
</hx-def>
20+
<hx-def>
21+
<hx-dt>Permitted Children</hx-dt>
22+
<hx-dd>flow content</hx-dd>
23+
</hx-def>
24+
<hx-def>
25+
<hx-dt>Events</hx-dt>
26+
<hx-dd>
27+
Any of the following:
28+
<ul>
29+
<li><code>close</code></li>
30+
<li><code>open</code></li>
31+
</ul>
32+
</hx-dd>
33+
</hx-def>
34+
</hx-dl>
35+
</section>
36+
{% endblock %}
37+
38+
{% block attributes %}
39+
<dl>
40+
<dt>open</dt>
41+
<dd>Opens the search assistance</dd>
42+
43+
<dt>position <small>{String="bottom-start"}</small></dt>
44+
<dd>Positions the search assistance</dd>
45+
46+
<dt>relative-to <small>(optional)</small></dt>
47+
<dd>ID of an element that the search assistance is positioned relative to.</dd>
48+
</dl>
49+
{% endblock %}
50+
51+
{% block properties %}
52+
<dl>
53+
<dt>open</dt>
54+
<dd>Opens the search assistance</dd>
55+
56+
<dt>position <small>{String="bottom-start"}</small></dt>
57+
<dd>Positions the search assistance</dd>
58+
59+
<dt>relativeTo <small>(optional)</small></dt>
60+
<dd>ID of an element that the search assistance is positioned relative to.</dd>
61+
</dl>
62+
{% endblock %}

docs/elements/hx-search/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
minver: 0.4.0
44
also:
55
components/search: Search
6+
elements/hx-search-assistance: <hx-search-assistance>
67
---
78
{% extends 'element.njk' %}
89
{% block content %}

src/helix-ui.less

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ figure {
6969
@import 'core/hx-popover-head';
7070
@import 'core/hx-reveal';
7171
@import 'core/hx-search';
72+
@import 'core/hx-search-assistance';
7273
@import 'core/hx-status';
7374
@import 'core/hx-tab';
7475
@import 'core/hx-tabcontent';
@@ -82,12 +83,13 @@ figure {
8283

8384

8485
/* ========== COMPONENTS ========== *\
85-
- Class Selectors ONLY
86-
- No Element Selectors
86+
- Complex CSS Selectors
8787
- NO !important
8888
\* ========== COMPONENTS ========== */
8989
@import 'components/layouts';
90-
// MODULES (convert to components)
90+
@import 'components/search';
91+
92+
// MODULES (TODO: convert to components)
9193
@import 'modules/box';
9294
@import 'modules/breadcrumb';
9395
@import 'modules/button';

src/helix-ui/elements.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export { HXModalElement } from './elements/HXModalElement.js';
1111
export { HXPopoverElement } from './elements/HXPopoverElement.js';
1212
export { HXRevealElement } from './elements/HXRevealElement.js';
1313
export { HXSearchElement } from './elements/HXSearchElement.js';
14+
export { HXSearchAssistanceElement } from './elements/HXSearchAssistanceElement.js';
1415
export { HXTabcontentElement } from './elements/HXTabcontentElement.js';
1516
export { HXTabElement } from './elements/HXTabElement.js';
1617
export { HXTablistElement } from './elements/HXTablistElement.js';
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { HXElement } from './HXElement';
2+
import { getPosition } from '../util';
3+
4+
export class HXSearchAssistanceElement extends HXElement {
5+
static get is () {
6+
return 'hx-search-assistance';
7+
}
8+
9+
static get observedAttributes () {
10+
return [ 'open' ];
11+
}
12+
13+
attributeChangedCallback (attr, oldVal, newVal) {
14+
let isOpen = (newVal !== null);
15+
if (newVal !== oldVal) {
16+
this.$emit(isOpen ? 'open' : 'close');
17+
}
18+
}
19+
20+
connectedCallback () {
21+
this.$upgradeProperty('open');
22+
this.$upgradeProperty('position');
23+
this.$upgradeProperty('relativeTo');
24+
this.$defaultAttribute('position', 'bottom-start');
25+
}
26+
27+
set position (value) {
28+
if (value) {
29+
this.setAttribute('position', value);
30+
} else {
31+
this.removeAttribute('position');
32+
}
33+
}
34+
35+
get position () {
36+
return this.getAttribute('position');
37+
}
38+
39+
set relativeTo (value) {
40+
this.setAttribute('relative-to', value);
41+
}
42+
43+
get relativeTo () {
44+
return this.getAttribute('relative-to');
45+
}
46+
47+
get relativeElement () {
48+
return this.getRootNode().getElementById(this.relativeTo);
49+
}
50+
51+
set open (value) {
52+
if (value) {
53+
this.setAttribute('open', '');
54+
this._setPosition();
55+
} else {
56+
this.removeAttribute('open');
57+
}
58+
}
59+
60+
get open () {
61+
return this.hasAttribute('open');
62+
}
63+
64+
_setPosition () {
65+
var offset = getPosition(this, this.relativeElement, {
66+
position: this.position,
67+
margin: 4,
68+
});
69+
this.style.top = offset.y + 'px';
70+
this.style.left = offset.x + 'px';
71+
}
72+
}//HXSearchAssistanceElement
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
hx-search-assistance {
2+
background-color: @gray-0;
3+
border-radius: 2px;
4+
border: 1px solid @gray-300;
5+
box-shadow: 0px 3px 3px 0 @shadow-color;
6+
max-height: 20rem; // 320px
7+
max-width: 32rem; // 512px
8+
min-width: 25rem; // 400px
9+
overflow-x: hidden;
10+
overflow-y: auto;
11+
position: absolute;
12+
z-index: @search-assistance-z-index;
13+
14+
> header {
15+
align-items: center;
16+
color: @gray-600;
17+
display: flex;
18+
height: 2.5rem; // 40px
19+
padding: 0 0.75rem;
20+
}
21+
22+
> section {
23+
border-top: 1px solid @gray-400;
24+
padding: 1rem 0;
25+
26+
> * {
27+
padding: 0 0.75rem;
28+
}
29+
30+
> header {
31+
color: @gray-600;
32+
font-size: 0.875rem;
33+
font-weight: 500;
34+
text-transform: uppercase;
35+
36+
+ * {
37+
margin-top: 0.5rem;
38+
}
39+
}
40+
}
41+
}
42+
43+
.hxSearchSuggestion {
44+
background-color: transparent; //polyfill browsers
45+
border: none;
46+
color: @gray-900;
47+
cursor: pointer;
48+
display: block;
49+
font-size: 0.875rem;
50+
line-height: 1.5rem;
51+
text-align: left;
52+
width: 100%;
53+
54+
&:hover {
55+
background-color: @cyan-50;
56+
}
57+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
hx-search-assistance {
2+
display: none;
3+
4+
&[open] {
5+
display: block;
6+
}
7+
}

0 commit comments

Comments
 (0)