-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Structure and slots for SearchBox, using Input as a slot (#28090)
- Loading branch information
1 parent
7516a6b
commit 89f6b7c
Showing
10 changed files
with
273 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 13 additions & 5 deletions
18
packages/react-components/react-search/src/components/SearchBox/SearchBox.types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,25 @@ | ||
import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; | ||
import { Input, InputState } from '@fluentui/react-input'; | ||
|
||
export type SearchBoxSlots = { | ||
root: Slot<'div'>; | ||
// Root of the component, wrapping the inputs | ||
root: NonNullable<Slot<typeof Input>>; | ||
|
||
// Last element in the input, within the input border | ||
dismiss?: Slot<'span'>; | ||
|
||
// Element after the input text, within the input border | ||
contentAfter?: Slot<'span'>; | ||
}; | ||
|
||
/** | ||
* SearchBox Props | ||
*/ | ||
export type SearchBoxProps = ComponentProps<SearchBoxSlots> & {}; | ||
export type SearchBoxProps = ComponentProps<SearchBoxSlots>; | ||
|
||
/** | ||
* State used in rendering SearchBox | ||
*/ | ||
export type SearchBoxState = ComponentState<SearchBoxSlots>; | ||
// TODO: Remove semicolon from previous line, uncomment next line, and provide union of props to pick from SearchBoxProps. | ||
// & Required<Pick<SearchBoxProps, 'propName'>> | ||
export type SearchBoxState = ComponentState<SearchBoxSlots> & | ||
Required<Pick<InputState, 'size'>> & | ||
Required<Pick<SearchBoxProps, 'disabled'>>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 0 additions & 28 deletions
28
packages/react-components/react-search/src/components/SearchBox/useSearchBox.ts
This file was deleted.
Oops, something went wrong.
73 changes: 73 additions & 0 deletions
73
packages/react-components/react-search/src/components/SearchBox/useSearchBox.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import * as React from 'react'; | ||
import { mergeCallbacks, resolveShorthand, useControllableState, useEventCallback } from '@fluentui/react-utilities'; | ||
import { Input } from '@fluentui/react-input'; | ||
import type { SearchBoxProps, SearchBoxState } from './SearchBox.types'; | ||
import { DismissRegular, SearchRegular } from '@fluentui/react-icons'; | ||
|
||
/** | ||
* Create the state required to render SearchBox. | ||
* | ||
* The returned state can be modified with hooks such as useSearchBoxStyles_unstable, | ||
* before being passed to renderSearchBox_unstable. | ||
* | ||
* @param props - props from this instance of SearchBox | ||
* @param ref - reference to root HTMLElement of SearchBox | ||
*/ | ||
export const useSearchBox_unstable = (props: SearchBoxProps, ref: React.Ref<HTMLInputElement>): SearchBoxState => { | ||
const { size = 'medium', disabled = false, contentBefore, dismiss, contentAfter, ...inputProps } = props; | ||
|
||
const [value, setValue] = useControllableState({ | ||
state: props.value, | ||
defaultState: props.defaultValue, | ||
initialState: '', | ||
}); | ||
|
||
const state: SearchBoxState = { | ||
components: { | ||
root: Input, | ||
dismiss: 'span', | ||
contentAfter: 'span', | ||
}, | ||
|
||
root: { | ||
ref, | ||
type: 'search', | ||
input: {}, // defining here to have access in styles hook | ||
value, | ||
|
||
contentBefore: resolveShorthand(contentBefore, { | ||
defaultProps: { | ||
children: <SearchRegular />, | ||
}, | ||
required: true, // TODO need to allow users to remove | ||
}), | ||
|
||
...inputProps, | ||
|
||
onChange: useEventCallback(ev => { | ||
const newValue = ev.target.value; | ||
props.onChange?.(ev, { value: newValue }); | ||
setValue(newValue); | ||
}), | ||
}, | ||
dismiss: resolveShorthand(dismiss, { | ||
defaultProps: { | ||
children: <DismissRegular />, | ||
role: 'button', | ||
'aria-label': 'clear', | ||
}, | ||
required: true, | ||
}), | ||
contentAfter: resolveShorthand(contentAfter, { required: true }), | ||
|
||
disabled, | ||
size, | ||
}; | ||
|
||
const onDismissClick = useEventCallback(mergeCallbacks(state.dismiss?.onClick, () => setValue(''))); | ||
if (state.dismiss) { | ||
state.dismiss.onClick = onDismissClick; | ||
} | ||
|
||
return state; | ||
}; |
Oops, something went wrong.