From ba994445154e9546645c0701b1666c4f0406cdcc Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Mon, 8 Apr 2019 18:34:48 -0700 Subject: [PATCH 1/5] Use @reach MenuButton for owner stack menu --- package.json | 1 + src/devtools/views/Components/OwnersStack.css | 43 +++-- src/devtools/views/Components/OwnersStack.js | 69 +++----- src/devtools/views/DevTools.js | 1 + yarn.lock | 153 +++++++++++++++++- 5 files changed, 204 insertions(+), 63 deletions(-) diff --git a/package.json b/package.json index 68c3bc693e..07019d599d 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@babel/preset-env": "^7.1.6", "@babel/preset-flow": "^7.0.0", "@babel/preset-react": "^7.0.0", + "@reach/menu-button": "^0.1.9", "adm-zip": "^0.4.7", "babel-core": "^7.0.0-bridge", "babel-eslint": "^9.0.0", diff --git a/src/devtools/views/Components/OwnersStack.css b/src/devtools/views/Components/OwnersStack.css index f7acd99612..9ea1641bdd 100644 --- a/src/devtools/views/Components/OwnersStack.css +++ b/src/devtools/views/Components/OwnersStack.css @@ -18,6 +18,7 @@ cursor: pointer; text-align: left; } +.Component[data-selected], .Component:hover { background-color: var(--color-hover-background); } @@ -39,10 +40,6 @@ flex: 1 0 auto; } -.Toggle { - margin-right: 0.5rem; -} - .VRule { flex: 0 0 auto; height: 20px; @@ -51,18 +48,46 @@ margin: 0 0.5rem; } -.Modal { - position: absolute; - top: calc(100% + 0.25rem); - left: 2.5rem; - z-index: 1; +.MenuButton { + border-radius: 0.25rem; + display: inline-flex; + align-items: center; + padding: 0.25rem; + cursor: pointer; + flex: 0 0 auto; + border: none; + background: var(--color-button-background); + color: var(--color-button); + margin-right: 0.5rem; +} +.MenuButton:hover { + background: var(--color-button-background-hover); + color: var(--color-button-hover); +} +.MenuButton[aria-expanded='true'], +.MenuButton[aria-expanded='true']:active { + background: var(--color-button-background-focus); + color: var(--color-button-focus); + outline: none; +} +.MenuButton:focus-within { + box-shadow: 0 0 0 2px var(--color-button-background-focus) inset; + outline: none; +} + +.Modal[data-reach-menu-list] { display: inline-flex; flex-direction: column; background-color: var(--color-background); + color: var(--color-text-color); padding: 0.5rem; padding-right: 0; border: 1px solid var(--color-border); border-radius: 0.25rem; max-height: 10rem; overflow: auto; + + /* Reach UI tries to set its own :( */ + font-family: var(--font-family-monospace); + font-size: var(--font-size-monospace-normal); } diff --git a/src/devtools/views/Components/OwnersStack.js b/src/devtools/views/Components/OwnersStack.js index e7cfcbb69d..e459e1eee4 100644 --- a/src/devtools/views/Components/OwnersStack.js +++ b/src/devtools/views/Components/OwnersStack.js @@ -1,18 +1,17 @@ // @flow import React, { - Fragment, useCallback, useContext, useLayoutEffect, useRef, useState, } from 'react'; +import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button'; import Button from '../Button'; import ButtonIcon from '../ButtonIcon'; -import Toggle from '../Toggle'; import { TreeContext } from './TreeContext'; import { StoreContext } from '../context'; -import { useIsOverflowing, useModalDismissSignal } from '../hooks'; +import { useIsOverflowing } from '../hooks'; import type { Element } from './types'; @@ -92,53 +91,27 @@ function ElementsDropdown({ const store = useContext(StoreContext); const { selectOwner } = useContext(TreeContext); - const [isDropdownVisible, setIsDropdownVisible] = useState(false); - - const handleDropdownButtonClick = useCallback(() => { - setIsDropdownVisible(!isDropdownVisible); - }, [isDropdownVisible, setIsDropdownVisible]); - - const handleElementClick = useCallback( - (id: number) => { - selectOwner(id); - setIsDropdownVisible(false); - }, - [selectOwner, setIsDropdownVisible] - ); - - const modalRef = useRef(null); - const dismissModal = useCallback(() => setIsDropdownVisible(false)); - - useModalDismissSignal(modalRef, dismissModal); - return ( - - + + - - {isDropdownVisible && ( -
- {ownerStack.map((id, index) => ( - - ))} -
- )} - +
+ + {ownerStack.map((id, index) => ( + selectOwner(id)} + > + {((store.getElementByID(id): any): Element).displayName} + + ))} + +
); } diff --git a/src/devtools/views/DevTools.js b/src/devtools/views/DevTools.js index e5cad6eb9e..0a3225f5fe 100644 --- a/src/devtools/views/DevTools.js +++ b/src/devtools/views/DevTools.js @@ -14,6 +14,7 @@ import ReactLogo from './ReactLogo'; import styles from './DevTools.css'; +import '@reach/menu-button/styles.css'; import './root.css'; import type { Bridge } from '../../types'; diff --git a/yarn.lock b/yarn.lock index 0f79da19d3..71cb56e316 100644 --- a/yarn.lock +++ b/yarn.lock @@ -745,6 +745,67 @@ resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw== +"@reach/component-component@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@reach/component-component/-/component-component-0.1.3.tgz#5d156319572dc38995b246f81878bc2577c517e5" + integrity sha512-a1USH7L3bEfDdPN4iNZGvMEFuBfkdG+QNybeyDv8RloVFgZYRoM+KGXyy2KOfEnTUM8QWDRSROwaL3+ts5Angg== + +"@reach/menu-button@^0.1.9": + version "0.1.9" + resolved "https://registry.yarnpkg.com/@reach/menu-button/-/menu-button-0.1.9.tgz#d5957f69efa51d29beb4239403eabf49f9a4bb3e" + integrity sha512-894lhzcCpaGJKvmCuUX8AJ7xg0Ov/xRKKR5RRVJUroHYuWNuvgZSluO657Y2fNaMKgG0LPqLrtOGUq2CN0golg== + dependencies: + "@reach/component-component" "^0.1.3" + "@reach/portal" "^0.1.3" + "@reach/rect" "^0.2.0" + "@reach/router" "^1.1.0" + "@reach/utils" "^0.2.0" + "@reach/window-size" "^0.1.3" + warning "^4.0.2" + +"@reach/observe-rect@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.0.3.tgz#2ea3dcc369ab22bd9f050a92ea319321356a61e8" + integrity sha1-LqPcw2mrIr2fBQqS6jGTITVqYeg= + +"@reach/portal@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.1.3.tgz#31d820f31bbab73570d5b5a449e2b0fa6457802f" + integrity sha512-yDcu5XZWfWKmKvbOs/uS7vITPVFXmn+XY5V6YcGhlz20KgwG+aJX2c7yvYzO++Zr0qvmtQCmxA4EGEciqIys6g== + dependencies: + "@reach/component-component" "^0.1.3" + +"@reach/rect@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.2.0.tgz#3e8dd4e2188294228ea223223a956885a8a33472" + integrity sha512-/C0r28VC/0dJ7ehKqkiebU7WvyiqXw5ViWC4KUWQRVTwauLENmslJ3jgEDUQZn6M3Ko63owaMZ2/rAivFfpIGQ== + dependencies: + "@reach/component-component" "^0.1.3" + "@reach/observe-rect" "^1.0.3" + +"@reach/router@^1.1.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@reach/router/-/router-1.2.1.tgz#34ae3541a5ac44fa7796e5506a5d7274a162be4e" + integrity sha512-kTaX08X4g27tzIFQGRukaHmNbtMYDS3LEWIS8+l6OayGIw6Oyo1HIF/JzeuR2FoF9z6oV+x/wJSVSq4v8tcUGQ== + dependencies: + create-react-context "^0.2.1" + invariant "^2.2.3" + prop-types "^15.6.1" + react-lifecycles-compat "^3.0.4" + warning "^3.0.0" + +"@reach/utils@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.2.0.tgz#504e84613b4aed7adf189aaa6b9d110b282ec523" + integrity sha512-AIfX18Ska78d4SjLt4awYHsgXEIVHhOUxLtxze2XT0D5aPOPx1XJl0seRZfQI0EVod4K1KVvHJnskEYSXqKQQg== + +"@reach/window-size@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@reach/window-size/-/window-size-0.1.3.tgz#eaf8ed8265cf20321a83037d2ab32dad936e79bd" + integrity sha512-XU/PdGZ9GoRHUkIqIEcARIKWvfEDYCR/b2/Yubo+acKXJQ2I/YkQJdpILdIhNqF93nGa4zIAHrRHXkXdW11Xyg== + dependencies: + "@reach/component-component" "^0.1.3" + "@samverschueren/stream-to-observable@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" @@ -3177,6 +3238,14 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" +create-react-context@^0.2.1: + version "0.2.3" + resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.2.3.tgz#9ec140a6914a22ef04b8b09b7771de89567cb6f3" + integrity sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag== + dependencies: + fbjs "^0.8.0" + gud "^1.0.0" + cross-spawn-async@^2.2.2: version "2.2.5" resolved "https://registry.yarnpkg.com/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz#845ff0c0834a3ded9d160daca6d390906bb288cc" @@ -3739,6 +3808,13 @@ emojis-list@^2.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= +encoding@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= + dependencies: + iconv-lite "~0.4.13" + end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" @@ -4487,6 +4563,19 @@ fbjs@0.5.1: ua-parser-js "^0.7.9" whatwg-fetch "^0.9.0" +fbjs@^0.8.0: + version "0.8.17" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd" + integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90= + dependencies: + core-js "^1.0.0" + isomorphic-fetch "^2.1.1" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.18" + fd-slicer@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" @@ -5169,6 +5258,11 @@ growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" +gud@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" + integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== + gulp-util@^3.0.4: version "3.0.8" resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" @@ -5469,7 +5563,7 @@ iconv-lite@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" -iconv-lite@^0.4.17, iconv-lite@^0.4.4: +iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -5642,7 +5736,7 @@ invariant@^2.2.0: dependencies: loose-envify "^1.0.0" -invariant@^2.2.2: +invariant@^2.2.2, invariant@^2.2.3: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -5967,7 +6061,7 @@ is-retry-allowed@^1.0.0: resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= -is-stream@^1.0.0, is-stream@^1.1.0: +is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= @@ -6041,6 +6135,14 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= +isomorphic-fetch@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= + dependencies: + node-fetch "^1.0.1" + whatwg-fetch ">=0.10.0" + isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -7597,6 +7699,14 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-fetch@^1.0.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + node-firefox-connect@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/node-firefox-connect/-/node-firefox-connect-1.2.0.tgz#42403848313240c98514ef14b3302816fe3b84e1" @@ -8467,7 +8577,14 @@ promise@^7.0.3: dependencies: asap "~2.0.3" -prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.2: +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== + dependencies: + asap "~2.0.3" + +prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -8674,6 +8791,11 @@ react-is@^16.8.4: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.4.tgz#90f336a68c3a29a096a3d648ab80e87ec61482a2" integrity sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA== +react-lifecycles-compat@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== + react-portal@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/react-portal/-/react-portal-3.2.0.tgz#4224e19b2b05d5cbe730a7ba0e34ec7585de0043" @@ -9375,7 +9497,7 @@ set-value@^2.0.0: is-plain-object "^2.0.3" split-string "^3.0.1" -setimmediate@^1.0.4: +setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= @@ -10369,7 +10491,7 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -ua-parser-js@^0.7.9: +ua-parser-js@^0.7.18, ua-parser-js@^0.7.9: version "0.7.19" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.19.tgz#94151be4c0a7fb1d001af7022fdaca4642659e4b" integrity sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ== @@ -10646,6 +10768,20 @@ walker@~1.0.5: dependencies: makeerror "1.0.x" +warning@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" + integrity sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w= + dependencies: + loose-envify "^1.0.0" + +warning@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" + integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== + dependencies: + loose-envify "^1.0.0" + watch@~0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" @@ -10781,6 +10917,11 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: dependencies: iconv-lite "0.4.19" +whatwg-fetch@>=0.10.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" + integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== + whatwg-fetch@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-0.9.0.tgz#0e3684c6cb9995b43efc9df03e4c365d95fd9cc0" From db629fa0734b51ff96bb31faf4edc11a9addedb7 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 9 Apr 2019 08:30:24 -0700 Subject: [PATCH 2/5] Updated OwnersStack CSS to properly override React styles --- src/devtools/views/Components/OwnersStack.css | 15 +++++++++++---- src/devtools/views/Components/OwnersStack.js | 6 +----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/devtools/views/Components/OwnersStack.css b/src/devtools/views/Components/OwnersStack.css index 9ea1641bdd..cf657f2757 100644 --- a/src/devtools/views/Components/OwnersStack.css +++ b/src/devtools/views/Components/OwnersStack.css @@ -6,6 +6,7 @@ } .Component, +.Component[data-reach-menu-item], .SelectedComponent { padding: 0.25rem; margin-right: 0.5rem; @@ -18,19 +19,25 @@ cursor: pointer; text-align: left; } -.Component[data-selected], -.Component:hover { + +.Component:hover, +.Component[data-reach-menu-item]:hover { background-color: var(--color-hover-background); } -.Component:focus { +.Component:focus, +.Component[data-reach-menu-item]:focus { outline: none; background-color: var(--color-hover-background); } -.SelectedComponent { +.Component[data-reach-menu-item][data-selected], +.Component[data-reach-menu-item][data-selected]:hover, +.SelectedComponent, +.SelectedComponent:hover { background-color: var(--color-selected-background); color: var(--color-selected-foreground); } +.Component[data-reach-menu-item][data-selected]:focus, .SelectedComponent:focus { outline: none; } diff --git a/src/devtools/views/Components/OwnersStack.js b/src/devtools/views/Components/OwnersStack.js index e459e1eee4..983d8e502a 100644 --- a/src/devtools/views/Components/OwnersStack.js +++ b/src/devtools/views/Components/OwnersStack.js @@ -100,11 +100,7 @@ function ElementsDropdown({ {ownerStack.map((id, index) => ( selectOwner(id)} > {((store.getElementByID(id): any): Element).displayName} From 163bc234df9b4d5f711ed3b8a34a2a020b153747 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 9 Apr 2019 08:36:54 -0700 Subject: [PATCH 3/5] Disable text selection for OwnersStack buttons --- src/devtools/views/Components/OwnersStack.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/devtools/views/Components/OwnersStack.css b/src/devtools/views/Components/OwnersStack.css index cf657f2757..9b85fec60a 100644 --- a/src/devtools/views/Components/OwnersStack.css +++ b/src/devtools/views/Components/OwnersStack.css @@ -18,6 +18,7 @@ background: none; cursor: pointer; text-align: left; + user-select: none; } .Component:hover, From a29ab9ab795f4962fc72f01ab85d9307f61a0808 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 9 Apr 2019 08:37:34 -0700 Subject: [PATCH 4/5] Tree arrow navigation respects event.defaultPrevented This prevents Reach MenuButton operations from also changing the tree selection in the background --- src/devtools/views/Components/Tree.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devtools/views/Components/Tree.js b/src/devtools/views/Components/Tree.js index 2c7d18f14a..42df5111c4 100644 --- a/src/devtools/views/Components/Tree.js +++ b/src/devtools/views/Components/Tree.js @@ -73,7 +73,7 @@ export default function Tree(props: Props) { } const handleKeyDown = (event: KeyboardEvent) => { - if ((event: any).target.tagName === 'INPUT') { + if ((event: any).target.tagName === 'INPUT' || event.defaultPrevented) { return; } From dbf6942512afd314981589b3b5df39766288b55f Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 9 Apr 2019 08:54:43 -0700 Subject: [PATCH 5/5] Added (local) fork of @reach/portal to unblock OwnersStack MenuButton PR --- .eslintignore | 1 + .prettierignore | 1 + package.json | 4 +- vendor/@reach/portal/.eslintignore | 1 + vendor/@reach/portal/es/index.js | 44 +++++++++++++++ .../@reach/portal/examples/basic.example.js | 35 ++++++++++++ vendor/@reach/portal/index.js | 56 +++++++++++++++++++ vendor/@reach/portal/package.json | 28 ++++++++++ vendor/@reach/portal/src/index.js | 30 ++++++++++ yarn.lock | 13 +---- 10 files changed, 201 insertions(+), 12 deletions(-) create mode 100644 vendor/@reach/portal/.eslintignore create mode 100644 vendor/@reach/portal/es/index.js create mode 100644 vendor/@reach/portal/examples/basic.example.js create mode 100644 vendor/@reach/portal/index.js create mode 100644 vendor/@reach/portal/package.json create mode 100644 vendor/@reach/portal/src/index.js diff --git a/.eslintignore b/.eslintignore index c21ee38faa..640e359715 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,6 +3,7 @@ node_modules shells/browser/chrome/build shells/browser/firefox/build shells/dev/build +vendor package-lock.json yarn.lock \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index c21ee38faa..640e359715 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,6 +3,7 @@ node_modules shells/browser/chrome/build shells/browser/firefox/build shells/dev/build +vendor package-lock.json yarn.lock \ No newline at end of file diff --git a/package.json b/package.json index 07019d599d..970f1f99d5 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,9 @@ ], "**/*.js": "eslint --max-warnings 0" }, + "resolutions": { + "@reach/portal": "file:./vendor/@reach/portal" + }, "dependencies": { "@babel/core": "^7.1.6", "@babel/plugin-proposal-class-properties": "^7.1.0", @@ -100,7 +103,6 @@ "react-color": "^2.11.7", "react-dom": "^16.8.4", "react-is": "^16.8.4", - "react-portal": "^3.1.0", "react-virtualized-auto-sizer": "^1.0.2", "react-window": "^1.5.1", "scheduler": "^0.13", diff --git a/vendor/@reach/portal/.eslintignore b/vendor/@reach/portal/.eslintignore new file mode 100644 index 0000000000..945ce43a90 --- /dev/null +++ b/vendor/@reach/portal/.eslintignore @@ -0,0 +1 @@ +index.js \ No newline at end of file diff --git a/vendor/@reach/portal/es/index.js b/vendor/@reach/portal/es/index.js new file mode 100644 index 0000000000..b08b2dce73 --- /dev/null +++ b/vendor/@reach/portal/es/index.js @@ -0,0 +1,44 @@ +import React from "react"; +import { createPortal } from "react-dom"; +import Component from "@reach/component-component"; + +var Portal = function Portal(_ref) { + var children = _ref.children, + _ref$type = _ref.type, + type = _ref$type === undefined ? "reach-portal" : _ref$type; + return React.createElement(Component, { + getRefs: function getRefs() { + return { mountNode: null, portalNode: null }; + }, + didMount: function didMount(_ref2) { + var refs = _ref2.refs, + forceUpdate = _ref2.forceUpdate; + + // It's possible that the content we are portal has, itself, been portaled. + // In that case, it's important to append to the correct document element. + var ownerDocument = refs.mountNode.ownerDocument; + refs.portalNode = ownerDocument.createElement(type); + ownerDocument.body.appendChild(refs.portalNode); + forceUpdate(); + }, + willUnmount: function willUnmount(_ref3) { + var portalNode = _ref3.refs.portalNode; + + portalNode.ownerDocument.body.removeChild(portalNode); + }, + render: function render(_ref4) { + var refs = _ref4.refs; + var portalNode = refs.portalNode; + + if (!portalNode) { + return React.createElement("div", { ref: function ref(div) { + return refs.mountNode = div; + } }); + } else { + return createPortal(children, portalNode); + } + } + }); +}; + +export default Portal; \ No newline at end of file diff --git a/vendor/@reach/portal/examples/basic.example.js b/vendor/@reach/portal/examples/basic.example.js new file mode 100644 index 0000000000..5f2e8c2e3b --- /dev/null +++ b/vendor/@reach/portal/examples/basic.example.js @@ -0,0 +1,35 @@ +import React from "react"; +import Portal from "../src/index"; + +export let name = "Basic"; + +export let Example = () => ( +
+
+ This is in the normal react root, with an overflow hidden parent, clips + the box. +
+ +
+ This is in the portal, rendered in the DOM at the document root so the + CSS doesn't screw things up, but we render it in the react hierarchy + where it makes sense. +
+
+
+); diff --git a/vendor/@reach/portal/index.js b/vendor/@reach/portal/index.js new file mode 100644 index 0000000000..738c274b0f --- /dev/null +++ b/vendor/@reach/portal/index.js @@ -0,0 +1,56 @@ +"use strict"; + +exports.__esModule = true; + +var _react = require("react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require("react-dom"); + +var _componentComponent = require("@reach/component-component"); + +var _componentComponent2 = _interopRequireDefault(_componentComponent); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var Portal = function Portal(_ref) { + var children = _ref.children, + _ref$type = _ref.type, + type = _ref$type === undefined ? "reach-portal" : _ref$type; + return _react2.default.createElement(_componentComponent2.default, { + getRefs: function getRefs() { + return { mountNode: null, portalNode: null }; + }, + didMount: function didMount(_ref2) { + var refs = _ref2.refs, + forceUpdate = _ref2.forceUpdate; + + // It's possible that the content we are portal has, itself, been portaled. + // In that case, it's important to append to the correct document element. + var ownerDocument = refs.mountNode.ownerDocument; + refs.portalNode = ownerDocument.createElement(type); + ownerDocument.body.appendChild(refs.portalNode); + forceUpdate(); + }, + willUnmount: function willUnmount(_ref3) { + var portalNode = _ref3.refs.portalNode; + + portalNode.ownerDocument.body.removeChild(portalNode); + }, + render: function render(_ref4) { + var refs = _ref4.refs; + var portalNode = refs.portalNode; + + if (!portalNode) { + return _react2.default.createElement("div", { ref: function ref(div) { + return refs.mountNode = div; + } }); + } else { + return (0, _reactDom.createPortal)(children, portalNode); + } + } + }); +}; + +exports.default = Portal; \ No newline at end of file diff --git a/vendor/@reach/portal/package.json b/vendor/@reach/portal/package.json new file mode 100644 index 0000000000..3641c4c70e --- /dev/null +++ b/vendor/@reach/portal/package.json @@ -0,0 +1,28 @@ +{ + "name": "@reach/portal", + "version": "0.1.3", + "description": "Declarative portals for React", + "main": "index.js", + "module": "es/index.js", + "scripts": { + "test": "echo \"Write some tests you bum!\"", + "build": "node ../../shared/build-package", + "lint": "eslint . --max-warnings=0" + }, + "dependencies": { + "@reach/component-component": "^0.1.3" + }, + "peerDependencies": { + "react": "^16.4.0", + "react-dom": "^16.4.0" + }, + "author": "", + "license": "MIT", + "files": [ + "es", + "src", + "lib", + "index.js", + "styles.css" + ] +} diff --git a/vendor/@reach/portal/src/index.js b/vendor/@reach/portal/src/index.js new file mode 100644 index 0000000000..6b569d5737 --- /dev/null +++ b/vendor/@reach/portal/src/index.js @@ -0,0 +1,30 @@ +import React from "react"; +import { createPortal } from "react-dom"; +import Component from "@reach/component-component"; + +let Portal = ({ children, type = "reach-portal" }) => ( + ({ mountNode: null, portalNode: null })} + didMount={({ refs, forceUpdate }) => { + // It's possible that the content we are portal has, itself, been portaled. + // In that case, it's important to append to the correct document element. + const ownerDocument = refs.mountNode.ownerDocument; + refs.portalNode = ownerDocument.createElement(type); + ownerDocument.body.appendChild(refs.portalNode); + forceUpdate(); + }} + willUnmount={({ refs: { portalNode } }) => { + portalNode.ownerDocument.body.removeChild(portalNode); + }} + render={({ refs }) => { + const { portalNode } = refs; + if (!portalNode) { + return
(refs.mountNode = div)} />; + } else { + return createPortal(children, portalNode); + } + }} + /> +); + +export default Portal; diff --git a/yarn.lock b/yarn.lock index 71cb56e316..25a54310d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -768,10 +768,8 @@ resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.0.3.tgz#2ea3dcc369ab22bd9f050a92ea319321356a61e8" integrity sha1-LqPcw2mrIr2fBQqS6jGTITVqYeg= -"@reach/portal@^0.1.3": +"@reach/portal@^0.1.3", "@reach/portal@file:./vendor/@reach/portal": version "0.1.3" - resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.1.3.tgz#31d820f31bbab73570d5b5a449e2b0fa6457802f" - integrity sha512-yDcu5XZWfWKmKvbOs/uS7vITPVFXmn+XY5V6YcGhlz20KgwG+aJX2c7yvYzO++Zr0qvmtQCmxA4EGEciqIys6g== dependencies: "@reach/component-component" "^0.1.3" @@ -8584,7 +8582,7 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2: +prop-types@^15.5.10, prop-types@^15.6.1, prop-types@^15.6.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -8796,13 +8794,6 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== -react-portal@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-portal/-/react-portal-3.2.0.tgz#4224e19b2b05d5cbe730a7ba0e34ec7585de0043" - integrity sha512-avb1FreAZAVCvNNyS2dCpxZiPYPJnAasHYPxdVBTROgNFeI+KSb+OoMHNsC1GbDawESCriPwCX+qKua6WSPIFw== - dependencies: - prop-types "^15.5.8" - react-virtualized-auto-sizer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.2.tgz#a61dd4f756458bbf63bd895a92379f9b70f803bd"