Skip to content

Commit 427ea3a

Browse files
Error messages & export description
1 parent 3054830 commit 427ea3a

File tree

16 files changed

+90
-6
lines changed

16 files changed

+90
-6
lines changed

.changeset/gorgeous-falcons-care.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@qwik-ui/headless': patch
3+
---
4+
5+
feat: new Select.ErrorMessage component
6+
7+
feat: data-invalid attribute to style when the select is invalid
8+
9+
feat: new Select.Description component

apps/website/src/routes/docs/headless/select/examples/validation.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ export default component$(() => {
3434
<Select.Trigger class="select-trigger">
3535
<Select.DisplayValue placeholder="Select an option" />
3636
</Select.Trigger>
37-
{field.error && <div style={{ color: '#D2122E' }}>{field.error}</div>}
37+
{field.error && (
38+
<Select.ErrorMessage style={{ color: '#D2122E' }}>
39+
{field.error}
40+
</Select.ErrorMessage>
41+
)}
3842
<Select.Popover class="select-popover">
3943
<Select.Listbox class="select-listbox">
4044
{users.map((user) => (

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,9 @@ The native select element is created when a form name has been given to `<Select
175175

176176
<Showcase name="validation" />
177177

178-
Above is an example of submitting a multi-select form.
178+
The `<Select.ErrorMessage />` component is used to display errors when the select is invalid.
179+
180+
To style based on the invalid state, use the `data-invalid` data attribute.
179181

180182
### Descriptions
181183

apps/website/src/routes/docs/headless/select/snippets/select.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
outline-offset: 2px;
2929
}
3030

31+
.select-trigger[data-invalid] {
32+
border: 2px dotted #d2122e;
33+
}
34+
3135
.select-popover {
3236
width: 100%;
3337
max-width: var(--select-width);

packages/kit-headless/src/components/accordion/accordion-root.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@ export const HAccordionRootImpl = component$((props: AccordionRootProps) => {
1919
disabled,
2020
collapsible = true,
2121
animated,
22+
itemsMap,
2223
...rest
2324
} = props;
2425

26+
itemsMap;
27+
2528
const selectedIndexSig = useSignal<number>(initialIndex ?? -1);
2629
const triggerRefsArray = useSignal<Array<Signal>>([]);
2730
const isAnimatedSig = useSignal<boolean>(animated === true);

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ export const HHiddenNativeSelect = component$(
4141
// @ts-expect-error modular forms ref function
4242
ref?.(element);
4343
}}
44+
onFocus$={() => {
45+
// override modular forms focus event
46+
return;
47+
}}
4448
multiple={context.multiple}
4549
tabIndex={-1}
4650
autocomplete={autoComplete}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
export { HSelectRoot as Root } from './select-inline';
22
export { HSelectLabel as Label } from './select-label';
33
export { HSelectTrigger as Trigger } from './select-trigger';
4-
export { HSelectDisplayText as DisplayValue } from './select-display-text';
4+
export { HSelectDisplayValue as DisplayValue } from './select-display-value';
55
export { HSelectPopover as Popover } from './select-popover';
66
export { HSelectListbox as Listbox } from './select-listbox';
77
export { HSelectGroup as Group } from './select-group';
@@ -11,3 +11,4 @@ export { HSelectItemLabel as ItemLabel } from './select-item-label';
1111
export { HSelectItemIndicator as ItemIndicator } from './select-item-indicator';
1212
export { HSelectDescription as Description } from './select-description';
1313
export { HHiddenNativeSelect as HiddenNativeSelect } from './hidden-select';
14+
export { HSelectErrorMessage as ErrorMessage } from './select-error-message';

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export type SelectContext = {
3939
* Specifies that the user must select a value before submitting the form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#required).
4040
*/
4141
required?: boolean;
42+
43+
isInvalidSig?: Signal<boolean>;
4244
};
4345

4446
export const groupContextId = createContextId<GroupContext>('Select-Group');

packages/kit-headless/src/components/select/select-display-text.tsx renamed to packages/kit-headless/src/components/select/select-display-value.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type SelectValueProps = PropsOf<'span'> & {
1515
placeholder?: string;
1616
};
1717

18-
export const HSelectDisplayText = component$((props: SelectValueProps) => {
18+
export const HSelectDisplayValue = component$((props: SelectValueProps) => {
1919
const { placeholder, ...rest } = props;
2020
const context = useContext(SelectContextId);
2121
const valueId = `${context.localId}-value`;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { PropsOf, Slot, component$, useContext } from '@builder.io/qwik';
2+
import SelectContextId from './select-context';
3+
4+
export const HSelectErrorMessage = component$((props: PropsOf<'div'>) => {
5+
const context = useContext(SelectContextId);
6+
const errorMessageId = `${context.localId}-error-message`;
7+
8+
return (
9+
<div role="alert" id={errorMessageId} {...props}>
10+
<Slot />
11+
</div>
12+
);
13+
});

0 commit comments

Comments
 (0)