Skip to content

Commit 6a1710e

Browse files
fix(autocomplete & website deploy fixes): autocomplete dropdown fix & deploy fix
1 parent 634541c commit 6a1710e

File tree

8 files changed

+101
-125
lines changed

8 files changed

+101
-125
lines changed

apps/website/src/_state/component-statuses.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export const componentsStatuses: ComponentKitsStatuses = {
4040
},
4141
headless: {
4242
Accordion: 'Planned',
43+
Autocomplete: 'Draft',
4344
Carousel: 'Planned',
4445
Popover: 'Planned',
4546
Select: 'Draft',

apps/website/src/routes/docs/headless/(components)/autocomplete/examples.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ export const Example01 = component$(() => {
2727
return (
2828
<PreviewCodeExample>
2929
<div q:slot="actualComponent">
30-
<AutocompleteRoot class="relative text-white">
31-
<AutocompleteLabel class="text-inherit font-semibold">
30+
<AutocompleteRoot class="relative">
31+
<AutocompleteLabel class=" font-semibold dark:text-white text-[#333333]">
3232
Personal Trainers ⚡
3333
</AutocompleteLabel>
3434
<AutocompleteTrigger class="bg-[#1f2532] flex items-center rounded-sm border-[#7d95b3] border-[1px] relative">
35-
<AutocompleteInput class="w-44 bg-inherit px-2 pr-6" />
35+
<AutocompleteInput class="w-44 bg-inherit px-2 pr-6 text-white" />
3636
<AutocompleteButton class="w-6 h-6 group absolute right-0">
3737
<svg
3838
xmlns="http://www.w3.org/2000/svg"
@@ -47,7 +47,7 @@ export const Example01 = component$(() => {
4747
</svg>
4848
</AutocompleteButton>
4949
</AutocompleteTrigger>
50-
<AutocompleteListbox class="w-full bg-[#1f2532] px-4 py-2 mt-2 rounded-sm border-[#7d95b3] border-[1px]">
50+
<AutocompleteListbox class="text-white w-full bg-[#1f2532] px-4 py-2 mt-2 rounded-sm border-[#7d95b3] border-[1px]">
5151
{trainers.map((trainer, index) => (
5252
<AutocompleteOption
5353
optionValue={trainer}

apps/website/src/routes/docs/headless/(components)/select/examples.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ export const Example01 = component$(() => {
1515
return (
1616
<PreviewCodeExample>
1717
<div q:slot="actualComponent">
18-
<SelectRoot class="dark:bg-gray-700">
19-
<SelectLabel class="text-white font-semibold ml-2">
18+
<SelectRoot>
19+
<SelectLabel class=" font-semibold ml-2 text-[#333333] dark:text-white">
2020
Qwik Fruits
2121
</SelectLabel>
2222
<SelectTrigger class="flex justify-between items-center px-8 bg-[#1f2532] border-[#7d95b3] border-[1px] rounded-md p-4 group peer">

packages/kit-headless/src/components/Autocomplete/autocomplete.spec.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
AutocompleteListbox,
99
AutocompleteOption,
1010
} from './autocomplete';
11-
import './autocompleteTest.css';
1211

1312
const fruits = [
1413
'Apple',

packages/kit-headless/src/components/Autocomplete/autocomplete.stories.tsx

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -139,60 +139,6 @@ const RegularAutocomplete = () => (
139139
))}
140140
</AutocompleteListbox>
141141
</AutocompleteRoot>
142-
{/* <AutocompleteRoot style="width: fit-content">
143-
<AutocompleteLabel>Label</AutocompleteLabel>
144-
<AutocompleteTrigger>
145-
<AutocompleteInput />
146-
<AutocompleteButton>
147-
<svg
148-
xmlns="http://www.w3.org/2000/svg"
149-
viewBox="0 0 24 24"
150-
fill="none"
151-
stroke="currentColor"
152-
stroke-width="2"
153-
stroke-linecap="round"
154-
stroke-linejoin="round"
155-
style="width: 20px; height: 20px;"
156-
>
157-
<polyline points="6 9 12 15 18 9"></polyline>
158-
</svg>
159-
</AutocompleteButton>
160-
</AutocompleteTrigger>
161-
<AutocompleteListbox class="listboxStyle">
162-
{fruits.map((fruit, index) => (
163-
<AutocompleteOption optionValue={fruit} key={index}>
164-
{fruit}
165-
</AutocompleteOption>
166-
))}
167-
</AutocompleteListbox>
168-
</AutocompleteRoot>
169-
<AutocompleteRoot style="width: fit-content">
170-
<AutocompleteLabel>Label</AutocompleteLabel>
171-
<AutocompleteTrigger>
172-
<AutocompleteInput />
173-
<AutocompleteButton>
174-
<svg
175-
xmlns="http://www.w3.org/2000/svg"
176-
viewBox="0 0 24 24"
177-
fill="none"
178-
stroke="currentColor"
179-
stroke-width="2"
180-
stroke-linecap="round"
181-
stroke-linejoin="round"
182-
style="width: 20px; height: 20px;"
183-
>
184-
<polyline points="6 9 12 15 18 9"></polyline>
185-
</svg>
186-
</AutocompleteButton>
187-
</AutocompleteTrigger>
188-
<AutocompleteListbox class="listboxStyle">
189-
{fruits.map((fruit, index) => (
190-
<AutocompleteOption optionValue={fruit} key={index}>
191-
{fruit}
192-
</AutocompleteOption>
193-
))}
194-
</AutocompleteListbox>
195-
</AutocompleteRoot> */}
196142
</>
197143
);
198144

packages/kit-headless/src/components/Autocomplete/autocomplete.tsx

Lines changed: 76 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@ import {
1313
useId,
1414
useOnWindow,
1515
useTask$,
16+
QwikKeyboardEvent,
1617
} from '@builder.io/qwik';
1718

19+
import { isBrowser, isServer } from '@builder.io/qwik/build';
20+
1821
import { KeyCode } from '../../utils/key-code.type';
1922

2023
// import { Popover, PopoverContent, PopoverTrigger } from '../popover';
@@ -226,14 +229,17 @@ export const AutocompleteRoot = component$(
226229

227230
return (
228231
<div
229-
onKeyDown$={(e) => {
230-
if (e.key === 'Escape') {
231-
contextService.isExpanded.value = false;
232-
const inputElement = contextService.triggerRef.value
233-
?.firstElementChild as HTMLElement;
234-
inputElement?.focus();
235-
}
236-
}}
232+
onKeyDown$={[
233+
$((e: QwikKeyboardEvent) => {
234+
if (e.key === 'Escape') {
235+
contextService.isExpanded.value = false;
236+
const inputElement = contextService.triggerRef.value
237+
?.firstElementChild as HTMLElement;
238+
inputElement?.focus();
239+
}
240+
}),
241+
props.onKeyDown$,
242+
]}
237243
{...props}
238244
>
239245
<Slot />
@@ -279,7 +285,13 @@ export const AutocompleteInput = component$((props: InputProps) => {
279285
const ref = useSignal<HTMLElement>();
280286
const contextService = useContext(AutocompleteContextId);
281287

282-
useTask$(({ track }) => {
288+
/*
289+
previously had useTask here, but noticed whenever it first renders,
290+
it won't focus the first option when hitting the down arrow key to open the listbox
291+
Also, all of our tests break on useTask, BUT it seems to work fine in the browser with useTask.
292+
Very odd.
293+
*/
294+
useVisibleTask$(({ track }) => {
283295
track(() => contextService.inputValue.value);
284296

285297
contextService.filteredOptions = contextService.options.filter(
@@ -326,12 +338,15 @@ export const AutocompleteInput = component$((props: InputProps) => {
326338
aria-autocomplete="list"
327339
aria-controls={contextService.listBoxId}
328340
bind:value={contextService.inputValue}
329-
onKeyDown$={(e) => {
330-
if (e.key === 'ArrowDown') {
331-
contextService.isExpanded.value = true;
332-
contextService.filteredOptions[0]?.value?.focus();
333-
}
334-
}}
341+
onKeyDown$={[
342+
$((e: QwikKeyboardEvent) => {
343+
if (e.key === 'ArrowDown') {
344+
contextService.isExpanded.value = true;
345+
contextService.filteredOptions[0]?.value?.focus();
346+
}
347+
}),
348+
props.onKeyDown$,
349+
]}
335350
{...props}
336351
/>
337352
);
@@ -382,38 +397,41 @@ export const AutocompleteListbox = component$((props: ListboxProps) => {
382397
role="listbox"
383398
{...props}
384399
// aria-label={!contextService.labelRef.value ? contextService.inputValue.value : undefined}
385-
onKeyDown$={(e) => {
386-
const availableOptions = contextService.filteredOptions.map(
387-
(option) => option.value
388-
);
400+
onKeyDown$={[
401+
$((e: QwikKeyboardEvent) => {
402+
const availableOptions = contextService.filteredOptions.map(
403+
(option) => option.value
404+
);
405+
406+
const target = e.target as HTMLElement;
407+
const currentIndex = availableOptions.indexOf(target);
408+
409+
if (e.key === 'ArrowDown') {
410+
if (currentIndex === availableOptions.length - 1) {
411+
availableOptions[0]?.focus();
412+
} else {
413+
availableOptions[currentIndex + 1]?.focus();
414+
}
415+
}
389416

390-
const target = e.target as HTMLElement;
391-
const currentIndex = availableOptions.indexOf(target);
417+
if (e.key === 'ArrowUp') {
418+
if (currentIndex <= 0) {
419+
availableOptions[availableOptions.length - 1]?.focus();
420+
} else {
421+
availableOptions[currentIndex - 1]?.focus();
422+
}
423+
}
392424

393-
if (e.key === 'ArrowDown') {
394-
if (currentIndex === availableOptions.length - 1) {
425+
if (e.key === 'Home') {
395426
availableOptions[0]?.focus();
396-
} else {
397-
availableOptions[currentIndex + 1]?.focus();
398427
}
399-
}
400428

401-
if (e.key === 'ArrowUp') {
402-
if (currentIndex <= 0) {
429+
if (e.key === 'End') {
403430
availableOptions[availableOptions.length - 1]?.focus();
404-
} else {
405-
availableOptions[currentIndex - 1]?.focus();
406431
}
407-
}
408-
409-
if (e.key === 'Home') {
410-
availableOptions[0]?.focus();
411-
}
412-
413-
if (e.key === 'End') {
414-
availableOptions[availableOptions.length - 1]?.focus();
415-
}
416-
}}
432+
}),
433+
props.onKeyDown$,
434+
]}
417435
>
418436
<Slot />
419437
</ul>
@@ -425,25 +443,32 @@ export type OptionProps = { optionValue: string } & QwikIntrinsicElements['li'];
425443
export const AutocompleteOption = component$((props: OptionProps) => {
426444
const ref = useSignal<HTMLElement>();
427445
const contextService = useContext(AutocompleteContextId);
446+
428447
contextService.options = [...contextService.options, ref];
429448

430449
return (
431450
<li
432451
ref={ref}
433452
role="option"
434-
onClick$={() => {
435-
contextService.inputValue.value = props.optionValue;
436-
contextService.isExpanded.value = false;
437-
}}
438-
onKeyDown$={(e) => {
439-
if (e.key === 'Enter' || e.key === ' ') {
453+
onClick$={[
454+
$(() => {
440455
contextService.inputValue.value = props.optionValue;
441456
contextService.isExpanded.value = false;
442-
const inputElement = contextService.triggerRef.value
443-
?.firstElementChild as HTMLElement;
444-
inputElement?.focus();
445-
}
446-
}}
457+
}),
458+
props.onClick$,
459+
]}
460+
onKeyDown$={[
461+
$((e: QwikKeyboardEvent) => {
462+
if (e.key === 'Enter' || e.key === ' ') {
463+
contextService.inputValue.value = props.optionValue;
464+
contextService.isExpanded.value = false;
465+
const inputElement = contextService.triggerRef.value
466+
?.firstElementChild as HTMLElement;
467+
inputElement?.focus();
468+
}
469+
}),
470+
props.onKeyDown$,
471+
]}
447472
tabIndex={0}
448473
{...props}
449474
>

packages/kit-headless/src/components/tabs/tab.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@ import {
88
useTask$,
99
$,
1010
useSignal,
11+
QwikIntrinsicElements,
1112
} from '@builder.io/qwik';
1213
import { tabsContextId } from './tabs-context-id';
1314
import { KeyCode } from '../../utils/key-code.type';
1415
import { isBrowser, isServer } from '@builder.io/qwik/build';
1516

16-
export interface TabProps {
17-
onClick?: PropFunction<() => void>;
17+
export type TabProps = {
1818
class?: string;
1919
selectedClassName?: string;
2020
disabled?: boolean;
21-
}
21+
} & QwikIntrinsicElements['button'];
2222

2323
export const Tab = component$((props: TabProps) => {
2424
const contextService = useContext(tabsContextId);
@@ -100,12 +100,12 @@ export const Tab = component$((props: TabProps) => {
100100
? `selected ${props.selectedClassName || ''}`
101101
: ''
102102
}${props.class ? ` ${props.class}` : ''}`}
103-
onClick$={() => {
104-
selectTab$();
105-
if (props.onClick) {
106-
props.onClick();
107-
}
108-
}}
103+
onClick$={[
104+
$(() => {
105+
selectTab$();
106+
}),
107+
props.onClick$,
108+
]}
109109
onKeyDown$={(e) => {
110110
contextService.onTabKeyDown$(
111111
e.key as KeyCode,

packages/kit-tailwind/src/components/tabs/tab.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
1-
import { component$, PropFunction, Slot } from '@builder.io/qwik';
1+
import {
2+
component$,
3+
PropFunction,
4+
Slot,
5+
QwikIntrinsicElements,
6+
} from '@builder.io/qwik';
27
import { Tab as HeadlessTab } from '@qwik-ui/headless';
38

4-
interface TabProps {
9+
export type TabProps = {
510
class?: string;
611
isLifted?: boolean;
712
isBordered?: boolean;
813
onClick$?: PropFunction<(clicked: number) => void>;
9-
}
14+
} & QwikIntrinsicElements['button'];
1015

1116
export const Tab = component$(
1217
({ isBordered, isLifted, onClick$, ...props }: TabProps) => {
1318
return (
1419
<HeadlessTab
15-
onClick={onClick$}
20+
onClick$={() => onClick$}
1621
class={`tab ${isBordered ? 'tab-bordered' : ''} ${
1722
isLifted ? 'tab-lifted' : ''
1823
}`}

0 commit comments

Comments
 (0)