Skip to content

Commit fe0fb3d

Browse files
committed
add ComboboxInput component
1 parent be7d77b commit fe0fb3d

17 files changed

Lines changed: 278 additions & 10 deletions

packages/react-combobox/etc/react-combobox.api.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
import type { ComponentProps } from '@fluentui/react-utilities';
88
import type { ComponentState } from '@fluentui/react-utilities';
99
import type { ForwardRefComponent } from '@fluentui/react-utilities';
10+
import type { InputProps } from '@fluentui/react-input';
11+
import type { InputSlots } from '@fluentui/react-input';
12+
import type { InputState } from '@fluentui/react-input';
1013
import type { PositioningShorthand } from '@fluentui/react-positioning';
1114
import * as React_2 from 'react';
1215
import type { Slot } from '@fluentui/react-utilities';
@@ -23,6 +26,23 @@ export type ComboboxContextValues = {
2326
combobox: ComboboxContextValue;
2427
};
2528

29+
// @public
30+
export const ComboboxInput: ForwardRefComponent<ComboboxInputProps>;
31+
32+
// @public (undocumented)
33+
export const comboboxInputClassNames: SlotClassNames<ComboboxInputSlots>;
34+
35+
// @public
36+
export type ComboboxInputProps = Partial<ComponentProps<ComboboxInputSlots>> & Omit<InputProps, 'contentBefore' | 'contentAfter'>;
37+
38+
// @public (undocumented)
39+
export type ComboboxInputSlots = Pick<InputSlots, 'root' | 'input'> & {
40+
expandIcon: Slot<'span'>;
41+
};
42+
43+
// @public
44+
export type ComboboxInputState = ComponentState<ComboboxInputSlots> & Omit<InputState, 'components' | 'contentBefore' | 'contentAfter'>;
45+
2646
// @public
2747
export type ComboboxOpenChangeData = {
2848
open: boolean;
@@ -83,7 +103,7 @@ export type ComboButtonSlots = {
83103
};
84104

85105
// @public
86-
export type ComboButtonState = ComponentState<ComboButtonSlots> & ComboButtonCommons & Required<Pick<ComboButtonProps, 'appearance' | 'size'>> & Pick<ComboButtonProps, 'placeholder'>;
106+
export type ComboButtonState = ComponentState<ComboButtonSlots> & Required<Pick<ComboButtonProps, 'appearance' | 'size'>> & Pick<ComboButtonProps, 'placeholder'>;
87107

88108
// @public
89109
export const Listbox: ForwardRefComponent<ListboxProps>;
@@ -162,6 +182,9 @@ export type OptionState = ComponentState<OptionSlots> & OptionCommons & {
162182
// @public
163183
export const renderCombobox_unstable: (state: ComboboxState, contextValues: ComboboxContextValues) => JSX.Element;
164184

185+
// @public
186+
export const renderComboboxInput_unstable: (state: ComboboxInputState) => JSX.Element;
187+
165188
// @public
166189
export const renderComboButton_unstable: (state: ComboButtonState) => JSX.Element;
167190

@@ -177,6 +200,12 @@ export const renderOptionGroup_unstable: (state: OptionGroupState) => JSX.Elemen
177200
// @public
178201
export const useCombobox_unstable: (props: ComboboxProps, ref: React_2.Ref<HTMLDivElement>) => ComboboxState;
179202

203+
// @public
204+
export const useComboboxInput_unstable: (props: ComboboxInputProps, ref: React_2.Ref<HTMLInputElement>) => ComboboxInputState;
205+
206+
// @public
207+
export const useComboboxInputStyles_unstable: (state: ComboboxInputState) => ComboboxInputState;
208+
180209
// @public
181210
export const useComboboxStyles_unstable: (state: ComboboxState) => ComboboxState;
182211

packages/react-combobox/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"@fluentui/keyboard-keys": "9.0.0-rc.4",
3737
"@fluentui/react-context-selector": "9.0.0-rc.6",
3838
"@fluentui/react-icons": "^2.0.166-rc.3",
39+
"@fluentui/react-input": "^9.0.0-beta.7",
3940
"@fluentui/react-portal": "9.0.0-rc.7",
4041
"@fluentui/react-positioning": "9.0.0-rc.6",
4142
"@fluentui/react-theme": "9.0.0-rc.5",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './components/ComboboxInput/index';

packages/react-combobox/src/components/ComboButton/ComboButton.types.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ export type ComboButtonSlots = {
1111
expandIcon: Slot<'span'>;
1212
};
1313

14-
type ComboButtonCommons = {};
15-
1614
/**
1715
* ComboButton Props
1816
*/
@@ -39,6 +37,5 @@ export type ComboButtonProps = Partial<ComponentProps<ComboButtonSlots, 'content
3937
* State used in rendering ComboButton
4038
*/
4139
export type ComboButtonState = ComponentState<ComboButtonSlots> &
42-
ComboButtonCommons &
4340
Required<Pick<ComboButtonProps, 'appearance' | 'size'>> &
4441
Pick<ComboButtonProps, 'placeholder'>;

packages/react-combobox/src/components/ComboButton/useComboButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export const useComboButton_unstable = (
2626
const contextOnBlur = useContextSelector(ComboboxContext, ctx => ctx.onTriggerBlur);
2727
const contextOnClick = useContextSelector(ComboboxContext, ctx => ctx.onTriggerClick);
2828
const contextOnKeyDown = useContextSelector(ComboboxContext, ctx => ctx.onTriggerKeyDown);
29-
const contextRef = useContextSelector(ComboboxContext, ctx => ctx.triggerRef);
29+
const contextRef = useContextSelector(ComboboxContext, ctx => ctx.triggerRef as React.RefObject<HTMLButtonElement>);
3030

3131
const nativeProps = getPartitionedNativeProps({
3232
props,

packages/react-combobox/src/components/Combobox/Combobox.types.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export type ComboboxState = ComponentState<ComboboxSlots> &
7777
popperContainerRef: React.MutableRefObject<HTMLDivElement>;
7878

7979
/* Ref to be used by the trigger */
80-
triggerRef: React.RefObject<HTMLButtonElement>;
80+
triggerRef: React.RefObject<HTMLButtonElement | HTMLInputElement>;
8181

8282
/* Callback when a the listbox is clicked, for internal use */
8383
onListboxClick(): void;
@@ -89,13 +89,13 @@ export type ComboboxState = ComponentState<ComboboxSlots> &
8989
onOptionClick(event: React.MouseEvent, option: OptionValue): void;
9090

9191
/* Callback when the trigger is blurred, for internal use */
92-
onTriggerBlur(event: React.FocusEvent<HTMLButtonElement>): void;
92+
onTriggerBlur(event: React.FocusEvent<HTMLButtonElement | HTMLInputElement>): void;
9393

9494
/* Callback when the trigger is clicked, for internal use */
95-
onTriggerClick(event: React.MouseEvent<HTMLButtonElement>): void;
95+
onTriggerClick(event: React.MouseEvent<HTMLButtonElement | HTMLInputElement>): void;
9696

9797
/* Callback for the trigger keydown event, for internal use */
98-
onTriggerKeyDown(event: React.KeyboardEvent<HTMLButtonElement>): void;
98+
onTriggerKeyDown(event: React.KeyboardEvent<HTMLButtonElement | HTMLInputElement>): void;
9999
};
100100

101101
export type ComboboxContextValues = {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import * as React from 'react';
2+
import { render } from '@testing-library/react';
3+
import { ComboboxInput } from './ComboboxInput';
4+
import { isConformant } from '../../common/isConformant';
5+
6+
describe('ComboboxInput', () => {
7+
isConformant({
8+
Component: ComboboxInput,
9+
displayName: 'ComboboxInput',
10+
primarySlot: 'input',
11+
// don't test deprecated className export on new components
12+
disabledTests: ['component-has-static-classname-exported'],
13+
});
14+
15+
// TODO add more tests here, and create visual regression tests in /apps/vr-tests
16+
17+
it('renders a default state', () => {
18+
const result = render(<ComboboxInput />);
19+
expect(result.container).toMatchSnapshot();
20+
});
21+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import * as React from 'react';
2+
import { useComboboxInput_unstable } from './useComboboxInput';
3+
import { renderComboboxInput_unstable } from './renderComboboxInput';
4+
import { useComboboxInputStyles_unstable } from './useComboboxInputStyles';
5+
import type { ComboboxInputProps } from './ComboboxInput.types';
6+
import type { ForwardRefComponent } from '@fluentui/react-utilities';
7+
8+
/**
9+
* ComboboxInput component - TODO: add more docs
10+
*/
11+
export const ComboboxInput: ForwardRefComponent<ComboboxInputProps> = React.forwardRef((props, ref) => {
12+
const state = useComboboxInput_unstable(props, ref);
13+
14+
useComboboxInputStyles_unstable(state);
15+
return renderComboboxInput_unstable(state);
16+
});
17+
18+
ComboboxInput.displayName = 'ComboboxInput';
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities';
2+
import type { InputProps, InputSlots, InputState } from '@fluentui/react-input';
3+
4+
export type ComboboxInputSlots = Pick<InputSlots, 'root' | 'input'> & {
5+
/* The dropdown arrow icon */
6+
expandIcon: Slot<'span'>;
7+
};
8+
9+
/**
10+
* ComboboxInput Props
11+
*/
12+
export type ComboboxInputProps = Partial<ComponentProps<ComboboxInputSlots>> &
13+
Omit<InputProps, 'contentBefore' | 'contentAfter'>;
14+
15+
/**
16+
* State used in rendering ComboboxInput
17+
*/
18+
export type ComboboxInputState = ComponentState<ComboboxInputSlots> &
19+
Omit<InputState, 'components' | 'contentBefore' | 'contentAfter'>;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export * from './ComboboxInput';
2+
export * from './ComboboxInput.types';
3+
export * from './renderComboboxInput';
4+
export * from './useComboboxInput';
5+
export * from './useComboboxInputStyles';

0 commit comments

Comments
 (0)