-
Notifications
You must be signed in to change notification settings - Fork 1.2k
[UserMenu] Update Topbar User Menu and Action List to reflect new designs #8856
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 all commits
9d7fa31
31f9011
413c28a
21558bf
1a81660
f7ab8a9
9fc6e67
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 |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| '@shopify/polaris': minor | ||
| --- | ||
|
|
||
| Updated top bar menu active state | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,5 @@ | ||||||||||||||||
| import React from 'react'; | ||||||||||||||||
| import {TickSmallMinor} from '@shopify/polaris-icons'; | ||||||||||||||||
|
|
||||||||||||||||
| import {classNames} from '../../../../utilities/css'; | ||||||||||||||||
| import type {ActionListItemDescriptor} from '../../../../types'; | ||||||||||||||||
|
|
@@ -11,6 +12,8 @@ import styles from '../../ActionList.scss'; | |||||||||||||||
| import {handleMouseUpByBlurring} from '../../../../utilities/focus'; | ||||||||||||||||
| import {HorizontalStack} from '../../../HorizontalStack'; | ||||||||||||||||
| import {Box} from '../../../Box'; | ||||||||||||||||
| import {Tooltip} from '../../../Tooltip'; | ||||||||||||||||
| import {Truncate} from '../../../Truncate'; | ||||||||||||||||
zakwarsame marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
|
|
||||||||||||||||
| export type ItemProps = ActionListItemDescriptor; | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -33,6 +36,7 @@ export function Item({ | |||||||||||||||
| ellipsis, | ||||||||||||||||
| active, | ||||||||||||||||
| role, | ||||||||||||||||
| truncate = false, | ||||||||||||||||
| }: ItemProps) { | ||||||||||||||||
| const className = classNames( | ||||||||||||||||
| styles.Item, | ||||||||||||||||
|
|
@@ -61,7 +65,15 @@ export function Item({ | |||||||||||||||
| ); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| const contentText = ellipsis && content ? `${content}…` : content; | ||||||||||||||||
| let contentText = null; | ||||||||||||||||
|
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. const contentText = ellipsis && content ? `${content}…` : (truncate ? truncateText(content) : content);
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. Thanks for the suggestion. Nesting a ternary operator is shorter, but the 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. You should consider using const most if not all places, and your condition is duplicated! const contextText = content
if (ellipsis && content) {
contentText = `${content}…`;
} else if (content && truncate) {
contentText = truncateText(content);
} remove the else, and assign contextText = content as default.
Member
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. We prefer clarity over brevity, especially in this case because theres multiple props that influence what's rendered and one needs to take precedence.
Suggested change
I do think that
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. Working on it here 😄 |
||||||||||||||||
|
|
||||||||||||||||
| if (ellipsis && content) { | ||||||||||||||||
| contentText = `${content}…`; | ||||||||||||||||
| } else if (content) { | ||||||||||||||||
| contentText = truncate ? truncateText(content) : content; | ||||||||||||||||
| } else { | ||||||||||||||||
| contentText = content; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| const contentMarkup = helpText ? ( | ||||||||||||||||
| <> | ||||||||||||||||
|
|
@@ -80,16 +92,28 @@ export function Item({ | |||||||||||||||
| </span> | ||||||||||||||||
| ); | ||||||||||||||||
|
|
||||||||||||||||
| const suffixMarkup = suffix && ( | ||||||||||||||||
| <Box> | ||||||||||||||||
| <span className={styles.Suffix}>{suffix}</span> | ||||||||||||||||
| </Box> | ||||||||||||||||
| ); | ||||||||||||||||
| let suffixMarkup: React.ReactNode | null = null; | ||||||||||||||||
|
|
||||||||||||||||
| if (active) { | ||||||||||||||||
| suffixMarkup = ( | ||||||||||||||||
| <Box> | ||||||||||||||||
| <span className={styles.Suffix}> | ||||||||||||||||
| <Icon source={TickSmallMinor} /> | ||||||||||||||||
| </span> | ||||||||||||||||
| </Box> | ||||||||||||||||
| ); | ||||||||||||||||
| } else if (suffix) { | ||||||||||||||||
| suffixMarkup = suffix && ( | ||||||||||||||||
| <Box> | ||||||||||||||||
| <span className={styles.Suffix}>{suffix}</span> | ||||||||||||||||
| </Box> | ||||||||||||||||
| ); | ||||||||||||||||
| } | ||||||||||||||||
|
Comment on lines
+95
to
+111
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. I tentatively made the suffix to always be |
||||||||||||||||
|
|
||||||||||||||||
| const textMarkup = <span className={styles.Text}>{contentMarkup}</span>; | ||||||||||||||||
|
|
||||||||||||||||
| const contentElement = ( | ||||||||||||||||
| <HorizontalStack blockAlign="center" gap="4"> | ||||||||||||||||
| <HorizontalStack blockAlign="center" gap="4" wrap={!truncate}> | ||||||||||||||||
| {prefixMarkup} | ||||||||||||||||
| {textMarkup} | ||||||||||||||||
| {badgeMarkup} | ||||||||||||||||
|
|
@@ -134,3 +158,19 @@ export function Item({ | |||||||||||||||
| </> | ||||||||||||||||
| ); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| const truncateText = (text: string) => { | ||||||||||||||||
| const trimmedText = text.trim(); | ||||||||||||||||
| return ( | ||||||||||||||||
| <Tooltip | ||||||||||||||||
| content={trimmedText} | ||||||||||||||||
| zIndexOverride={514} | ||||||||||||||||
| preferredPosition="above" | ||||||||||||||||
| hoverDelay={1000} | ||||||||||||||||
| > | ||||||||||||||||
| <Text truncate as="p" variant="bodyMd"> | ||||||||||||||||
| <Truncate>{trimmedText}</Truncate> | ||||||||||||||||
| </Text> | ||||||||||||||||
| </Tooltip> | ||||||||||||||||
| ); | ||||||||||||||||
| }; | ||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,13 @@ | ||
| import React, {useCallback, useState} from 'react'; | ||
| import type {ComponentMeta} from '@storybook/react'; | ||
| import {ActionList, Frame, Icon, TopBar, Text} from '@shopify/polaris'; | ||
| import {ArrowLeftMinor, QuestionMarkMajor} from '@shopify/polaris-icons'; | ||
| import {ActionList, Frame, Icon, TopBar, Text, Avatar} from '@shopify/polaris'; | ||
| import { | ||
| ArrowLeftMinor, | ||
| QuestionMarkMajor, | ||
| EditMinor, | ||
| TickSmallMinor, | ||
| SearchMinor, | ||
| } from '@shopify/polaris-icons'; | ||
|
|
||
| export default { | ||
| component: TopBar, | ||
|
|
@@ -49,15 +55,42 @@ export function Default() { | |
| <TopBar.UserMenu | ||
| actions={[ | ||
| { | ||
| items: [{content: 'Back to Shopify', icon: ArrowLeftMinor}], | ||
| items: [ | ||
| { | ||
| active: true, | ||
| content: 'Jaded Pixel', | ||
| prefix: <Avatar size="small" name="Jaded Pixel" />, | ||
| suffix: <Icon source={TickSmallMinor} />, | ||
| truncate: true, | ||
| }, | ||
| { | ||
| content: 'Jaded Pixel 2.0', | ||
| prefix: <Avatar size="small" name="Jaded Pixel 2.0" />, | ||
| truncate: true, | ||
| }, | ||
| { | ||
| content: 'View all 3 stores', | ||
| prefix: <Icon source={SearchMinor} />, | ||
| }, | ||
| ], | ||
| }, | ||
| { | ||
| items: [{content: 'Community forums'}], | ||
| }, | ||
| { | ||
| items: [{content: 'Help Center'}], | ||
| }, | ||
| { | ||
| items: [{content: 'Keyboard shortcuts'}], | ||
| }, | ||
| { | ||
| title: 'Dharma Johnson', | ||
| items: [{content: 'Manage account'}, {content: 'Log out'}], | ||
| }, | ||
|
Comment on lines
+86
to
+89
Member
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. Are all user menus going to have the store switcher eventually instead of the Stores action list item that links out to an identity page? If not, should this use case be documented as its own story since it's unique to merchants who have the store switcher?
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. Yup! Our current project aims to roll out the new store switcher to all our merchants except Plus, who have a separate nav.
Member
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. Ah okay! In that case, should we:
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. For future reference: moved |
||
| ]} | ||
| name="Dharma" | ||
| detail="Jaded Pixel" | ||
| initials="D" | ||
| initials="JP" | ||
| open={isUserMenuOpen} | ||
| onToggle={toggleIsUserMenuOpen} | ||
| /> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -204,6 +204,8 @@ export interface ActionListItemDescriptor | |
| suffix?: React.ReactNode; | ||
| /** Add an ellipsis suffix to action content */ | ||
| ellipsis?: boolean; | ||
| /** Truncate action content */ | ||
| truncate?: boolean; | ||
|
Member
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. @kyle Should |
||
| /** Whether the action is active or not */ | ||
| active?: boolean; | ||
| /** Defines a role for the action */ | ||
|
|
@@ -212,7 +214,7 @@ export interface ActionListItemDescriptor | |
|
|
||
| export interface ActionListSection { | ||
| /** Section title */ | ||
| title?: string; | ||
| title?: string | React.ReactNode; | ||
| /** Collection of action items for the list */ | ||
| items: readonly ActionListItemDescriptor[]; | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
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.