Advanced picker components for selecting people, tags, and other items with search, filtering, and suggestion capabilities. Fluent UI React provides a comprehensive picker system with extensible architecture.
Comprehensive people/user selection component with search, suggestions, and multiple selection modes.
/**
* Normal people picker component for user selection
* @param props - People picker properties
* @returns JSX element for people picker
*/
function NormalPeoplePicker(props: IPeoplePickerProps): JSX.Element;
/**
* Compact people picker with reduced visual footprint
* @param props - People picker properties
* @returns JSX element for compact people picker
*/
function CompactPeoplePicker(props: IPeoplePickerProps): JSX.Element;
/**
* List-style people picker for larger selections
* @param props - People picker properties
* @returns JSX element for list people picker
*/
function ListPeoplePicker(props: IPeoplePickerProps): JSX.Element;
interface IPeoplePickerProps {
/** Callback to resolve people suggestions */
onResolveSuggestions: (filterText: string, currentPersonas?: IPersonaProps[], limitResults?: number) => IPersonaProps[] | Promise<IPersonaProps[]>;
/** Additional suggestion callbacks */
onEmptyInputFocus?: (selectedItems?: IPersonaProps[]) => IPersonaProps[] | Promise<IPersonaProps[]>;
/** Get text from persona for search */
getTextFromItem?: (persona: IPersonaProps, currentValue?: string) => string;
/** Currently selected items */
selectedItems?: IPersonaProps[];
/** Default selected items */
defaultSelectedItems?: IPersonaProps[];
/** Change event handler */
onChange?: (items?: IPersonaProps[]) => void;
/** Item selection handler */
onItemSelected?: (selectedItem?: IPersonaProps) => IPersonaProps | Promise<IPersonaProps>;
/** Maximum selected personas */
itemLimit?: number;
/** Whether picker is disabled */
disabled?: boolean;
/** Picker input placeholder */
inputProps?: IInputProps;
/** Custom styles */
styles?: IPeoplePickerStyles;
/** Theme */
theme?: ITheme;
/** Class name */
className?: string;
/** Validation callback */
onValidateInput?: (input: string) => ValidationState;
/** Remove button aria label */
removeButtonAriaLabel?: string;
}
interface IPersonaProps {
/** Primary text (usually name) */
primaryText?: string;
/** Secondary text (usually title) */
secondaryText?: string;
/** Tertiary text (usually department) */
tertiaryText?: string;
/** Optional text (usually location) */
optionalText?: string;
/** Image URL */
imageUrl?: string;
/** Alternative image URL */
imageAlt?: string;
/** Persona size */
size?: PersonaSize;
/** Presence status */
presence?: PersonaPresence;
/** Initials color */
initialsColor?: PersonaInitialsColor;
}
enum ValidationState {
valid = 0,
warning = 1,
invalid = 2,
}Usage Examples:
import React, { useState } from "react";
import { NormalPeoplePicker, IPersonaProps, ValidationState } from "@fluentui/react";
const mockPeople: IPersonaProps[] = [
{
primaryText: 'John Doe',
secondaryText: 'Software Engineer',
tertiaryText: 'Engineering',
optionalText: 'Seattle',
imageUrl: '/avatars/john.jpg',
},
{
primaryText: 'Jane Smith',
secondaryText: 'Product Manager',
tertiaryText: 'Product',
optionalText: 'Redmond',
imageUrl: '/avatars/jane.jpg',
},
{
primaryText: 'Bob Johnson',
secondaryText: 'Designer',
tertiaryText: 'Design',
optionalText: 'San Francisco',
imageUrl: '/avatars/bob.jpg',
},
];
function PeoplePickerExample() {
const [selectedPeople, setSelectedPeople] = useState<IPersonaProps[]>([]);
const onResolveSuggestions = (filterText: string): IPersonaProps[] => {
return filterText
? mockPeople.filter(person =>
person.primaryText?.toLowerCase().includes(filterText.toLowerCase()) ||
person.secondaryText?.toLowerCase().includes(filterText.toLowerCase())
).slice(0, 5)
: [];
};
const onValidateInput = (input: string): ValidationState => {
if (input.includes('@')) {
return ValidationState.valid;
}
return input.length > 1 ? ValidationState.warning : ValidationState.invalid;
};
return (
<NormalPeoplePicker
onResolveSuggestions={onResolveSuggestions}
selectedItems={selectedPeople}
onChange={setSelectedPeople}
itemLimit={5}
inputProps={{
placeholder: 'Enter names or email addresses...',
}}
onValidateInput={onValidateInput}
removeButtonAriaLabel="Remove selected person"
/>
);
}Enhanced people picker with additional features like member lists and specialized selection.
/**
* Extended people picker with advanced functionality
* @param props - Extended people picker properties
* @returns JSX element for extended people picker
*/
function ExtendedPeoplePicker(props: IExtendedPeoplePickerProps): JSX.Element;
/**
* Member list people picker for team/group management
* @param props - People picker properties
* @returns JSX element for member list people picker
*/
function MemberListPeoplePicker(props: IPeoplePickerProps): JSX.Element;
interface IExtendedPeoplePickerProps extends IPeoplePickerProps {
/** Header component */
headerComponent?: JSX.Element;
/** Footer component */
footerComponent?: JSX.Element;
/** Search more text */
searchMoreText?: string;
/** Loading text */
loadingText?: string;
/** No results found text */
noResultsFoundText?: string;
/** Results maximum count */
resultsMaximumNumber?: number;
/** Show remove buttons */
showRemoveButtons?: boolean;
}Floating picker component that appears as an overlay for people selection.
/**
* Floating people picker that appears as overlay
* @param props - Floating people picker properties
* @returns JSX element for floating people picker
*/
function FloatingPeoplePicker(props: IBaseFloatingPickerProps<IPersonaProps>): JSX.Element;
interface IBaseFloatingPickerProps<T> {
/** Target input element */
targetElement?: HTMLInputElement;
/** Suggestion providers */
onResolveSuggestions: (filter: string, selectedItems?: T[]) => T[] | PromiseLike<T[]>;
/** Results loading callback */
onRenderSuggestionsItem?: (props: T, itemProps: ISuggestionItemProps<T>) => JSX.Element;
/** Picker width */
pickerWidth?: string;
/** Suggestion callbacks */
onSuggestionSelected?: (ev: React.MouseEvent<HTMLElement>, item: T) => void;
/** Custom styles */
pickerSuggestionsProps?: IBasePickerSuggestionsProps;
/** Class name */
className?: string;
}Component for selecting and managing tags, keywords, or categorical items.
/**
* Tag picker component for selecting tags/categories
* @param props - Tag picker properties
* @returns JSX element for tag picker
*/
function TagPicker(props: ITagPickerProps): JSX.Element;
interface ITagPickerProps {
/** Callback to resolve tag suggestions */
onResolveSuggestions: (filterText: string, tagList?: ITag[]) => ITag[] | Promise<ITag[]>;
/** Currently selected tags */
selectedItems?: ITag[];
/** Default selected tags */
defaultSelectedItems?: ITag[];
/** Change event handler */
onChange?: (items?: ITag[]) => void;
/** Item selection handler */
onItemSelected?: (selectedItem?: ITag) => ITag | Promise<ITag>;
/** Get text from tag */
getTextFromItem?: (item: ITag) => string;
/** Maximum number of tags */
itemLimit?: number;
/** Whether picker is disabled */
disabled?: boolean;
/** Input properties */
inputProps?: IInputProps;
/** Custom styles */
styles?: ITagPickerStyles;
/** Theme */
theme?: ITheme;
/** Remove button aria label */
removeButtonAriaLabel?: string;
/** Create generic item callback */
createGenericItem?: (input: string, ValidationState: ValidationState) => ITag;
}
interface ITag {
/** Tag key/ID */
key: string;
/** Display name */
name: string;
/** Additional data */
[key: string]: any;
}Usage Examples:
import React, { useState } from "react";
import { TagPicker, ITag } from "@fluentui/react";
const mockTags: ITag[] = [
{ key: 'react', name: 'React' },
{ key: 'typescript', name: 'TypeScript' },
{ key: 'javascript', name: 'JavaScript' },
{ key: 'css', name: 'CSS' },
{ key: 'html', name: 'HTML' },
{ key: 'azure', name: 'Azure' },
{ key: 'devops', name: 'DevOps' },
];
function TagPickerExample() {
const [selectedTags, setSelectedTags] = useState<ITag[]>([]);
const onResolveSuggestions = (filterText: string): ITag[] => {
return filterText
? mockTags.filter(tag =>
tag.name.toLowerCase().includes(filterText.toLowerCase())
).slice(0, 5)
: [];
};
const createGenericItem = (input: string): ITag => {
return {
key: input.toLowerCase().replace(/\s+/g, '-'),
name: input,
};
};
return (
<TagPicker
onResolveSuggestions={onResolveSuggestions}
selectedItems={selectedTags}
onChange={setSelectedTags}
itemLimit={10}
inputProps={{
placeholder: 'Enter tags...',
}}
createGenericItem={createGenericItem}
removeButtonAriaLabel="Remove tag"
/>
);
}Low-level picker components for building custom picker experiences.
/**
* Base picker component for custom picker implementations
* @param props - Base picker properties
* @returns JSX element for base picker
*/
function BasePicker<T>(props: IBasePickerProps<T>): JSX.Element;
/**
* Base floating picker for overlay-style pickers
* @param props - Base floating picker properties
* @returns JSX element for base floating picker
*/
function BaseFloatingPicker<T>(props: IBaseFloatingPickerProps<T>): JSX.Element;
interface IBasePickerProps<T> {
/** Currently selected items */
selectedItems?: T[];
/** Change callback */
onChange?: (items?: T[]) => void;
/** Suggestion resolver */
onResolveSuggestions: (filter: string, selectedItems?: T[]) => T[] | PromiseLike<T[]>;
/** Get text from item */
getTextFromItem?: (item: T, currentValue?: string) => string;
/** Custom item renderer */
onRenderItem?: (props: IPickerItemProps<T>) => JSX.Element;
/** Custom suggestions renderer */
onRenderSuggestionsItem?: (props: T, itemProps: ISuggestionItemProps<T>) => JSX.Element;
/** Picker input props */
inputProps?: IInputProps;
/** Enable tabbing between suggestions */
enableTabKeyNavigation?: boolean;
/** Custom styles */
styles?: IBasePickerStyles;
/** Theme */
theme?: ITheme;
}/**
* Create a generic item from user input
* @param input - User input text
* @param validationState - Current validation state
* @returns Created item
*/
function createGenericItem(input: string, validationState: ValidationState): any;
/**
* Validation states for picker input
*/
enum ValidationState {
valid = 0,
warning = 1,
invalid = 2,
}
/**
* Suggestion action types
*/
enum SuggestionActionType {
none = 0,
forceResolve = 1,
searchMore = 2,
}Pickers support extensive customization through styles and render props:
// Custom people picker with styling
<NormalPeoplePicker
styles={{
root: { maxWidth: 400 },
input: { fontSize: 16 },
itemsWrapper: { maxHeight: 200 }
}}
onRenderItem={(props) => (
<div className="custom-picker-item">
<Persona {...props.item} size={PersonaSize.size24} />
<IconButton
iconProps={{ iconName: 'Cancel' }}
onClick={props.onRemoveItem}
/>
</div>
)}
/>