Skip to content

Action Menu - #1152

Merged
VanAnderson merged 125 commits into
mainfrom
VanAnderson/action-menu
Apr 16, 2021
Merged

Action Menu#1152
VanAnderson merged 125 commits into
mainfrom
VanAnderson/action-menu

Conversation

@VanAnderson

@VanAndersonVanAnderson commented Apr 2, 2021

Copy link
Copy Markdown
Contributor

Putting this into review although there are still a few outstanding items that need some attention - it should be ready to start getting eyes on it.

This component uses the ActionList as a base to create an accessible and customizable dropdown menu.

image

Fixes#1069

@changeset-bot

changeset-botBot commented Apr 2, 2021

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 91da62d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercelBot commented Apr 2, 2021

Copy link
Copy Markdown

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://vercel.com/primer/primer-components/6Pf5QKqrxDs9MszsjKXK38WbVK52
✅ Preview: https://primer-components-git-vananderson-action-menu-primer.vercel.app

Comment on lines +1 to +23
---
title: ActionMenu
---

An `ActionMenu` is a simple ActionList based component for define selectable menus.

## Default example

```jsx live
<ActionMenu
buttonContent="Menu"
items={[
{text: 'New file', onClick: () => console.log('Do Something!')},
ActionMenu.Divider,
{text: 'Copy link'},
{text: 'Edit file'},
{text: 'Delete file', variant: 'danger'}
]}
/>
```

## Component props

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going to fill this out just a bit more when the API settles out 👍

Comment threadsrc/stories/ActionMenu.stories.tsx Outdated
ComplexListStory.storyName = 'Complex List'

export function CustomTrigger(): JSX.Element {
const customAnchor = (props: any) => <Link {...props} />

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making a note on this - ideally we should just be able to pass Link directly to renderAnchor, but that doesn't seem to work in the way I thought it would.

@smocklesmockle mentioned this pull request Apr 5, 2021
7 tasks
@VanAnderson
VanAndersonforce-pushed the VanAnderson/action-menu branch from 5f93566 to 4b5023fCompareApril 7, 2021 14:37
@VanAnderson
VanAnderson marked this pull request as ready for review April 8, 2021 14:44
@VanAndersonVanAnderson changed the title [WIP] Action MenuAction MenuApr 8, 2021
Comment threadsrc/ActionMenu.tsx Outdated
renderAnchor?: (props: any) => JSX.Element
triggerContent?: React.ReactNode
renderItem?: (props: ItemProps) => JSX.Element
onActivate?: (props: ItemProps) => void

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onActivate is passed in and will trigger when a menu item is clicked or selected with the keyboard keys. This will pass ItemProps into the callback so the action can use the selected item to respond to the click or keyboard event.

This onActivate method might be more useful to users if we allowed a meta key of item props, where users could store actionable information about an item that could be used by onActivate to perform the items task/route to the proper place.

@smocklesmockleApr 8, 2021

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity: Does (an ActionMenu-level) onActivate prop support any use case that couldn’t be handled by (Item-level) onClick handlers?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think part of what this is trying to make a bit nicer is handling both click and keyboard functionality in one interface. I think to do the same thing with item level handlers would end up being a bit messy.

Comment thread@types/get-random-values/index.d.ts Outdated
@@ -0,0 +1,4 @@
declare module 'get-random-values' {

@VanAndersonVanAndersonApr 8, 2021

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes for easier testing in node, rather than using window.crypto.getRandomValue

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Historically, I believe we’ve avoided introducing external dependencies (especially ones without types) merely to improve the Primer developer experience (i.e. dependencies that do not also improve the experience of Primer consumers and the experience of their end-users).

Follow-up questions:

  1. Do we have established guidance about when to add third-party dependencies @colebemis@T-Hugs? (e.g. specific criteria dependencies must meet, specific situations when we’d avoid third-party solutions, guidelines for choosing between alternatives)
  2. If window.crypto.getRandomValue is onerous, how many lines of code would it take to produce a utility function which provides a nicer API but uses window.crypto.getRandomValue internally?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's such a simple method, I went ahead and just replaced it with a util that will generate a random string 👍

@VanAnderson

Copy link
Copy Markdown
ContributorAuthor

Not sure why vercel is failing - I don't have access to check the logs.

Comment threadsrc/ActionList/List.tsx Outdated
Comment on lines +46 to +50

// **
tabIndex?: number

ref?: React.RefObject<HTMLDivElement>

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there some sort of predefined type or interface we can use for these?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both tabIndex and ref would be available if the ListPropsBase interface extends’d React.ComponentPropsWithRef<'div'>

Comment threadsrc/ActionList/Item.tsx Outdated
<div>{text}</div>
{description && <DescriptionContainer>{description}</DescriptionContainer>}
</StyledTextContainer>
{AuxilaryIcon && (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work here! I love how this is consistent with the other conditional rendering (based on props) 🎊

Comment threadsrc/ActionList/List.tsx Outdated

return (
<StyledList {...props}>
<StyledList ref={containerRef as React.RefObject<HTMLDivElement>} {...props}>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid the as here?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had trouble making typescript happy here without it - though this pattern seems to be used other places in the code for this specific use case of the focusZone/focusTrap hooks.

I think there is going to be some changes incoming to how focusZones/focusTraps are implemented into ActionMenu/DropdownMenu/ActionList - I will keep an eye on how that work settles out. This might be something good to pair on that we can fix in a few places if we can find a better pattern.

@VanAnderson
VanAndersonforce-pushed the VanAnderson/action-menu branch from 0df23c9 to b1c11d7CompareApril 9, 2021 20:24
@VanAnderson
VanAnderson requested a review from smockleApril 9, 2021 20:33
Base automatically changed from dropdownmenu to mainApril 16, 2021 19:37
@VanAnderson
VanAndersonforce-pushed the VanAnderson/action-menu branch from f289a2a to d6095b9CompareApril 16, 2021 19:59
Comment threadsrc/ActionMenu.tsx Outdated
]}
/>
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add an example that uses groupMetadata?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, just pulled from our ActionList docs on this one and kept them parallel.

@colebemis

Copy link
Copy Markdown
Contributor

Is this difference in spacing between the right and the left intentional?

CleanShot 2021-04-16 at 13 20 52@2x

Co-authored-by: Cole Bemis <colebemis@github.com>
@VanAnderson

Copy link
Copy Markdown
ContributorAuthor

Is this difference in spacing between the right and the left intentional?

Not intentional, just didn't notice it. I knocked out the right margin for the trailingVisualContainer, and I think this looks pretty even now:

image

@colebemiscolebemis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Nice work, @VanAnderson! ✨

@VanAnderson
VanAnderson requested a review from dgreifApril 16, 2021 21:17

@dgreifdgreif left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking great! Just a couple tweaks/questions 😄

Comment threaddocs/content/ActionMenu.mdx Outdated
Comment threadsrc/ActionList/Item.tsx
Comment threadsrc/ActionMenu.tsx Outdated
Comment threadsrc/Portal/Portal.tsx Outdated
Comment threadsrc/index.ts
Comment threadsrc/stories/ActionMenu.stories.tsx Outdated
@VanAnderson
VanAnderson merged commit a975b5d into mainApr 16, 2021
@VanAnderson
VanAnderson deleted the VanAnderson/action-menu branch April 16, 2021 22:06
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ActionMenu

5 participants

@VanAnderson@colebemis@T-Hugs@dgreif@smockle