From 78895275f26852049028c9d40f883b984bf11c0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 09:52:44 -0500 Subject: [PATCH 01/10] chore(deps-dev): bump cross-env from 7.0.2 to 7.0.3 (#4561) Bumps [cross-env](https://github.com/kentcdodds/cross-env) from 7.0.2 to 7.0.3. - [Release notes](https://github.com/kentcdodds/cross-env/releases) - [Changelog](https://github.com/kentcdodds/cross-env/blob/master/CHANGELOG.md) - [Commits](https://github.com/kentcdodds/cross-env/compare/v7.0.2...v7.0.3) --- updated-dependencies: - dependency-name: cross-env dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package.json | 2 +- package-lock.json | 70 +---------------------------------------------- 2 files changed, 2 insertions(+), 70 deletions(-) diff --git a/docs/package.json b/docs/package.json index 1e1fbbad655..5305b4fc1c3 100644 --- a/docs/package.json +++ b/docs/package.json @@ -34,7 +34,7 @@ "styled-system": "^5.1.0" }, "devDependencies": { - "cross-env": "7.0.2", + "cross-env": "7.0.3", "eslint": "8.56.0", "eslint-config-react-app": "7.0.1", "globby": "^11.0.4", diff --git a/package-lock.json b/package-lock.json index 1bff63ded85..6b496f7880c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -80,7 +80,7 @@ "styled-system": "^5.1.0" }, "devDependencies": { - "cross-env": "7.0.2", + "cross-env": "7.0.3", "eslint": "8.56.0", "eslint-config-react-app": "7.0.1", "globby": "^11.0.4", @@ -261,38 +261,6 @@ "@xtuc/long": "4.2.2" } }, - "docs/node_modules/cross-env": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.2.tgz", - "integrity": "sha512-KZP/bMEOJEDCkDQAyRhu3RL2ZO/SUVrxQVI0G3YEQ+OLbRA3c6zgixe8Mq8a/z7+HKlNEjo8oiLUs8iRijY2Rw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } - }, - "docs/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, "docs/node_modules/es-module-lexer": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.6.0.tgz", @@ -309,27 +277,6 @@ "yallist": "^3.0.0" } }, - "docs/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "docs/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "docs/node_modules/webpack": { "version": "5.40.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.40.0.tgz", @@ -376,21 +323,6 @@ } } }, - "docs/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "docs/node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", From 3cae7c85629be91380dc7f3e36919cb3413486af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 09:53:05 -0500 Subject: [PATCH 02/10] chore(deps-dev): bump @babel/plugin-transform-modules-commonjs (#4562) Bumps [@babel/plugin-transform-modules-commonjs](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-modules-commonjs) from 7.23.3 to 7.24.1. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.24.1/packages/babel-plugin-transform-modules-commonjs) --- updated-dependencies: - dependency-name: "@babel/plugin-transform-modules-commonjs" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 43 +++++-------------------------------- packages/react/package.json | 2 +- 2 files changed, 6 insertions(+), 39 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6b496f7880c..ef68b069116 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1835,13 +1835,12 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", - "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", + "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", "dependencies": { "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-simple-access": "^7.22.5" }, "engines": { @@ -2452,22 +2451,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", - "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", - "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-simple-access": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -2543,22 +2526,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-typescript/node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", - "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", - "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-simple-access": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/register": { "version": "7.23.7", "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.23.7.tgz", @@ -62108,7 +62075,7 @@ "@babel/parser": "7.23.6", "@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6", "@babel/plugin-proposal-optional-chaining": "7.21.0", - "@babel/plugin-transform-modules-commonjs": "7.23.3", + "@babel/plugin-transform-modules-commonjs": "7.24.1", "@babel/preset-react": "7.23.3", "@babel/preset-typescript": "7.24.1", "@primer/css": "^21.0.1", diff --git a/packages/react/package.json b/packages/react/package.json index a979bdb0e88..3e7bc317c6b 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -123,7 +123,7 @@ "@babel/parser": "7.23.6", "@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6", "@babel/plugin-proposal-optional-chaining": "7.21.0", - "@babel/plugin-transform-modules-commonjs": "7.23.3", + "@babel/plugin-transform-modules-commonjs": "7.24.1", "@babel/preset-react": "7.23.3", "@babel/preset-typescript": "7.24.1", "@primer/css": "^21.0.1", From e094a39677c72e4c06819293ba77172be83deffb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 09:53:26 -0500 Subject: [PATCH 03/10] chore(deps-dev): bump jest-fail-on-console from 3.1.1 to 3.2.0 (#4563) Bumps [jest-fail-on-console](https://github.com/ValentinH/jest-fail-on-console) from 3.1.1 to 3.2.0. - [Release notes](https://github.com/ValentinH/jest-fail-on-console/releases) - [Commits](https://github.com/ValentinH/jest-fail-on-console/compare/v3.1.1...v3.2.0) --- updated-dependencies: - dependency-name: jest-fail-on-console dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 81 ++----------------------------------- packages/react/package.json | 2 +- 2 files changed, 5 insertions(+), 78 deletions(-) diff --git a/package-lock.json b/package-lock.json index ef68b069116..60d2a66f405 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40273,84 +40273,11 @@ } }, "node_modules/jest-fail-on-console": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/jest-fail-on-console/-/jest-fail-on-console-3.1.1.tgz", - "integrity": "sha512-g9HGhKcWOz8lHeZhLCXGg+RD/7upngiKkkBrHimsO/tGB0qi++QZffOgybjeI2bDW1qgdFiJJEG6t/WeTlfmOw==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0" - } - }, - "node_modules/jest-fail-on-console/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-fail-on-console/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-fail-on-console/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-fail-on-console/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jest-fail-on-console/-/jest-fail-on-console-3.2.0.tgz", + "integrity": "sha512-GSqvjURdT/U+yu9JEr3EUTEB4kZi9feXMWS/jXGXB/lsnXXHcdU9Xsm2tEupSdqSEtrhTjOCqEJseFMrQ1ryvg==", "dev": true }, - "node_modules/jest-fail-on-console/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-fail-on-console/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-get-type": { "version": "29.6.3", "license": "MIT", @@ -62138,7 +62065,7 @@ "jest-axe": "7.0.1", "jest-css-modules": "2.1.0", "jest-environment-jsdom": "29.7.0", - "jest-fail-on-console": "3.1.1", + "jest-fail-on-console": "3.2.0", "jest-matchmedia-mock": "1.1.0", "jest-styled-components": "7.2.0", "jscodeshift": "0.15.0", diff --git a/packages/react/package.json b/packages/react/package.json index 3e7bc317c6b..d5e20f33828 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -186,7 +186,7 @@ "jest-axe": "7.0.1", "jest-css-modules": "2.1.0", "jest-environment-jsdom": "29.7.0", - "jest-fail-on-console": "3.1.1", + "jest-fail-on-console": "3.2.0", "jest-matchmedia-mock": "1.1.0", "jest-styled-components": "7.2.0", "jscodeshift": "0.15.0", From ed31476f040dda41f00c2c7f4324120afb20cc18 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Mon, 6 May 2024 10:59:56 -0500 Subject: [PATCH 04/10] feat(FeatureFlags): broaden feature flag type to accept undefined (#4554) * feat(FeatureFlags): loosen feature flag type to accept undefined * chore: add changeset * Update .changeset/grumpy-coats-worry.md --------- Co-authored-by: Josh Black --- .changeset/grumpy-coats-worry.md | 5 +++++ packages/react/src/FeatureFlags/FeatureFlagScope.ts | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 .changeset/grumpy-coats-worry.md diff --git a/.changeset/grumpy-coats-worry.md b/.changeset/grumpy-coats-worry.md new file mode 100644 index 00000000000..584f41f81a0 --- /dev/null +++ b/.changeset/grumpy-coats-worry.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +Broaden feature flag type for experimental FeatureFlags to accept undefined diff --git a/packages/react/src/FeatureFlags/FeatureFlagScope.ts b/packages/react/src/FeatureFlags/FeatureFlagScope.ts index 4aee95cf715..379c29a9e76 100644 --- a/packages/react/src/FeatureFlags/FeatureFlagScope.ts +++ b/packages/react/src/FeatureFlags/FeatureFlagScope.ts @@ -1,5 +1,5 @@ export type FeatureFlags = { - [key: string]: boolean + [key: string]: boolean | undefined } export class FeatureFlagScope { @@ -24,7 +24,10 @@ export class FeatureFlagScope { flags: Map constructor(flags: FeatureFlags = {}) { - this.flags = new Map(Object.entries(flags)) + this.flags = new Map() + for (const [key, value] of Object.entries(flags)) { + this.flags.set(key, value ?? false) + } } /** From 09ac01ece43e162d35dc7359085e53a3050ed171 Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Tue, 7 May 2024 02:23:45 +0200 Subject: [PATCH 05/10] prevent form submit (#4551) --- packages/react/src/Autocomplete/Autocomplete.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/Autocomplete/Autocomplete.stories.tsx b/packages/react/src/Autocomplete/Autocomplete.stories.tsx index 52553e6bae9..0ff949cb574 100644 --- a/packages/react/src/Autocomplete/Autocomplete.stories.tsx +++ b/packages/react/src/Autocomplete/Autocomplete.stories.tsx @@ -229,7 +229,7 @@ export const Default = (args: FormControlArgs) => { } return ( - + event.preventDefault()}> From 495935bd1648d9d26fa87352e6eb11829a415a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arma=C4=9Fan?= Date: Tue, 7 May 2024 10:30:16 +1000 Subject: [PATCH 06/10] deprecate title prop on ActionList.Group component on docs (#4544) --- packages/react/src/ActionList/ActionList.docs.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/react/src/ActionList/ActionList.docs.json b/packages/react/src/ActionList/ActionList.docs.json index 90770f12475..20ffc93e1c6 100644 --- a/packages/react/src/ActionList/ActionList.docs.json +++ b/packages/react/src/ActionList/ActionList.docs.json @@ -256,7 +256,8 @@ "name": "title", "type": "string", "defaultValue": "", - "description": "Title of the group." + "description": "Please use `ActionList.GroupHeading` instead.", + "deprecated": true }, { "name": "auxiliaryText", From 7e587b62a4c9e2eead8b6484e5de95f54727e9dd Mon Sep 17 00:00:00 2001 From: Josh Black Date: Tue, 7 May 2024 10:50:40 -0500 Subject: [PATCH 07/10] chore: add hydro analytics to storybook (#4558) * chore: add hydro analytics to storybook * chore: use previewHead over managerHead * Update build-docs --------- Co-authored-by: Josh Black --- packages/react/.storybook/main.js | 16 ++++++++++++++++ script/build-docs | 2 ++ 2 files changed, 18 insertions(+) diff --git a/packages/react/.storybook/main.js b/packages/react/.storybook/main.js index a3cd97ce78b..54d0375cb1a 100644 --- a/packages/react/.storybook/main.js +++ b/packages/react/.storybook/main.js @@ -1,3 +1,7 @@ +'use strict' + +const {DEPLOY_ENV = 'development'} = process.env + /** * @type {import('@storybook/core-common').StorybookConfig} */ @@ -53,4 +57,16 @@ module.exports = { typescript: { reactDocgen: 'react-docgen', }, + previewHead: head => { + if (DEPLOY_ENV === 'development') { + return head + } + return `${head}\n` + }, + previewBody: body => { + if (DEPLOY_ENV === 'development') { + return body + } + return `${body}\n` + }, } diff --git a/script/build-docs b/script/build-docs index 24ab7d3c95b..0d71259534d 100755 --- a/script/build-docs +++ b/script/build-docs @@ -2,9 +2,11 @@ set -e if [ -n "$1" ]; then + export DEPLOY_ENV="preview" npm run build:preview -w docs npm run build:storybook preview else + export DEPLOY_ENV="production" npm run build -w docs npm run build:storybook fi From 447a1fd1d37e4f61f38345babab954540b58e53b Mon Sep 17 00:00:00 2001 From: Ian Sanders Date: Tue, 7 May 2024 12:05:14 -0400 Subject: [PATCH 08/10] Revert "Revert "Add support for nested submenus to `ActionMenu`"" (#4486) * Revert "Revert "Add support for nested submenus to `ActionMenu` (#4386)" (#4472)" This reverts commit 82072eb7169578bb686c07c64b3dd52eac764e38. * just want a change to trigger rebuild --------- Co-authored-by: Siddharth Kshetrapal Co-authored-by: Pavithra Kodmad --- .changeset/wild-students-bow.md | 5 + .../ActionList/ActionListContainerContext.tsx | 1 + packages/react/src/ActionList/Item.tsx | 14 +- .../ActionMenu.features.stories.tsx | 53 +++++- packages/react/src/ActionMenu/ActionMenu.tsx | 96 ++++++++-- .../react/src/__tests__/ActionMenu.test.tsx | 170 +++++++++++++++++- .../src/hooks/useMenuKeyboardNavigation.ts | 31 +++- 7 files changed, 348 insertions(+), 22 deletions(-) create mode 100644 .changeset/wild-students-bow.md diff --git a/.changeset/wild-students-bow.md b/.changeset/wild-students-bow.md new file mode 100644 index 00000000000..111e2d290e9 --- /dev/null +++ b/.changeset/wild-students-bow.md @@ -0,0 +1,5 @@ +--- +"@primer/react": minor +--- + +Adds support for nested submenus to `ActionMenu` diff --git a/packages/react/src/ActionList/ActionListContainerContext.tsx b/packages/react/src/ActionList/ActionListContainerContext.tsx index 1127042aa56..57370225370 100644 --- a/packages/react/src/ActionList/ActionListContainerContext.tsx +++ b/packages/react/src/ActionList/ActionListContainerContext.tsx @@ -14,6 +14,7 @@ type ContextProps = { // eslint-disable-next-line @typescript-eslint/ban-types afterSelect?: Function enableFocusZone?: boolean + defaultTrailingVisual?: React.ReactElement } export const ActionListContainerContext = React.createContext({}) diff --git a/packages/react/src/ActionList/Item.tsx b/packages/react/src/ActionList/Item.tsx index f75a6e5d826..517f188b0ba 100644 --- a/packages/react/src/ActionList/Item.tsx +++ b/packages/react/src/ActionList/Item.tsx @@ -74,6 +74,15 @@ export const Item = React.forwardRef( inlineDescription: [Description, props => props.variant !== 'block'], }) + const {container, afterSelect, selectionAttribute, defaultTrailingVisual} = + React.useContext(ActionListContainerContext) + + // Be sure to avoid rendering the container unless there is a default + const wrappedDefaultTrailingVisual = defaultTrailingVisual ? ( + {defaultTrailingVisual} + ) : null + const trailingVisual = slots.trailingVisual ?? wrappedDefaultTrailingVisual + const { variant: listVariant, role: listRole, @@ -81,7 +90,6 @@ export const Item = React.forwardRef( selectionVariant: listSelectionVariant, } = React.useContext(ListContext) const {selectionVariant: groupSelectionVariant} = React.useContext(GroupContext) - const {container, afterSelect, selectionAttribute} = React.useContext(ActionListContainerContext) const inactive = Boolean(inactiveText) const showInactiveIndicator = inactive && container === undefined @@ -308,7 +316,7 @@ export const Item = React.forwardRef( sx={{display: 'flex', flexDirection: 'column', flexGrow: 1, minWidth: 0}} > ( ) : ( // If it's not inactive, or it has a leading visual that can be replaced, // just render the trailing visual slot. - slots.trailingVisual + trailingVisual ) } diff --git a/packages/react/src/ActionMenu/ActionMenu.features.stories.tsx b/packages/react/src/ActionMenu/ActionMenu.features.stories.tsx index f417e8cb1f4..670e3b49cc8 100644 --- a/packages/react/src/ActionMenu/ActionMenu.features.stories.tsx +++ b/packages/react/src/ActionMenu/ActionMenu.features.stories.tsx @@ -1,6 +1,15 @@ import React from 'react' import {ActionMenu, ActionList, Box} from '../' -import {WorkflowIcon, ArchiveIcon, GearIcon, CopyIcon, RocketIcon, CommentIcon, BookIcon} from '@primer/octicons-react' +import { + WorkflowIcon, + ArchiveIcon, + GearIcon, + CopyIcon, + RocketIcon, + CommentIcon, + BookIcon, + SparkleFillIcon, +} from '@primer/octicons-react' export default { title: 'Components/ActionMenu/Features', @@ -181,3 +190,45 @@ export const InactiveItems = () => ( ) + +export const Submenus = () => ( + + Edit + + + Cut + Copy + Paste + + + + + + + Paste special + + + + + Paste plain text + Paste formulas + Paste with formatting + + + Paste from + + + + Current clipboard + History + Another device + + + + + + + + + +) diff --git a/packages/react/src/ActionMenu/ActionMenu.tsx b/packages/react/src/ActionMenu/ActionMenu.tsx index d33212d8a87..619272c40b1 100644 --- a/packages/react/src/ActionMenu/ActionMenu.tsx +++ b/packages/react/src/ActionMenu/ActionMenu.tsx @@ -1,5 +1,5 @@ -import React, {useEffect, useState} from 'react' -import {TriangleDownIcon} from '@primer/octicons-react' +import React, {useCallback, useContext, useMemo, useEffect, useState} from 'react' +import {TriangleDownIcon, ChevronRightIcon} from '@primer/octicons-react' import type {AnchoredOverlayProps} from '../AnchoredOverlay' import {AnchoredOverlay} from '../AnchoredOverlay' import type {OverlayProps} from '../Overlay' @@ -13,11 +13,16 @@ import type {MandateProps} from '../utils/types' import type {ForwardRefComponent as PolymorphicForwardRefComponent} from '../utils/polymorphic' import {Tooltip} from '../TooltipV2/Tooltip' +export type MenuCloseHandler = ( + gesture: 'anchor-click' | 'click-outside' | 'escape' | 'tab' | 'item-select' | 'arrow-left', +) => void + export type MenuContextProps = Pick< AnchoredOverlayProps, 'anchorRef' | 'renderAnchor' | 'open' | 'onOpen' | 'anchorId' > & { - onClose?: (gesture: 'anchor-click' | 'click-outside' | 'escape' | 'tab') => void + onClose?: MenuCloseHandler + isSubmenu?: boolean } const MenuContext = React.createContext({renderAnchor: null, open: false}) @@ -44,9 +49,23 @@ const Menu: React.FC> = ({ onOpenChange, children, }: ActionMenuProps) => { + const parentMenuContext = useContext(MenuContext) + const [combinedOpenState, setCombinedOpenState] = useProvidedStateOrCreate(open, onOpenChange, false) const onOpen = React.useCallback(() => setCombinedOpenState(true), [setCombinedOpenState]) - const onClose = React.useCallback(() => setCombinedOpenState(false), [setCombinedOpenState]) + const onClose: MenuCloseHandler = React.useCallback( + gesture => { + setCombinedOpenState(false) + + // Close the parent stack when an item is selected or the user tabs out of the menu entirely + switch (gesture) { + case 'tab': + case 'item-select': + parentMenuContext.onClose?.(gesture) + } + }, + [setCombinedOpenState, parentMenuContext], + ) const menuButtonChild = React.Children.toArray(children).find( child => React.isValidElement(child) && (child.type === MenuButton || child.type === Anchor), @@ -100,7 +119,18 @@ const Menu: React.FC> = ({ }) return ( - + {contents} ) @@ -108,7 +138,40 @@ const Menu: React.FC> = ({ export type ActionMenuAnchorProps = {children: React.ReactElement; id?: string} const Anchor = React.forwardRef(({children, ...anchorProps}, anchorRef) => { - return React.cloneElement(children, {...anchorProps, ref: anchorRef}) + const {onOpen, isSubmenu} = React.useContext(MenuContext) + + const openSubmenuOnRightArrow: React.KeyboardEventHandler = useCallback( + event => { + children.props.onKeyDown?.(event) + if (isSubmenu && event.key === 'ArrowRight' && !event.defaultPrevented) onOpen?.('anchor-key-press') + }, + [children, isSubmenu, onOpen], + ) + + // Add right chevron icon to submenu anchors rendered using `ActionList.Item` + const parentActionListContext = useContext(ActionListContainerContext) + const thisActionListContext = useMemo( + () => + isSubmenu + ? { + ...parentActionListContext, + defaultTrailingVisual: , + // Default behavior is to close after selecting; we want to open the submenu instead + afterSelect: () => onOpen?.('anchor-click'), + } + : parentActionListContext, + [isSubmenu, onOpen, parentActionListContext], + ) + + return ( + + {React.cloneElement(children, { + ...anchorProps, + ref: anchorRef, + onKeyDown: openSubmenuOnRightArrow, + })} + + ) }) /** this component is syntactical sugar 🍭 */ @@ -133,19 +196,24 @@ type MenuOverlayProps = Partial & const Overlay: React.FC> = ({ children, align = 'start', - side = 'outside-bottom', + side, 'aria-labelledby': ariaLabelledby, ...overlayProps }) => { // we typecast anchorRef as required instead of optional // because we know that we're setting it in context in Menu - const {anchorRef, renderAnchor, anchorId, open, onOpen, onClose} = React.useContext(MenuContext) as MandateProps< - MenuContextProps, - 'anchorRef' - > + const { + anchorRef, + renderAnchor, + anchorId, + open, + onOpen, + onClose, + isSubmenu = false, + } = React.useContext(MenuContext) as MandateProps const containerRef = React.useRef(null) - useMenuKeyboardNavigation(open, onClose, containerRef, anchorRef) + useMenuKeyboardNavigation(open, onClose, containerRef, anchorRef, isSubmenu) // If the menu anchor is an icon button, we need to label the menu by tooltip that also labelled the anchor. const [anchorAriaLabelledby, setAnchorAriaLabelledby] = useState(null) @@ -167,7 +235,7 @@ const Overlay: React.FC> = ({ onOpen={onOpen} onClose={onClose} align={align} - side={side} + side={side ?? (isSubmenu ? 'outside-right' : 'outside-bottom')} overlayProps={overlayProps} focusZoneSettings={{focusOutBehavior: 'wrap'}} > @@ -179,7 +247,7 @@ const Overlay: React.FC> = ({ // If there is a custom aria-labelledby, use that. Otherwise, if exists, use the id that labels the anchor such as tooltip. If none of them exist, use anchor id. listLabelledBy: ariaLabelledby || anchorAriaLabelledby || anchorId, selectionAttribute: 'aria-checked', // Should this be here? - afterSelect: onClose, + afterSelect: () => onClose?.('item-select'), }} > {children} diff --git a/packages/react/src/__tests__/ActionMenu.test.tsx b/packages/react/src/__tests__/ActionMenu.test.tsx index 8ec6fd70624..0c6c9ace83a 100644 --- a/packages/react/src/__tests__/ActionMenu.test.tsx +++ b/packages/react/src/__tests__/ActionMenu.test.tsx @@ -1,4 +1,4 @@ -import {render as HTMLRender, waitFor, act} from '@testing-library/react' +import {render as HTMLRender, waitFor, act, within} from '@testing-library/react' import userEvent from '@testing-library/user-event' import {axe} from 'jest-axe' import React from 'react' @@ -78,6 +78,60 @@ function ExampleWithTooltipV2(actionMenuTrigger: React.ReactElement): JSX.Elemen ) } +function ExampleWithSubmenus(): JSX.Element { + return ( + + + + + Toggle Menu + + + New file + + Copy link + Edit file + + Paste + + + Paste special + + + + Paste plain text + Paste formulas + Paste with formatting + + + Paste from + + + + { + /*noop*/ + }} + > + Current clipboard + + History + Another device + + + + + + + + + + + + + ) +} + describe('ActionMenu', () => { behavesAsComponent({ Component: ActionList, @@ -435,6 +489,7 @@ describe('ActionMenu', () => { expect(button.id).toBe(buttonId) }) + it('should use the tooltip id to name the menu when the anchor is icon button', async () => { const component = HTMLRender( @@ -464,4 +519,117 @@ describe('ActionMenu', () => { expect(toggleButton).toHaveAttribute('aria-labelledby') expect(component.getByRole('menu')).toHaveAttribute('aria-labelledby', toggleButton.getAttribute('aria-labelledby')) }) + + describe('submenus', () => { + it('sets `aria-haspopup` and `aria-expanded` on submenu anchors', async () => { + const component = HTMLRender() + const user = userEvent.setup() + + const baseAnchor = component.getByRole('button', {name: 'Toggle Menu'}) + await user.click(baseAnchor) + + const submenuAnchor = component.getByRole('menuitem', {name: 'Paste special'}) + expect(submenuAnchor).toHaveAttribute('aria-haspopup') + await user.click(submenuAnchor) + expect(submenuAnchor).toHaveAttribute('aria-expanded') + + const subSubmenuAnchor = component.getByRole('menuitem', {name: 'Paste from'}) + expect(subSubmenuAnchor).toHaveAttribute('aria-haspopup') + await user.click(subSubmenuAnchor) + expect(subSubmenuAnchor).toHaveAttribute('aria-expanded') + }) + + it('sets labels on submenus', async () => { + const component = HTMLRender() + const user = userEvent.setup() + + const baseAnchor = component.getByRole('button', {name: 'Toggle Menu'}) + await user.click(baseAnchor) + + const submenuAnchor = component.getByRole('menuitem', {name: 'Paste special'}) + await user.click(submenuAnchor) + const submenu = component.getByRole('menu', {name: 'Paste special'}) + expect(submenu).toBeVisible() + + const subSubmenuAnchor = within(submenu).getByRole('menuitem', {name: 'Paste from'}) + await user.click(subSubmenuAnchor) + const subSubmenu = component.getByRole('menu', {name: 'Paste from'}) + expect(subSubmenu).toBeVisible() + }) + + it('does not open top-level menu on right arrow key press', async () => { + const component = HTMLRender() + const user = userEvent.setup() + + const baseAnchor = component.getByRole('button', {name: 'Toggle Menu'}) + baseAnchor.focus() + + await user.keyboard('{ArrowRight}') + expect(component.queryByRole('menu')).not.toBeInTheDocument() + expect(baseAnchor).not.toHaveAttribute('aria-expanded', 'true') + }) + + it('opens submenus on enter or right arrow key press', async () => { + const component = HTMLRender() + const user = userEvent.setup() + + const baseAnchor = component.getByRole('button', {name: 'Toggle Menu'}) + await user.click(baseAnchor) + + const submenuAnchor = component.getByRole('menuitem', {name: 'Paste special'}) + expect(submenuAnchor).toHaveAttribute('aria-haspopup', 'true') + submenuAnchor.focus() + await user.keyboard('{Enter}') + expect(submenuAnchor).toHaveAttribute('aria-expanded', 'true') + + const subSubmenuAnchor = component.getByRole('menuitem', {name: 'Paste from'}) + subSubmenuAnchor.focus() + await user.keyboard('{ArrowRight}') + expect(subSubmenuAnchor).toHaveAttribute('aria-expanded', 'true') + }) + + it('closes top menu on escape or left arrow key press', async () => { + const component = HTMLRender() + const user = userEvent.setup() + + const baseAnchor = component.getByRole('button', {name: 'Toggle Menu'}) + await user.click(baseAnchor) + + const submenuAnchor = component.getByRole('menuitem', {name: 'Paste special'}) + await user.click(submenuAnchor) + + const subSubmenuAnchor = component.getByRole('menuitem', {name: 'Paste from'}) + await user.click(subSubmenuAnchor) + + expect(subSubmenuAnchor).toHaveAttribute('aria-expanded', 'true') + + await user.keyboard('{Escape}') + expect(subSubmenuAnchor).not.toHaveAttribute('aria-expanded', 'true') + expect(submenuAnchor).toHaveAttribute('aria-expanded', 'true') + + await user.keyboard('{ArrowLeft}') + expect(submenuAnchor).not.toHaveAttribute('aria-expanded', 'true') + + expect(baseAnchor).toHaveAttribute('aria-expanded', 'true') + }) + + it('closes all menus when an item is selected', async () => { + const component = HTMLRender() + const user = userEvent.setup() + + const baseAnchor = component.getByRole('button', {name: 'Toggle Menu'}) + await user.click(baseAnchor) + + const submenuAnchor = component.getByRole('menuitem', {name: 'Paste special'}) + await user.click(submenuAnchor) + + const subSubmenuAnchor = component.getByRole('menuitem', {name: 'Paste from'}) + await user.click(subSubmenuAnchor) + + const subSubmenuItem = component.getByRole('menuitem', {name: 'Current clipboard'}) + await user.click(subSubmenuItem) + + expect(baseAnchor).not.toHaveAttribute('aria-expanded', 'true') + }) + }) }) diff --git a/packages/react/src/hooks/useMenuKeyboardNavigation.ts b/packages/react/src/hooks/useMenuKeyboardNavigation.ts index 8adbb52778a..4000fd578fe 100644 --- a/packages/react/src/hooks/useMenuKeyboardNavigation.ts +++ b/packages/react/src/hooks/useMenuKeyboardNavigation.ts @@ -2,7 +2,7 @@ import React from 'react' import {iterateFocusableElements} from '@primer/behaviors/utils' import {useMenuInitialFocus} from './useMenuInitialFocus' import {useMnemonics} from './useMnemonics' -import type {MenuContextProps} from '../ActionMenu' +import type {MenuCloseHandler} from '../ActionMenu' /** * Keyboard navigation is a mix of 4 hooks @@ -13,14 +13,16 @@ import type {MenuContextProps} from '../ActionMenu' */ export const useMenuKeyboardNavigation = ( open: boolean, - onClose: MenuContextProps['onClose'], + onClose: MenuCloseHandler | undefined, containerRef: React.RefObject, anchorRef: React.RefObject, + isSubmenu: boolean, ) => { useMenuInitialFocus(open, containerRef, anchorRef) useMnemonics(open, containerRef) useCloseMenuOnTab(open, onClose, containerRef, anchorRef) useMoveFocusToMenuItem(open, containerRef, anchorRef) + useCloseSubmenuOnArrow(open, isSubmenu, onClose, containerRef) } /** @@ -29,7 +31,7 @@ export const useMenuKeyboardNavigation = ( */ const useCloseMenuOnTab = ( open: boolean, - onClose: MenuContextProps['onClose'], + onClose: MenuCloseHandler | undefined, containerRef: React.RefObject, anchorRef: React.RefObject, ) => { @@ -50,6 +52,29 @@ const useCloseMenuOnTab = ( }, [open, onClose, containerRef, anchorRef]) } +/** + * Close submenu when left arrow key is pressed + */ +const useCloseSubmenuOnArrow = ( + open: boolean, + isSubmenu: boolean, + onClose: MenuCloseHandler | undefined, + containerRef: React.RefObject, +) => { + React.useEffect(() => { + const container = containerRef.current + + const handler = (event: KeyboardEvent) => { + if (open && isSubmenu && event.key === 'ArrowLeft') onClose?.('arrow-left') + } + + container?.addEventListener('keydown', handler) + return () => { + container?.removeEventListener('keydown', handler) + } + }, [open, onClose, containerRef, isSubmenu]) +} + /** * When Arrow Keys are pressed and the focus is on the anchor, * focus should move to a menu item From 32c088d263a58913d11c836ddb3ee4ffefd0a3ad Mon Sep 17 00:00:00 2001 From: Josh Black Date: Tue, 7 May 2024 11:30:11 -0500 Subject: [PATCH 09/10] chore(deps): update typescript to 5.4.5 (#4568) Co-authored-by: Josh Black --- examples/app-router/package.json | 2 +- examples/codesandbox/package.json | 2 +- package-lock.json | 57 ++++++++++++++++--------------- package.json | 2 +- packages/react/package.json | 4 +-- 5 files changed, 34 insertions(+), 33 deletions(-) diff --git a/examples/app-router/package.json b/examples/app-router/package.json index aa6a13cbff4..e516a20a79d 100644 --- a/examples/app-router/package.json +++ b/examples/app-router/package.json @@ -14,7 +14,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "styled-components": "5.x", - "typescript": "^5.3.3" + "typescript": "^5.4.5" }, "devDependencies": { "@next/eslint-plugin-next": "14.1.0", diff --git a/examples/codesandbox/package.json b/examples/codesandbox/package.json index 525f084d3b7..3c36b671117 100644 --- a/examples/codesandbox/package.json +++ b/examples/codesandbox/package.json @@ -25,7 +25,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.5", "styled-components": "5.x", - "typescript": "^5.2.2", + "typescript": "^5.4.5", "vite": "^5.2.6" } } diff --git a/package-lock.json b/package-lock.json index 60d2a66f405..9bfa3b3d4b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,7 +47,7 @@ "prettier": "3.0.3", "rimraf": "5.0.5", "size-limit": "11.0.2", - "typescript": "5.3.3" + "typescript": "5.4.5" }, "engines": { "node": ">=12", @@ -337,7 +337,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "styled-components": "5.x", - "typescript": "^5.3.3" + "typescript": "^5.4.5" }, "devDependencies": { "@next/eslint-plugin-next": "14.1.0", @@ -421,7 +421,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.5", "styled-components": "5.x", - "typescript": "^5.2.2", + "typescript": "^5.4.5", "vite": "^5.2.6" } }, @@ -55145,9 +55145,9 @@ } }, "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" }, "node_modules/saxes": { "version": "6.0.0", @@ -56892,15 +56892,15 @@ } }, "node_modules/stylus": { - "version": "0.59.0", - "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.59.0.tgz", - "integrity": "sha512-lQ9w/XIOH5ZHVNuNbWW8D822r+/wBSO/d6XvtyHLF7LW4KaCIDeVbvn5DF8fGCJAUCwVhVi/h6J0NUcnylUEjg==", + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.62.0.tgz", + "integrity": "sha512-v3YCf31atbwJQIMtPNX8hcQ+okD4NQaTuKGUWfII8eaqn+3otrbttGL1zSMZAAtiPsBztQnujVBugg/cXFUpyg==", "dev": true, "dependencies": { - "@adobe/css-tools": "^4.0.1", + "@adobe/css-tools": "~4.3.1", "debug": "^4.3.2", "glob": "^7.1.6", - "sax": "~1.2.4", + "sax": "~1.3.0", "source-map": "^0.7.3" }, "bin": { @@ -58657,8 +58657,9 @@ } }, "node_modules/typescript": { - "version": "5.3.3", - "license": "Apache-2.0", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -58668,27 +58669,27 @@ } }, "node_modules/typescript-plugin-css-modules": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/typescript-plugin-css-modules/-/typescript-plugin-css-modules-5.0.2.tgz", - "integrity": "sha512-ej/Og4Y8mF+43P14P9Ik1MGqNXcXBVgO1TltkESegdnZsaaRXnaJ5CoJmTPRkg25ysQlOV6P94wNhI4VxIzlkw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/typescript-plugin-css-modules/-/typescript-plugin-css-modules-5.1.0.tgz", + "integrity": "sha512-6h+sLBa4l+XYSTn/31vZHd/1c3SvAbLpobY6FxDiUOHJQG1eD9Gh3eCs12+Eqc+TCOAdxcO+zAPvUq0jBfdciw==", "dev": true, "dependencies": { - "@types/postcss-modules-local-by-default": "^4.0.0", - "@types/postcss-modules-scope": "^3.0.1", - "dotenv": "^16.0.3", + "@types/postcss-modules-local-by-default": "^4.0.2", + "@types/postcss-modules-scope": "^3.0.4", + "dotenv": "^16.4.2", "icss-utils": "^5.1.0", - "less": "^4.1.3", + "less": "^4.2.0", "lodash.camelcase": "^4.3.0", - "postcss": "^8.4.21", + "postcss": "^8.4.35", "postcss-load-config": "^3.1.4", "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.4", + "postcss-modules-scope": "^3.1.1", "reserved-words": "^0.1.2", - "sass": "^1.58.3", + "sass": "^1.70.0", "source-map-js": "^1.0.2", - "stylus": "^0.59.0", - "tsconfig-paths": "^4.1.2" + "stylus": "^0.62.0", + "tsconfig-paths": "^4.2.0" }, "peerDependencies": { "typescript": ">=4.0.0" @@ -62095,8 +62096,8 @@ "terser": "5.27.0", "ts-toolbelt": "9.6.0", "tsx": "4.7.0", - "typescript": "5.3.3", - "typescript-plugin-css-modules": "5.0.2", + "typescript": "5.4.5", + "typescript-plugin-css-modules": "5.1.0", "unist-util-find": "3.0.0", "unist-util-find-before": "4.0.0", "unist-util-flat-filter": "2.0.0", diff --git a/package.json b/package.json index ad73d95cbc2..4e6378da082 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "prettier": "3.0.3", "rimraf": "5.0.5", "size-limit": "11.0.2", - "typescript": "5.3.3" + "typescript": "5.4.5" }, "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "^4.9.6" diff --git a/packages/react/package.json b/packages/react/package.json index d5e20f33828..50675e18617 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -216,8 +216,8 @@ "terser": "5.27.0", "ts-toolbelt": "9.6.0", "tsx": "4.7.0", - "typescript": "5.3.3", - "typescript-plugin-css-modules": "5.0.2", + "typescript": "5.4.5", + "typescript-plugin-css-modules": "5.1.0", "unist-util-find": "3.0.0", "unist-util-find-before": "4.0.0", "unist-util-flat-filter": "2.0.0", From e39fcf8dc9e7447c5f04124f408f550f73659dc1 Mon Sep 17 00:00:00 2001 From: Dusty Greif Date: Tue, 7 May 2024 09:32:56 -0700 Subject: [PATCH 10/10] Use dynamic height and width for dialogs (#4567) * Use dynamic height and width for dialogs * Update tall-forks-bathe.md --------- Co-authored-by: Siddharth Kshetrapal --- .changeset/tall-forks-bathe.md | 5 +++++ packages/react/src/Dialog.tsx | 4 ++-- packages/react/src/Dialog/Dialog.tsx | 18 +++++++++--------- 3 files changed, 16 insertions(+), 11 deletions(-) create mode 100644 .changeset/tall-forks-bathe.md diff --git a/.changeset/tall-forks-bathe.md b/.changeset/tall-forks-bathe.md new file mode 100644 index 00000000000..4998b637e00 --- /dev/null +++ b/.changeset/tall-forks-bathe.md @@ -0,0 +1,5 @@ +--- +'@primer/react': patch +--- + +Dialog: Use dynamic view height/width. This allows available visible space to be properly computed on iOS devices. diff --git a/packages/react/src/Dialog.tsx b/packages/react/src/Dialog.tsx index cd177925a5a..50bb47d11cb 100644 --- a/packages/react/src/Dialog.tsx +++ b/packages/react/src/Dialog.tsx @@ -33,10 +33,10 @@ const DialogBase = styled.div` outline: none; @media screen and (max-width: 750px) { - width: 100vw; + width: 100dvw; margin: 0; border-radius: 0; - height: 100vh; + height: 100dvh; } ${sx}; diff --git a/packages/react/src/Dialog/Dialog.tsx b/packages/react/src/Dialog/Dialog.tsx index 15460063739..81692f9ae45 100644 --- a/packages/react/src/Dialog/Dialog.tsx +++ b/packages/react/src/Dialog/Dialog.tsx @@ -239,8 +239,8 @@ const StyledDialog = styled.div` width: ${props => widthMap[props.width ?? ('xlarge' as const)]}; height: ${props => heightMap[props.height ?? ('auto' as const)]}; min-width: 296px; - max-width: calc(100vw - 64px); - max-height: calc(100vh - 64px); + max-width: calc(100dvw - 64px); + max-height: calc(100dvh - 64px); border-radius: 12px; opacity: 1; @@ -257,7 +257,7 @@ const StyledDialog = styled.div` } &[data-position-regular='left'] { - height: 100vh; + height: 100dvh; max-height: unset; border-radius: var(--borderRadius-large, 0.75rem); border-top-left-radius: 0; @@ -269,7 +269,7 @@ const StyledDialog = styled.div` } &[data-position-regular='right'] { - height: 100vh; + height: 100dvh; max-height: unset; border-radius: var(--borderRadius-large, 0.75rem); border-top-right-radius: 0; @@ -288,10 +288,10 @@ const StyledDialog = styled.div` } &[data-position-narrow='bottom'] { - width: 100vw; + width: 100dvw; height: auto; - max-width: 100vw; - max-height: calc(100vh - 64px); + max-width: 100dvw; + max-height: calc(100dvh - 64px); border-radius: var(--borderRadius-large, 0.75rem); border-bottom-right-radius: 0; border-bottom-left-radius: 0; @@ -303,9 +303,9 @@ const StyledDialog = styled.div` &[data-position-narrow='fullscreen'] { width: 100%; - max-width: 100vw; + max-width: 100dvw; height: 100%; - max-height: 100vh; + max-height: 100dvh; border-radius: unset !important; flex-grow: 1;