diff --git a/package-lock.json b/package-lock.json
index 9649251e7..d5f25689a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2399,6 +2399,7 @@
},
"node_modules/@clack/prompts/node_modules/is-unicode-supported": {
"version": "1.3.0",
+ "extraneous": true,
"inBundle": true,
"license": "MIT",
"engines": {
diff --git a/packages/components/combobox/src/Combobox.doc.mdx b/packages/components/combobox/src/Combobox.doc.mdx
index d39ac4619..542dfc380 100644
--- a/packages/components/combobox/src/Combobox.doc.mdx
+++ b/packages/components/combobox/src/Combobox.doc.mdx
@@ -30,10 +30,15 @@ import { Combobox } from '@spark-ui/combobox'
of={Combobox}
description="A form input used for selecting a value: when collapsed it shows the currently selected option and when expanded, it shows a scrollable list of predefined options for the user to choose from."
subcomponents={{
+ 'Combobox.Trigger': {
+ of: Combobox.Trigger,
+ description:
+ 'The area that toggles the combobox popover. The Select.Popover will position itself by aligning with its trigger.',
+ },
'Combobox.Input': {
of: Combobox.Input,
description:
- 'The button that toggles the select. The Select.Popover will position itself by aligning over the trigger.',
+ 'The typing area in which the user can type. The input behaviour will differ if `autoComplete` is used or not.',
},
'Combobox.LeadingIcon': {
of: Combobox.LeadingIcon,
@@ -136,7 +141,7 @@ You can style this element directly, or you can use it as a wrapper to put an ic
### Leading icon
-Use `Combobox.LeadingIcon` inside `Combobox.Input` to prefix your trigger with an icon.
+Use `Combobox.LeadingIcon` inside `Combobox.Trigger` to prefix your trigger with an icon.
diff --git a/packages/components/combobox/src/Combobox.stories.tsx b/packages/components/combobox/src/Combobox.stories.tsx
index b4bd620bf..1436aca67 100644
--- a/packages/components/combobox/src/Combobox.stories.tsx
+++ b/packages/components/combobox/src/Combobox.stories.tsx
@@ -64,7 +64,9 @@ export const Default: StoryFn = _args => {
return (
-
+
+
+
@@ -88,12 +90,14 @@ export const Controlled: StoryFn = () => {
return (
-
+
+
+
@@ -126,7 +130,9 @@ export const ControlledOpenState: StoryFn = () => {
-
+
+
+
@@ -148,7 +154,9 @@ export const CustomItem: StoryFn = _args => {
return (
-
+
+
+
@@ -187,7 +195,9 @@ export const Disabled: StoryFn = _args => {
return (
-
+
+
+
@@ -217,7 +227,9 @@ export const FilteringAutoFilter: StoryFn = _args => {
return (
-
+
+
+
@@ -248,12 +260,14 @@ export const FilteringManual: StoryFn = () => {
return (
-
+
+
+
@@ -278,7 +292,9 @@ export const ReadOnly: StoryFn = _args => {
return (
-
+
+
+
@@ -299,7 +315,9 @@ export const DisabledItem: StoryFn = _args => {
return (
-
+
+
+
@@ -322,7 +340,9 @@ export const Grouped: StoryFn = _args => {
return (
-
+
+
+
@@ -351,7 +371,9 @@ export const LeadingIcon: StoryFn = _args => {
return (
-
+
+
+
@@ -374,7 +396,9 @@ export const ItemIndicator: StoryFn = _args => {
return (
-
+
+
+
@@ -419,7 +443,9 @@ export const Statuses: StoryFn = () => {
{statuses.map(status => {
return (
-
+
+
+
@@ -442,7 +468,9 @@ export const MultipleSelection: StoryFn = _args => {
return (
-
+
+
+
@@ -475,12 +503,14 @@ export const MultipleSelectionControlled: StoryFn = () => {
return (
-
+
+
+
@@ -505,7 +535,9 @@ export const FormFieldLabel: StoryFn = _args => {
Book
-
+
+
+
To Kill a Mockingbird
@@ -530,7 +562,9 @@ export const FormFieldHiddenLabel: StoryFn = _args => {
Book
-
+
+
+
To Kill a Mockingbird
@@ -553,7 +587,9 @@ export const FormFieldReadOnly: StoryFn = _args => {
Book
-
+
+
+
@@ -577,7 +613,9 @@ export const FormFieldDisabled: StoryFn = _args => {
Book
-
+
+
+
To Kill a Mockingbird
@@ -600,7 +638,9 @@ export const FormFieldRequired: StoryFn = _args => {
Book
-
+
+
+
To Kill a Mockingbird
@@ -629,7 +669,9 @@ export const FormFieldValidation: StoryFn = () => {
setState(value === 'default' ? undefined : (value as 'success' | 'alert' | 'error'))
}}
>
-
+
+
+
default
diff --git a/packages/components/combobox/src/ComboboxInput.tsx b/packages/components/combobox/src/ComboboxInput.tsx
index cf4237955..f2a7b37b8 100644
--- a/packages/components/combobox/src/ComboboxInput.tsx
+++ b/packages/components/combobox/src/ComboboxInput.tsx
@@ -1,20 +1,17 @@
-/* eslint-disable complexity */
-import { Icon } from '@spark-ui/icon'
-import { IconButton } from '@spark-ui/icon-button'
-import { ArrowHorizontalDown } from '@spark-ui/icons/dist/icons/ArrowHorizontalDown'
import { Popover } from '@spark-ui/popover'
import { useMergeRefs } from '@spark-ui/use-merge-refs'
import { VisuallyHidden } from '@spark-ui/visually-hidden'
+import { cx } from 'class-variance-authority'
import { ComponentPropsWithoutRef, forwardRef, Fragment, type Ref, useEffect } from 'react'
import { useComboboxContext } from './ComboboxContext'
-import { styles } from './ComboboxInput.styles'
-import { LeadingIcon } from './ComboboxLeadingIcon'
type InputPrimitiveProps = ComponentPropsWithoutRef<'input'>
-interface InputProps extends InputPrimitiveProps {
+interface InputProps extends Omit {
className?: string
+ placeholder?: string
+ value?: string
onValueChange?: (value: string) => void
}
@@ -31,7 +28,6 @@ export const Input = forwardRef(
forwardedRef: Ref
) => {
const {
- getToggleButtonProps,
getDropdownProps,
getInputProps,
getLabelProps,
@@ -41,7 +37,6 @@ export const Input = forwardRef(
inputValue,
setInputValue,
setIsInputControlled,
- state,
setLastInteractionType,
setOnInputValueChange,
multiple,
@@ -72,10 +67,6 @@ export const Input = forwardRef(
}
}, [])
- const [PopoverAnchor, popoverAnchorProps] = hasPopover
- ? [Popover.Anchor, { asChild: true, type: undefined }]
- : [Fragment, {}]
-
const [PopoverTrigger, popoverTriggerProps] = hasPopover
? [Popover.Trigger, { asChild: true, type: undefined }]
: [Fragment, {}]
@@ -96,50 +87,20 @@ export const Input = forwardRef(
{ariaLabel}
)}
-
-
- {/* 1 - Leading icon (optional) */}
-
-
-
-
- {/* 2 - TODO - selected items (optional, multiple selection only) */}
-
[selected items chips (v2)]
-
- {/* 3 - Input typing area - MANDATORY */}
-
-
-
-
- {/* 4 - Combobox clear button (optional) */}
-
[clear]
- {/* 5 - Combobox disclosure button (optional, advised for autoComplete not autoSuggest) */}
-
-
-
-
-
-
-
-
-
+
+
+
>
)
}
diff --git a/packages/components/combobox/src/ComboboxInput.styles.tsx b/packages/components/combobox/src/ComboboxTrigger.styles.tsx
similarity index 100%
rename from packages/components/combobox/src/ComboboxInput.styles.tsx
rename to packages/components/combobox/src/ComboboxTrigger.styles.tsx
diff --git a/packages/components/combobox/src/ComboboxTrigger.tsx b/packages/components/combobox/src/ComboboxTrigger.tsx
new file mode 100644
index 000000000..eef3e8411
--- /dev/null
+++ b/packages/components/combobox/src/ComboboxTrigger.tsx
@@ -0,0 +1,63 @@
+/* eslint-disable complexity */
+import { Icon } from '@spark-ui/icon'
+import { IconButton } from '@spark-ui/icon-button'
+import { ArrowHorizontalDown } from '@spark-ui/icons/dist/icons/ArrowHorizontalDown'
+import { Popover } from '@spark-ui/popover'
+import { forwardRef, Fragment, ReactNode, type Ref } from 'react'
+
+import { useComboboxContext } from './ComboboxContext'
+import { LeadingIcon } from './ComboboxLeadingIcon'
+import { styles } from './ComboboxTrigger.styles'
+
+interface TriggerProps {
+ className?: string
+ children?: ReactNode
+}
+
+export const Trigger = forwardRef(
+ ({ className, children }: TriggerProps, forwardedRef: Ref) => {
+ const { getToggleButtonProps, hasPopover, disabled, readOnly, state } = useComboboxContext()
+
+ const [PopoverAnchor, popoverAnchorProps] = hasPopover
+ ? [Popover.Anchor, { asChild: true, type: undefined }]
+ : [Fragment, {}]
+
+ return (
+ <>
+
+
+ {/* 1 - Leading icon (optional) */}
+
+
+
+
+ {/* 2 - TODO - selected items (optional, multiple selection only) */}
+
[selected items chips (v2)]
+
+ {children}
+
+ {/* 4 - Combobox clear button (optional) */}
+
[clear]
+
+ {/* 5 - Combobox disclosure button (optional, advised for autoComplete not autoSuggest) */}
+
+
+
+
+
+
+
+
+
+ >
+ )
+ }
+)
+
+Trigger.displayName = 'Combobox.Trigger'
diff --git a/packages/components/combobox/src/index.ts b/packages/components/combobox/src/index.ts
index ec95b688a..645be9df5 100644
--- a/packages/components/combobox/src/index.ts
+++ b/packages/components/combobox/src/index.ts
@@ -13,6 +13,7 @@ import { ItemText } from './ComboboxItemText'
import { Label } from './ComboboxLabel'
import { LeadingIcon } from './ComboboxLeadingIcon'
import { Popover } from './ComboboxPopover'
+import { Trigger } from './ComboboxTrigger'
export { useComboboxContext, ComboboxProvider }
@@ -25,9 +26,10 @@ export const Combobox: FC & {
Label: typeof Label
Popover: typeof Popover
Divider: typeof Divider
- Input: typeof Input
+ Trigger: typeof Trigger
LeadingIcon: typeof LeadingIcon
Empty: typeof Empty
+ Input: typeof Input
} = Object.assign(Root, {
Group,
Item,
@@ -37,9 +39,10 @@ export const Combobox: FC & {
Label,
Popover,
Divider,
- Input,
+ Trigger,
LeadingIcon,
Empty,
+ Input,
})
Combobox.displayName = 'Combobox'
@@ -51,6 +54,7 @@ ItemIndicator.displayName = 'Combobox.ItemIndicator'
Label.displayName = 'Combobox.Label'
Popover.displayName = 'Combobox.Popover'
Divider.displayName = 'Combobox.Divider'
-Input.displayName = 'Combobox.Input'
+Trigger.displayName = 'Combobox.Trigger'
LeadingIcon.displayName = 'Combobox.LeadingIcon'
Empty.displayName = 'Combobox.Empty'
+Input.displayName = 'Combobox.Input'
diff --git a/packages/components/combobox/src/tests/Combobox.test.tsx b/packages/components/combobox/src/tests/Combobox.test.tsx
index 5e65439d5..cb7f6aa88 100644
--- a/packages/components/combobox/src/tests/Combobox.test.tsx
+++ b/packages/components/combobox/src/tests/Combobox.test.tsx
@@ -10,7 +10,9 @@ describe('Combobox', () => {
it('should render input and list of items', () => {
render(
-
+
+
+
War and Peace
@@ -37,7 +39,9 @@ describe('Combobox', () => {
// Given a close combobox (default state)
render(
-
+
+
+
War and Peace
@@ -71,7 +75,9 @@ describe('Combobox', () => {
// Given a close combobox without a popover(default state)
render(
-
+
+
+
War and Peace
@@ -104,7 +110,9 @@ describe('Combobox', () => {
// Given a combobox that should remain opened
render(
-
+
+
+
War and Peace
@@ -130,7 +138,9 @@ describe('Combobox', () => {
// Given a combobox that should remain opened
render(
-
+
+
+
War and Peace
@@ -156,7 +166,9 @@ describe('Combobox', () => {
// Given a combobox with no selected value yet
render(
-
+
+
+
No results found
@@ -186,7 +198,9 @@ describe('Combobox', () => {
// Given a combobox with no selected value yet
render(
-
+
+
+
War and Peace
@@ -218,7 +232,9 @@ describe('Combobox', () => {
// Given a combobox with a default selected value
render(
-
+
+
+
War and Peace
@@ -237,7 +253,9 @@ describe('Combobox', () => {
// Given a combobox with a default selected value
render(
-
+
+
+
@@ -271,7 +289,9 @@ describe('Combobox', () => {
return (
-
+
+
+
War and Peace
@@ -303,7 +323,9 @@ describe('Combobox', () => {
// Given a combobox with no selected value yet
render(
-
+
+
+
War and Peace
diff --git a/packages/components/combobox/src/tests/itemsGroups.test.tsx b/packages/components/combobox/src/tests/itemsGroups.test.tsx
index 9c01c24bd..19c35faa4 100644
--- a/packages/components/combobox/src/tests/itemsGroups.test.tsx
+++ b/packages/components/combobox/src/tests/itemsGroups.test.tsx
@@ -10,7 +10,9 @@ describe('Combobox', () => {
// Given a combobox with items groups and group labels
render(
-
+
+
+
diff --git a/packages/components/combobox/src/tests/multipleSelection.test.tsx b/packages/components/combobox/src/tests/multipleSelection.test.tsx
index c03fdd931..581ed0571 100644
--- a/packages/components/combobox/src/tests/multipleSelection.test.tsx
+++ b/packages/components/combobox/src/tests/multipleSelection.test.tsx
@@ -13,7 +13,9 @@ describe('Combobox', () => {
// Given a combobox with no selected value yet
render(
-
+
+
+
War and Peace
@@ -47,7 +49,9 @@ describe('Combobox', () => {
// Given a combobox with no selected value yet
render(
-
+
+
+
War and Peace
@@ -82,7 +86,9 @@ describe('Combobox', () => {
// Given a combobox with no selected value yet
render(
-
+
+
+
War and Peace
diff --git a/packages/components/combobox/src/tests/withFormField.test.tsx b/packages/components/combobox/src/tests/withFormField.test.tsx
index 689c28a66..be1272735 100644
--- a/packages/components/combobox/src/tests/withFormField.test.tsx
+++ b/packages/components/combobox/src/tests/withFormField.test.tsx
@@ -12,7 +12,9 @@ describe('Combobox', () => {
Book
-
+
+
+
War and Peace