From f60ab798082be9ecd77fdd39e064de421ea60687 Mon Sep 17 00:00:00 2001 From: Leonardo Luiz Date: Mon, 18 Nov 2024 15:26:31 -0300 Subject: [PATCH 1/5] feat(Dialog): improve accessibility --- packages/yoga/package.json | 1 + .../__snapshots__/BottomSheet.test.jsx.snap | 16 +++- packages/yoga/src/Dialog/web/Dialog.jsx | 15 +++- packages/yoga/src/Dialog/web/Header.jsx | 2 +- .../web/__snapshots__/Dialog.test.jsx.snap | 34 ++++++-- packages/yoga/src/Dialog/web/utils.js | 5 ++ .../web/__snapshots__/Drawer.test.jsx.snap | 11 +++ yarn.lock | 77 ++++++++++++------- 8 files changed, 123 insertions(+), 38 deletions(-) create mode 100644 packages/yoga/src/Dialog/web/utils.js diff --git a/packages/yoga/package.json b/packages/yoga/package.json index f74d526d96..beb295efdd 100644 --- a/packages/yoga/package.json +++ b/packages/yoga/package.json @@ -51,6 +51,7 @@ "prop-types": "^15.7.2", "proxy-polyfill": "^0.3.1", "rc-slider": "^8.7.1", + "react-focus-lock": "^2.13.2", "react-google-font-loader": "^1.1.0", "react-phone-input-2": "^2.15.1" }, diff --git a/packages/yoga/src/BottomSheet/web/__snapshots__/BottomSheet.test.jsx.snap b/packages/yoga/src/BottomSheet/web/__snapshots__/BottomSheet.test.jsx.snap index cd1ade5224..288ed15c31 100644 --- a/packages/yoga/src/BottomSheet/web/__snapshots__/BottomSheet.test.jsx.snap +++ b/packages/yoga/src/BottomSheet/web/__snapshots__/BottomSheet.test.jsx.snap @@ -202,14 +202,21 @@ exports[` should match snapshot 1`] = `
+
-
Title -
+

@@ -226,6 +233,11 @@ exports[` should match snapshot 1`] = `

+
diff --git a/packages/yoga/src/Dialog/web/Dialog.jsx b/packages/yoga/src/Dialog/web/Dialog.jsx index 30e2b4275a..04c7a173da 100644 --- a/packages/yoga/src/Dialog/web/Dialog.jsx +++ b/packages/yoga/src/Dialog/web/Dialog.jsx @@ -1,11 +1,13 @@ import React, { useEffect, useCallback } from 'react'; import { createPortal } from 'react-dom'; +import FocusLock from 'react-focus-lock'; import styled, { css } from 'styled-components'; import { func, bool, node, number, string } from 'prop-types'; import { Close } from '@gympass/yoga-icons'; import { usePortal, useCombinedRefs } from '../../hooks'; import { Button, Card, Box } from '../..'; +import { focusOnFirstProgrammaticFocusableElement } from './utils'; export const StyledDialog = styled(Card)` ${({ @@ -119,7 +121,16 @@ const Dialog = React.forwardRef( ref={dialogRef} zIndex={zIndex} > - + {isCloseButtonVisible && ( )} {children} - + , dialogElement, ) diff --git a/packages/yoga/src/Dialog/web/Header.jsx b/packages/yoga/src/Dialog/web/Header.jsx index 25ca8a29a1..3645d5cc71 100644 --- a/packages/yoga/src/Dialog/web/Header.jsx +++ b/packages/yoga/src/Dialog/web/Header.jsx @@ -2,7 +2,7 @@ import React from 'react'; import Text from '../../Text'; const Header = props => ( - + ); Header.displayName = 'Dialog.Header'; diff --git a/packages/yoga/src/Dialog/web/__snapshots__/Dialog.test.jsx.snap b/packages/yoga/src/Dialog/web/__snapshots__/Dialog.test.jsx.snap index 1ad9dfcb2a..6a1d384715 100644 --- a/packages/yoga/src/Dialog/web/__snapshots__/Dialog.test.jsx.snap +++ b/packages/yoga/src/Dialog/web/__snapshots__/Dialog.test.jsx.snap @@ -155,14 +155,21 @@ exports[` should match snapshot 1`] = `
+
-
Title -
+

@@ -179,6 +186,11 @@ exports[`

should match snapshot 1`] = `
+
@@ -403,7 +415,7 @@ exports[` should match snapshot with close button 1`] = ` } .c2 { - padding: 24px 32px 32px; + padding: 40px 32px 32px; width: 580px; min-height: 160px; border-radius: 16px; @@ -464,8 +476,14 @@ exports[` should match snapshot with close button 1`] = `
+
should match snapshot with close button 1`] = ` />
-
Title -
+

@@ -504,6 +523,11 @@ exports[`

should match snapshot with close button 1`] = `
+
diff --git a/packages/yoga/src/Dialog/web/utils.js b/packages/yoga/src/Dialog/web/utils.js new file mode 100644 index 0000000000..66dffeaf32 --- /dev/null +++ b/packages/yoga/src/Dialog/web/utils.js @@ -0,0 +1,5 @@ +export function focusOnFirstProgrammaticFocusableElement(container) { + const element = container.querySelector('[tabindex="-1"]'); + + element?.focus(); +} diff --git a/packages/yoga/src/Drawer/web/__snapshots__/Drawer.test.jsx.snap b/packages/yoga/src/Drawer/web/__snapshots__/Drawer.test.jsx.snap index c8efcf4547..deac42e597 100644 --- a/packages/yoga/src/Drawer/web/__snapshots__/Drawer.test.jsx.snap +++ b/packages/yoga/src/Drawer/web/__snapshots__/Drawer.test.jsx.snap @@ -174,8 +174,14 @@ exports[` should match snapshot 1`] = `
+
should match snapshot 1`] = `
+
diff --git a/yarn.lock b/yarn.lock index 7587ce2a72..e59fe7c888 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2341,6 +2341,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.12.13": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" + integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/runtime@^7.13.10": version "7.17.9" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.9.tgz#d19fbf802d01a8cb6cf053a64e472d42c434ba72" @@ -12839,6 +12846,13 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" +focus-lock@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-1.3.5.tgz#aa644576e5ec47d227b57eb14e1efb2abf33914c" + integrity sha512-QFaHbhv9WPUeLYBDe/PAuLKJ4Dd9OPvKs9xZBr3yLXnUrDNaVXKu2baDBXe3naPY30hgHYSsf2JW4jzas2mDEQ== + dependencies: + tslib "^2.0.3" + follow-redirects@^1.0.0, follow-redirects@^1.14.0: version "1.15.1" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" @@ -21890,6 +21904,13 @@ react-burgers@^1.3.0: dependencies: styled-jsx "^2.2.6" +react-clientside-effect@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz#29f9b14e944a376b03fb650eed2a754dd128ea3a" + integrity sha512-XGGGRQAKY+q25Lz9a/4EPqom7WRjz3z9R2k4jhVKA/puQFH/5Nt27vFZYql4m4NVNdUvX8PS3O7r/Zzm7cjUlg== + dependencies: + "@babel/runtime" "^7.12.13" + react-dev-utils@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-4.2.3.tgz#5b42d9ea58d5e9e017a2f57a40a8af408a3a46fb" @@ -21992,6 +22013,18 @@ react-fast-compare@^2.0.2: resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== +react-focus-lock@^2.13.2: + version "2.13.2" + resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.13.2.tgz#e1addac2f8b9550bc0581f3c416755ba0f81f5ef" + integrity sha512-T/7bsofxYqnod2xadvuwjGKHOoL5GH7/EIPI5UyEvaU/c2CcphvGI371opFtuY/SYdbMsNiuF4HsHQ50nA/TKQ== + dependencies: + "@babel/runtime" "^7.0.0" + focus-lock "^1.3.5" + prop-types "^15.6.2" + react-clientside-effect "^1.2.6" + use-callback-ref "^1.3.2" + use-sidecar "^1.1.2" + react-google-font-loader@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/react-google-font-loader/-/react-google-font-loader-1.1.0.tgz#9c9ae97aae3d2177e922c9bf4ab6312b903abc79" @@ -22497,6 +22530,11 @@ regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.3, regenerator-runtime@^0 resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + regenerator-transform@^0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537" @@ -24066,7 +24104,7 @@ string-similarity@^1.2.2: lodash.map "^4.6.0" lodash.maxby "^4.6.0" -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -24084,15 +24122,6 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -24247,7 +24276,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -24275,13 +24304,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -25784,6 +25806,13 @@ use-callback-ref@^1.3.0: dependencies: tslib "^2.0.0" +use-callback-ref@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.2.tgz#6134c7f6ff76e2be0b56c809b17a650c942b1693" + integrity sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA== + dependencies: + tslib "^2.0.0" + use-isomorphic-layout-effect@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" @@ -26548,7 +26577,8 @@ worker-rpc@^0.1.0: dependencies: microevent.ts "~0.1.1" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: + name wrap-ansi-cjs version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -26583,15 +26613,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 999d8d07c8bfb3e144a1cc2ec2a7624db5696326 Mon Sep 17 00:00:00 2001 From: Leonardo Luiz Date: Mon, 18 Nov 2024 15:45:26 -0300 Subject: [PATCH 2/5] feat(Dialog): add closeLabel prop --- .../components/components/dialog/index.mdx | 152 +++++++++--------- packages/yoga/src/Dialog/web/Dialog.jsx | 14 +- packages/yoga/src/Dialog/web/Dialog.test.jsx | 4 +- 3 files changed, 91 insertions(+), 79 deletions(-) diff --git a/packages/doc/content/components/components/dialog/index.mdx b/packages/doc/content/components/components/dialog/index.mdx index a586dc0fff..c059a1cdfc 100644 --- a/packages/doc/content/components/components/dialog/index.mdx +++ b/packages/doc/content/components/components/dialog/index.mdx @@ -15,6 +15,7 @@ Gympass `` is a component which has the purpose of providing prioritar - `` ### Recommendations of use Buttons + The right positioning of the buttons starting with the primary followed by the secondary ### Usage @@ -37,18 +38,15 @@ render(() => { <> - - - We couldn't confirm your eligibility - - - Double check your info and company selection. If it still doesn’t work, contact your HR team. - - - - + + We couldn't confirm your eligibility + + Double check your info and company selection. If it still doesn’t + work, contact your HR team. + + + + ); @@ -71,21 +69,22 @@ render(() => { return ( <> - - - - - Are you sure you want to downgrade to a Platinum plan? - - - Double check your info and company selection. If it still doesn’t work, contact your HR team. - - - - Cancel - + + + + + Are you sure you want to downgrade to a Platinum plan? + + + Double check your info and company selection. If it still doesn’t + work, contact your HR team. + + + + Cancel + ); @@ -110,20 +109,18 @@ render(() => { <> - - - Are you sure you want to downgrade to a Platinum plan? - - - The change will happen at the end of your billing cycle on March, 28. Until then, enjoy your Black plan - you’ve already paid for it. - - + + + Are you sure you want to downgrade to a Platinum plan? + + + The change will happen at the end of your billing cycle on March, 28. + Until then, enjoy your Black plan - you’ve already paid for it. + + Cancel - + ); @@ -146,18 +143,18 @@ render(() => { return ( <> - - - - - Are you sure you want to downgrade to a Platinum plan? - - + + + + + Are you sure you want to downgrade to a Platinum plan? + + Cancel - + ); @@ -183,26 +180,25 @@ render(() => { }; useEffect(() => { - if(isOpen && dialogRef.current && buttonRef.current) { + if (isOpen && dialogRef.current && buttonRef.current) { buttonRef.current.focus(); } - },[dialogRef, buttonRef, isOpen]); + }, [dialogRef, buttonRef, isOpen]); return ( <> - - - - - I am an example on how a custom ref option can be used - - + + + + + I am an example on how a custom ref option can be used + + Close - + ); @@ -228,27 +224,31 @@ render(() => { return ( <> - + - - With a custom id I can open an isolated dialog - - - - + + With a custom id I can open an isolated dialog + + + + Close - + - - I am a nested dialog - + I am a nested dialog - - setIsNestedOpen(false)}>Close - + + setIsNestedOpen(false)}> + Close + + ); diff --git a/packages/yoga/src/Dialog/web/Dialog.jsx b/packages/yoga/src/Dialog/web/Dialog.jsx index 04c7a173da..f735c3753d 100644 --- a/packages/yoga/src/Dialog/web/Dialog.jsx +++ b/packages/yoga/src/Dialog/web/Dialog.jsx @@ -80,7 +80,16 @@ const CloseButton = styled(Button.Icon)` const Dialog = React.forwardRef( ( - { isOpen, hideCloseButton, children, dialogId, onClose, zIndex, ...props }, + { + isOpen, + hideCloseButton, + children, + dialogId, + onClose, + zIndex, + closeLabel, + ...props + }, forwardedRef, ) => { const dialogRef = useCombinedRefs(forwardedRef); @@ -134,6 +143,7 @@ const Dialog = React.forwardRef( {isCloseButtonVisible && ( ', () => { render( - + Title , ); - const button = screen.getByRole('button'); + const button = screen.getByRole('button', { name: 'Close' }); fireEvent.click(button); From fc2b20106be78f797deea76924fe2dc8bf34277f Mon Sep 17 00:00:00 2001 From: Leonardo Luiz Date: Mon, 18 Nov 2024 16:04:09 -0300 Subject: [PATCH 3/5] fix(Dialog): add lock props to FocusLock --- packages/yoga/src/Dialog/web/Dialog.jsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/yoga/src/Dialog/web/Dialog.jsx b/packages/yoga/src/Dialog/web/Dialog.jsx index f735c3753d..81f682f479 100644 --- a/packages/yoga/src/Dialog/web/Dialog.jsx +++ b/packages/yoga/src/Dialog/web/Dialog.jsx @@ -95,6 +95,11 @@ const Dialog = React.forwardRef( const dialogRef = useCombinedRefs(forwardedRef); const dialogElement = usePortal(dialogId ?? 'dialog'); const isCloseButtonVisible = onClose && !hideCloseButton; + const lockProps = { + role: 'dialog', + 'aria-modal': true, + onClose, + }; const closeDialog = useCallback( e => { @@ -132,11 +137,9 @@ const Dialog = React.forwardRef( > From 13e60817eaa108a04f539841905992c373e7a254 Mon Sep 17 00:00:00 2001 From: Leonardo Luiz Date: Mon, 18 Nov 2024 16:06:11 -0300 Subject: [PATCH 4/5] test: update snapshots --- .../BottomSheet/web/__snapshots__/BottomSheet.test.jsx.snap | 2 ++ .../yoga/src/Dialog/web/__snapshots__/Dialog.test.jsx.snap | 6 +++++- .../yoga/src/Drawer/web/__snapshots__/Drawer.test.jsx.snap | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/yoga/src/BottomSheet/web/__snapshots__/BottomSheet.test.jsx.snap b/packages/yoga/src/BottomSheet/web/__snapshots__/BottomSheet.test.jsx.snap index 288ed15c31..238bd92b26 100644 --- a/packages/yoga/src/BottomSheet/web/__snapshots__/BottomSheet.test.jsx.snap +++ b/packages/yoga/src/BottomSheet/web/__snapshots__/BottomSheet.test.jsx.snap @@ -208,8 +208,10 @@ exports[` should match snapshot 1`] = ` tabindex="0" />