Skip to content

Commit 094a21e

Browse files
docs(select): document props
1 parent acbde64 commit 094a21e

File tree

6 files changed

+69
-20
lines changed

6 files changed

+69
-20
lines changed

apps/website/src/routes/docs/headless/contributing/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ Absolutely, documentation is a critical part of the project, and something that
262262

263263
## Where should I learn the Qwik parts?
264264

265-
If you find yourself stuck on a certain pattern, try taking a look through Qwik UI beta components. For example, the [modal component](https://github.com/qwikifiers/qwik-ui/tree/main/packages/kit-headless/src/components/modal) would be a good one to look through.
265+
If you find yourself stuck on a certain pattern, try taking a look through Qwik UI beta components. For example, the [select component](https://github.com/qwikifiers/qwik-ui/tree/main/packages/kit-headless/src/components/select) would be a good one to look through.
266266

267267
We're also happy to help! We love experimenting with things and having a blast while doing it.
268268

packages/kit-headless/src/components/select/notes.md

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,15 @@ resource: https://joshwayne.com/posts/the-problem-with-dropdowns/
6767
- [x] Scrollable
6868
- [x] Aria (controls, roles, etc)
6969

70+
Nice to haves:
71+
- [ ] Example using modular forms with validation
72+
7073
## Props:
7174

7275
### State
7376

77+
#### Root:
78+
7479
name: value
7580
type: string
7681
description: uncontrolled select value
@@ -87,17 +92,13 @@ resource: https://joshwayne.com/posts/the-problem-with-dropdowns/
8792
type: PropFunction
8893
description: function called when the listbox opens or closes.
8994

90-
---
91-
92-
### Behavior
93-
94-
name: placeholder
95-
type: string
96-
description: sets a placeholder instead of a selected value.
97-
9895
name: disabled
9996
type: boolean
100-
description: When true, the option is disabled.
97+
description: disables the select
98+
99+
name: required
100+
type: boolean
101+
description: Ensure the user selects an option, as well as custom client and server-side validation.
101102

102103
name: multiple
103104
type: boolean
@@ -109,6 +110,24 @@ resource: https://joshwayne.com/posts/the-problem-with-dropdowns/
109110

110111
---
111112

113+
### Select Value:
114+
115+
name: placeholder
116+
type: string
117+
description: sets a placeholder instead of a selected value.
118+
119+
### Select Option:
120+
121+
name: value
122+
type: string
123+
description: Give the select a value other than what is displayed in the option.
124+
125+
name: disabled
126+
type: boolean
127+
description: When true, the option is disabled.
128+
129+
---
130+
112131
### Forms
113132

114133
name: name

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export const Select: Component<SelectProps> = (props: SelectProps) => {
6767
);
6868
}
6969

70-
child.props.index = currentIndex;
70+
child.props._index = currentIndex;
7171
const isDisabled = child.props.disabled === true;
7272
const value = (
7373
child.props.value ? child.props.value : child.props.children

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

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,37 @@ import { isServer, isBrowser } from '@builder.io/qwik/build';
1212
import SelectContextId from './select-context';
1313

1414
export type SelectOptionProps = PropsOf<'li'> & {
15-
index?: number;
15+
/** Internal index we get from the inline component. Please see select-inline.tsx */
16+
_index?: number;
17+
18+
/** If true, option is not selectable or focusable. */
1619
disabled?: boolean;
20+
21+
/** Selected value associated with the option. */
1722
value?: string;
1823
};
1924

2025
export const SelectOption = component$<SelectOptionProps>((props) => {
2126
/* look at select-inline on how we get the index. */
22-
const { index, disabled, ...rest } = props;
27+
const { _index, disabled, ...rest } = props;
2328
const context = useContext(SelectContextId);
2429
const optionRef = useSignal<HTMLLIElement>();
2530
const localIndexSig = useSignal<number | null>(null);
26-
const optionId = `${context.localId}-${index}`;
31+
const optionId = `${context.localId}-${_index}`;
2732

2833
const isSelectedSig = useComputed$(() => {
29-
return !disabled && context.selectedIndexSig.value === index;
34+
return !disabled && context.selectedIndexSig.value === _index;
3035
});
3136

3237
const isHighlightedSig = useComputed$(() => {
33-
return !disabled && context.highlightedIndexSig.value === index;
38+
return !disabled && context.highlightedIndexSig.value === _index;
3439
});
3540

3641
useTask$(function getIndexTask() {
37-
if (index === undefined)
42+
if (_index === undefined)
3843
throw Error('Qwik UI: Select component option cannot find its proper index.');
3944

40-
localIndexSig.value = index;
45+
localIndexSig.value = _index;
4146
});
4247

4348
useTask$(function scrollableTask({ track, cleanup }) {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import { component$, useContext, type PropsOf, useComputed$ } from '@builder.io/
33
import SelectContextId from './select-context';
44

55
type SelectValueProps = PropsOf<'span'> & {
6+
/**
7+
* Optional text displayed when no option is selected.
8+
*/
69
placeholder?: string;
710
};
811

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

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,41 @@ import { isBrowser } from '@builder.io/qwik/build';
1717
import { getActiveDescendant } from './utils';
1818

1919
export type SelectProps = PropsOf<'div'> & {
20+
/** The initial selected value (uncontrolled). */
2021
value?: string;
22+
23+
/** A signal that contains the current selected value (controlled). */
2124
'bind:value'?: Signal<string>;
2225

23-
// our source of truth for the options. We get this at pre-render time in the inline component, that way we do not need textContent, etc.
26+
/** Our source of truth for the options. We get this at pre-render time in the inline component, that way we do not need to call native methods such as textContent.
27+
**/
2428
_options?: Opt[];
2529

26-
// when a value is passed, we check if it's an actual option value, and get its index at pre-render time.
30+
/** When a value is passed, we check if it's an actual option value, and get its index at pre-render time.
31+
**/
2732
_valuePropIndex?: number | null;
2833

34+
/**
35+
* QRL handler that runs when a select value changes.
36+
* @param value The new value as a string.
37+
*/
2938
onChange$?: QRL<(value: string) => void>;
39+
40+
/**
41+
* QRL handler that runs when the listbox opens or closes.
42+
* @param open The new state of the listbox.
43+
*
44+
*/
3045
onOpenChange$?: QRL<(open: boolean) => void>;
3146

47+
/**
48+
* The native scrollIntoView method is used to scroll the options into view when the user highlights an option. This allows customization of the scroll behavior.
49+
*/
3250
scrollOptions?: ScrollIntoViewOptions;
51+
52+
/**
53+
* Enables looped behavior when the user navigates through the options using the arrow keys.
54+
*/
3355
loop?: boolean;
3456
};
3557

0 commit comments

Comments
 (0)