Skip to content

Components · Identity

AssigneePicker

People picker with avatars, "you" first, Unassigned, Assign to me and an avatar stack.

@rookcom/monarch-reactComponent

Assignee with you and Unassigned

Usage examples

Several reviewers

Purpose

Assigns one or several people (owners, assignees, reviewers) from a searchable list of avatar rows. It is EntityPicker preset for people: the product passes its members, Monarch handles avatars, ordering, the shortcuts and the trigger summary.

Use when

  • Assigning a ticket, issue, task or alert to a person.
  • Choosing reviewers, watchers or members (multiple).

Avoid when

  • Records that are not people: use EntityPicker.
  • Mentioning people inside text: use a mention menu in the editor.

Design principles

  • People are recognised by face and name: every row has an Avatar, with presence when the product knows it.
  • The most likely choices come first: Unassigned, then you, then the product’s order (groups such as "In this team").
  • The product owns the people: members come in as people or from onSearch; nothing is fetched by Monarch.

API reference

import { AssigneePicker } from '@rookcom/monarch-react';
ExportKindRenderingRoot class
AssigneePickercomponentclient.mn-assignee-picker

Accepts every EntityPicker prop except options, onSearch, valueOptions, clearOption, onCreate and renderValue, which it builds from people.

Forwards its ref to the trigger button. Values are person ids; Unassigned is null (single) or [] (multiple).

Generated from the TypeScript declarations of packages/react/src/components/identity/assignee-picker.

Properties

AssigneePerson is { id, name, email?, avatarUrl?, status?, hint?, group?, disabled? }.

AssigneePicker

People picker: assign one or several people from a searchable list with avatars, the current user first, an "Unassigned" option and an "Assign to me" shortcut. The trigger shows the assignee, or an avatar stack for several. Built on EntityPicker and Avatar; the product supplies the people.

PropTypeDescription
align"center" | "start" | "end"Popover alignment against the trigger. Default `start`.
allowUnassignedbooleanOffer an "Unassigned" option that clears the selection. Default true.
classNamestring
closeOnSelectbooleanClose after a pick. Default: true, or false with `multiple`.
contentClassNamestringClass on the popover panel.
currentUserIdstring | nullThe signed-in user: listed first (within their group) as "(you)", with an "Assign to me" shortcut.
defaultOpenboolean
defaultValuestring | null
defaultValuesstring[]
disabledboolean
emptyMessageReactNodeShown when nothing matches.
filter((option: ComboboxOption, query: string) => boolean)Custom filter for static `options`. Default: label, hint and keywords.
footerReactNode | ((context: EntityPickerFooterContext) => ReactNode)Content under the list, such as "Manage projects". A function gets `close` and the query.
idstring
invalidboolean
limitnumberRender at most this many matches, with a message to keep typing.
loadingbooleanShown while records load.
maxAvatarsnumberAvatars shown in the trigger before a "+N" tile, with `multiple`. Default 3.
messages(Partial<AssigneePickerMessages> & Partial<ComboboxMessages>)Interface text, for translation.
minSearchLengthnumberShortest query `onSearch` runs for. Default 0.
multiplebooleanPick several records; the list stays open after each pick.
onOpenChange((open: boolean) => void)
onSearch((query: string, context: ComboboxSearchContext) => Promise<AssigneePerson[]>)Search people on a server instead of filtering `people`. Debounced and aborted like Combobox `onSearch`.
onValueChange((value: string | null) => void)
onValuesChange((values: string[]) => void)
openbooleanWhether the picker is open (controlled).
peopleAssigneePerson[]The people to choose from, such as workspace members.
placeholderstringTrigger text when nothing is selected. Default "Select…".
renderOption((option: ComboboxOption, state: ComboboxOptionState) => ReactNode)Custom option content. Default: media, label, description, hint and a check mark.
searchDebouncenumberMilliseconds to wait after typing before `onSearch`. Default 250.
searchLabelstringAccessible name of the search box. Default: `searchPlaceholder`.
searchPlaceholderstringPlaceholder of the search box. Default "Search…".
showAssignToMebooleanShow the "Assign to me" footer shortcut when `currentUserId` is set. Default true.
size"sm" | "md" | "lg"
sortByMatchbooleanRank matches whose label starts with the query first. Default true.
triggerReactElement<unknown, string | import("/home/runner/work/monarch/monarch/node_modules/@types/react/index").JSXElementConstructor<any>>A custom trigger element (a chip, an icon button). It must accept a ref and name itself, for example `aria-label="Status: Open"`. Default: a field-style button.
valuestring | nullSelected record id (controlled). Single-select only.
valuePeopleAssigneePerson[]People for the current value(s) when they may not be in `people`. Used for names and avatars.
valuesstring[]

Variants

PropValuesDescription
multiple'false''true'One assignee with avatar and name, or several as an avatar stack and a count.
size'sm''md''lg'Trigger height, as EntityPicker.

States

StateExposed asBehaviour
Unassigneddata-placeholderNo one assigned: "Unassigned" in muted text.
Assigned–The trigger shows the avatar and name ("(you)" for the current user).
Several–An AvatarGroup (up to maxAvatars, then +N) and "N people".
Openaria-expanded="true"The people list with search.
Invalid / disableddata-invalid, disabledFrom invalid, disabled or the Field.

Interaction behaviour

  • Search matches name and email.
  • The current user (currentUserId) is listed first as "Name (you)"; "Assign to me" in the footer assigns them in one click.
  • "Unassigned" (on by default, allowUnassigned={false} to hide) clears the assignment.
  • Single closes after a pick; multiple toggles people and stays open.
  • With onSearch, people are searched on the server with debounce and abort, as in Combobox.

Keyboard support

KeysAction
Enter / Space / ArrowDown (trigger)Opens the picker.
ArrowDown / ArrowUp, Home / EndMoves through people.
EnterAssigns (or toggles) the active person.
TabReaches "Assign to me" in the footer.
EscapeCloses and returns focus to the trigger.

Accessibility

Role
select-only combobox opening a dialog with a search combobox and listbox
Accessible name
The Field label or aria-label; the current assignee is the trigger’s content.
  • Avatars in rows and the trigger are decorative; the name (and "(you)") carries the meaning.
  • Presence is shown on row avatars; give status in hint too when it matters, as colour alone is not enough.
  • Inherits EntityPicker’s dialog, combobox and listbox semantics.

Responsive behaviour

  • The list is at least 16rem wide; names and emails truncate.
  • The trigger keeps the avatar stack and truncates the text.

Theme support

  • Avatars fall back to initials on seeded colours; everything else uses semantic tokens in all themes.

Do and don't

Do

  • Pass currentUserId so people can assign themselves quickly.
  • Group people the way the product thinks ("In this team", "Everyone else") with group.
  • Pass valuePeople when the assignee may not be in the loaded list.

Don't

  • Do not use a native select of members; it loses search and avatars.
  • Do not put the person’s availability only in the presence dot colour.

Dependencies

KindDepends on
npm packagesreact
Monarch componentsAvatar, EntityPicker

Testing coverage

  • Lists Unassigned, then you, then everyone with avatars; search matches email; picks and updates the trigger.
  • "Assign to me" assigns and disappears once assigned; Unassigned clears.
  • Multiple stays open and summarises as an avatar stack with a count.
  • Server search keeps the picked name; valuePeople and translated messages.
CheckCovered
Axe in jsdomYes
Server renderingYes
Browser suitesVisual baselines: /__gallery/assignee-picker; Cross-browser axe: /components/assignee-picker

Tests: packages/react/src/components/identity/assignee-picker