From 1855bdf69a6c42faaa6d63232b86ff836b170ffd Mon Sep 17 00:00:00 2001 From: Derrick Marcey Date: Tue, 5 May 2020 16:59:59 -0400 Subject: [PATCH 1/7] Add align='right' prop to SelectMenu.Modal --- docs/content/SelectMenu.md | 23 ++++++++++++++++++++++- index.d.ts | 4 +++- src/SelectMenu/SelectMenuModal.js | 4 +++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/docs/content/SelectMenu.md b/docs/content/SelectMenu.md index fd3d009b130..b16b42d64ba 100644 --- a/docs/content/SelectMenu.md +++ b/docs/content/SelectMenu.md @@ -86,12 +86,33 @@ Used to wrap the content in a `SelectMenu`. ``` +### Right-aligned Example +```jsx live + + + + + Projects + + Primer Components bugs + Primer Components roadmap + Project 3 + Project 4 + + + + +``` + ### System Props SelectMenu.Modal components get `COMMON` system props. Read our [System Props](/system-props) doc page for a full list of available props. ### Component Props -SelectMenu.Modal components do not get any additional props besides system props. + +| Prop name | Type | Description | +| :-------- | :----- | :------------------------------------------------ | +| align | String | Use `right` to align the select menu to the right | ## SelectMenu.List diff --git a/index.d.ts b/index.d.ts index 309e1b315b7..225b320670b 100644 --- a/index.d.ts +++ b/index.d.ts @@ -298,7 +298,9 @@ declare module '@primer/components' { initialTab?: string } - export interface SelectMenuModalProps extends CommonProps, Omit, 'color'> {} + export interface SelectMenuModalProps extends CommonProps, Omit, 'color'> { + align?: 'left' | 'right' + } export interface SelectMenuListProps extends CommonProps, Omit, 'color'> {} diff --git a/src/SelectMenu/SelectMenuModal.js b/src/SelectMenu/SelectMenuModal.js index fc172c2cecf..ecd17d45558 100644 --- a/src/SelectMenu/SelectMenuModal.js +++ b/src/SelectMenu/SelectMenuModal.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import styled, {keyframes, css} from 'styled-components' import {COMMON, get} from '../constants' import theme from '../theme' @@ -68,7 +69,7 @@ const modalWrapperStyles = css` @media (min-width: ${get('breakpoints.0')}) { position: absolute; top: auto; - right: auto; + right: ${props => (props.align === 'right' ? '0' : 'auto')}; bottom: auto; left: auto; padding: 0; @@ -93,6 +94,7 @@ const SelectMenuModal = ({children, theme, ...rest}) => { } SelectMenuModal.defaultProps = { + align: PropTypes.oneOf(['left', 'right']), theme } From 39ae3a2fff1c0aa0ca296f6ea4c633e3edc1d555 Mon Sep 17 00:00:00 2001 From: Derrick Marcey Date: Wed, 6 May 2020 09:50:13 -0400 Subject: [PATCH 2/7] Add default for align to docs --- docs/content/SelectMenu.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/SelectMenu.md b/docs/content/SelectMenu.md index b16b42d64ba..4c9e314b3a4 100644 --- a/docs/content/SelectMenu.md +++ b/docs/content/SelectMenu.md @@ -110,9 +110,9 @@ SelectMenu.Modal components get `COMMON` system props. Read our [System Props](/ ### Component Props -| Prop name | Type | Description | -| :-------- | :----- | :------------------------------------------------ | -| align | String | Use `right` to align the select menu to the right | +| Prop name | Type | Default | Description | +| :-------- | :----- | :------ | ------------------------------------------------- | +| align | String | 'left' | Use `right` to align the select menu to the right | ## SelectMenu.List From 6a2c78e6e73670f2c25782daa53e96428aa6f843 Mon Sep 17 00:00:00 2001 From: Derrick Marcey Date: Wed, 6 May 2020 09:50:33 -0400 Subject: [PATCH 3/7] Add defaultProps for SelectMenuModal Co-authored-by: Michelle Tilley --- src/SelectMenu/SelectMenuModal.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/SelectMenu/SelectMenuModal.js b/src/SelectMenu/SelectMenuModal.js index ecd17d45558..9c13664831a 100644 --- a/src/SelectMenu/SelectMenuModal.js +++ b/src/SelectMenu/SelectMenuModal.js @@ -93,11 +93,15 @@ const SelectMenuModal = ({children, theme, ...rest}) => { ) } -SelectMenuModal.defaultProps = { +SelectMenuModal.propTypes = { align: PropTypes.oneOf(['left', 'right']), - theme + theme: PropTypes.object } +SelectMenuModal.defaultProps = { + align: 'left', + theme +} SelectMenuModal.propTypes = { ...COMMON.propTypes } From ffc2ebf58ef2e35e00e7ada3bb7ee759aee52588 Mon Sep 17 00:00:00 2001 From: Derrick Marcey Date: Wed, 6 May 2020 10:02:00 -0400 Subject: [PATCH 4/7] Added test for right-aligned SelectMenu --- src/__tests__/SelectMenu.js | 23 +- .../__snapshots__/SelectMenu.js.snap | 626 ++++++++++++++++++ 2 files changed, 641 insertions(+), 8 deletions(-) create mode 100644 src/__tests__/__snapshots__/SelectMenu.js.snap diff --git a/src/__tests__/SelectMenu.js b/src/__tests__/SelectMenu.js index 250d0084e56..120a716751b 100644 --- a/src/__tests__/SelectMenu.js +++ b/src/__tests__/SelectMenu.js @@ -1,18 +1,21 @@ -import React from 'react' -import SelectMenu from '../SelectMenu' -import Button from '../Button' +import 'babel-polyfill' + +import {render as HTMLRender, cleanup, render} from '@testing-library/react' +import {axe, toHaveNoViolations} from 'jest-axe' import {mount, renderRoot} from '../utils/testing' + +import Button from '../Button' import {COMMON} from '../constants' -import {render as HTMLRender, cleanup} from '@testing-library/react' -import {axe, toHaveNoViolations} from 'jest-axe' -import 'babel-polyfill' +import React from 'react' +import SelectMenu from '../SelectMenu' + expect.extend(toHaveNoViolations) -const BasicSelectMenu = ({onClick, as}) => { +const BasicSelectMenu = ({onClick, as, align = 'left'}) => { return ( - + Primer Components bugs @@ -123,4 +126,8 @@ describe('SelectMenu', () => { item.simulate('click') expect(component.getDOMNode().attributes.open).toBeFalsy() }) + + it('right-aligned modal has right: 0px', () => { + expect(render()).toMatchSnapshot() + }) }) diff --git a/src/__tests__/__snapshots__/SelectMenu.js.snap b/src/__tests__/__snapshots__/SelectMenu.js.snap new file mode 100644 index 00000000000..4bc61e7675a --- /dev/null +++ b/src/__tests__/__snapshots__/SelectMenu.js.snap @@ -0,0 +1,626 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SelectMenu right-aligned modal has right: 0px 1`] = ` +Object { + "asFragment": [Function], + "baseElement": .c1 { + position: relative; + display: inline-block; + padding: 6px 16px; + font-weight: 600; + line-height: 20px; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border-radius: 6px; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + font-size: 14px; + color: #24292e; + background-color: #fafbfc; + border: 1px solid rgba(27,31,35,0.12); + box-shadow: 0px 1px 0px rgba(27,31,35,0.04),inset 0px 2px 0px rgba(255,255,255,0.25); +} + +.c1:hover { + -webkit-text-decoration: none; + text-decoration: none; +} + +.c1:focus { + outline: none; +} + +.c1:disabled { + cursor: default; +} + +.c1:disabled svg { + opacity: 0.6; +} + +.c1:hover { + background-color: #F3F4F6; + box-shadow: 0px 1px 0px rgba(209,213,218,0.2),inset 0px 2px 0px rgba(255,255,255,0.1); +} + +.c1:focus { + border-color: transparent; + box-shadow: 0 0 0 3px rgba(3,102,214,0.3); +} + +.c1:active { + background-color: #edeff2; + box-shadow: inset 0px 2px 0px rgba(149,157,165,0.1); + border-color: #d1d5da; +} + +.c1:disabled { + color: #959da5; + background-color: #fafbfc; + border-color: #eaecef; +} + +.c6 { + padding: 4px 16px; + margin: 0; + font-size: 12px; + font-weight: 600; + color: #6a737d; + background-color: #f6f8fa; + border-bottom: 1px solid #eaecef; +} + +.c7 { + margin-top: -1px; + padding: 8px 16px; + font-size: 12px; + color: #6a737d; + text-align: center; + border-top: 1px solid #e1e4e8; +} + +.c5 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + padding: 16px; + overflow: hidden; + text-align: left; + cursor: pointer; + background-color: #fff; + border: 0; + border-bottom: 1px solid #eaecef; + color: #586069; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c5:hover { + -webkit-text-decoration: none; + text-decoration: none; +} + +.c5:focus { + outline: none; +} + +.c5[hidden] { + display: none !important; +} + +.c5 .SelectMenu-icon { + width: 16px; + margin-right: 8px; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; +} + +.c5 .SelectMenu-selected-icon { + visibility: hidden; + -webkit-transition: -webkit-transform 0.12s cubic-bezier(0.5,0.1,1,0.5),visibility 0s 0.12s linear; + -webkit-transition: transform 0.12s cubic-bezier(0.5,0.1,1,0.5),visibility 0s 0.12s linear; + transition: transform 0.12s cubic-bezier(0.5,0.1,1,0.5),visibility 0s 0.12s linear; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); +} + +.c5[aria-checked='true'] { + font-weight: 500; + color: #24292e; +} + +.c5[aria-checked='true'] .SelectMenu-selected-icon { + visibility: visible; + -webkit-transition: -webkit-transform 0.12s cubic-bezier(0,0,0.2,1),visibility 0s linear; + -webkit-transition: transform 0.12s cubic-bezier(0,0,0.2,1),visibility 0s linear; + transition: transform 0.12s cubic-bezier(0,0,0.2,1),visibility 0s linear; + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); +} + +.c4 { + position: relative; + padding: 0; + margin: 0; + -webkit-flex: auto; + -ms-flex: auto; + flex: auto; + overflow-x: hidden; + overflow-y: auto; + background-color: #fff; + -webkit-overflow-scrolling: touch; +} + +.c3 { + position: relative; + z-index: 99; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + max-height: 66%; + margin: auto 0; + overflow: hidden; + pointer-events: auto; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + background-color: #fff; + border-radius: 6px; + box-shadow: 0 1px 5px rgba(27,31,35,0.15); + -webkit-animation: lejQAW 0.12s cubic-bezier(0,0.1,0.1,1) backwards; + animation: lejQAW 0.12s cubic-bezier(0,0.1,0.1,1) backwards; +} + +.c2 { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 99; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 16px; + pointer-events: none; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; +} + +.c2::before { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + pointer-events: none; + content: ''; + background-color: rgba(27,31,35,0.5); +} + +.c0[open] > summary::before { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 80; + display: block; + cursor: default; + content: ' '; + background: transparent; +} + +.c0 > summary { + list-style: none; +} + +.c0 > summary::before { + display: none; +} + +.c0 > summary::-webkit-details-marker { + display: none; +} + +@media (min-width:544px) { + .c7 { + padding: 4px 8px; + } +} + +@media (min-width:544px) { + .c5 { + padding-top: 8px; + padding-bottom: 8px; + } +} + +@media (hover:hover) { + .c5 body:not(.intent-mouse) .SelectMenu-item:focus, + .c5:hover, + .c5:active, + .c5:focus { + background-color: #f6f8fa; + } +} + +@media (hover:none) { + .c5 { + -webkit-tap-highlight-color: rgba(#d1d5da,0.5); + } + + .c5:focus, + .c5:active { + background-color: #fafbfc; + } +} + +@media (hover:hover) { + .c4 .SelectMenuTab:focus { + background-color: #dbedff; + } + + .c4 .SelectMenuTab:not([aria-checked='true']):hover { + color: #24292e; + background-color: #e1e4e8; + } + + .c4 .SelectMenuTab:not([aria-checked='true']):active { + color: #24292e; + background-color: #f6f8fa; + } +} + +@media (min-width:544px) { + .c3 { + width: '300px'; + height: auto; + max-height: 350px; + margin: 4px 0 16px 0; + font-size: 12px; + border: 1px solid #d1d5da; + border-radius: 6px; + box-shadow: 0 1px 5px rgba(27,31,35,0.15) !default; + } +} + +@media (min-width:544px) { + .c2::before { + display: none; + } +} + +@media (min-width:544px) { + .c2 { + position: absolute; + top: auto; + right: 0; + bottom: auto; + left: auto; + padding: 0; + } +} + + + + , + "container": , + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; From 5da82014acee3265ac7dcb9a546f6aa4d0ca5c21 Mon Sep 17 00:00:00 2001 From: Derrick Marcey Date: Wed, 6 May 2020 10:26:20 -0400 Subject: [PATCH 5/7] Updated snapshot for right-align menu --- .../__snapshots__/SelectMenu.js.snap | 577 +++++++----------- 1 file changed, 216 insertions(+), 361 deletions(-) diff --git a/src/__tests__/__snapshots__/SelectMenu.js.snap b/src/__tests__/__snapshots__/SelectMenu.js.snap index 4bc61e7675a..800bcbfa294 100644 --- a/src/__tests__/__snapshots__/SelectMenu.js.snap +++ b/src/__tests__/__snapshots__/SelectMenu.js.snap @@ -1,73 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`SelectMenu right-aligned modal has right: 0px 1`] = ` -Object { - "asFragment": [Function], - "baseElement": .c1 { - position: relative; - display: inline-block; - padding: 6px 16px; - font-weight: 600; - line-height: 20px; - white-space: nowrap; - vertical-align: middle; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - border-radius: 6px; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - -webkit-text-decoration: none; - text-decoration: none; - font-size: 14px; - color: #24292e; - background-color: #fafbfc; - border: 1px solid rgba(27,31,35,0.12); - box-shadow: 0px 1px 0px rgba(27,31,35,0.04),inset 0px 2px 0px rgba(255,255,255,0.25); -} - -.c1:hover { - -webkit-text-decoration: none; - text-decoration: none; -} - -.c1:focus { - outline: none; -} - -.c1:disabled { - cursor: default; -} - -.c1:disabled svg { - opacity: 0.6; -} - -.c1:hover { - background-color: #F3F4F6; - box-shadow: 0px 1px 0px rgba(209,213,218,0.2),inset 0px 2px 0px rgba(255,255,255,0.1); -} - -.c1:focus { - border-color: transparent; - box-shadow: 0 0 0 3px rgba(3,102,214,0.3); -} - -.c1:active { - background-color: #edeff2; - box-shadow: inset 0px 2px 0px rgba(149,157,165,0.1); - border-color: #d1d5da; -} - -.c1:disabled { - color: #959da5; - background-color: #fafbfc; - border-color: #eaecef; -} - .c6 { padding: 4px 16px; margin: 0; @@ -106,6 +39,8 @@ Object { color: #586069; -webkit-text-decoration: none; text-decoration: none; + font-size: 12px; + width: 100%; } .c5:hover { @@ -242,6 +177,72 @@ Object { display: none; } +.c1 { + position: relative; + display: inline-block; + padding: 6px 16px; + font-weight: 600; + line-height: 20px; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border-radius: 6px; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + text-align: center; + font-size: 14px; + color: #24292e; + background-color: #fafbfc; + border: 1px solid rgba(27,31,35,0.12); + box-shadow: 0px 1px 0px rgba(27,31,35,0.04),inset 0px 2px 0px rgba(255,255,255,0.25); +} + +.c1:hover { + -webkit-text-decoration: none; + text-decoration: none; +} + +.c1:focus { + outline: none; +} + +.c1:disabled { + cursor: default; +} + +.c1:disabled svg { + opacity: 0.6; +} + +.c1:hover { + background-color: #F3F4F6; + box-shadow: 0px 1px 0px rgba(209,213,218,0.2),inset 0px 2px 0px rgba(255,255,255,0.1); +} + +.c1:focus { + border-color: transparent; + box-shadow: 0 0 0 3px rgba(3,102,214,0.3); +} + +.c1:active { + background-color: #edeff2; + box-shadow: inset 0px 2px 0px rgba(149,157,165,0.1); + border-color: #d1d5da; +} + +.c1:disabled { + color: #959da5; + background-color: #fafbfc; + border-color: #eaecef; +} + @media (min-width:544px) { .c7 { padding: 4px 8px; @@ -321,306 +322,160 @@ Object { } } - -
-
+ + Projects + +
+
+
- - Projects - - -
-
- , - "container":
-
- - Projects - - -
-
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} + + + `; From 2f1d9d377db89576e05d8d3a468b0c613527ba14 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Thu, 7 May 2020 10:03:52 -0700 Subject: [PATCH 6/7] Fixup SelectMenuModal propTypes --- src/SelectMenu/SelectMenuModal.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/SelectMenu/SelectMenuModal.js b/src/SelectMenu/SelectMenuModal.js index c351876d230..1767e6bf9a0 100644 --- a/src/SelectMenu/SelectMenuModal.js +++ b/src/SelectMenu/SelectMenuModal.js @@ -95,16 +95,13 @@ const SelectMenuModal = ({children, theme, ...rest}) => { ) } -SelectMenuModal.propTypes = { - align: PropTypes.oneOf(['left', 'right']), - theme: PropTypes.object -} - SelectMenuModal.defaultProps = { align: 'left', theme } SelectMenuModal.propTypes = { + align: PropTypes.oneOf(['left', 'right']), + theme: PropTypes.object, ...COMMON.propTypes, ...sx.propTypes } From a224c9524ce5c3884ab3fb11829de51f939efcb6 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Thu, 7 May 2020 11:24:54 -0700 Subject: [PATCH 7/7] Update docs --- docs/content/SelectMenu.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/content/SelectMenu.md b/docs/content/SelectMenu.md index 302019fcf8b..f315a4d20e5 100644 --- a/docs/content/SelectMenu.md +++ b/docs/content/SelectMenu.md @@ -86,7 +86,10 @@ Used to wrap the content in a `SelectMenu`. ``` -### Right-aligned Example +### Right-aligned modal + +Use the `align='right'` prop to align the modal to the right. Note that this only aligns the modal contents, and not the SelectMenu itself. + ```jsx live