Skip to content

Commit e57dd03

Browse files
feat: new Search component (#506)
* fix(combobox): stop onInputChange trigger on onChange * feat(combobox): add `noResetInputOnBlur` feature to prevent input resets on combobox blur * fix(combobox): `allowsEmptyCollection` should display dropdown even when `options` is empty --------- Co-authored-by: jer3m01 <[email protected]>
1 parent 5312ce7 commit e57dd03

File tree

19 files changed

+2750
-365
lines changed

19 files changed

+2750
-365
lines changed

.npmrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
auto-install-peers=true
22
strict-peer-dependencies=false
3+
link-workspace-packages=true
4+
prefer-workspace-packages=true

apps/docs/package.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,37 +34,38 @@
3434
"dependencies": {
3535
"@docsearch/css": "3.5.2",
3636
"@docsearch/js": "3.5.2",
37-
"@kobalte/core": "0.13.7",
37+
"@kobalte/core": "workspace:*",
3838
"@solidjs/meta": "0.29.3",
3939
"@solidjs/router": "0.12.4",
40+
"@solidjs/start": "0.6.1",
4041
"@tanstack/solid-virtual": "3.0.0-beta.6",
4142
"clsx": "2.0.0",
43+
"minisearch": "7.1.0",
4244
"solid-js": "1.8.15",
43-
"@solidjs/start": "0.6.1",
44-
"vinxi": "0.3.9",
45-
"undici": "5.23.0"
45+
"undici": "5.23.0",
46+
"vinxi": "0.3.9"
4647
},
4748
"devDependencies": {
4849
"@kobalte/tailwindcss": "0.9.0",
4950
"@mdx-js/mdx": "3.0.0",
5051
"@mdx-js/rollup": "3.0.0",
5152
"@tailwindcss/typography": "0.5.9",
53+
"@vinxi/plugin-mdx": "3.7.1",
5254
"acorn": "8.10.0",
5355
"autoprefixer": "10.4.15",
5456
"github-slugger": "2.0.0",
5557
"postcss": "8.4.28",
5658
"rehype-pretty-code": "0.12.3",
57-
"remark-shiki-twoslash": "3.1.3",
5859
"rehype-raw": "7.0.0",
5960
"rehype-slug": "6.0.0",
6061
"remark-gfm": "4.0.0",
62+
"remark-shiki-twoslash": "3.1.3",
6163
"shiki": "0.14.7",
6264
"solid-mdx": "0.0.7",
6365
"tailwindcss": "3.3.3",
6466
"typescript": "4.9.5",
6567
"unist-util-visit": "5.0.0",
66-
"vite": "5.1.4",
67-
"@vinxi/plugin-mdx": "3.7.1"
68+
"vite": "5.1.4"
6869
},
6970
"engines": {
7071
"node": ">=18"

apps/docs/src/components/icons.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,41 @@ export function ArrowIcon(props: ComponentProps<"svg">) {
269269
</svg>
270270
);
271271
}
272+
273+
export function MagnifyingGlassIcon(props: ComponentProps<"svg">) {
274+
return (
275+
<svg
276+
xmlns="http://www.w3.org/2000/svg"
277+
viewBox="0 0 15 15"
278+
fill="currentColor"
279+
{...props}
280+
>
281+
<title>Magnifying Glass</title>
282+
<path
283+
d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z"
284+
fill="currentColor"
285+
fill-rule="evenodd"
286+
clip-rule="evenodd"
287+
/>
288+
</svg>
289+
);
290+
}
291+
292+
export function ReloadIcon(props: ComponentProps<"svg">) {
293+
return (
294+
<svg
295+
xmlns="http://www.w3.org/2000/svg"
296+
viewBox="0 0 15 15"
297+
fill="currentColor"
298+
{...props}
299+
>
300+
<title>Reload</title>
301+
<path
302+
d="M1.84998 7.49998C1.84998 4.66458 4.05979 1.84998 7.49998 1.84998C10.2783 1.84998 11.6515 3.9064 12.2367 5H10.5C10.2239 5 10 5.22386 10 5.5C10 5.77614 10.2239 6 10.5 6H13.5C13.7761 6 14 5.77614 14 5.5V2.5C14 2.22386 13.7761 2 13.5 2C13.2239 2 13 2.22386 13 2.5V4.31318C12.2955 3.07126 10.6659 0.849976 7.49998 0.849976C3.43716 0.849976 0.849976 4.18537 0.849976 7.49998C0.849976 10.8146 3.43716 14.15 7.49998 14.15C9.44382 14.15 11.0622 13.3808 12.2145 12.2084C12.8315 11.5806 13.3133 10.839 13.6418 10.0407C13.7469 9.78536 13.6251 9.49315 13.3698 9.38806C13.1144 9.28296 12.8222 9.40478 12.7171 9.66014C12.4363 10.3425 12.0251 10.9745 11.5013 11.5074C10.5295 12.4963 9.16504 13.15 7.49998 13.15C4.05979 13.15 1.84998 10.3354 1.84998 7.49998Z"
303+
fill="currentColor"
304+
fill-rule="evenodd"
305+
clip-rule="evenodd"
306+
/>
307+
</svg>
308+
);
309+
}
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
.search__control {
2+
overflow: hidden;
3+
display: inline-flex;
4+
justify-content: space-between;
5+
width: 250px;
6+
border-radius: 6px;
7+
font-size: 16px;
8+
line-height: 1;
9+
outline: none;
10+
background-color: white;
11+
border: 1px solid hsl(240 6% 90%);
12+
color: hsl(240 4% 16%);
13+
transition:
14+
border-color 250ms,
15+
color 250ms;
16+
}
17+
18+
.search__control_multi {
19+
width: 100%;
20+
min-width: 250px;
21+
max-width: 300px;
22+
}
23+
24+
.search__input {
25+
appearance: none;
26+
display: inline-flex;
27+
width: 100%;
28+
min-height: 40px;
29+
padding-left: 16px;
30+
font-size: 16px;
31+
background: transparent;
32+
border-top-left-radius: 6px;
33+
border-bottom-left-radius: 6px;
34+
outline: none;
35+
}
36+
37+
.search__input::placeholder {
38+
color: hsl(240 4% 46%);
39+
}
40+
41+
.search__indicator {
42+
appearance: none;
43+
display: inline-flex;
44+
justify-content: center;
45+
align-items: center;
46+
width: auto;
47+
outline: none;
48+
padding: 0 10px;
49+
background-color: hsl(240 5% 96%);
50+
border-right: 1px solid hsl(240 6% 90%);
51+
color: hsl(240 4% 16%);
52+
font-size: 16px;
53+
line-height: 0;
54+
transition: 250ms background-color;
55+
}
56+
57+
.search__icon {
58+
height: 20px;
59+
width: 20px;
60+
flex: 0 0 16px;
61+
display: grid;
62+
justify-items: center;
63+
}
64+
65+
.load__icon {
66+
height: 20px;
67+
width: 20px;
68+
display: grid;
69+
justify-items: center;
70+
flex: 0 0 14px;
71+
}
72+
73+
.center__icon {
74+
margin: auto;
75+
}
76+
77+
.spin__icon {
78+
animation: spin 600ms linear;
79+
animation-iteration-count: infinite;
80+
margin: auto;
81+
}
82+
83+
.search__description {
84+
margin-top: 8px;
85+
color: hsl(240 5% 26%);
86+
font-size: 12px;
87+
user-select: none;
88+
}
89+
90+
.search__content {
91+
background-color: white;
92+
border-radius: 6px;
93+
border: 1px solid hsl(240 6% 90%);
94+
box-shadow:
95+
0 4px 6px -1px rgb(0 0 0 / 0.1),
96+
0 2px 4px -2px rgb(0 0 0 / 0.1);
97+
transform-origin: var(--kb-search-content-transform-origin);
98+
animation: contentHide 250ms ease-in forwards;
99+
}
100+
101+
.search__content[data-expanded] {
102+
animation: contentShow 250ms ease-out;
103+
}
104+
105+
.search__listbox {
106+
overflow-y: auto;
107+
max-height: 360px;
108+
padding: 8px;
109+
display: grid;
110+
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
111+
row-gap: 6px;
112+
column-gap: 6px;
113+
line-height: 1;
114+
}
115+
116+
.search__listbox:focus {
117+
outline: none;
118+
}
119+
120+
.search__item {
121+
font-size: 24px;
122+
line-height: 1;
123+
color: hsl(240 4% 16%);
124+
border-radius: 16px;
125+
padding: 8px;
126+
position: relative;
127+
user-select: none;
128+
outline: none;
129+
display: grid;
130+
justify-items: center;
131+
}
132+
133+
.search__item[data-disabled] {
134+
color: hsl(240 5% 65%);
135+
opacity: 0.5;
136+
pointer-events: none;
137+
}
138+
139+
.search__item[data-highlighted] {
140+
outline: none;
141+
box-sizing: border-box;
142+
box-shadow: inset 0 0 0 2px hsl(200 98% 39%);
143+
}
144+
145+
.search__section {
146+
padding: 8px 0 0 8px;
147+
font-size: 14px;
148+
line-height: 32px;
149+
color: hsl(240 4% 46%);
150+
}
151+
152+
.search__no_result {
153+
text-align: center;
154+
padding: 8px;
155+
padding-bottom: 24px;
156+
margin: auto;
157+
color: hsl(240 4% 46%);
158+
}
159+
160+
@keyframes spin {
161+
from {
162+
transform: rotate(0deg);
163+
}
164+
to {
165+
transform: rotate(360deg);
166+
}
167+
}
168+
169+
@keyframes contentShow {
170+
from {
171+
opacity: 0;
172+
transform: translateY(-8px);
173+
}
174+
to {
175+
opacity: 1;
176+
transform: translateY(0);
177+
}
178+
}
179+
180+
@keyframes contentHide {
181+
from {
182+
opacity: 1;
183+
transform: translateY(0);
184+
}
185+
to {
186+
opacity: 0;
187+
transform: translateY(-8px);
188+
}
189+
}
190+
191+
[data-kb-theme="dark"] .search__control {
192+
background-color: hsl(240 4% 16%);
193+
border: 1px solid hsl(240 5% 34%);
194+
color: hsl(0 100% 100% / 0.9);
195+
}
196+
197+
[data-kb-theme="dark"] .search__control:hover {
198+
border-color: hsl(240 4% 46%);
199+
}
200+
201+
[data-kb-theme="dark"] .search__input::placeholder {
202+
color: hsl(0 100% 100% / 0.5);
203+
}
204+
205+
[data-kb-theme="dark"] .search__indicator {
206+
background: hsl(240 5% 26%);
207+
border-right: 1px solid hsl(240 5% 34%);
208+
color: hsl(0 100% 100% / 0.9);
209+
}
210+
211+
[data-kb-theme="dark"] .search__content {
212+
border: 1px solid hsl(240 5% 26%);
213+
background-color: hsl(240 4% 16%);
214+
box-shadow: none;
215+
}
216+
217+
[data-kb-theme="dark"] .search__section {
218+
color: hsl(0 100% 100% / 0.7);
219+
}
220+
221+
[data-kb-theme="dark"] .search__item {
222+
color: hsl(0 100% 100% / 0.9);
223+
}
224+
225+
[data-kb-theme="dark"] .search__description {
226+
color: hsl(0 100% 100% / 0.7);
227+
}
228+
229+
.result__content {
230+
margin-top: 16px;
231+
font-size: 16px;
232+
line-height: 1;
233+
}
234+
235+
.search__root_cmdk {
236+
min-height: 240px;
237+
min-width: 250px;
238+
display: flex;
239+
flex-direction: column;
240+
}
241+
242+
.search__control_cmdk {
243+
overflow: hidden;
244+
display: inline-flex;
245+
justify-content: space-between;
246+
border-radius: 12px 12px 0 0;
247+
font-size: 16px;
248+
line-height: 1;
249+
outline: none;
250+
background-color: white;
251+
border: 1px solid hsl(240 6% 90%);
252+
color: hsl(240 4% 16%);
253+
transition:
254+
border-color 250ms,
255+
color 250ms;
256+
}
257+
258+
.search__content_cmdk {
259+
height: 100%;
260+
flex-grow: 1;
261+
background-color: white;
262+
border-radius: 0 0 12px 12px;
263+
border: 1px solid hsl(240 6% 90%);
264+
border-top: none;
265+
display: flex;
266+
flex-direction: column;
267+
}
268+
269+
.search__no_result_cmdk {
270+
text-align: center;
271+
margin: auto;
272+
padding-bottom: 24px;
273+
color: hsl(240 4% 46%);
274+
}
275+
276+
[data-kb-theme="dark"] .search__control_cmdk {
277+
background-color: hsl(240 4% 16%);
278+
border: 1px solid hsl(240 5% 34%);
279+
color: hsl(0 100% 100% / 0.9);
280+
}
281+
282+
[data-kb-theme="dark"] .search__content_cmdk {
283+
background-color: hsl(240 4% 16%);
284+
border: 1px solid hsl(240 5% 34%);
285+
}

0 commit comments

Comments
 (0)