Skip to content

Commit 86cb10a

Browse files
Merge pull request #659 from thejackshelton/select-v2
feat(select): hidden select is synchronized with headless select
2 parents 5b708fc + 7f774e1 commit 86cb10a

File tree

5 files changed

+54
-34
lines changed

5 files changed

+54
-34
lines changed

.changeset/green-months-camp.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik-ui/headless': patch
3+
---
4+
5+
fix: select component now has a flexible hierarchy

packages/kit-headless/src/components/select/hidden-select.tsx

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,58 @@
66
* https://github.com/adobe/react-spectrum/blob/5c1920e50d4b2b80c826ca91aff55c97350bf9f9/packages/@react-aria/select/src/HiddenSelect.tsx
77
*/
88

9-
import { PropsOf, component$ } from '@builder.io/qwik';
9+
import { component$, useContext } from '@builder.io/qwik';
10+
import { Opt } from './select-inline';
11+
import SelectContextId from './select-context';
1012

11-
export interface AriaHiddenSelectProps {
13+
export type AriaHiddenSelectProps = {
1214
/**
1315
* Describes the type of autocomplete functionality the input should provide if any. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefautocomplete).
1416
*/
1517
autoComplete?: string;
1618

1719
/** The text label for the select. */
18-
label?: PropsOf<'label'>;
20+
label?: string;
1921

2022
/** HTML form input name. */
2123
name?: string;
2224

2325
/** Sets the disabled state of the select and input. */
2426
disabled?: boolean;
25-
}
27+
};
28+
29+
export type SelectDataProps = {
30+
options: Opt[] | undefined;
31+
};
2632

2733
// export function useHiddenSelect(props: AriaHiddenSelectProps) {
2834
// const { autoComplete, name, disabled } = props;
2935
// }
3036

31-
export const HiddenSelect = component$((props: AriaHiddenSelectProps) => {
32-
const { name, disabled } = props;
37+
export const HiddenSelect = component$(
38+
(props: AriaHiddenSelectProps & SelectDataProps) => {
39+
const { label, options } = props;
40+
const context = useContext(SelectContextId);
3341

34-
return (
35-
<>
42+
// TODO: make conditional logic to show either input or select based on the size of the options.
43+
return (
3644
<div>
37-
<input />
45+
<label>
46+
{label}
47+
<select>
48+
<option />
49+
{options?.map((opt: Opt) => (
50+
<option
51+
value={opt.value}
52+
selected={context.selectedIndexSig.value === opt.index}
53+
key={opt.value}
54+
>
55+
{opt.displayValue}
56+
</option>
57+
))}
58+
</select>
59+
</label>
3860
</div>
39-
{name && <input type="hidden" name={name} disabled={disabled} />}
40-
</>
41-
);
42-
});
61+
);
62+
},
63+
);

packages/kit-headless/src/components/select/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ export * from './select-trigger';
77
export * from './select-value';
88
export * from './select-group';
99
export * from './select-label';
10+
export * from './hidden-select';

packages/kit-headless/src/components/select/select-inline.tsx

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export type Opt = {
66
isDisabled: boolean;
77
value: string;
88
displayValue?: string;
9+
index: number;
910
};
1011

1112
/*
@@ -55,6 +56,7 @@ export const Select: Component<SelectProps> = (props: SelectProps) => {
5556
isDisabled,
5657
value,
5758
displayValue: child.props.children as string,
59+
index: currentIndex,
5860
};
5961

6062
opts.push(opt);
@@ -69,21 +71,11 @@ export const Select: Component<SelectProps> = (props: SelectProps) => {
6971
}
7072

7173
default: {
72-
// Qwik components
73-
if (child && child.props) {
74-
const componentChildren = Array.isArray(child.props.children)
75-
? [...child.props.children]
76-
: [child.props.children];
77-
childrenToProcess.unshift(...componentChildren);
78-
}
79-
80-
// regular JSX nodes
81-
if (typeof child.type === 'string' && child.children !== undefined) {
82-
const nodeChildren = Array.isArray(child.children)
74+
if (child) {
75+
const anyChildren = Array.isArray(child.children)
8376
? [...child.children]
8477
: [child.children];
85-
86-
childrenToProcess.unshift(...(nodeChildren as JSXNode[]));
78+
childrenToProcess.unshift(...(anyChildren as JSXNode[]));
8779
}
8880

8981
break;

packages/kit-headless/src/components/select/select.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
import {
2-
PropsOf,
3-
Signal,
4-
Slot,
52
component$,
6-
useComputed$,
7-
useContextProvider,
8-
useId,
3+
Slot,
4+
type PropsOf,
95
useSignal,
6+
useContextProvider,
7+
Signal,
108
useTask$,
9+
useComputed$,
1110
type QRL,
11+
useId,
1212
} from '@builder.io/qwik';
13-
import { isBrowser } from '@builder.io/qwik/build';
14-
import SelectContextId, { type SelectContext } from './select-context';
13+
import { type SelectContext } from './select-context';
14+
import SelectContextId from './select-context';
1515
import { Opt } from './select-inline';
16+
import { isBrowser } from '@builder.io/qwik/build';
1617
import { getActiveDescendant } from './utils';
1718

1819
export type InternalSelectProps = {

0 commit comments

Comments
 (0)