Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/avatars/demo/stories/AvatarStory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ interface IArgs extends IAvatarProps {
export const AvatarStory: Story<IArgs> = ({ children, type, ...args }) => (
<Avatar
{...args}
backgroundColor={args.backgroundColor || (type === 'image' ? undefined : PALETTE.kale[800])}
backgroundColor={args.backgroundColor || (type === 'image' ? undefined : PALETTE.kale[1000])}
>
{
{
Expand Down
139 changes: 63 additions & 76 deletions packages/avatars/demo/~patterns/stories/MenuStory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,93 +5,80 @@
* found at http://www.apache.org/licenses/LICENSE-2.0.
*/

import React, { useState } from 'react';
import { Story } from '@storybook/react';
import Icon from '@zendeskgarden/svg-icons/src/16/chevron-down-stroke.svg';
import { PALETTE } from '@zendeskgarden/react-theming';
import React, { useCallback, useState } from 'react';
import { StoryFn } from '@storybook/react';
import { getColor } from '@zendeskgarden/react-theming';
import { Grid } from '@zendeskgarden/react-grid';
import {
Dropdown,
Trigger,
Menu,
MediaItem,
MediaFigure,
MediaBody,
ItemMeta
} from '@zendeskgarden/react-dropdowns.legacy';
import { Button } from '@zendeskgarden/react-buttons';
import { Avatar } from '@zendeskgarden/react-avatars';
import { Menu, Item } from '@zendeskgarden/react-dropdowns';
import { Avatar, IAvatarProps } from '@zendeskgarden/react-avatars';
import { useTheme } from 'styled-components';

export const MenuStory: Story = ({ isCompact }) => {
const [highlightedItem, setHighlightedItem] = useState<number | null>();
const [isOpen, setIsOpen] = useState<boolean | undefined>();
const items: {
value: string;
label: string;
avatarProps: IAvatarProps;
}[] = [
{
value: 'linden',
label: 'Linden',
avatarProps: {
status: 'away',
badge: undefined
}
},
{
value: 'reed',
label: 'Reed',
avatarProps: {
status: 'available',
badge: undefined
}
},
{
value: 'sage',
label: 'Sage',
avatarProps: {
status: undefined,
badge: '3'
}
}
];

export const MenuStory: StoryFn = ({ isCompact }) => {
const [highlightedValue, setHighlightedValue] = useState<string | null>();
const theme = useTheme();
const surfaceColor = getColor({ variable: 'background.raised', theme });
const highlightedColor = getColor({ variable: 'background.primary', theme });

const onChange = useCallback(({ focusedValue }: { focusedValue?: string | null }) => {
focusedValue !== undefined && setHighlightedValue(focusedValue);
}, []);

return (
<Grid>
<Grid.Row style={{ height: 'calc(100vh - 80px)' }}>
<Grid.Col textAlign="center" alignSelf="center">
<Dropdown
onStateChange={changes => {
setHighlightedItem(changes.highlightedIndex);
Object.prototype.hasOwnProperty.call(changes, 'isOpen') && setIsOpen(changes.isOpen);
}}
>
<Trigger>
<Button size={isCompact && 'small'}>
Demo
<Button.EndIcon isRotated={isOpen}>
<Icon />
</Button.EndIcon>
</Button>
</Trigger>
<Menu isCompact={isCompact}>
<MediaItem value="linden">
<MediaFigure>
<Avatar
size={isCompact ? 'extraextrasmall' : 'small'}
status="away"
surfaceColor={highlightedItem === 0 ? PALETTE.blue[100] : undefined}
>
<img alt="Linden" src="images/avatars/linden.png" />
</Avatar>
</MediaFigure>
<MediaBody>
Linden
<ItemMeta>[email protected]</ItemMeta>
</MediaBody>
</MediaItem>
<MediaItem value="reed">
<MediaFigure>
<Avatar
size={isCompact ? 'extraextrasmall' : 'small'}
status="available"
surfaceColor={highlightedItem === 1 ? PALETTE.blue[100] : undefined}
>
<img alt="Reed" src="images/avatars/reed.png" />
</Avatar>
</MediaFigure>
<MediaBody>
Reed
<ItemMeta>[email protected]</ItemMeta>
</MediaBody>
</MediaItem>
<MediaItem value="sage">
<MediaFigure>
<Menu button="Demo" isCompact={isCompact} onChange={onChange}>
{items.map(item => (
<Item
key={item.value}
value={item.value}
icon={
<Avatar
size={isCompact ? 'extraextrasmall' : 'small'}
badge="3"
surfaceColor={highlightedItem === 2 ? PALETTE.blue[100] : undefined}
status={item.avatarProps.status}
badge={item.avatarProps.badge}
surfaceColor={highlightedValue === item.value ? highlightedColor : surfaceColor}
>
<img alt="Sage" src="images/avatars/sage.png" />
<img alt={item.label} src={`images/avatars/${item.value}.png`} />
</Avatar>
</MediaFigure>
<MediaBody>
Sage
<ItemMeta>[email protected]</ItemMeta>
</MediaBody>
</MediaItem>
</Menu>
</Dropdown>
}
>
{item.label}
<Item.Meta>{item.value}@zendesk.garden</Item.Meta>
</Item>
))}
</Menu>
</Grid.Col>
</Grid.Row>
</Grid>
Expand Down
70 changes: 40 additions & 30 deletions packages/avatars/demo/~patterns/stories/StatusMenuStory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,51 +5,61 @@
* found at http://www.apache.org/licenses/LICENSE-2.0.
*/

import React, { useState } from 'react';
import React, { useCallback, useState } from 'react';
import { Story } from '@storybook/react';
import { Grid } from '@zendeskgarden/react-grid';
import { Dropdown, Trigger, Menu, Item } from '@zendeskgarden/react-dropdowns.legacy';
import { Avatar, IStatusIndicatorProps, StatusIndicator } from '@zendeskgarden/react-avatars';
import { IconButton } from '@zendeskgarden/react-buttons';
import { Item, Menu } from '@zendeskgarden/react-dropdowns';
import styled from 'styled-components';

const StyledIconButton = styled(IconButton)`
overflow: visible;
`;

export const StatusMenuStory: Story = ({ isCompact }) => {
const [selectedType, setSelectedType] = useState<IStatusIndicatorProps['type']>();

const onChange = useCallback(({ value }: { value?: string }) => {
value && setSelectedType(value as IStatusIndicatorProps['type']);
}, []);

return (
<Grid>
<Grid.Row style={{ height: 'calc(100vh - 80px)' }}>
<Grid.Col textAlign="center" alignSelf="center">
<Dropdown selectedItem={selectedType} onSelect={value => setSelectedType(value)}>
<Trigger>
<IconButton>
<Menu
button={props => (
<StyledIconButton {...props} aria-label="Select status">
<Avatar status={selectedType} size={isCompact ? 'small' : 'medium'}>
<img alt="Example User" src="images/avatars/chrome.png" />
</Avatar>
</IconButton>
</Trigger>
<Menu isCompact={isCompact}>
<Item value="offline">
<StatusIndicator isCompact={isCompact} type="offline">
Offline
</StatusIndicator>
</Item>
<Item value="available">
<StatusIndicator isCompact={isCompact} type="available">
Online
</StatusIndicator>
</Item>
<Item value="transfers">
<StatusIndicator isCompact={isCompact} type="transfers">
Transfers only
</StatusIndicator>
</Item>
<Item value="away">
<StatusIndicator isCompact={isCompact} type="away">
Away
</StatusIndicator>
</Item>
</Menu>
</Dropdown>
</StyledIconButton>
)}
onChange={onChange}
isCompact={isCompact}
>
<Item value="offline">
<StatusIndicator isCompact={isCompact} type="offline">
Offline
</StatusIndicator>
</Item>
<Item value="available">
<StatusIndicator isCompact={isCompact} type="available">
Online
</StatusIndicator>
</Item>
<Item value="transfers">
<StatusIndicator isCompact={isCompact} type="transfers">
Transfers only
</StatusIndicator>
</Item>
<Item value="away">
<StatusIndicator isCompact={isCompact} type="away">
Away
</StatusIndicator>
</Item>
</Menu>
</Grid.Col>
</Grid.Row>
</Grid>
Expand Down
1 change: 1 addition & 0 deletions packages/avatars/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"styled-components": "^5.3.1"
},
"devDependencies": {
"@zendeskgarden/react-dropdowns": "^9.0.0-next.17",
"@zendeskgarden/react-theming": "^9.0.0-next.17",
"@zendeskgarden/svg-icons": "7.1.1"
},
Expand Down
6 changes: 4 additions & 2 deletions packages/avatars/src/elements/Avatar.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@

import React from 'react';
import { render, cleanup } from 'garden-test-utils';
import { getColorV8, DEFAULT_THEME } from '@zendeskgarden/react-theming';
import { DEFAULT_THEME, getColor } from '@zendeskgarden/react-theming';
import { Avatar } from './Avatar';

const activeBoxShadow = DEFAULT_THEME.shadows.sm(getColorV8('crimson', 400)!);
const activeBoxShadow = DEFAULT_THEME.shadows.sm(
getColor({ hue: 'crimson', shade: 700, theme: DEFAULT_THEME })!
);

describe('Avatar', () => {
afterEach(cleanup);
Expand Down
18 changes: 9 additions & 9 deletions packages/avatars/src/elements/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,22 @@ const AvatarComponent = forwardRef<HTMLElement, IAvatarProps>(
return (
<StyledAvatar
ref={ref}
isSystem={isSystem}
size={size}
status={computedStatus}
surfaceColor={surfaceColor}
backgroundColor={backgroundColor}
foregroundColor={foregroundColor}
$isSystem={isSystem}
$size={size}
$status={computedStatus}
$surfaceColor={surfaceColor}
$backgroundColor={backgroundColor}
$foregroundColor={foregroundColor}
aria-atomic="true"
aria-live="polite"
{...props}
>
{Children.only(children)}
{computedStatus && (
<StyledStatusIndicator
size={size}
type={computedStatus}
surfaceColor={surfaceColor}
$size={size}
$type={computedStatus}
$surfaceColor={surfaceColor}
aria-label={statusLabel}
as="figcaption"
>
Expand Down
4 changes: 2 additions & 2 deletions packages/avatars/src/elements/StatusIndicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ export const StatusIndicator = forwardRef<HTMLElement, IStatusIndicatorProps>(
{/* eslint-disable-next-line jsx-a11y/prefer-tag-over-role */}
<StyledStandaloneStatusIndicator
role="img"
type={type}
size={isCompact ? 'small' : 'medium'}
$type={type}
$size={isCompact ? 'small' : 'medium'}
aria-label={ariaLabel}
>
{type === 'away' ? <ClockIcon data-icon-status={type} aria-hidden="true" /> : null}
Expand Down
Loading