-
Notifications
You must be signed in to change notification settings - Fork 1.4k
feat: add Avatar support for ComboBoxItem and PickerItem #8926
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
21670b9
92b0681
56829d4
6ea182c
4081c01
f5b3cc7
6cee98d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,7 +33,8 @@ import { | |
| Virtualizer | ||
| } from 'react-aria-components'; | ||
| import {AsyncLoadable, FocusableRef, FocusableRefValue, GlobalDOMAttributes, HelpTextProps, LoadingState, PressEvent, RefObject, SpectrumLabelableProps} from '@react-types/shared'; | ||
| import {baseColor, edgeToText, focusRing, style} from '../style' with {type: 'macro'}; | ||
| import {AvatarContext} from './Avatar'; | ||
| import {baseColor, edgeToText, focusRing, fontRelative, style} from '../style' with {type: 'macro'}; | ||
| import {box, iconStyles as checkboxIconStyles} from './Checkbox'; | ||
| import {centerBaseline} from './CenterBaseline'; | ||
| import { | ||
|
|
@@ -241,6 +242,13 @@ const iconStyles = style({ | |
| } | ||
| }); | ||
|
|
||
| const avatar = style({ | ||
| gridArea: 'icon', | ||
| marginEnd: 'text-to-visual', | ||
| marginTop: fontRelative(6), // made up, need feedback | ||
| alignSelf: 'center' | ||
| }); | ||
|
|
||
| const loadingWrapperStyles = style({ | ||
| gridColumnStart: '1', | ||
| gridColumnEnd: '-1', | ||
|
|
@@ -571,6 +579,13 @@ export interface PickerItemProps extends Omit<ListBoxItemProps, 'children' | 'st | |
| children: ReactNode | ||
| } | ||
|
|
||
| const avatarSize = { | ||
| S: 16, | ||
| M: 20, | ||
| L: 22, | ||
| XL: 26 | ||
| } as const; | ||
|
|
||
| const checkmarkIconSize = { | ||
| S: 'XS', | ||
| M: 'M', | ||
|
|
@@ -599,21 +614,27 @@ export function PickerItem(props: PickerItemProps): ReactNode { | |
| icon: {render: centerBaseline({slot: 'icon', styles: iconCenterWrapper}), styles: icon} | ||
| }}}> | ||
| <DefaultProvider | ||
| context={TextContext} | ||
| value={{ | ||
| slots: { | ||
| [DEFAULT_SLOT]: {styles: label({size})}, | ||
| label: {styles: label({size})}, | ||
| description: {styles: description({...renderProps, size})} | ||
| } | ||
| }}> | ||
| {renderProps.selectionMode === 'single' && !isLink && <CheckmarkIcon size={checkmarkIconSize[size]} className={checkmark({...renderProps, size})} />} | ||
| {renderProps.selectionMode === 'multiple' && !isLink && ( | ||
| <div className={mergeStyles(checkbox, box(checkboxRenderProps))}> | ||
| <CheckmarkIcon size={size} className={checkboxIconStyles} /> | ||
| </div> | ||
| context={AvatarContext} | ||
| value={{slots: { | ||
| avatar: {size: avatarSize[size], styles: avatar} | ||
| }}}> | ||
|
Comment on lines
+617
to
+620
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this the right approach to add another child |
||
| <DefaultProvider | ||
| context={TextContext} | ||
| value={{ | ||
| slots: { | ||
| [DEFAULT_SLOT]: {styles: label({size})}, | ||
| label: {styles: label({size})}, | ||
| description: {styles: description({...renderProps, size})} | ||
| } | ||
| }}> | ||
| {renderProps.selectionMode === 'single' && !isLink && <CheckmarkIcon size={checkmarkIconSize[size]} className={checkmark({...renderProps, size})} />} | ||
| {renderProps.selectionMode === 'multiple' && !isLink && ( | ||
| <div className={mergeStyles(checkbox, box(checkboxRenderProps))}> | ||
| <CheckmarkIcon size={size} className={checkboxIconStyles} /> | ||
| </div> | ||
| )} | ||
| {typeof children === 'string' ? <Text slot="label">{children}</Text> : children} | ||
| {typeof children === 'string' ? <Text slot="label">{children}</Text> : children} | ||
| </DefaultProvider> | ||
| </DefaultProvider> | ||
| </DefaultProvider> | ||
| ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,7 +53,7 @@ function Example() { | |
|
|
||
| ### Slots | ||
|
|
||
| `PickerItem` supports icons, and `label` and `description` text slots. | ||
| `PickerItem` supports icons, avatars, and `label` and `description` text slots. | ||
|
|
||
| ```tsx render | ||
| "use client"; | ||
|
|
@@ -83,6 +83,29 @@ import UserSettings from '@react-spectrum/s2/icons/UserSettings'; | |
| </Picker> | ||
| ``` | ||
|
|
||
| ```tsx render | ||
| "use client"; | ||
| import {Avatar, Picker, PickerItem, Text} from '@react-spectrum/s2'; | ||
|
|
||
| const users = Array.from({length: 10}, (_, i) => ({ | ||
| name: `User ${i + 1}`, | ||
| email: `user${i + 1}@example.com`, | ||
| avatar: `https://i.imgur.com/kJOwAdv.png` | ||
| })); | ||
|
|
||
| <Picker label="Share" items={users}> | ||
| {(item) => ( | ||
| <PickerItem textValue={item.name}> | ||
| {/*- begin highlight -*/} | ||
| <Avatar slot="avatar" src={item.avatar} /> | ||
| {/*- end highlight -*/} | ||
| <Text slot="label">{item.name}</Text> | ||
| <Text slot="description">{item.email}</Text> | ||
| </PickerItem> | ||
| )} | ||
| </Picker> | ||
| ``` | ||
|
Comment on lines
86
to
108
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if this doc example is good enough for the site, or if it's okay to have two |
||
|
|
||
| <InlineAlert variant="notice"> | ||
| <Heading>Accessibility</Heading> | ||
| <Content>Interactive elements (e.g. buttons) within picker items are not allowed. This will break keyboard and screen reader navigation. Only add textual or decorative graphics (e.g. icons) as children.</Content> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The style macro variables in Picker.tsx and ComboBox.tsx are named a bit inconsistently, do you prefer this to be called
avataroravatarStyle(s)?