Skip to content
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

Create Selectable component #660

Merged
merged 32 commits into from
Dec 17, 2020
Merged

Create Selectable component #660

merged 32 commits into from
Dec 17, 2020

Conversation

lazytype
Copy link
Contributor

✍️ Proposed changes

🎟 Jira ticket: Select React Component

🛠 Types of changes

  • Tooling (updates to workspace config or internal tooling)
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

✅ Checklist

  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)
  • I have run yarn changeset and documented my changes
  • I have added my new package to the global tsconfig
  • I have added my new package to the Table of Contents on the global README

💬 Further comments

@lazytype lazytype force-pushed the PD-271-Select branch 3 times, most recently from 542a41e to 9895ba2 Compare October 21, 2020 04:00
@github-actions
Copy link
Contributor

github-actions bot commented Oct 21, 2020

Size Change: 0 B

Total Size: 320 kB

ℹ️ View Unchanged
Filename Size Change
packages/badge/dist/index.js 1.28 kB 0 B
packages/banner/dist/index.js 1.93 kB 0 B
packages/box/dist/index.js 684 B 0 B
packages/button/dist/index.js 3.38 kB 0 B
packages/callout/dist/index.js 1.65 kB 0 B
packages/card/dist/index.js 1.22 kB 0 B
packages/checkbox/dist/index.js 73.1 kB 0 B
packages/code/dist/index.js 3.48 kB 0 B
packages/confirmation-modal/dist/index.js 2.01 kB 0 B
packages/copyable/dist/index.js 2.66 kB 0 B
packages/emotion/dist/index.js 613 B 0 B
packages/hooks/dist/index.js 2 kB 0 B
packages/icon-button/dist/index.js 2.44 kB 0 B
packages/icon/dist/ActivityFeed.js 1.72 kB 0 B
packages/icon/dist/ArrowDown.js 1.69 kB 0 B
packages/icon/dist/ArrowLeft.js 1.68 kB 0 B
packages/icon/dist/ArrowRight.js 1.64 kB 0 B
packages/icon/dist/ArrowUp.js 1.68 kB 0 B
packages/icon/dist/Beaker.js 2.55 kB 0 B
packages/icon/dist/Bell.js 1.67 kB 0 B
packages/icon/dist/Building.js 1.41 kB 0 B
packages/icon/dist/Bulb.js 1.79 kB 0 B
packages/icon/dist/CaretDown.js 1.42 kB 0 B
packages/icon/dist/CaretLeft.js 1.46 kB 0 B
packages/icon/dist/CaretRight.js 1.47 kB 0 B
packages/icon/dist/CaretUp.js 1.46 kB 0 B
packages/icon/dist/Charts.js 1.34 kB 0 B
packages/icon/dist/Checkmark.js 1.37 kB 0 B
packages/icon/dist/CheckmarkWithCircle.js 1.46 kB 0 B
packages/icon/dist/ChevronDown.js 1.36 kB 0 B
packages/icon/dist/ChevronLeft.js 1.36 kB 0 B
packages/icon/dist/ChevronRight.js 1.36 kB 0 B
packages/icon/dist/ChevronUp.js 1.36 kB 0 B
packages/icon/dist/Cloud.js 1.69 kB 0 B
packages/icon/dist/Copy.js 1.32 kB 0 B
packages/icon/dist/CreditCard.js 1.39 kB 0 B
packages/icon/dist/Download.js 1.73 kB 0 B
packages/icon/dist/Edit.js 1.33 kB 0 B
packages/icon/dist/Ellipsis.js 1.42 kB 0 B
packages/icon/dist/Folder.js 1.6 kB 0 B
packages/icon/dist/GovernmentBuilding.js 1.52 kB 0 B
packages/icon/dist/ImportantWithCircle.js 1.42 kB 0 B
packages/icon/dist/index.js 10.5 kB 0 B
packages/icon/dist/InfoWithCircle.js 1.45 kB 0 B
packages/icon/dist/InviteUser.js 1.82 kB 0 B
packages/icon/dist/Laptop.js 1.38 kB 0 B
packages/icon/dist/Lock.js 1.4 kB 0 B
packages/icon/dist/MagnifyingGlass.js 1.6 kB 0 B
packages/icon/dist/Megaphone.js 1.96 kB 0 B
packages/icon/dist/Menu.js 1.3 kB 0 B
packages/icon/dist/NotAllowed.js 1.52 kB 0 B
packages/icon/dist/OpenNewTab.js 1.39 kB 0 B
packages/icon/dist/Person.js 1.48 kB 0 B
packages/icon/dist/PersonWithLock.js 1.61 kB 0 B
packages/icon/dist/Plus.js 1.3 kB 0 B
packages/icon/dist/PlusWithCircle.js 1.38 kB 0 B
packages/icon/dist/QuestionMarkWithCircle.js 2.25 kB 0 B
packages/icon/dist/Refresh.js 1.55 kB 0 B
packages/icon/dist/Save.js 1.37 kB 0 B
packages/icon/dist/Settings.js 2.03 kB 0 B
packages/icon/dist/SortAscending.js 1.83 kB 0 B
packages/icon/dist/SortDescending.js 1.79 kB 0 B
packages/icon/dist/Stitch.js 1.36 kB 0 B
packages/icon/dist/Support.js 1.46 kB 0 B
packages/icon/dist/Trash.js 1.42 kB 0 B
packages/icon/dist/University.js 1.76 kB 0 B
packages/icon/dist/Unsorted.js 1.57 kB 0 B
packages/icon/dist/UpDownCarets.js 1.46 kB 0 B
packages/icon/dist/VerticalEllipsis.js 1.65 kB 0 B
packages/icon/dist/Warning.js 1.67 kB 0 B
packages/icon/dist/X.js 1.31 kB 0 B
packages/icon/dist/XWithCircle.js 1.43 kB 0 B
packages/inline-definition/dist/index.js 1.06 kB 0 B
packages/interaction-ring/dist/index.js 2.33 kB 0 B
packages/leafygreen-provider/dist/index.js 1.25 kB 0 B
packages/lib/dist/index.js 1.63 kB 0 B
packages/logo/dist/index.js 10.2 kB 0 B
packages/marketing-modal/dist/index.js 1.7 kB 0 B
packages/menu/dist/index.js 6.09 kB 0 B
packages/modal/dist/index.js 3.04 kB 0 B
packages/mongo-nav/dist/index.js 27 kB 0 B
packages/palette/dist/index.js 539 B 0 B
packages/pipeline/dist/index.js 5.57 kB 0 B
packages/popover/dist/index.js 4.44 kB 0 B
packages/portal/dist/index.js 1.03 kB 0 B
packages/radio-box-group/dist/index.js 3.59 kB 0 B
packages/radio-group/dist/index.js 3.42 kB 0 B
packages/select/dist/index.js 7.01 kB 0 B
packages/side-nav/dist/index.js 3.62 kB 0 B
packages/stepper/dist/index.js 3.96 kB 0 B
packages/syntax/dist/index.js 4.67 kB 0 B
packages/table/dist/index.js 5.51 kB 0 B
packages/tabs/dist/index.js 3.58 kB 0 B
packages/testing-lib/dist/index.js 1.51 kB 0 B
packages/text-area/dist/index.js 2.44 kB 0 B
packages/text-input/dist/index.js 3.32 kB 0 B
packages/theme/dist/index.js 550 B 0 B
packages/toast/dist/index.js 2.61 kB 0 B
packages/toggle/dist/index.js 3.55 kB 0 B
packages/tokens/dist/index.js 417 B 0 B
packages/tooltip/dist/index.js 3.56 kB 0 B
packages/typography/dist/index.js 3.63 kB 0 B

compressed-size-action

background-color: ${colorSet.option.background.base};
box-shadow: 0 3px 7px 0 ${colorSet.menu.shadow};

@media only screen and (max-width: ${breakpoints.Desktop}px) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

we use facepaint to help with media queries. not sure if necessary here, just a thought

const sizeSet = sizeSets[size];

const baseBoxShadow = `inset 0 -1px 0 0 ${colorSet.shadow.base}`;
let boxShadowExpanded = `0 0 0 3px ${colorSet.shadow.expanded}`;
Copy link
Collaborator

Choose a reason for hiding this comment

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

is there a reason not to turn this into a ternary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the boxShadowExpanded definition below uses the value of this definition

@bruugey
Copy link
Collaborator

bruugey commented Oct 21, 2020

Very very excited to have this in the repo

const onKeyDown = useCallback(
(event: React.KeyboardEvent) => {
// No support for modifiers yet
/* istanbul ignore if */
Copy link
Collaborator

Choose a reason for hiding this comment

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

do we need these comments in production too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it only affects test coverage reporting. it should get stripped out when bundled

Copy link
Collaborator

@DesignerDave DesignerDave left a comment

Choose a reason for hiding this comment

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

Just took a first look at this PR, and noticed a few things from an interaction perspective.

  • The dropdown doesn't transition in any way. Is there a reason we don't use Portal for this component? It has transitions built in.
  • The gradient, and border for the trigger don't transition between states. We should transition those like we do our button (if not using the button itself directly).
  • The interaction ring's background color doesn't appear to transition between background colors.
  • In general, we should transition between all states (selected, hover, focus, open).
  • It looks like the line-height of wrapping options is a bit too tight. Is that up to spec?
  • I think @audroue has some designs ready for an updated selected state for the component. That would be great to include.


export const sizeSets: Record<Size, SizeSet> = {
[Size.XSmall]: {
height: 22,
Copy link
Collaborator

Choose a reason for hiding this comment

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

What's the benefit to this versus simply writing out the CSS declarations here?

| `description` | `string` | Text that gives more detail about the requirements for the input. | |
| `placeholder` | `string` | The placeholder text shown in the input element when an option is not selected. | `'Select'` |
| `disabled` | `boolean` | Disables the component from being edited. | `false` |
| `value` | `string` | Sets the `<Option />` that will appear selected and makes the component a controlled component. | `''` |
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we consider allowing ReactElements to be passed here as well? A use case I'm thinking about is when we have Icons that would be part of Option value. Let me know what you think cc @DesignerDave

Copy link
Collaborator

Choose a reason for hiding this comment

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

Agreed, just because weird use-cases do come up, and it's low effort to support the flexibility.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wouldn't consider it low-effort. It would require being able to parse out the text content of arbitrary JSX and even further work if we would want to be able to differentiate between <><XIcon/> Icon</> and <><PlusIcon/> Icon</>. I wouldn't want to implement this unless it was specifically asked for, "YAGNI"

Copy link
Collaborator

Choose a reason for hiding this comment

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

You're right 🤦 I was thinking this was in reference to the display value for an option for some reason.

Copy link
Collaborator

@DesignerDave DesignerDave left a comment

Choose a reason for hiding this comment

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

Hey Michael! This is looking close.

There's a few design-related issues to note that I can see:

  • The padding to the left of the text in the select input toggle should be aligned with the padding of the labels in the dropdown. The caret on the right should also reflect this spacing.
  • The hover state for select options should transition.
  • Clicking the labels for option groups closes the dropdown. I'd confirm with Rob what the behavior should be here, but this feels like it would be annoying if you misclick when selecting an option.
  • The dropdown should animate its position as it opens instead of only fading in (though we should keep the opacity transition as well). Adding a translate3d(0, -8px, 0) to the inactive state, and translate3d(0, 0, 0) to the active one, and transitioning the value should improve things!

We might even want to go a little further and mimic our popover component:

# inactive
transition: opacity 150ms ease-in-out, transform 150ms ease-in-out;
opacity: 0;
transform: translate3d(0, -8px, 0) scale(0.95);
transform-origin: center top;

# active
opacity: 1;
transform: translate3d(0, -8px, 0) scale(0.95);

Copy link
Contributor Author

@lazytype lazytype left a comment

Choose a reason for hiding this comment

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

The caret on the right should also reflect this spacing.

Worth pointing out that the caret might not necessarily align with option labels since there may or may not be a scrollbar

| `description` | `string` | Text that gives more detail about the requirements for the input. | |
| `placeholder` | `string` | The placeholder text shown in the input element when an option is not selected. | `'Select'` |
| `disabled` | `boolean` | Disables the component from being edited. | `false` |
| `value` | `string` | Sets the `<Option />` that will appear selected and makes the component a controlled component. | `''` |
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wouldn't consider it low-effort. It would require being able to parse out the text content of arbitrary JSX and even further work if we would want to be able to differentiate between <><XIcon/> Icon</> and <><PlusIcon/> Icon</>. I wouldn't want to implement this unless it was specifically asked for, "YAGNI"

@DesignerDave
Copy link
Collaborator

The caret on the right should also reflect this spacing.

Worth pointing out that the caret might not necessarily align with option labels since there may or may not be a scrollbar

That's fine! It'll look better visually overall, and align better with the specs.

Copy link
Collaborator

@bruugey bruugey left a comment

Choose a reason for hiding this comment

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

Just want to note that I noticed that the combobox aria role is incorrectly applied here (as raised by both the accessibility knob and axe dev tools). I don't want to spend time trying to figure out on our own how to make this more accessible, as we're getting the results of the audit back on Wednesday, and I think their guidance will be very instructive in terms of next steps.

In the meantime, happy to get this in (maybe as a beta, since we know there will be some changes coming soon? cc: @DesignerDave )! Very excited to have this component in the repo.

@lazytype
Copy link
Contributor Author

lazytype commented Dec 9, 2020

Just want to note that I noticed that the combobox aria role is incorrectly applied here (as raised by both the accessibility knob and axe dev tools).

I've brought this up in a previous meeting but I can document it here for posterity. I've implemented combobox in conformance with the WAI-ARIA 1.2 spec https://www.w3.org/TR/wai-aria-1.2/#combobox. The accessibility guidance provided by storybook and axe is still based on WAI-ARIA 1.1 https://www.w3.org/TR/wai-aria-1.1/#combobox

@lazytype
Copy link
Contributor Author

lazytype commented Dec 9, 2020

dequelabs/axe-core#2505 is the tracking issue for Deque to update axe

@bruugey
Copy link
Collaborator

bruugey commented Dec 9, 2020

dequelabs/axe-core#2505 is the tracking issue for Deque to update axe

SGTM

Copy link
Collaborator

@DesignerDave DesignerDave left a comment

Choose a reason for hiding this comment

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

Let's get folks pressure-testing this!

@lazytype lazytype merged commit 0963164 into master Dec 17, 2020
@lazytype lazytype deleted the PD-271-Select branch December 17, 2020 19:55
bruugey pushed a commit that referenced this pull request Aug 9, 2023
* Create Selectable component

* PR feedback and adjustments

* More code reuse

* prettier

* updated design

* update readme

* use button as input

* Delegate focus to button

* cleanup

* use updated button

* revert eslintignore

* Make name optional

* PR feedback

* fix readme

* prettier

* supply darkMode prop to Buton

* fix scroll

* prettier

* Give option group aria label and hide caret icon

Co-authored-by: Michael Mitchell <[email protected]>
Sign up for free to 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.

3 participants