Skip to content

Commit 3113b89

Browse files
committed
Fix inconsistent data attribute location for web component
For the most part 1.3.0, expected data attributes on the `<form>` element, but this didn't work right for styling where we largely swap selectors from `.tsmb-form` to `typesense-minibar`. This means the following selector didn't work right in web component context: ``` .tsmb-form[data-group="true"] .tsmb-suggestion_title typesense-minibar[data-group="true"] .tsmb-suggestion_title ``` Thinking about it some more, it seems more elegant to have these on the custom element rather than on the form. So rather than fix the bug by changing the styles, let's change the place where we set the data attributes to match the style. Also use this time to promote the web component by default in documentation.
1 parent 2c1f279 commit 3113b89

File tree

6 files changed

+173
-104
lines changed

6 files changed

+173
-104
lines changed

API-Style.md

Lines changed: 93 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ This works best for making minor changes, such as changing the link and
1212
highlight color, or creating a dark mode. Copy or import the [typesense-minibar.css](./typesense-minibar.css)
1313
stylesheet, then override any of the below variables from your own stylesheet.
1414

15-
Note: Set variables on the `.tsmb-form` selector only. The variables are
15+
Note: Set variables on the `.tsmb-form` or `typesense-minibar` selector only. The variables are
1616
automatically picked up by the internal more specific selectors.
1717
You don't have to write any custom CSS rules!
1818

@@ -46,7 +46,19 @@ Primary colors, by default only used in the active layout:
4646
* `--tsmb-color-primary50`: Medium contrast, for colorful links or buttons.
4747
* `--tsmb-color-primary90`: Subtle contrast, for selection background.
4848

49-
Example:
49+
Example (Web Component):
50+
51+
```css
52+
/* Dark theme for inactive input field. */
53+
typesense-minibar {
54+
--tsmb-color-base-background: #691c69;
55+
--tsmb-color-base30: #390f39;
56+
--tsmb-color-base50: #c090c0;
57+
--tsmb-color-base90: #c090c0;
58+
}
59+
```
60+
61+
Example (class):
5062

5163
```css
5264
/* Dark theme for inactive input field. */
@@ -67,12 +79,12 @@ In that case, we recommend you target the documented selectors below.
6779
| --- | :---
6880
| `.tsmb-form--slash …` | Pressing a slash will activate this form. Use as basis for longer selectors.<br/><br/>This selector matches after the JavaScript code has run, unless configured with `data-slash=false`). This ensures you can safely use it to create a slash icon, and trust that it won't be displayed if JavaScript failed, was unsupported, or was disabled.<br><br>**Example**: `.tsmb-form--slash:not(:focus-within)::after { content: '/'; }`
6981
| `.tsmb-form--open` | The form currently has an open result box.
70-
| `.tsmb-form[data-group=true] …` | Override styled when using grouped results. Use as basis for longer selectors.
71-
| `.tsmb-form input[type=search]`<br><br>`.tsmb-form input[type=search]::placeholder` | Input field.
72-
| `.tsmb-form [role=listbox]` | Dropdown menu, populated with either one or more search results, or `.tsmb-empty`. When the results are closed, this element is hidden by setting the native `hidden` attribute.
73-
| `.tsmb-form [role=option]`<br><br>`.tsmb-form [role=option][aria-selected=true]` | Search result.
74-
| `.tsmb-form [role=option] a` | Clickable portion of result (title + content). This covers the full search result, except when results are grouped, then the first result in a group additionally contains `.tsmb-suggestion_group` outside the clickable portion.
75-
| `.tsmb-form [role=option] mark` | Matching characters or words, e.g. in the excerpt.
82+
| `.tsmb-form[data-group=true] …`<br><br>`typesense-minibar[data-group=true] …` | Override styled when using grouped results. Use as basis for longer selectors.
83+
| `.tsmb-form input[type=search]`<br><br>`.tsmb-form input[type=search]::placeholder`<br><br>`typesense-minibar input[type=search]` | Input field.
84+
| `.tsmb-form [role=listbox]`<br><br>`typesense-minibar [role=listbox]` | Dropdown menu, populated with either one or more search results, or `.tsmb-empty`. When the results are closed, this element is hidden by setting the native `hidden` attribute.
85+
| `.tsmb-form [role=option]`<br><br>`.tsmb-form [role=option][aria-selected=true]`<br><br>`typesense-minibar [role=option]` | Search result.
86+
| `.tsmb-form [role=option] a`<br><br>`typesense-minibar [role=option] a` | Clickable portion of result (title + content). This covers the full search result, except when results are grouped, then the first result in a group additionally contains `.tsmb-suggestion_group` outside the clickable portion.
87+
| `.tsmb-form [role=option] mark`<br><br>`typesense-minibar [role=option] mark` | Matching characters or words, e.g. in the excerpt.
7688
| `.tsmb-suggestion_group` | Group heading, may appear if the form is configured with `data-group=true`.
7789
| `.tsmb-suggestion_title` | Page title and optionally heading breadcrumbs to the matching paragraph.
7890
| `.tsmb-suggestion_content` | Page excerpt, typically a matching sentence.
@@ -82,67 +94,88 @@ In that case, we recommend you target the documented selectors below.
8294
Example DOM, stripped of internal details:
8395

8496
```html
85-
<form role="search" data-origin="" data-collection="" data-key=""
86-
class="tsmb-form"
87-
>
88-
<input type="search">
89-
90-
<div role="listbox">
91-
<div role="option" aria-selected="true">
92-
<a href="">
93-
<div class="tsmb-suggestion_title">…</div>
94-
<div class="tsmb-suggestion_content">…</div>
95-
</a>
96-
</div>
97-
<div role="option">…</div>
98-
</div>
99-
100-
<svg class="tsmb-icon-close">…</svg>
97+
<typesense-minibar data-origin="" data-collection="" data-key="">
98+
<form role="search">
99+
<input type="search">
100+
101+
<div role="listbox">
102+
<div role="option" aria-selected="true">
103+
<a href="">
104+
<div class="tsmb-suggestion_title">…</div>
105+
<div class="tsmb-suggestion_content">…</div>
106+
</a>
107+
</div>
108+
<div role="option">…</div>
109+
</div>
110+
111+
<svg class="tsmb-icon-close">…</svg>
112+
</form>
113+
</typesense-minibar>
114+
```
115+
116+
Example DOM, when using the HTML class:
117+
118+
```html
119+
<form role="search" class="tsmb-form"
120+
data-origin="" data-collection="" data-key="">
121+
<input type="search">
122+
123+
<div role="listbox">
124+
<div role="option" aria-selected="true">
125+
<a href="">
126+
<div class="tsmb-suggestion_title">…</div>
127+
<div class="tsmb-suggestion_content">…</div>
128+
</a>
129+
</div>
130+
<div role="option">…</div>
131+
</div>
132+
133+
<svg class="tsmb-icon-close">…</svg>
101134
</form>
102135
```
103136

104137
Example DOM, when using `data-group=true`:
105138

106139
```html
107-
<form role="search" data-origin="" data-collection="" data-key=""
108-
class="tsmb-form"
109-
data-group="true"
110-
>
111-
<input type="search">
112-
113-
<div role="listbox">
114-
<div role="option">
115-
<div class="tsmb-suggestion_group">My Group</div>
116-
<a href="">…</a>
117-
</div>
118-
<div role="option">
119-
<a href="">…</a>
120-
</div>
121-
<div role="option">
122-
<div class="tsmb-suggestion_group">My Second Group</div>
123-
<a href="">…</a>
124-
</div>
125-
</div>
126-
127-
<svg class="tsmb-icon-close">…</svg>
128-
</form>
140+
<typesense-minibar data-origin="" data-collection="" data-key=""
141+
data-group="true">
142+
<form role="search">
143+
<input type="search">
144+
145+
<div role="listbox">
146+
<div role="option">
147+
<div class="tsmb-suggestion_group">My Group</div>
148+
<a href="">…</a>
149+
</div>
150+
<div role="option">
151+
<a href="">…</a>
152+
</div>
153+
<div role="option">
154+
<div class="tsmb-suggestion_group">My Second Group</div>
155+
<a href="">…</a>
156+
</div>
157+
</div>
158+
159+
<svg class="tsmb-icon-close">…</svg>
160+
</form>
161+
</typesense-minibar>
129162
```
130163

131164
Example DOM, when using `data-foot=true`:
132165

133166
```html
134-
<form role="search" data-origin="" data-collection="" data-key=""
135-
class="tsmb-form"
136-
data-foot="true"
137-
>
138-
<input type="search">
139-
140-
<div role="listbox">
141-
<div role="option">…</div>
142-
<div role="option">…</div>
143-
<a class="tsmb-foot" href="https://typesense.org" title="Search by Typesense"></a>
144-
</div>
145-
146-
<svg class="tsmb-icon-close">…</svg>
147-
</form>
167+
<typesense-minibar data-origin="" data-collection="" data-key=""
168+
data-foot="true">
169+
<form role="search">
170+
<input type="search">
171+
172+
<div role="listbox">
173+
<div role="option">…</div>
174+
<div role="option">…</div>
175+
<a class="tsmb-foot" href="https://typesense.org" title="Search by Typesense"></a>
176+
</div>
177+
178+
<svg class="tsmb-icon-close">…</svg>
179+
</form>
180+
</typesense-minibar>
148181
```

README.md

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,12 @@
2626
**[Demo](https://jquery.github.io/typesense-minibar/demo/)**
2727

2828
```html
29-
<form role="search" class="tsmb-form" action="https://duckduckgo.com"
30-
data-origin=""
31-
data-collection=""
32-
data-key="">
33-
<input type="search" name="q" placeholder="Search..." autocomplete="off">
34-
<input type="hidden" name="sites" value="example.org">
35-
</form>
29+
<typesense-minibar data-origin="" data-collection="" data-key="">
30+
<form role="search" action="https://duckduckgo.com">
31+
<input type="search" name="q" placeholder="Search..." autocomplete="off">
32+
<input type="hidden" name="sites" value="example.org">
33+
</form>
34+
</typesense-minibar>
3635
```
3736

3837
```html
@@ -57,24 +56,37 @@ Distribution:
5756

5857
## API
5958

60-
### Web Component
59+
### Markup
6160

62-
`<typesense-minibar><form>…</form></typesense-minibar>` is equivalent to `<form class="tsmb-form">`.
61+
As HTML custom element (aka Web Component):
6362

6463
```html
65-
<typesense-minibar>
66-
<form role="search" action="https://duckduckgo.com"
67-
data-origin=""
68-
data-collection=""
69-
data-key="">
64+
<typesense-minibar data-origin="" data-collection="" data-key="">
65+
<form role="search" action="https://duckduckgo.com">
7066
<input type="search" name="q" placeholder="Search..." autocomplete="off">
7167
<input type="hidden" name="sites" value="example.org">
7268
</form>
7369
</typesense-minibar>
7470
```
7571

72+
`<typesense-minibar><form>…</form></typesense-minibar>` is equivalent to `<form class="tsmb-form">`,
73+
which you can also use directly:
74+
75+
```html
76+
<form role="search" action="https://duckduckgo.com" class="tsmb-form"
77+
data-origin=""
78+
data-collection=""
79+
data-key=""
80+
>
81+
<input type="search" name="q" placeholder="Search..." autocomplete="off">
82+
<input type="hidden" name="sites" value="example.org">
83+
</form>
84+
```
85+
7686
### Configuration
7787

88+
Set these attributes on `<typesense-minibar>` or `<form class="tsmb-form">`:
89+
7890
* ***data-origin*** (Required): Base URL to your Typesense server.
7991

8092
Include the `https://` or `http://` protocol, and (if non-default) the port number.

demo/index.html

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,51 +13,61 @@
1313
<header>
1414
<a href="../" class="demo-logo">Minibar</a>
1515

16-
<form role="search" class="tsmb-form" data-origin="https://typesense.jquery.com" data-collection="qunitjs_com" data-key="Zh8mMgohXECel9wjPwqT7lekLSG3OCgz" data-foot="true" action="https://duckduckgo.com">
17-
<input type="search" name="q" aria-label="Search" placeholder="Search..." autocomplete="off">
18-
<input type="hidden" name="sites" value="qunitjs.com">
19-
</form>
16+
<typesense-minibar data-origin="https://typesense.jquery.com" data-collection="qunitjs_com" data-key="Zh8mMgohXECel9wjPwqT7lekLSG3OCgz" data-foot="true">
17+
<form role="search" action="https://duckduckgo.com">
18+
<input type="search" name="q" aria-label="Search" placeholder="Search..." autocomplete="off">
19+
<input type="hidden" name="sites" value="qunitjs.com">
20+
</form>
21+
</typesense-minibar>
2022
</header>
2123
<header>
2224
<span class="demo-logo"></span>
23-
<!-- With data-group=true and right aligned. -->
25+
<!-- HTML class, with data-group=true, and right aligned. -->
2426
<form role="search" class="tsmb-form demo-right-form" data-origin="https://typesense.jquery.com" data-collection="jquery_com" data-key="Zh8mMgohXECel9wjPwqT7lekLSG3OCgz" data-foot="true" data-group="true" action="https://duckduckgo.com">
2527
<input type="search" name="q" aria-label="Search" placeholder="Search..." autocomplete="off">
2628
<input type="hidden" name="sites" value="jquery.com">
2729
</form>
2830
</header>
2931
<header>
3032
<span class="demo-logo"></span>
31-
<!-- Web Component -->
32-
<typesense-minibar class="demo-right-form">
33-
<form role="search" data-origin="https://typesense.jquery.com" data-collection="jquery_com" data-key="Zh8mMgohXECel9wjPwqT7lekLSG3OCgz" data-foot="true" data-group="true" action="https://duckduckgo.com">
33+
<!-- Web Component class, with data-group=true, and right aligned. -->
34+
<typesense-minibar class="demo-right-form" data-origin="https://typesense.jquery.com" data-collection="jquery_com" data-key="Zh8mMgohXECel9wjPwqT7lekLSG3OCgz" data-foot="true" data-group="true">
35+
<form role="search" action="https://duckduckgo.com">
3436
<input type="search" name="q" aria-label="Search" placeholder="Search..." autocomplete="off">
3537
<input type="hidden" name="sites" value="jquery.com">
3638
</form>
3739
</typesense-minibar>
3840
</header>
3941
<main>
4042
<h2>Web Component</h2>
41-
<typesense-minibar>
42-
<form role="search" data-origin="https://typesense.jquery.com" data-collection="qunitjs_com" data-key="Zh8mMgohXECel9wjPwqT7lekLSG3OCgz" data-foot="true" action="https://duckduckgo.com">
43+
<typesense-minibar data-origin="https://typesense.jquery.com" data-collection="qunitjs_com" data-key="Zh8mMgohXECel9wjPwqT7lekLSG3OCgz" data-foot="true">
44+
<form role="search" action="https://duckduckgo.com">
4345
<input type="search" name="q" aria-label="Search" placeholder="Search..." autocomplete="off">
4446
<input type="hidden" name="sites" value="qunitjs.com">
4547
</form>
4648
</typesense-minibar>
4749

48-
<h2>Class</h2>
50+
<h2>HTML class</h2>
4951
<form role="search" class="tsmb-form" data-origin="https://typesense.jquery.com" data-collection="qunitjs_com" data-key="Zh8mMgohXECel9wjPwqT7lekLSG3OCgz" data-foot="true" action="https://duckduckgo.com">
5052
<input type="search" name="q" aria-label="Search" placeholder="Search..." autocomplete="off">
5153
<input type="hidden" name="sites" value="qunitjs.com">
5254
</form>
5355

54-
<h2>customize layout</h2>
56+
<h2>Style API (customize --tsmb-size-* variables)</h2>
5557
<form role="search" class="tsmb-form demo-custom-form" data-origin="https://typesense.jquery.com" data-collection="jquery_com" data-key="Zh8mMgohXECel9wjPwqT7lekLSG3OCgz" data-foot="true" data-group="true" action="https://duckduckgo.com">
5658
<input type="search" name="q" aria-label="Search" placeholder="Search..." autocomplete="off">
5759
<input type="hidden" name="sites" value="jquery.com">
5860
</form>
5961

60-
<h2>JavaScript disabled</h2>
62+
<h2>JavaScript disabled (Web Component)</h2>
63+
<typesense-minibar>
64+
<form role="search" action="https://duckduckgo.com">
65+
<input type="search" name="q" aria-label="Search" placeholder="Search..." autocomplete="off">
66+
<input type="hidden" name="sites" value="jquery.com">
67+
</form>
68+
</typesense-minibar>
69+
70+
<h2>JavaScript disabled (HTML class)</h2>
6171
<form role="search" class="tsmb-form" action="https://duckduckgo.com">
6272
<input type="search" name="q" aria-label="Search" placeholder="Search..." autocomplete="off">
6373
<input type="hidden" name="sites" value="jquery.com">

test/test.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ QUnit.module('typesense-minibar', hooks => {
532532
});
533533

534534
QUnit.test('Web Component [input, listbox, re-focus]', async assert => {
535-
const element = parseHTML('<typesense-minibar><form><input type="search"></form></typesense-minibar>');
535+
const element = parseHTML('<typesense-minibar data-origin="x"><form><input type="search"></form></typesense-minibar>');
536536
document.querySelector('#qunit-fixture').append(element);
537537
const form = element.querySelector('form');
538538
assert.equal(form.className, 'tsmb-form--slash', 'set form class');
@@ -555,4 +555,19 @@ QUnit.module('typesense-minibar', hooks => {
555555
input.focus();
556556
assert.false(listbox.hidden, 'listbox re-opened');
557557
});
558+
559+
QUnit.test('Web Component [data-slash=false]', async assert => {
560+
const element = parseHTML('<typesense-minibar data-origin="x" data-slash="false"><form><input type="search"></form></typesense-minibar>');
561+
document.querySelector('#qunit-fixture').append(element);
562+
const form = element.querySelector('form');
563+
assert.equal(form.className, '', 'form class unchanged');
564+
assert.false(form.contains(document.activeElement || null), 'focus after contruct');
565+
566+
// should be ignored when data-slash=false
567+
simulate(document, 'keydown', {}, { key: '/' });
568+
assert.false(form.contains(document.activeElement || null), 'focus after slash');
569+
570+
await new Promise(resolve => setTimeout(resolve));
571+
assert.false(form.contains(document.activeElement || null), 'focus after slash and timeout');
572+
});
558573
});

typesense-minibar.css

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,12 @@ typesense-minibar [role=option] a {
173173
}
174174

175175
.tsmb-form:not([data-group=true]) [role=option]:not(:first-child) a,
176-
typesense-minibar form:not([data-group=true]) [role=option]:not(:first-child) a {
176+
typesense-minibar:not([data-group=true]) [role=option]:not(:first-child) a {
177177
border-top: var(--tsmb-size-edge) solid var(--tsmb-color-focus90);
178178
}
179179

180180
.tsmb-form[data-group=true] [role=option] a,
181-
typesense-minibar form[data-group=true] [role=option] a {
181+
typesense-minibar[data-group=true] [role=option] a {
182182
margin: 0 var(--tsmb-size-base);
183183
padding: var(--tsmb-size-sm);
184184
}
@@ -210,7 +210,8 @@ typesense-minibar [role=option] mark {
210210
.tsmb-suggestion_title {
211211
color: var(--tsmb-color-primary30);
212212
}
213-
.tsmb-form[data-group=true] .tsmb-suggestion_title {
213+
.tsmb-form[data-group=true] .tsmb-suggestion_title,
214+
typesense-minibar[data-group=true] .tsmb-suggestion_title {
214215
font-weight: bold;
215216
font-size: var(--tsmb-size-sm);
216217
}

0 commit comments

Comments
 (0)