diff --git a/.changeset/angry-brooms-knock.md b/.changeset/angry-brooms-knock.md new file mode 100644 index 00000000000..87df637cb1c --- /dev/null +++ b/.changeset/angry-brooms-knock.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +Added className prop to the AvatarStack component diff --git a/.changeset/angry-tigers-jump.md b/.changeset/angry-tigers-jump.md new file mode 100644 index 00000000000..8ab9717c248 --- /dev/null +++ b/.changeset/angry-tigers-jump.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +ActionListGroup description style bug fix diff --git a/.changeset/dry-pens-pay.md b/.changeset/dry-pens-pay.md new file mode 100644 index 00000000000..86dc46d51d2 --- /dev/null +++ b/.changeset/dry-pens-pay.md @@ -0,0 +1,5 @@ +--- +'@primer/react': patch +--- + +Fixes negative and invalid pages in data table pagination on re-render. diff --git a/.changeset/dull-beans-dance.md b/.changeset/dull-beans-dance.md new file mode 100644 index 00000000000..7b3e87e49f7 --- /dev/null +++ b/.changeset/dull-beans-dance.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +Set the `min-width` of `IconButton` to `unset` to resolve layout issues. diff --git a/.changeset/dull-mirrors-dream.md b/.changeset/dull-mirrors-dream.md new file mode 100644 index 00000000000..b20c5ced863 --- /dev/null +++ b/.changeset/dull-mirrors-dream.md @@ -0,0 +1,5 @@ +--- +'@primer/react': major +--- + +Move Octicon, Pagehead, Dialog (v1), and Tooltip (v1) to `@primer/react/deprecated` diff --git a/.changeset/eight-avocados-lick.md b/.changeset/eight-avocados-lick.md new file mode 100644 index 00000000000..5b98b3dba35 --- /dev/null +++ b/.changeset/eight-avocados-lick.md @@ -0,0 +1,5 @@ +--- +"@primer/react": minor +--- + +Tooltip: Do not export all types publicly in the experimental bundle diff --git a/.changeset/five-seas-scream.md b/.changeset/five-seas-scream.md new file mode 100644 index 00000000000..3f7aac42e6a --- /dev/null +++ b/.changeset/five-seas-scream.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +Move CSS modules feature flag from staff to ga for Avatar component diff --git a/.changeset/itchy-paws-bake.md b/.changeset/itchy-paws-bake.md new file mode 100644 index 00000000000..532507c7a46 --- /dev/null +++ b/.changeset/itchy-paws-bake.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +fix(SegmentedControl): set global focus styles diff --git a/.changeset/khaki-dolls-reflect.md b/.changeset/khaki-dolls-reflect.md new file mode 100644 index 00000000000..24f9e125038 --- /dev/null +++ b/.changeset/khaki-dolls-reflect.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +Promote Dialog, Tooltip, and Stack from `@primer/react/experimental` to `@primer/react` diff --git a/.changeset/large-glasses-provide.md b/.changeset/large-glasses-provide.md new file mode 100644 index 00000000000..7452e63c888 --- /dev/null +++ b/.changeset/large-glasses-provide.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +Add focus styles to Pagination component diff --git a/.changeset/large-plants-unite.md b/.changeset/large-plants-unite.md new file mode 100644 index 00000000000..d0be95ef007 --- /dev/null +++ b/.changeset/large-plants-unite.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +Bug fix(Avatar): Changed rounded border calculation for the "square" Avatar to better align with existing border styles diff --git a/.changeset/modern-cooks-invite.md b/.changeset/modern-cooks-invite.md new file mode 100644 index 00000000000..df4fde36b37 --- /dev/null +++ b/.changeset/modern-cooks-invite.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +fix(Banner): rewrite PrimaryAction & SecondaryAction types diff --git a/.changeset/perfect-fishes-camp.md b/.changeset/perfect-fishes-camp.md new file mode 100644 index 00000000000..7bc8ee2b346 --- /dev/null +++ b/.changeset/perfect-fishes-camp.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +fix(TooltipV2): always add aria-hidden diff --git a/.changeset/plenty-books-agree.md b/.changeset/plenty-books-agree.md new file mode 100644 index 00000000000..e893025c849 --- /dev/null +++ b/.changeset/plenty-books-agree.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +fix for `toggleStyledComponent` utility, When the feature flag is enabled and sx prop is passed in use, Box diff --git a/.changeset/pre.json b/.changeset/pre.json index 6f72683463d..7d1b0cf362e 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -11,25 +11,34 @@ "example-theming": "0.0.0" }, "changesets": [ + "angry-tigers-jump", "beige-schools-kneel", "big-pumas-sit", "blue-stingrays-decide", "breezy-boxes-jog", "breezy-buckets-wash", "calm-forks-pull", + "clean-lions-learn", "clever-birds-press", "cool-llamas-live", "cool-lobsters-nail", "curvy-goats-sell", "dirty-pianos-wash", + "dry-pens-pay", "dry-trainers-protect", + "dull-beans-dance", "dull-dolphins-bake", + "dull-mirrors-dream", "dull-turkeys-cheer", "early-lions-vanish", + "eight-avocados-lick", "eighty-houses-beg", "eleven-drinks-kiss", "fifty-foxes-drop", + "fifty-rockets-joke", + "five-seas-scream", "flat-avocados-cheer", + "flat-weeks-battle", "fluffy-ravens-thank", "forty-ants-tell", "four-shoes-yell", @@ -37,20 +46,32 @@ "friendly-boats-serve", "fuzzy-jobs-deny", "gold-cups-explode", + "good-years-attack", "green-poems-play", "green-schools-smell", + "happy-fireants-mate", "honest-ligers-fly", "hot-baboons-allow", + "khaki-dolls-reflect", + "large-glasses-provide", + "large-plants-unite", "lemon-candles-deny", + "light-chefs-bow", + "little-bats-approve", + "long-pans-travel", "lovely-days-march", + "lucky-oranges-camp", "mighty-parrots-carry", + "modern-cooks-invite", "moody-rivers-impress", "nervous-llamas-ring", "new-shirts-beam", "nice-moles-know", "odd-rings-applaud", "olive-donkeys-exercise", + "orange-steaks-do", "pink-actors-cross", + "plenty-books-agree", "purple-apricots-relax", "quick-adults-buy", "quick-feet-sip", @@ -61,26 +82,42 @@ "serious-terms-sniff", "seven-scissors-explain", "short-boats-cover", + "silent-fireants-kneel", + "silent-planes-grab", "silly-weeks-clap", + "silver-cheetahs-compare", "six-owls-walk", "sixty-olives-glow", + "slow-walls-drum", "soft-tips-chew", "sour-cooks-dress", + "sour-cycles-warn", "spicy-eggs-melt", "spicy-flies-sniff", + "spotty-melons-sit", "stale-lizards-report", "stale-pets-tan", + "strong-tables-rest", + "stupid-monkeys-beg", "tall-wasps-end", "tame-boats-hide", "ten-gifts-own", "ten-masks-smoke", + "thin-planes-grow", "thirty-pets-impress", "thirty-tips-bow", + "three-coins-tell", + "three-scissors-hide", "tidy-bats-warn", "tidy-clocks-marry", + "tidy-impalas-remain", "tough-pans-punch", "twelve-tables-leave", + "twenty-spoons-give", "weak-hats-type", + "weak-ravens-greet", + "wet-apples-hide", + "wet-otters-pull", "wicked-books-occur", "yellow-tools-call", "young-meals-worry" diff --git a/.changeset/real-seahorses-grab.md b/.changeset/real-seahorses-grab.md new file mode 100644 index 00000000000..7cc1bcb47ec --- /dev/null +++ b/.changeset/real-seahorses-grab.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +Add ButtonBase to `@primer/react/experimental` to help with wildcard import interop diff --git a/.changeset/selfish-garlics-approve.md b/.changeset/selfish-garlics-approve.md new file mode 100644 index 00000000000..bde5a2e4709 --- /dev/null +++ b/.changeset/selfish-garlics-approve.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +[SelectPanel] Implement loading states diff --git a/.changeset/shiny-otters-call.md b/.changeset/shiny-otters-call.md new file mode 100644 index 00000000000..bc858921712 --- /dev/null +++ b/.changeset/shiny-otters-call.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +[SegmentedControl, Autocomplete] Support passing React.ReactElements for icons. diff --git a/.changeset/silent-fireants-kneel.md b/.changeset/silent-fireants-kneel.md new file mode 100644 index 00000000000..9ce53633f3f --- /dev/null +++ b/.changeset/silent-fireants-kneel.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +Add the `useFeatureFlag` hook to `@primer/react/experimental` diff --git a/.changeset/silver-cheetahs-compare.md b/.changeset/silver-cheetahs-compare.md new file mode 100644 index 00000000000..cb207d8e358 --- /dev/null +++ b/.changeset/silver-cheetahs-compare.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +Bug fix for `IconButton` to respect the `style` prop width when the feature flag is on. diff --git a/.changeset/sour-cycles-warn.md b/.changeset/sour-cycles-warn.md new file mode 100644 index 00000000000..e2b8d18cd88 --- /dev/null +++ b/.changeset/sour-cycles-warn.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +Add ResponsiveValue type to `@primer/react` entrypoint diff --git a/.changeset/stupid-monkeys-beg.md b/.changeset/stupid-monkeys-beg.md new file mode 100644 index 00000000000..685c96bab90 --- /dev/null +++ b/.changeset/stupid-monkeys-beg.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +SelectPanel: Fix items not being selected when defined within scope (track selection by item.id) diff --git a/.changeset/thin-planes-grow.md b/.changeset/thin-planes-grow.md new file mode 100644 index 00000000000..2c5d81f819c --- /dev/null +++ b/.changeset/thin-planes-grow.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +SelectPanel: Fix font weight from active styles for modern ActionList (behind feature flag) diff --git a/.changeset/tidy-impalas-remain.md b/.changeset/tidy-impalas-remain.md new file mode 100644 index 00000000000..d595d5b4197 --- /dev/null +++ b/.changeset/tidy-impalas-remain.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +Use the IconButton for the close button on Dialog diff --git a/.changeset/wet-apples-hide.md b/.changeset/wet-apples-hide.md new file mode 100644 index 00000000000..6aeb72adb44 --- /dev/null +++ b/.changeset/wet-apples-hide.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +Correctly pass styled system typography and common props to the `Box` component in the `Text` component when the CSS modules feature flag is enabled. diff --git a/.changeset/wet-otters-pull.md b/.changeset/wet-otters-pull.md new file mode 100644 index 00000000000..ca7b0df27b8 --- /dev/null +++ b/.changeset/wet-otters-pull.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +Banner: Fix margin for inline actions diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index f630701b4dc..0df1623e91f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,6 @@ { "name": "Primer React", - "image": "mcr.microsoft.com/vscode/devcontainers/typescript-node:18", + "image": "mcr.microsoft.com/vscode/devcontainers/typescript-node:22", "extensions": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint", "DavidAnson.vscode-markdownlint"], "forwardPorts": [8000], "onCreateCommand": ["/bin/bash", "-c", "npm run setup"], diff --git a/.github/actions/pagerduty/action.yml b/.github/actions/pagerduty/action.yml index 00065517dd8..83d5ff951d3 100644 --- a/.github/actions/pagerduty/action.yml +++ b/.github/actions/pagerduty/action.yml @@ -38,7 +38,7 @@ runs: - name: Set up Node.js uses: actions/setup-node@v3 with: - node-version: 20 + node-version: 22 - name: Get PagerDuty Schedule id: pagerduty uses: actions/github-script@v6 diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5206c25fd82..97e16d1b9f5 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,16 +9,7 @@ updates: directory: '/' schedule: interval: 'weekly' - labels: - - 'dependencies' - - 'skip changeset' - - - package-ecosystem: 'npm' - directory: '/docs' - schedule: - interval: 'weekly' - allow: - - dependency-name: '@primer/gatsby-theme-doctocat' + versioning-strategy: increase labels: - 'dependencies' - 'skip changeset' diff --git a/.github/workflows/assign_release_conductor.yml b/.github/workflows/assign_release_conductor.yml index 8cbc24e21c0..baacf81c019 100644 --- a/.github/workflows/assign_release_conductor.yml +++ b/.github/workflows/assign_release_conductor.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 - run: npm i -g npm@^10.5.1 - run: npm ci - uses: ./.github/actions/pagerduty diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4298feee3e0..fc8437f0215 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: Install dependencies @@ -41,7 +41,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: Install dependencies @@ -61,7 +61,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: Install dependencies @@ -79,7 +79,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: Install dependencies @@ -97,7 +97,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: Install dependencies @@ -106,7 +106,7 @@ jobs: run: npm run build -ws --if-present vrt-runner: - runs-on: ubuntu-latest-8-cores + runs-on: ubuntu-latest-16-cores strategy: fail-fast: false matrix: @@ -116,7 +116,7 @@ jobs: - name: Use Node.js 20.x uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: Install dependencies @@ -133,7 +133,7 @@ jobs: echo "pid=$pid" >> $GITHUB_OUTPUT sleep 5 - name: Run VRT - uses: docker://mcr.microsoft.com/playwright:v1.43.0-jammy + uses: docker://mcr.microsoft.com/playwright:v1.47.2-jammy env: STORYBOOK_URL: 'http://172.17.0.1:6006' with: @@ -144,7 +144,7 @@ jobs: if: ${{ always() }} uses: actions/upload-artifact@v4 with: - name: vrt-${{ matrix.shard }} + name: vrt-no-flag-${{ matrix.shard }} path: blob-report retention-days: 1 @@ -157,7 +157,7 @@ jobs: - name: Use Node.js 20.x uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: install dependencies @@ -166,21 +166,99 @@ jobs: uses: actions/download-artifact@v4 with: path: all-blob-reports - pattern: vrt-* + pattern: vrt-no-flag-* merge-multiple: true - name: merge all reports run: npx playwright merge-reports --reporter html ./all-blob-reports - name: Upload report uses: actions/upload-artifact@v4 with: - name: vrt + name: vrt-no-flag + path: playwright-report + - name: check vrt-runner job status + if: ${{ needs.vrt-runner.result == 'failure' }} + run: exit 1 + + vrt-runner-all-flags: + runs-on: ubuntu-latest-16-cores + strategy: + fail-fast: false + matrix: + shard: [1, 2, 3, 4] + env: + VITE_PRIMER_REACT_CSS_MODULES_TEAM: 1 + VITE_PRIMER_REACT_CSS_MODULES_STAFF: 1 + VITE_PRIMER_REACT_CSS_MODULES_GA: 1 + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 20.x + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: 'npm' + - run: npm i -g npm@^10.5.1 + - name: Install dependencies + run: npm ci + - name: Build storybook + run: npx storybook build + working-directory: packages/react + - name: Run storybook + id: storybook + working-directory: packages/react + run: | + npx serve -l 6006 storybook-static & + pid=$! + echo "pid=$pid" >> $GITHUB_OUTPUT + sleep 5 + - name: Run VRT + uses: docker://mcr.microsoft.com/playwright:v1.47.2-jammy + env: + STORYBOOK_URL: 'http://172.17.0.1:6006' + with: + args: npx playwright test --grep @vrt --shard="${{ matrix.shard }}/${{ strategy.job-total }}" + - name: Stop storybook + run: kill ${{ steps.storybook.outputs.pid }} + - name: Upload report + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: vrt-all-flags-${{ matrix.shard }} + path: blob-report + retention-days: 1 + + vrt-all-flags: + if: ${{ always() }} + runs-on: ubuntu-latest + needs: vrt-runner-all-flags + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 20.x + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: 'npm' + - run: npm i -g npm@^10.5.1 + - name: install dependencies + run: npm ci + - name: download all reports + uses: actions/download-artifact@v4 + with: + path: all-blob-reports + pattern: vrt-all-flags-* + merge-multiple: true + - name: merge all reports + run: npx playwright merge-reports --reporter html ./all-blob-reports + - name: Upload report + uses: actions/upload-artifact@v4 + with: + name: vrt-all-flags path: playwright-report - name: check vrt-runner job status if: ${{ needs.vrt-runner.result == 'failure' }} run: exit 1 aat-runner: - runs-on: ubuntu-latest-8-cores + runs-on: ubuntu-latest-16-cores strategy: fail-fast: false matrix: @@ -190,7 +268,7 @@ jobs: - name: Use Node.js 20.x uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: Install dependencies @@ -207,7 +285,7 @@ jobs: echo "pid=$pid" >> $GITHUB_OUTPUT sleep 5 - name: Run AAT - uses: docker://mcr.microsoft.com/playwright:v1.43.0-jammy + uses: docker://mcr.microsoft.com/playwright:v1.47.2-jammy env: STORYBOOK_URL: 'http://172.17.0.1:6006' with: @@ -218,7 +296,7 @@ jobs: if: ${{ always() }} uses: actions/upload-artifact@v4 with: - name: axe-${{ matrix.shard }} + name: axe-no-flag-${{ matrix.shard }} path: blob-report retention-days: 1 @@ -231,7 +309,7 @@ jobs: - name: Use Node.js 20.x uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: install dependencies @@ -240,7 +318,7 @@ jobs: uses: actions/download-artifact@v4 with: path: all-blob-reports - pattern: axe-* + pattern: axe-no-flag-* merge-multiple: true - name: merge all reports run: npx playwright merge-reports --reporter html ./all-blob-reports @@ -253,6 +331,84 @@ jobs: if: ${{ needs.aat-runner.result == 'failure' }} run: exit 1 + aat-runner-all-flags: + runs-on: ubuntu-latest-16-cores + strategy: + fail-fast: false + matrix: + shard: [1, 2, 3, 4] + env: + VITE_PRIMER_REACT_CSS_MODULES_TEAM: 1 + VITE_PRIMER_REACT_CSS_MODULES_STAFF: 1 + VITE_PRIMER_REACT_CSS_MODULES_GA: 1 + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 20.x + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: 'npm' + - run: npm i -g npm@^10.5.1 + - name: Install dependencies + run: npm ci + - name: Build storybook + run: npx storybook build + working-directory: packages/react + - name: Run storybook + id: storybook + working-directory: packages/react + run: | + npx serve -l 6006 storybook-static & + pid=$! + echo "pid=$pid" >> $GITHUB_OUTPUT + sleep 5 + - name: Run AAT + uses: docker://mcr.microsoft.com/playwright:v1.47.2-jammy + env: + STORYBOOK_URL: 'http://172.17.0.1:6006' + with: + args: npx playwright test --grep @aat --shard="${{ matrix.shard }}/${{ strategy.job-total }}" + - name: Stop storybook + run: kill ${{ steps.storybook.outputs.pid }} + - name: Upload report + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: axe-all-flags-${{ matrix.shard }} + path: blob-report + retention-days: 1 + + aat-all-flags: + if: ${{ always() }} + runs-on: ubuntu-latest + needs: aat-runner-all-flags + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 20.x + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: 'npm' + - run: npm i -g npm@^10.5.1 + - name: install dependencies + run: npm ci + - name: download all reports + uses: actions/download-artifact@v4 + with: + path: all-blob-reports + pattern: axe-all-flags-* + merge-multiple: true + - name: merge all reports + run: npx playwright merge-reports --reporter html ./all-blob-reports + - name: Upload report + uses: actions/upload-artifact@v4 + with: + name: axe-all-flags + path: playwright-report + - name: Check aat-runner job status + if: ${{ needs.aat-runner.result == 'failure' }} + run: exit 1 + build-components-json: runs-on: ubuntu-latest steps: @@ -261,7 +417,7 @@ jobs: - name: Use Node.js 20.x uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: Install dependencies @@ -277,7 +433,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: Install dependencies diff --git a/.github/workflows/codescan.yml b/.github/workflows/codescan.yml index ed6bcb78c9a..3ebb8186f6c 100644 --- a/.github/workflows/codescan.yml +++ b/.github/workflows/codescan.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: Install dependencies diff --git a/.github/workflows/consumer_test.yml b/.github/workflows/consumer_test.yml index 52276a5257a..f9bccebd6ce 100644 --- a/.github/workflows/consumer_test.yml +++ b/.github/workflows/consumer_test.yml @@ -14,7 +14,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: npm - run: npm i -g npm@^10.5.1 - name: Remove "prepare" script diff --git a/.github/workflows/deploy_preview.yml b/.github/workflows/deploy_preview.yml index ac9266642fc..f8d7810bedd 100644 --- a/.github/workflows/deploy_preview.yml +++ b/.github/workflows/deploy_preview.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: Install dependencies diff --git a/.github/workflows/deploy_preview_forks.yml b/.github/workflows/deploy_preview_forks.yml index 0c59811c9fd..ae3fa7f9845 100644 --- a/.github/workflows/deploy_preview_forks.yml +++ b/.github/workflows/deploy_preview_forks.yml @@ -17,7 +17,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: Install dependencies diff --git a/.github/workflows/figma_connect_publish.yml b/.github/workflows/figma_connect_publish.yml index 18a0336f1bc..b9992d7741b 100644 --- a/.github/workflows/figma_connect_publish.yml +++ b/.github/workflows/figma_connect_publish.yml @@ -18,7 +18,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 - name: Cache dependencies uses: actions/cache@v4 diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 1da519d0301..d35991ca6e5 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 - name: Get or Create Comment uses: actions/github-script@v7 diff --git a/.github/workflows/recommend-integration-tests.yml b/.github/workflows/recommend-integration-tests.yml new file mode 100644 index 00000000000..ddeb07db8d3 --- /dev/null +++ b/.github/workflows/recommend-integration-tests.yml @@ -0,0 +1,74 @@ +name: Recommend integration tests +on: + pull_request: + +jobs: + recommend: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Get source files changes + id: source-files + run: | + DIFF=$(git diff --name-only origin/main | grep 'packages/react' | grep -Ev '.stories.tsx|.docs.json' || true) + if [ -z "$DIFF" ]; then + echo "diff=" >> $GITHUB_OUTPUT + else + echo "diff=true" >> $GITHUB_OUTPUT + fi + + - name: Has diff? + run: echo ${{ steps.source-files.outputs.diff != '' }} + + - name: Get or Create Comment + if: ${{ steps.source-files.outputs.diff != '' }} + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const result = await github.paginate(github.rest.issues.listComments, { + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo + }); + + const previousComment = result.filter(c => c.user.login == 'github-actions[bot]' && c.body.startsWith('')) + if (!previousComment.length) { + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: '\n\n :wave: Hi, this pull request contains changes to the source code that github/github depends on. If you are GitHub staff, we recommend testing these changes with github/github using the [integration workflow](https://gh.io/testing_primer_at_dotcom). Thanks!' + }) + } + + - name: Add label + if: ${{ steps.source-files.outputs.diff != '' }} + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const result = await github.rest.issues.listLabelsOnIssue({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + }) + + const integrationLabels = result.data.filter(label => label.name.startsWith('integration-tests')) + if (!integrationLabels.length) { + await github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['integration-tests: recommended'], + }) + } diff --git a/.github/workflows/release-schedule.yml b/.github/workflows/release-schedule.yml index 05ea7c517cb..d032decd5ca 100644 --- a/.github/workflows/release-schedule.yml +++ b/.github/workflows/release-schedule.yml @@ -30,7 +30,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 - run: npm i -g npm@^10.5.1 - name: Install packages for github-script run: npm i date-fns diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 22b6809159d..c27d25e24a7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,7 +22,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 diff --git a/.github/workflows/release_canary.yml b/.github/workflows/release_canary.yml index a58ac8bcc33..4d2c650469c 100644 --- a/.github/workflows/release_canary.yml +++ b/.github/workflows/release_canary.yml @@ -25,7 +25,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: Install dependencies diff --git a/.github/workflows/release_candidate.yml b/.github/workflows/release_candidate.yml index 9ce3dfb396b..bc2431774a8 100644 --- a/.github/workflows/release_candidate.yml +++ b/.github/workflows/release_candidate.yml @@ -21,7 +21,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 diff --git a/.github/workflows/statuses.yml b/.github/workflows/statuses.yml index cf29166af88..58caad824a6 100644 --- a/.github/workflows/statuses.yml +++ b/.github/workflows/statuses.yml @@ -22,7 +22,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 - name: Install node deps run: npm ci - name: Install ruby deps diff --git a/.github/workflows/storybook-tests.yml b/.github/workflows/storybook-tests.yml index 41308daa00f..c4a15304970 100644 --- a/.github/workflows/storybook-tests.yml +++ b/.github/workflows/storybook-tests.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - name: Install dependencies run: npm i diff --git a/.github/workflows/vrt.yml b/.github/workflows/vrt.yml index ae2efa5521a..1cd02e91ebd 100644 --- a/.github/workflows/vrt.yml +++ b/.github/workflows/vrt.yml @@ -37,7 +37,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: 'npm' - run: npm i -g npm@^10.5.1 - name: Install dependencies @@ -53,7 +53,7 @@ jobs: echo "pid=$pid" >> $GITHUB_OUTPUT sleep 5 - name: Run VRT - uses: docker://mcr.microsoft.com/playwright:v1.43.0-jammy + uses: docker://mcr.microsoft.com/playwright:v1.47.2-jammy env: STORYBOOK_URL: 'http://172.17.0.1:6006' with: diff --git a/.husky/pre-commit b/.husky/pre-commit index 3c64a3df557..c27d8893a99 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,6 +1 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -[ -z "$HUSKY_ENABLED" ] && exit 0 - -npx lint-staged \ No newline at end of file +lint-staged diff --git a/.nvmrc b/.nvmrc index 9a2a0e219c9..53d1c14db37 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v20 +v22 diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-colorblind-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-colorblind-linux.png index 07a1b9a0764..2a98f13bf72 100644 Binary files a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-colorblind-linux.png and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-high-contrast-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-high-contrast-linux.png index 9e349c0ed8d..0052a5ca4e6 100644 Binary files a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-high-contrast-linux.png and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-linux.png index 07a1b9a0764..2a98f13bf72 100644 Binary files a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-linux.png and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-tritanopia-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-tritanopia-linux.png index 07a1b9a0764..2a98f13bf72 100644 Binary files a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-tritanopia-linux.png and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-high-contrast-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-high-contrast-linux.png index 554d38cc4ac..de78a731cff 100644 Binary files a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-high-contrast-linux.png and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-colorblind-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-colorblind-linux.png index c9d3bf663df..234d98f4b41 100644 Binary files a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-colorblind-linux.png and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-high-contrast-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-high-contrast-linux.png index b37a7ec3f2b..043d7fa29b1 100644 Binary files a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-high-contrast-linux.png and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-linux.png index c9d3bf663df..234d98f4b41 100644 Binary files a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-linux.png and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-tritanopia-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-tritanopia-linux.png index c9d3bf663df..234d98f4b41 100644 Binary files a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-tritanopia-linux.png and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-light-high-contrast-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-light-high-contrast-linux.png index 2ed48cfcd1a..ba88fc8601d 100644 Binary files a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-light-high-contrast-linux.png and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndSecondaryAction-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Default-dark-dimmed-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Default-dark-dimmed-linux.png index 5f865837797..3abac2ad943 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Default-dark-dimmed-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Default-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-colorblind-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-colorblind-linux.png index f6743f394e5..e9df71e78bf 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-colorblind-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-dimmed-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-dimmed-linux.png index a0714ba53cf..898c4156a07 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-dimmed-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-high-contrast-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-high-contrast-linux.png index f4b199e5099..fb174f1d6f7 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-high-contrast-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-linux.png index f6743f394e5..e9df71e78bf 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-tritanopia-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-tritanopia-linux.png index f6743f394e5..e9df71e78bf 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-tritanopia-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-colorblind-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-colorblind-linux.png index fe285469cc7..455bbb65e9f 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-colorblind-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-high-contrast-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-high-contrast-linux.png index 04e1f365b4c..7b798c5100b 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-high-contrast-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-linux.png index fe285469cc7..455bbb65e9f 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-tritanopia-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-tritanopia-linux.png index fe285469cc7..455bbb65e9f 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-tritanopia-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-bottom-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-colorblind-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-colorblind-linux.png index f6743f394e5..e9df71e78bf 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-colorblind-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-dimmed-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-dimmed-linux.png index a0714ba53cf..898c4156a07 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-dimmed-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-high-contrast-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-high-contrast-linux.png index f4b199e5099..fb174f1d6f7 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-high-contrast-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-linux.png index f6743f394e5..e9df71e78bf 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-tritanopia-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-tritanopia-linux.png index f6743f394e5..e9df71e78bf 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-tritanopia-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-colorblind-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-colorblind-linux.png index fe285469cc7..455bbb65e9f 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-colorblind-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-high-contrast-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-high-contrast-linux.png index 04e1f365b4c..7b798c5100b 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-high-contrast-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-linux.png index fe285469cc7..455bbb65e9f 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-tritanopia-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-tritanopia-linux.png index fe285469cc7..455bbb65e9f 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-tritanopia-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-fullscreen-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-colorblind-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-colorblind-linux.png index a7ba61f5f28..fb63a4b582d 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-colorblind-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-dimmed-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-dimmed-linux.png index da9db6dd00d..d2137b3496b 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-dimmed-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-high-contrast-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-high-contrast-linux.png index 7e2c1e126bb..a83b9bc0f3e 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-high-contrast-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-linux.png index a7ba61f5f28..fb63a4b582d 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-tritanopia-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-tritanopia-linux.png index a7ba61f5f28..fb63a4b582d 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-tritanopia-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-colorblind-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-colorblind-linux.png index acb8b3adc50..1d70c59b77c 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-colorblind-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-high-contrast-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-high-contrast-linux.png index 5f2ee1b541b..b35f1b4204e 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-high-contrast-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-linux.png index acb8b3adc50..1d70c59b77c 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-tritanopia-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-tritanopia-linux.png index acb8b3adc50..1d70c59b77c 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-tritanopia-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Position-sidesheet-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-colorblind-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-colorblind-linux.png index c4b78b9b2a2..926012870d0 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-colorblind-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-dimmed-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-dimmed-linux.png index 48c74ada840..eeb1138fc51 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-dimmed-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-high-contrast-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-high-contrast-linux.png index aac2bd1f5cc..ce9e29eac63 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-high-contrast-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-linux.png index 12fa78af014..bb91780ff88 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-tritanopia-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-tritanopia-linux.png index 4bb1ae1398e..682bb941182 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-tritanopia-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-colorblind-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-colorblind-linux.png index 6480afe8175..5a53f135866 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-colorblind-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-high-contrast-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-high-contrast-linux.png index 45e2ec1b349..722a9cf272e 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-high-contrast-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-linux.png index 69cdf049125..29348e4b89d 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-tritanopia-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-tritanopia-linux.png index 7896c2580cd..e88c5ee3221 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-tritanopia-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-Stress-Test-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-With-Custom-Renderers-dark-dimmed-linux.png b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-With-Custom-Renderers-dark-dimmed-linux.png index 4a9c8150fb1..8fdc1ed71f3 100644 Binary files a/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-With-Custom-Renderers-dark-dimmed-linux.png and b/.playwright/snapshots/components/Dialog.test.ts-snapshots/Dialog-With-Custom-Renderers-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-colorblind-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-colorblind-linux.png index 529be7a4eba..6586dff7587 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-colorblind-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-colorblind-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-colorblind-modern-action-list--true-linux.png index 6bab4fb23dc..711307592a0 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-colorblind-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-colorblind-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-dimmed-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-dimmed-linux.png index dd00e9e0d25..e7bdb2789b5 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-dimmed-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-dimmed-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-dimmed-modern-action-list--true-linux.png index b2e5c476252..278ff7c6978 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-dimmed-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-dimmed-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-high-contrast-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-high-contrast-linux.png index f2e6fc4ca41..c57938b7e7f 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-high-contrast-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-high-contrast-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-high-contrast-modern-action-list--true-linux.png index 4db094bf4c0..834518c3da7 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-high-contrast-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-high-contrast-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-linux.png index 529be7a4eba..6586dff7587 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-modern-action-list--true-linux.png index 6bab4fb23dc..711307592a0 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-tritanopia-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-tritanopia-linux.png index 529be7a4eba..6586dff7587 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-tritanopia-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-tritanopia-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-tritanopia-modern-action-list--true-linux.png index 6bab4fb23dc..711307592a0 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-tritanopia-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-tritanopia-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-forced-colors-dark-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-forced-colors-dark-modern-action-list--true-linux.png index 25d8a0cf18b..febdfd9066d 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-forced-colors-dark-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-forced-colors-dark-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-forced-colors-light-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-forced-colors-light-modern-action-list--true-linux.png index 2c12a24a104..7d47e5b7083 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-forced-colors-light-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-forced-colors-light-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-colorblind-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-colorblind-linux.png index 51003be5974..a6a76085ad0 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-colorblind-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-colorblind-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-colorblind-modern-action-list--true-linux.png index 732d18f5ba4..3de31d83a06 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-colorblind-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-colorblind-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-high-contrast-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-high-contrast-linux.png index d06a2f20e6a..9c9fd53b926 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-high-contrast-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-high-contrast-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-high-contrast-modern-action-list--true-linux.png index 25817585a80..c77643c7ba2 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-high-contrast-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-high-contrast-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-linux.png index 51003be5974..a6a76085ad0 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-modern-action-list--true-linux.png index 732d18f5ba4..3de31d83a06 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-tritanopia-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-tritanopia-linux.png index 51003be5974..a6a76085ad0 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-tritanopia-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-tritanopia-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-tritanopia-modern-action-list--true-linux.png index 732d18f5ba4..3de31d83a06 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-tritanopia-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-tritanopia-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-colorblind-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-colorblind-linux.png index 4bf7e046e82..842c8b3490f 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-colorblind-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-colorblind-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-colorblind-modern-action-list--true-linux.png index f745c6b6750..842c8b3490f 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-colorblind-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-colorblind-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-dimmed-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-dimmed-linux.png index 7fd1f5a0d19..da0c03e84cd 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-dimmed-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-dimmed-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-dimmed-modern-action-list--true-linux.png index dd9ed5215ba..da0c03e84cd 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-dimmed-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-dimmed-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-high-contrast-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-high-contrast-linux.png index 80159d482d4..a20f42cffd0 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-high-contrast-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-high-contrast-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-high-contrast-modern-action-list--true-linux.png index 80159d482d4..a20f42cffd0 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-high-contrast-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-high-contrast-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-linux.png index 4bf7e046e82..842c8b3490f 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-modern-action-list--true-linux.png index f745c6b6750..842c8b3490f 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-tritanopia-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-tritanopia-linux.png index 4bf7e046e82..842c8b3490f 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-tritanopia-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-tritanopia-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-tritanopia-modern-action-list--true-linux.png index f745c6b6750..842c8b3490f 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-tritanopia-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-dark-tritanopia-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-colorblind-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-colorblind-linux.png index d046a0c6158..4dedb9fdd38 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-colorblind-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-colorblind-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-colorblind-modern-action-list--true-linux.png index 07a2a90e169..4dedb9fdd38 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-colorblind-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-colorblind-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-high-contrast-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-high-contrast-linux.png index 1d69edbed3b..ff8d5202ba9 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-high-contrast-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-high-contrast-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-high-contrast-modern-action-list--true-linux.png index 1d69edbed3b..ff8d5202ba9 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-high-contrast-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-high-contrast-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-linux.png index d046a0c6158..4dedb9fdd38 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-modern-action-list--true-linux.png index 07a2a90e169..4dedb9fdd38 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-tritanopia-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-tritanopia-linux.png index d046a0c6158..4dedb9fdd38 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-tritanopia-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-tritanopia-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-tritanopia-modern-action-list--true-linux.png index 07a2a90e169..4dedb9fdd38 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-tritanopia-modern-action-list--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Height-Initial-with-Underflowing-Items-After-Fetch-light-tritanopia-modern-action-list--true-linux.png differ diff --git a/e2e/components/Avatar.test.ts b/e2e/components/Avatar.test.ts index 3fd9ec03779..dab9f9de809 100644 --- a/e2e/components/Avatar.test.ts +++ b/e2e/components/Avatar.test.ts @@ -3,151 +3,139 @@ import {visit} from '../test-helpers/storybook' import {themes} from '../test-helpers/themes' test.describe('Avatar', () => { - for (const enabled of [true, false]) { - test.describe(`Feature flag enabled: ${enabled}`, () => { - test.describe('Default', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-avatar--default', - globals: { - colorScheme: theme, - primer_react_css_modules_staff: enabled, - }, - }) + test.describe('Default', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-avatar--default', + globals: { + colorScheme: theme, + }, + }) - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Avatar.Default.${theme}.png`) - }) + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Avatar.Default.${theme}.png`) + }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-avatar--default', - globals: { - colorScheme: theme, - primer_react_css_modules_staff: enabled, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-avatar--default', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, }) - } + }) }) + } + }) - test.describe('Size', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-avatar-features--size', - globals: { - colorScheme: theme, - primer_react_css_modules_staff: enabled, - }, - }) + test.describe('Size', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-avatar-features--size', + globals: { + colorScheme: theme, + }, + }) - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Avatar.Size.${theme}.png`) - }) + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Avatar.Size.${theme}.png`) + }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-avatar-features--size', - globals: { - colorScheme: theme, - primer_react_css_modules_staff: enabled, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-avatar-features--size', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, }) - } + }) }) + } + }) - test.describe('Size Responsive', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-avatar-features--size-responsive', - globals: { - colorScheme: theme, - primer_react_css_modules_staff: enabled, - }, - }) + test.describe('Size Responsive', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-avatar-features--size-responsive', + globals: { + colorScheme: theme, + }, + }) - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Avatar.Size Responsive.${theme}.png`) - }) + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Avatar.Size Responsive.${theme}.png`) + }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-avatar-features--size-responsive', - globals: { - colorScheme: theme, - primer_react_css_modules_staff: enabled, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-avatar-features--size-responsive', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, }) - } + }) }) + } + }) - test.describe('Square', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-avatar-features--square', - globals: { - colorScheme: theme, - primer_react_css_modules_staff: enabled, - }, - }) + test.describe('Square', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-avatar-features--square', + globals: { + colorScheme: theme, + }, + }) - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Avatar.Square.${theme}.png`) - }) + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Avatar.Square.${theme}.png`) + }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-avatar-features--square', - globals: { - colorScheme: theme, - primer_react_css_modules_staff: enabled, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-avatar-features--square', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, }) - } + }) }) - }) - } + } + }) }) diff --git a/e2e/components/Banner.test.ts b/e2e/components/Banner.test.ts index 36162e47f88..83b93892dc3 100644 --- a/e2e/components/Banner.test.ts +++ b/e2e/components/Banner.test.ts @@ -82,24 +82,6 @@ test.describe('Banner', () => { id: story.id, globals: { colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: true, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Banner.${story.title}.${theme}.png`) - }) - - test('default (styled-components) @vrt', async ({page}) => { - await visit(page, { - id: story.id, - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: false, - }, }, }) @@ -112,22 +94,6 @@ test.describe('Banner', () => { id: story.id, globals: { colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: true, - }, - }, - }) - await expect(page).toHaveNoViolations() - }) - - test('axe (styled-components) @aat', async ({page}) => { - await visit(page, { - id: story.id, - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: false, - }, }, }) await expect(page).toHaveNoViolations() @@ -140,29 +106,6 @@ test.describe('Banner', () => { test(`${name} @vrt`, async ({page}) => { await visit(page, { id: story.id, - globals: { - featureFlags: { - primer_react_css_modules_team: true, - }, - }, - }) - const width = viewports[name] - - await page.setViewportSize({ - width, - height: 667, - }) - expect(await page.screenshot()).toMatchSnapshot(`Banner.${story.title}.${name}.png`) - }) - - test(`${name} (styled-components) @vrt`, async ({page}) => { - await visit(page, { - id: story.id, - globals: { - featureFlags: { - primer_react_css_modules_team: false, - }, - }, }) const width = viewports[name] diff --git a/e2e/components/Button.test.ts b/e2e/components/Button.test.ts index c86326eb1a5..1e444ac106f 100644 --- a/e2e/components/Button.test.ts +++ b/e2e/components/Button.test.ts @@ -3,748 +3,627 @@ import {visit} from '../test-helpers/storybook' import {themes} from '../test-helpers/themes' test.describe('Button', () => { - for (const featureFlagOn of [true, false]) { - test.describe(`Feature flag: ${featureFlagOn ? 'on' : 'off'}`, () => { - test.describe('Danger', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--danger', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Danger.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button-features--danger', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } - }) + test.describe('Danger', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--danger', + globals: { + colorScheme: theme, + }, + }) - test.describe('Default', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button--default', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Default.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button--default', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } - }) + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Button.Danger.${theme}.png`) + }) - test.describe('Disabled', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--disabled', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Disabled.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button-features--disabled', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button-features--danger', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) - test.describe('Invisible', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--invisible', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Invisible.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button-features--invisible', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test.describe('Default', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button--default', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Button.Default.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button--default', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) - test.describe('Link', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--link', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Link.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button-features--link', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test.describe('Disabled', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--disabled', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Button.Disabled.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button-features--disabled', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) - test.describe('Large', () => { + test.describe('Invisible', () => { + for (const theme of themes) { + test.describe(theme, () => { test('default @vrt', async ({page}) => { await visit(page, { - id: 'components-button-features--large', + id: 'components-button-features--invisible', globals: { - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Button.Invisible.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button-features--invisible', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', }, }, }) + }) + }) + } + }) + + test.describe('Link', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--link', + globals: { + colorScheme: theme, + }, + }) // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Large.png`) + expect(await page.screenshot()).toMatchSnapshot(`Button.Link.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button-features--link', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) }) }) + } + }) - test.describe('Leading Visual', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--leading-visual', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Leading Visual.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button-features--leading-visual', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test.describe('Large', () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--large', }) - test.describe('Medium', () => { + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Button.Large.png`) + }) + }) + + test.describe('Leading Visual', () => { + for (const theme of themes) { + test.describe(theme, () => { test('default @vrt', async ({page}) => { await visit(page, { - id: 'components-button-features--medium', + id: 'components-button-features--leading-visual', globals: { - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, + colorScheme: theme, }, }) // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Medium.png`) + expect(await page.screenshot()).toMatchSnapshot(`Button.Leading Visual.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button-features--leading-visual', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) }) }) + } + }) - test.describe('Primary', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--primary', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Primary.${theme}.png`) - }) - - test.fixme('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button-features--primary', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test.describe('Medium', () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--medium', }) - test.describe('Small', () => { + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Button.Medium.png`) + }) + }) + + test.describe('Primary', () => { + for (const theme of themes) { + test.describe(theme, () => { test('default @vrt', async ({page}) => { await visit(page, { - id: 'components-button-features--small', + id: 'components-button-features--primary', globals: { - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, + colorScheme: theme, }, }) // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Small.png`) + expect(await page.screenshot()).toMatchSnapshot(`Button.Primary.${theme}.png`) + }) + + test.fixme('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button-features--primary', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) }) }) + } + }) - test.describe('Trailing Action', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--trailing-action', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Trailing Action.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button-features--trailing-action', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test.describe('Small', () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--small', }) - test.describe('Trailing Counter', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--trailing-counter', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Trailing Counter.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button-features--trailing-counter', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Button.Small.png`) + }) + }) + + test.describe('Trailing Action', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--trailing-action', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Button.Trailing Action.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button-features--trailing-action', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) + }) + } + }) + + test.describe('Trailing Counter', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--trailing-counter', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Button.Trailing Counter.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button-features--trailing-counter', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) - test.describe('Trailing Visual', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--trailing-visual', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Trailing Visual.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button-features--trailing-visual', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test.describe('Trailing Visual', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--trailing-visual', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Button.Trailing Visual.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button-features--trailing-visual', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) - test.describe('Inactive', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--inactive', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Inactive.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button-features--inactive', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test.describe('Inactive', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--inactive', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Button.Inactive.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button-features--inactive', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) - test.describe('Loading', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--loading', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(`Button.Loading.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button-features--loading', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test.describe('Loading', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--loading', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(`Button.Loading.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button-features--loading', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Loading With Leading Visual', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--loading-with-leading-visual', + globals: { + colorScheme: theme, + }, + }) - test.describe('Loading With Leading Visual', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--loading-with-leading-visual', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( - `Button.Loading With Leading Visual.${theme}.png`, - ) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button-features--loading-with-leading-visual', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + // Default state + expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( + `Button.Loading With Leading Visual.${theme}.png`, + ) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button-features--loading-with-leading-visual', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) - test.describe('Loading With Trailing Visual', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--loading-with-trailing-visual', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( - `Button.Loading With Trailing Visual.${theme}.png`, - ) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button-features--loading-with-trailing-visual', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test.describe('Loading With Trailing Visual', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--loading-with-trailing-visual', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( + `Button.Loading With Trailing Visual.${theme}.png`, + ) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button-features--loading-with-trailing-visual', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) - test.describe('Loading With Trailing Action', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--loading-with-trailing-action', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( - `Button.Loading With Trailing Action.${theme}.png`, - ) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-button-features--loading-with-trailing-action', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test.describe('Loading With Trailing Action', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--loading-with-trailing-action', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( + `Button.Loading With Trailing Action.${theme}.png`, + ) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-button-features--loading-with-trailing-action', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) - test.describe('Dev: Invisible Variants', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-devonly--invisible-variants', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.Invisible Variants.${theme}.png`) - }) - }) - } + test.describe('Dev: Invisible Variants', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-devonly--invisible-variants', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Button.Invisible Variants.${theme}.png`) + }) }) + } + }) - test.describe('Dev: sx prop', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-devonly--test-sx-prop', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Button.sx prop.${theme}.png`) - }) - }) - } + test.describe('Dev: sx prop', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-devonly--test-sx-prop', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Button.sx prop.${theme}.png`) + }) }) + } + }) + + test.describe('Aria expanded buttons', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-button-features--expanded-button', + globals: { + colorScheme: theme, + }, + }) - test.describe('Aria expanded buttons', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-button-features--expanded-button', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( - `Button.Aria expanded buttons.${theme}.png`, - ) - }) - - // temporarily disabled due to a bug in primer/primitves - - // eslint-disable-next-line jest/no-commented-out-tests - // test('axe @aat', async ({page}) => { - // await visit(page, { - // id: 'components-button-features--expanded-button', - // globals: { - // colorScheme: theme, - // featureFlags: { - // primer_react_css_modules_staff: featureFlagOn, - // }, - // }, - // }) - // await expect(page).toHaveNoViolations({ - // rules: { - // 'color-contrast': { - // enabled: theme !== 'dark_dimmed', - // }, - // }, - // }) - // }) - }) - } + // Default state + expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( + `Button.Aria expanded buttons.${theme}.png`, + ) + }) + + // temporarily disabled due to a bug in primer/primitves + + // eslint-disable-next-line jest/no-commented-out-tests + // test('axe @aat', async ({page}) => { + // await visit(page, { + // id: 'components-button-features--expanded-button', + // globals: { + // colorScheme: theme, + // }, + // }) + // await expect(page).toHaveNoViolations({ + // rules: { + // 'color-contrast': { + // enabled: theme !== 'dark_dimmed', + // }, + // }, + // }) + // }) }) - }) - } + } + }) }) diff --git a/e2e/components/ButtonGroup.test.ts b/e2e/components/ButtonGroup.test.ts index 4fdcd7ab984..c3ca9822ff7 100644 --- a/e2e/components/ButtonGroup.test.ts +++ b/e2e/components/ButtonGroup.test.ts @@ -11,24 +11,6 @@ test.describe('ButtonGroup', () => { id: 'components-buttongroup--default', globals: { colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: true, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`ButtonGroup.Default.${theme}.png`) - }) - - test('default @vrt (styled-components)', async ({page}) => { - await visit(page, { - id: 'components-buttongroup--default', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: false, - }, }, }) @@ -41,22 +23,6 @@ test.describe('ButtonGroup', () => { id: 'components-buttongroup--default', globals: { colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: true, - }, - }, - }) - await expect(page).toHaveNoViolations() - }) - - test('axe @aat (styled-components)', async ({page}) => { - await visit(page, { - id: 'components-buttongroup--default', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: false, - }, }, }) await expect(page).toHaveNoViolations() @@ -73,24 +39,6 @@ test.describe('ButtonGroup', () => { id: 'components-buttongroup--playground', globals: { colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: true, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`ButtonGroup.Playground.${theme}.png`) - }) - - test('default @vrt (styled-components)', async ({page}) => { - await visit(page, { - id: 'components-buttongroup--playground', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: false, - }, }, }) @@ -103,22 +51,6 @@ test.describe('ButtonGroup', () => { id: 'components-buttongroup--playground', globals: { colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: true, - }, - }, - }) - await expect(page).toHaveNoViolations() - }) - - test('axe @aat (styled-components)', async ({page}) => { - await visit(page, { - id: 'components-buttongroup--playground', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: false, - }, }, }) await expect(page).toHaveNoViolations() @@ -135,24 +67,6 @@ test.describe('ButtonGroup', () => { id: 'components-buttongroup-features--icon-buttons', globals: { colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: true, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`ButtonGroup.Icon Buttons.${theme}.png`) - }) - - test('default @vrt (styled-components)', async ({page}) => { - await visit(page, { - id: 'components-buttongroup-features--icon-buttons', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: false, - }, }, }) @@ -165,22 +79,6 @@ test.describe('ButtonGroup', () => { id: 'components-buttongroup-features--icon-buttons', globals: { colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: true, - }, - }, - }) - await expect(page).toHaveNoViolations() - }) - - test('axe @aat (styled-components)', async ({page}) => { - await visit(page, { - id: 'components-buttongroup-features--icon-buttons', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: false, - }, }, }) await expect(page).toHaveNoViolations() diff --git a/e2e/components/Checkbox.test.ts b/e2e/components/Checkbox.test.ts index a3ae857d7ca..68bdc98193f 100644 --- a/e2e/components/Checkbox.test.ts +++ b/e2e/components/Checkbox.test.ts @@ -42,33 +42,6 @@ test.describe('Checkbox', () => { id: story.id, globals: { colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: true, - }, - }, - args: 'args' in story ? story.args : {}, - }) - - // Default state - expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( - `Checkbox.${story.title}.${theme}.png`, - ) - - // Focus state - await page.keyboard.press('Tab') - expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( - `Checkbox.${story.title}.focus.${theme}.png`, - ) - }) - - test('default (styled-components) @vrt', async ({page}) => { - await visit(page, { - id: story.id, - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: false, - }, }, args: 'args' in story ? story.args : {}, }) @@ -90,21 +63,6 @@ test.describe('Checkbox', () => { id: story.id, globals: { colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: true, - }, - }, - args: 'args' in story ? story.args : {}, - }) - await expect(page).toHaveNoViolations() - }) - - test('axe (styled-components) @aat', async ({page}) => { - await visit(page, { - id: story.id, - globals: { - colorScheme: theme, - primer_react_css_modules_team: false, }, args: 'args' in story ? story.args : {}, }) diff --git a/e2e/components/CounterLabel.test.ts b/e2e/components/CounterLabel.test.ts index 7933b5b4597..c3945c74083 100644 --- a/e2e/components/CounterLabel.test.ts +++ b/e2e/components/CounterLabel.test.ts @@ -27,24 +27,6 @@ test.describe('CounterLabel', () => { id: story.id, globals: { colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: true, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`CounterLabel.${story.title}.${theme}.png`) - }) - - test('default (styled-components) @vrt', async ({page}) => { - await visit(page, { - id: story.id, - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: false, - }, }, }) @@ -57,22 +39,6 @@ test.describe('CounterLabel', () => { id: story.id, globals: { colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: true, - }, - }, - }) - await expect(page).toHaveNoViolations() - }) - - test('axe (styled-components) @aat', async ({page}) => { - await visit(page, { - id: story.id, - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_team: false, - }, }, }) await expect(page).toHaveNoViolations() diff --git a/e2e/components/IconButton.test.ts b/e2e/components/IconButton.test.ts index e045f5a4c15..86a6b3d1c26 100644 --- a/e2e/components/IconButton.test.ts +++ b/e2e/components/IconButton.test.ts @@ -3,442 +3,372 @@ import {visit} from '../test-helpers/storybook' import {themes} from '../test-helpers/themes' test.describe('IconButton', () => { - for (const featureFlagOn of [true, false]) { - test.describe(`Feature flag: ${featureFlagOn ? 'on' : 'off'}`, () => { - test.describe('Playground', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton--playground', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Playground.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton--playground', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test.describe('Playground', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton--playground', + globals: { + colorScheme: theme, + }, }) - } + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Playground.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton--playground', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Danger', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--danger', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Danger.${theme}.png`) + }) - test.describe('Danger', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--danger', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Danger.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--danger', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--danger', + globals: { + colorScheme: theme, + }, }) - } + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Default', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton--default', + globals: { + colorScheme: theme, + }, + }) - test.describe('Default', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton--default', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Default.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton--default', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Default.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton--default', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, }) - } + }) }) + } + }) + + test.describe('Disabled', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--disabled', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Disabled.${theme}.png`) + }) - test.describe('Disabled', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--disabled', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Disabled.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--disabled', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--disabled', + globals: { + colorScheme: theme, + }, }) - } + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Invisible', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--invisible', + globals: { + colorScheme: theme, + }, + }) - test.describe('Invisible', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--invisible', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Invisible.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--invisible', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Invisible.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--invisible', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, }) - } + }) }) + } + }) + + test.describe('Large', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--large', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Large.${theme}.png`) + }) - test.describe('Large', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--large', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Large.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--large', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--large', + globals: { + colorScheme: theme, + }, }) - } + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Medium', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--medium', + globals: { + colorScheme: theme, + }, + }) - test.describe('Medium', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--medium', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Medium.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--medium', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Medium.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--medium', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, }) - } + }) }) + } + }) + + test.describe('Primary', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--primary', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Primary.${theme}.png`) + }) - test.describe('Primary', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--primary', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Primary.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--primary', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--primary', + globals: { + colorScheme: theme, + }, }) - } + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Small', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--small', + globals: { + colorScheme: theme, + }, + }) - test.describe('Small', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--small', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Small.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--small', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Small.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--small', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, }) - } + }) }) - test.describe('Keyshortcuts', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--keyshortcuts', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - await page.keyboard.press('Tab') // focus on icon button - expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( - `IconButton.Keyshortcuts.${theme}.png`, - ) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--keyshortcuts', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await page.keyboard.press('Tab') // focus on icon button - await expect(page).toHaveNoViolations() - }) + } + }) + test.describe('Keyshortcuts', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--keyshortcuts', + globals: { + colorScheme: theme, + }, }) - } + + // Default state + await page.keyboard.press('Tab') // focus on icon button + expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( + `IconButton.Keyshortcuts.${theme}.png`, + ) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--keyshortcuts', + globals: { + colorScheme: theme, + }, + }) + await page.keyboard.press('Tab') // focus on icon button + await expect(page).toHaveNoViolations() + }) }) + } + }) + + test.describe('Keyshortcuts on Description', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--keyshortcuts-on-description', + globals: { + colorScheme: theme, + }, + }) - test.describe('Keyshortcuts on Description', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--keyshortcuts-on-description', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - await page.keyboard.press('Tab') // focus on icon button - expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( - `IconButton.Keyshortcuts on Description.${theme}.png`, - ) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--keyshortcuts-on-description', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await page.keyboard.press('Tab') // focus on icon button - await expect(page).toHaveNoViolations() - }) + // Default state + await page.keyboard.press('Tab') // focus on icon button + expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( + `IconButton.Keyshortcuts on Description.${theme}.png`, + ) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--keyshortcuts-on-description', + globals: { + colorScheme: theme, + }, }) - } + await page.keyboard.press('Tab') // focus on icon button + await expect(page).toHaveNoViolations() + }) }) - }) - } + } + }) }) diff --git a/e2e/components/Label.test.ts b/e2e/components/Label.test.ts index e54f64022d3..b28b9f7fffb 100644 --- a/e2e/components/Label.test.ts +++ b/e2e/components/Label.test.ts @@ -3,527 +3,445 @@ import {visit} from '../test-helpers/storybook' import {themes} from '../test-helpers/themes' test.describe('Label', () => { - for (const enabled of [true, false]) { - test.describe(`Feature flag enabled: ${enabled}`, () => { - test.describe('Default', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-label--default', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Label.Default.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-label--default', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test.describe('Default', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-label--default', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Label.Default.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-label--default', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Playground', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-label--playground', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Label.Playground.${theme}.png`) + }) - test.describe('Playground', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-label--playground', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Label.Playground.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-label--playground', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-label--playground', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Accent', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-label-features--accent', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Label.Accent.${theme}.png`) + }) - test.describe('Accent', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-label-features--accent', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Label.Accent.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-label-features--accent', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-label-features--accent', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Attention', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-label-features--attention', + globals: { + colorScheme: theme, + }, + }) - test.describe('Attention', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-label-features--attention', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Label.Attention.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-label-features--attention', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Label.Attention.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-label-features--attention', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Danger', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-label-features--danger', + globals: { + colorScheme: theme, + }, + }) - test.describe('Danger', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-label-features--danger', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Label.Danger.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-label-features--danger', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Label.Danger.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-label-features--danger', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Done', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-label-features--done', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Label.Done.${theme}.png`) + }) - test.describe('Done', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-label-features--done', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Label.Done.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-label-features--done', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-label-features--done', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Primary', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-label-features--primary', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Label.Primary.${theme}.png`) + }) - test.describe('Primary', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-label-features--primary', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Label.Primary.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-label-features--primary', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-label-features--primary', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Secondary', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-label-features--secondary', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Label.Secondary.${theme}.png`) + }) - test.describe('Secondary', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-label-features--secondary', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Label.Secondary.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-label-features--secondary', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-label-features--secondary', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Severe', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-label-features--severe', + globals: { + colorScheme: theme, + }, + }) - test.describe('Severe', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-label-features--severe', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Label.Severe.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-label-features--severe', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Label.Severe.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-label-features--severe', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Size Large', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-label-features--size-large', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Label.Size Large.${theme}.png`) + }) - test.describe('Size Large', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-label-features--size-large', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Label.Size Large.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-label-features--size-large', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-label-features--size-large', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Size Small', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-label-features--size-small', + globals: { + colorScheme: theme, + }, + }) - test.describe('Size Small', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-label-features--size-small', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Label.Size Small.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-label-features--size-small', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Label.Size Small.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-label-features--size-small', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Sponsors', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-label-features--sponsors', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Label.Sponsors.${theme}.png`) + }) - test.describe('Sponsors', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-label-features--sponsors', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Label.Sponsors.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-label-features--sponsors', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-label-features--sponsors', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Success', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-label-features--success', + globals: { + colorScheme: theme, + }, + }) - test.describe('Success', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-label-features--success', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Label.Success.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-label-features--success', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: enabled, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Label.Success.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-label-features--success', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) - }) - } + } + }) }) diff --git a/e2e/components/Link.test.ts b/e2e/components/Link.test.ts index 19a1b60d470..692444882f2 100644 --- a/e2e/components/Link.test.ts +++ b/e2e/components/Link.test.ts @@ -31,9 +31,6 @@ test.describe('Link', () => { id: story.id, globals: { colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: true, - }, }, }) @@ -50,39 +47,6 @@ test.describe('Link', () => { }) test('axe @aat', async ({page}) => { - await visit(page, { - id: story.id, - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_ga: true, - }, - }, - }) - await expect(page).toHaveNoViolations() - }) - - test('default (styled-component) @vrt', async ({page}) => { - await visit(page, { - id: story.id, - globals: { - colorScheme: theme, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Link.${story.title}.${theme}.png`) - - // Hover state - await page.getByRole('link').hover() - expect(await page.screenshot()).toMatchSnapshot(`Link.${story.title}.${theme}.hover.png`) - - // Focus state - await page.keyboard.press('Tab') - expect(await page.screenshot()).toMatchSnapshot(`Link.${story.title}.${theme}.focus.png`) - }) - - test('axe (styled-component) @aat', async ({page}) => { await visit(page, { id: story.id, globals: { diff --git a/e2e/components/LinkButton.test.ts b/e2e/components/LinkButton.test.ts index eea305787fc..98a92c22704 100644 --- a/e2e/components/LinkButton.test.ts +++ b/e2e/components/LinkButton.test.ts @@ -3,447 +3,377 @@ import {visit} from '../test-helpers/storybook' import {themes} from '../test-helpers/themes' test.describe('LinkButton', () => { - for (const featureFlagOn of [true, false]) { - test.describe(`Feature flag: ${featureFlagOn ? 'on' : 'off'}`, () => { - test.describe('Playground', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton--playground', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Playground.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton--playground', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test.describe('Playground', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton--playground', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Playground.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton--playground', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Danger', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--danger', + globals: { + colorScheme: theme, + }, + }) - test.describe('Danger', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--danger', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Danger.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--danger', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Danger.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--danger', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Default', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton--default', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Default.${theme}.png`) + }) - test.describe('Default', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton--default', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Default.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton--default', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton--default', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Invisible', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--invisible', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Invisible.${theme}.png`) + }) - test.describe('Invisible', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--invisible', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Invisible.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--invisible', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--invisible', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Large', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--large', + globals: { + colorScheme: theme, + }, + }) - test.describe('Large', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--large', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Large.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--large', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Large.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--large', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Leading Visual', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--leading-visual', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Leading Visual.${theme}.png`) + }) - test.describe('Leading Visual', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--leading-visual', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Leading Visual.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--leading-visual', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--leading-visual', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Medium', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--medium', + globals: { + colorScheme: theme, + }, + }) - test.describe('Medium', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--medium', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Medium.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--medium', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Medium.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--medium', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Primary', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--primary', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Primary.${theme}.png`) + }) - test.describe('Primary', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--primary', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Primary.${theme}.png`) - }) - - test.fixme('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--primary', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test.fixme('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--primary', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Small', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--small', + globals: { + colorScheme: theme, + }, + }) - test.describe('Small', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--small', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Small.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--small', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Small.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--small', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('Trailing Visual', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--trailing-visual', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Trailing Visual.${theme}.png`) + }) - test.describe('Trailing Visual', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--trailing-visual', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Trailing Visual.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--trailing-visual', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--trailing-visual', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) + } + }) + + test.describe('With React Router', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--with-react-router', + globals: { + colorScheme: theme, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.With React Router.${theme}.png`) + }) - test.describe('With React Router', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--with-react-router', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.With React Router.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--with-react-router', - globals: { - colorScheme: theme, - featureFlags: { - primer_react_css_modules_staff: featureFlagOn, - }, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) - }) - } + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--with-react-router', + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) - }) - } + } + }) }) diff --git a/e2e/components/Octicon.test.ts b/e2e/components/Octicon.test.ts index ce0cf701146..a5862af1fa5 100644 --- a/e2e/components/Octicon.test.ts +++ b/e2e/components/Octicon.test.ts @@ -2,60 +2,45 @@ import {test, expect} from '@playwright/test' import {visit} from '../test-helpers/storybook' import {themes} from '../test-helpers/themes' -test.describe('Octicon', () => { - test.describe('Default', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-octicon--default', - globals: { - colorScheme: theme, - }, - }) +const stories = [ + { + title: 'Default', + id: 'deprecated-components-octicon--default', + }, + { + title: 'Playground', + id: 'deprecated-components-octicon--playground', + }, +] as const - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Octicon.Default.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-octicon--default', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations() - }) - }) - } - }) +test.describe('Octicon', () => { + for (const story of stories) { + test.describe(story.title, () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: story.id, + globals: { + colorScheme: theme, + }, + }) - test.describe('Playground', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-octicon--playground', - globals: { - colorScheme: theme, - }, + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Octicon.${story.title}.${theme}.png`) }) - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Octicon.Playground.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-octicon--playground', - globals: { - colorScheme: theme, - }, + test('axe @aat', async ({page}) => { + await visit(page, { + id: story.id, + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations() }) - await expect(page).toHaveNoViolations() }) - }) - } - }) + } + }) + } }) diff --git a/e2e/components/Pagehead.test.ts b/e2e/components/Pagehead.test.ts index 00f077d663b..550f0887451 100644 --- a/e2e/components/Pagehead.test.ts +++ b/e2e/components/Pagehead.test.ts @@ -2,32 +2,41 @@ import {test, expect} from '@playwright/test' import {visit} from '../test-helpers/storybook' import {themes} from '../test-helpers/themes' +const stories = [ + { + title: 'Default', + id: 'deprecated-components-pagehead--default', + }, +] as const + test.describe('Pagehead', () => { - test.describe('Default', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-pagehead--default', - globals: { - colorScheme: theme, - }, - }) + for (const story of stories) { + test.describe(story.id, () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: story.id, + globals: { + colorScheme: theme, + }, + }) - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Pagehead.Default.${theme}.png`) - }) + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Pagehead.${story.title}.${theme}.png`) + }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-pagehead--default', - globals: { - colorScheme: theme, - }, + test('axe @aat', async ({page}) => { + await visit(page, { + id: story.id, + globals: { + colorScheme: theme, + }, + }) + await expect(page).toHaveNoViolations() }) - await expect(page).toHaveNoViolations() }) - }) - } - }) + } + }) + } }) diff --git a/e2e/components/TabNav.test.ts b/e2e/components/TabNav.test.ts index a896f2f1808..98fc71ba1c0 100644 --- a/e2e/components/TabNav.test.ts +++ b/e2e/components/TabNav.test.ts @@ -2,38 +2,41 @@ import {test, expect} from '@playwright/test' import {visit} from '../test-helpers/storybook' import {themes} from '../test-helpers/themes' -test.describe('TabNav', () => { - test.describe('Default', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-tabnav--default', - globals: { - colorScheme: theme, - }, - }) +const stories = [ + { + title: 'Default', + id: 'deprecated-components-tabnav--default', + }, +] as const - // Default state - expect(await page.screenshot()).toMatchSnapshot(`TabNav.Default.${theme}.png`) - }) +test.describe('TabNav', () => { + for (const story of stories) { + test.describe(story.title, () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: story.id, + globals: { + colorScheme: theme, + }, + }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-tabnav--default', - globals: { - colorScheme: theme, - }, + // Default state + expect(await page.screenshot()).toMatchSnapshot(`TabNav.${story.title}.${theme}.png`) }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', + + test('axe @aat', async ({page}) => { + await visit(page, { + id: story.id, + globals: { + colorScheme: theme, }, - }, + }) + await expect(page).toHaveNoViolations() }) }) - }) - } - }) + } + }) + } }) diff --git a/e2e/components/Text.test.ts b/e2e/components/Text.test.ts index e039bac12c4..031a4adf876 100644 --- a/e2e/components/Text.test.ts +++ b/e2e/components/Text.test.ts @@ -44,25 +44,6 @@ test.describe('Text', () => { test('default @vrt', async ({page}) => { await visit(page, { id: story.id, - globals: { - featureFlags: { - primer_react_css_modules_ga: true, - }, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`Text.${story.title}.png`) - }) - - test('default (styled-system) @vrt', async ({page}) => { - await visit(page, { - id: story.id, - globals: { - featureFlags: { - primer_react_css_modules_ga: false, - }, - }, }) // Default state @@ -72,23 +53,6 @@ test.describe('Text', () => { test('axe @aat', async ({page}) => { await visit(page, { id: story.id, - globals: { - featureFlags: { - primer_react_css_modules_ga: true, - }, - }, - }) - await expect(page).toHaveNoViolations() - }) - - test('axe (styled-system) @aat', async ({page}) => { - await visit(page, { - id: story.id, - globals: { - featureFlags: { - primer_react_css_modules_ga: false, - }, - }, }) await expect(page).toHaveNoViolations() }) diff --git a/e2e/components/Tooltip.test.ts b/e2e/components/Tooltip.test.ts index 38bca6c51d1..27910acd8cf 100644 --- a/e2e/components/Tooltip.test.ts +++ b/e2e/components/Tooltip.test.ts @@ -8,7 +8,7 @@ test.describe('Tooltip', () => { test.describe(theme, () => { test('default @vrt', async ({page}) => { await visit(page, { - id: 'components-tooltip--default', + id: 'deprecated-components-tooltip--default', globals: { colorScheme: theme, }, @@ -21,7 +21,7 @@ test.describe('Tooltip', () => { test('axe @aat', async ({page}) => { await visit(page, { - id: 'components-tooltip--default', + id: 'deprecated-components-tooltip--default', globals: { colorScheme: theme, }, diff --git a/examples/app-router/package.json b/examples/app-router/package.json index 176da19b8a1..f760501a4fa 100644 --- a/examples/app-router/package.json +++ b/examples/app-router/package.json @@ -10,7 +10,7 @@ "type-check": "tsc --noEmit" }, "dependencies": { - "@primer/react": "37.0.0-rc.6", + "@primer/react": "37.0.0-rc.10", "next": "^14.2.10", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/examples/codesandbox/package.json b/examples/codesandbox/package.json index f7c9082c722..e12ea6dd6a1 100644 --- a/examples/codesandbox/package.json +++ b/examples/codesandbox/package.json @@ -20,7 +20,7 @@ "@typescript-eslint/eslint-plugin": "^7.11.0", "@typescript-eslint/parser": "^7.3.1", "@vitejs/plugin-react": "^4.2.1", - "@primer/react": "37.0.0-rc.6", + "@primer/react": "37.0.0-rc.10", "eslint": "^8.56.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.7", diff --git a/examples/consumer-test/package.json b/examples/consumer-test/package.json index 7778c88a9ee..91858def69d 100644 --- a/examples/consumer-test/package.json +++ b/examples/consumer-test/package.json @@ -9,7 +9,7 @@ "@types/react": "^18.2.14", "@types/react-dom": "^18.2.19", "@types/styled-components": "^5.1.11", - "@primer/react": "37.0.0-rc.6", + "@primer/react": "37.0.0-rc.10", "react": "^18.0.0", "react-dom": "^18.0.0", "styled-components": "^5.3.11", diff --git a/examples/theming/package.json b/examples/theming/package.json index 7fbb77f9f4a..1ed3680e828 100644 --- a/examples/theming/package.json +++ b/examples/theming/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@primer/octicons-react": "^19.9.0", - "@primer/react": "37.0.0-rc.6", + "@primer/react": "37.0.0-rc.10", "clsx": "^1.2.1", "next": "^14.2.10", "react": "^18.3.1", diff --git a/package-lock.json b/package-lock.json index 17cb868d1f7..6570545e8f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@github/markdownlint-github": "^0.6.0", "@github/prettier-config": "0.0.6", "@mdx-js/react": "1.6.22", - "@playwright/test": "1.43.0", + "@playwright/test": "^1.47.2", "@prettier/sync": "0.5.1", "@primer/stylelint-config": "^13.0.1-rc.5358628", "@size-limit/preset-big-lib": "11.0.2", @@ -31,7 +31,7 @@ "eslint-plugin-github": "5.0.1", "eslint-plugin-jest": "28.8.3", "eslint-plugin-jsx-a11y": "6.7.1", - "eslint-plugin-mdx": "3.0.0", + "eslint-plugin-mdx": "3.1.5", "eslint-plugin-playwright": "0.15.1", "eslint-plugin-prettier": "5.0.0", "eslint-plugin-primer-react": "5.4.0", @@ -40,7 +40,7 @@ "eslint-plugin-ssr-friendly": "1.3.0", "eslint-plugin-storybook": "0.8.0", "eslint-plugin-testing-library": "6.0.2", - "husky": "8.0.3", + "husky": "9.1.6", "jest": "29.7.0", "jest-watch-typeahead": "2.2.2", "lint-staged": "15.2.2", @@ -64,7 +64,7 @@ "name": "example-app-router", "version": "0.0.0", "dependencies": { - "@primer/react": "37.0.0-rc.6", + "@primer/react": "37.0.0-rc.10", "next": "^14.2.10", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -83,7 +83,7 @@ "react-dom": "^18.3.1" }, "devDependencies": { - "@primer/react": "37.0.0-rc.6", + "@primer/react": "37.0.0-rc.10", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.11.0", @@ -101,7 +101,7 @@ "name": "example-consumer-test", "version": "0.0.0", "dependencies": { - "@primer/react": "37.0.0-rc.6", + "@primer/react": "37.0.0-rc.10", "@types/react": "^18.2.14", "@types/react-dom": "^18.2.19", "@types/styled-components": "^5.1.11", @@ -127,7 +127,7 @@ "version": "0.0.0", "dependencies": { "@primer/octicons-react": "^19.9.0", - "@primer/react": "37.0.0-rc.6", + "@primer/react": "37.0.0-rc.10", "clsx": "^1.2.1", "next": "^14.2.10", "react": "^18.3.1", @@ -6012,16 +6012,18 @@ } }, "node_modules/@npmcli/config": { - "version": "8.0.3", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@npmcli/config/-/config-8.3.4.tgz", + "integrity": "sha512-01rtHedemDNhUXdicU7s+QYz/3JyV5Naj84cvdXGH4mgCdL+agmSYaLF4LUG4vMCLzhBO8YtS0gPpH1FGvbgAw==", "dev": true, "license": "ISC", "dependencies": { "@npmcli/map-workspaces": "^3.0.2", + "@npmcli/package-json": "^5.1.1", "ci-info": "^4.0.0", - "ini": "^4.1.0", - "nopt": "^7.0.0", - "proc-log": "^3.0.0", - "read-package-json-fast": "^3.0.2", + "ini": "^4.1.2", + "nopt": "^7.2.1", + "proc-log": "^4.2.0", "semver": "^7.3.5", "walk-up-path": "^3.0.1" }, @@ -6031,6 +6033,8 @@ }, "node_modules/@npmcli/config/node_modules/ci-info": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", + "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", "dev": true, "funding": [ { @@ -6045,14 +6049,82 @@ }, "node_modules/@npmcli/config/node_modules/ini": { "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", "dev": true, "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/@npmcli/git": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.8.tgz", + "integrity": "sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/promise-spawn": "^7.0.0", + "ini": "^4.1.3", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^9.0.0", + "proc-log": "^4.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/ini": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, "node_modules/@npmcli/map-workspaces": { - "version": "3.0.4", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-3.0.6.tgz", + "integrity": "sha512-tkYs0OYnzQm6iIRdfy+LcLBjcKuQCeE5YLb8KnrIlutJfheNaPvPpgoFEyEFgbjzl5PLZ3IA/BWAwRU0eHuQDA==", "dev": true, "license": "ISC", "dependencies": { @@ -6067,6 +6139,8 @@ }, "node_modules/@npmcli/map-workspaces/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "license": "MIT", "dependencies": { @@ -6075,6 +6149,8 @@ }, "node_modules/@npmcli/map-workspaces/node_modules/glob": { "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "license": "ISC", "dependencies": { @@ -6094,6 +6170,8 @@ }, "node_modules/@npmcli/map-workspaces/node_modules/jackspeak": { "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -6108,6 +6186,8 @@ }, "node_modules/@npmcli/map-workspaces/node_modules/minimatch": { "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "license": "ISC", "dependencies": { @@ -6122,14 +6202,184 @@ }, "node_modules/@npmcli/name-from-folder": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz", + "integrity": "sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==", "dev": true, "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/@npmcli/package-json": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.2.1.tgz", + "integrity": "sha512-f7zYC6kQautXHvNbLEWgD/uGu1+xCn9izgqBfgItWSx22U0ZDekxN08A1vM8cTxj/cRVe0Q94Ode+tdoYmIOOQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.0", + "glob": "^10.2.2", + "hosted-git-info": "^7.0.0", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "proc-log": "^4.0.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/package-json/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/json-parse-even-better-errors": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@npmcli/package-json/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/package-json/node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz", + "integrity": "sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, "node_modules/@oddbird/popover-polyfill": { - "version": "0.3.8", + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@oddbird/popover-polyfill/-/popover-polyfill-0.4.4.tgz", + "integrity": "sha512-n9q0ZXYRct6aYmOjjF5E+i5i0RSjVCkoKDJWILzJAkDBk4jmWOAZFjQfExtcAiJa0buX/Lx/CzBdGgiSSAlbrw==", "license": "BSD-3-Clause" }, "node_modules/@pkgjs/parseargs": { @@ -6140,6 +6390,19 @@ "node": ">=14" } }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@pkgr/utils": { "version": "2.4.2", "dev": true, @@ -6206,17 +6469,19 @@ } }, "node_modules/@playwright/test": { - "version": "1.43.0", + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.2.tgz", + "integrity": "sha512-jTXRsoSPONAs8Za9QEQdyjFn+0ZQFjCiIztAIF6bi1HqhBzG9Ma7g1WotyiGqFSBRZjIEqMdT8RUlbk1QVhzCQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.43.0" + "playwright": "1.47.2" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/@prettier/sync": { @@ -6368,11 +6633,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@primer/view-components/node_modules/@oddbird/popover-polyfill": { - "version": "0.4.4", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/@puppeteer/browsers": { "version": "2.1.0", "dev": true, @@ -8601,6 +8861,8 @@ }, "node_modules/@types/concat-stream": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-2.0.3.tgz", + "integrity": "sha512-3qe4oQAPNwVNwK4C9c8u+VJqv9kez+2MR4qJpoPFfXtgxxif1QbFusvXzK0/Wra2VX07smostI2VMmJNSpZjuQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8705,6 +8967,8 @@ }, "node_modules/@types/is-empty": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/is-empty/-/is-empty-1.2.3.tgz", + "integrity": "sha512-4J1l5d79hoIvsrKh5VUKVRA1aIdsOb10Hu5j3J2VfP/msDnfTdGPmNp2E1Wg+vs97Bktzo+MZePFFXSGoykYJw==", "dev": true, "license": "MIT" }, @@ -8788,7 +9052,9 @@ "license": "MIT" }, "node_modules/@types/lodash.groupby": { - "version": "4.6.7", + "version": "4.6.9", + "resolved": "https://registry.npmjs.org/@types/lodash.groupby/-/lodash.groupby-4.6.9.tgz", + "integrity": "sha512-z2xtCX2ko7GrqORnnYea4+ksT7jZNAvaOcLd6mP9M7J09RHvJs06W8BGdQQAX8ARef09VQLdeRilSOcfHlDQJQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9001,6 +9267,8 @@ }, "node_modules/@types/supports-color": { "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@types/supports-color/-/supports-color-8.1.3.tgz", + "integrity": "sha512-Hy6UMpxhE3j1tLpl27exp1XqHD7n8chAiNPzWfz16LPZoMMoSc4dzLl6w9qijkEb/r5O1ozdu1CWGA2L83ZeZg==", "dev": true, "license": "MIT" }, @@ -9692,6 +9960,8 @@ }, "node_modules/abbrev": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", "dev": true, "license": "ISC", "engines": { @@ -10471,6 +10741,8 @@ }, "node_modules/bail": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", "dev": true, "license": "MIT", "funding": { @@ -11288,6 +11560,37 @@ "dev": true, "license": "MIT" }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/concat-with-sourcemaps": { "version": "1.1.0", "dev": true, @@ -12552,6 +12855,16 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/diff-sequences": { "version": "29.6.3", "dev": true, @@ -12912,6 +13225,13 @@ "node": ">=6" } }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true, + "license": "MIT" + }, "node_modules/errno": { "version": "0.1.8", "dev": true, @@ -13271,18 +13591,20 @@ } }, "node_modules/eslint-mdx": { - "version": "3.0.0", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/eslint-mdx/-/eslint-mdx-3.1.5.tgz", + "integrity": "sha512-ynztX0k7CQ3iDL7fDEIeg3g0O/d6QPv7IBI9fdYLhXp5fAp0fi8X22xF/D3+Pk0f90R27uwqa1clHpay6t0l8Q==", "dev": true, "license": "MIT", "dependencies": { - "acorn": "^8.11.2", + "acorn": "^8.11.3", "acorn-jsx": "^5.3.2", "espree": "^9.6.1", "estree-util-visit": "^2.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", - "synckit": "^0.8.6", + "synckit": "^0.9.0", "tslib": "^2.6.2", "unified": "^11.0.4", "unified-engine": "^11.2.0", @@ -13301,6 +13623,23 @@ "eslint": ">=8.0.0" } }, + "node_modules/eslint-mdx/node_modules/synckit": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/eslint-module-utils": { "version": "2.7.4", "dev": true, @@ -13720,11 +14059,13 @@ } }, "node_modules/eslint-plugin-mdx": { - "version": "3.0.0", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-mdx/-/eslint-plugin-mdx-3.1.5.tgz", + "integrity": "sha512-lUE7tP7IrIRHU3gTtASDe5u4YM2SvQveYVJfuo82yn3MLh/B/v05FNySURCK4aIxIYF1QYo3IRemQG/lyQzpAg==", "dev": true, "license": "MIT", "dependencies": { - "eslint-mdx": "^3.0.0", + "eslint-mdx": "^3.1.5", "eslint-plugin-markdown": "^3.0.1", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", @@ -14744,6 +15085,8 @@ }, "node_modules/extend": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true, "license": "MIT" }, @@ -15970,14 +16313,16 @@ } }, "node_modules/husky": { - "version": "8.0.3", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz", + "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==", "dev": true, "license": "MIT", "bin": { - "husky": "lib/bin.js" + "husky": "bin.js" }, "engines": { - "node": ">=14" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/typicode" @@ -16129,7 +16474,9 @@ } }, "node_modules/import-meta-resolve": { - "version": "4.0.0", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", "dev": true, "license": "MIT", "funding": { @@ -16394,6 +16741,8 @@ }, "node_modules/is-empty": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-empty/-/is-empty-1.2.0.tgz", + "integrity": "sha512-F2FnH/otLNJv0J6wc73A5Xo7oHLNnqplYqZhUu01tD54DIPvxIRSTSLkrUB/M0nHO4vo1O9PDfN4KoTxCzLh/w==", "dev": true, "license": "MIT" }, @@ -19634,7 +19983,9 @@ } }, "node_modules/load-plugin": { - "version": "6.0.1", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/load-plugin/-/load-plugin-6.0.3.tgz", + "integrity": "sha512-kc0X2FEUZr145odl68frm+lMJuQ23+rTXYmR6TImqPtbpmXC4vVXbWKDQ9IzndA0HfyQamWfKLhzsqGSTxE63w==", "dev": true, "license": "MIT", "dependencies": { @@ -21881,6 +22232,8 @@ }, "node_modules/mri": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", "dev": true, "license": "MIT", "engines": { @@ -22158,7 +22511,9 @@ } }, "node_modules/nopt": { - "version": "7.2.0", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", "dev": true, "license": "ISC", "dependencies": { @@ -22216,14 +22571,81 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/npm-install-checks": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", + "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/npm-normalize-package-bin": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", "dev": true, "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/npm-package-arg": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.3.tgz", + "integrity": "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==", + "dev": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^7.0.0", + "proc-log": "^4.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/npm-pick-manifest": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.1.0.tgz", + "integrity": "sha512-nkc+3pIIhqHVQr085X9d2JzPzLyjzQS96zbruppqC9aZRm/x8xx6xhI98gHtsfELP2bE+loHq8ZaHFHhe+NauA==", + "dev": true, + "license": "ISC", + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^11.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "dev": true, @@ -22909,31 +23331,35 @@ } }, "node_modules/playwright": { - "version": "1.43.0", + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.2.tgz", + "integrity": "sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.43.0" + "playwright-core": "1.47.2" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { - "version": "1.43.0", + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.2.tgz", + "integrity": "sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==", "dev": true, "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/polished": { @@ -24640,7 +25066,9 @@ "license": "MIT" }, "node_modules/proc-log": { - "version": "3.0.0", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", "dev": true, "license": "ISC", "engines": { @@ -24668,6 +25096,27 @@ "node": ">=0.4.0" } }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/promise.series": { "version": "0.2.0", "dev": true, @@ -25145,6 +25594,8 @@ }, "node_modules/read-package-json-fast": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", "dev": true, "license": "ISC", "dependencies": { @@ -25157,6 +25608,8 @@ }, "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", "dev": true, "license": "MIT", "engines": { @@ -25414,6 +25867,8 @@ }, "node_modules/remark-mdx": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", + "integrity": "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==", "dev": true, "license": "MIT", "dependencies": { @@ -25427,6 +25882,8 @@ }, "node_modules/remark-parse": { "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", "dev": true, "license": "MIT", "dependencies": { @@ -25442,6 +25899,8 @@ }, "node_modules/remark-parse/node_modules/@types/mdast": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", "dev": true, "license": "MIT", "dependencies": { @@ -25450,6 +25909,8 @@ }, "node_modules/remark-stringify": { "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", "dev": true, "license": "MIT", "dependencies": { @@ -25464,6 +25925,8 @@ }, "node_modules/remark-stringify/node_modules/@types/mdast": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", "dev": true, "license": "MIT", "dependencies": { @@ -25564,6 +26027,16 @@ "node": ">=8" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "dev": true, @@ -26536,6 +27009,8 @@ }, "node_modules/sade": { "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", "dev": true, "license": "MIT", "dependencies": { @@ -28483,6 +28958,8 @@ }, "node_modules/trough": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", "dev": true, "license": "MIT", "funding": { @@ -28908,6 +29385,8 @@ }, "node_modules/typedarray": { "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "dev": true, "license": "MIT" }, @@ -29074,6 +29553,8 @@ }, "node_modules/unified": { "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", "dev": true, "license": "MIT", "dependencies": { @@ -29091,7 +29572,9 @@ } }, "node_modules/unified-engine": { - "version": "11.2.0", + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/unified-engine/-/unified-engine-11.2.1.tgz", + "integrity": "sha512-xBAdZ8UY2X4R9Hm6X6kMne4Nz0PlpOc1oE6DPeqJnewr5Imkb8uT5Eyvy1h7xNekPL3PSWh3ZJyNrMW6jnNQBg==", "dev": true, "license": "MIT", "dependencies": { @@ -29100,9 +29583,9 @@ "@types/is-empty": "^1.0.0", "@types/node": "^20.0.0", "@types/unist": "^3.0.0", - "@ungap/structured-clone": "^1.0.0", "concat-stream": "^2.0.0", "debug": "^4.0.0", + "extend": "^3.0.0", "glob": "^10.0.0", "ignore": "^5.0.0", "is-empty": "^1.0.0", @@ -29124,33 +29607,25 @@ }, "node_modules/unified-engine/node_modules/@types/unist": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "dev": true, "license": "MIT" }, "node_modules/unified-engine/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, - "node_modules/unified-engine/node_modules/concat-stream": { - "version": "2.0.0", - "dev": true, - "engines": [ - "node >= 6.0" - ], - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, "node_modules/unified-engine/node_modules/glob": { "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "license": "ISC", "dependencies": { @@ -29170,6 +29645,8 @@ }, "node_modules/unified-engine/node_modules/is-plain-obj": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "dev": true, "license": "MIT", "engines": { @@ -29181,6 +29658,8 @@ }, "node_modules/unified-engine/node_modules/jackspeak": { "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -29195,6 +29674,8 @@ }, "node_modules/unified-engine/node_modules/json-parse-even-better-errors": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", "dev": true, "license": "MIT", "engines": { @@ -29203,6 +29684,8 @@ }, "node_modules/unified-engine/node_modules/lines-and-columns": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", + "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", "dev": true, "license": "MIT", "engines": { @@ -29211,6 +29694,8 @@ }, "node_modules/unified-engine/node_modules/minimatch": { "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "license": "ISC", "dependencies": { @@ -29225,6 +29710,8 @@ }, "node_modules/unified-engine/node_modules/parse-json": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", + "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==", "dev": true, "license": "MIT", "dependencies": { @@ -29241,21 +29728,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/unified-engine/node_modules/readable-stream": { - "version": "3.6.2", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/unified-engine/node_modules/type-fest": { "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -29267,11 +29743,15 @@ }, "node_modules/unified/node_modules/@types/unist": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "dev": true, "license": "MIT" }, "node_modules/unified/node_modules/is-plain-obj": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "dev": true, "license": "MIT", "engines": { @@ -29342,7 +29822,9 @@ } }, "node_modules/unist-util-inspect": { - "version": "8.0.0", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/unist-util-inspect/-/unist-util-inspect-8.1.0.tgz", + "integrity": "sha512-mOlg8Mp33pR0eeFpo5d2902ojqFFOKMMG2hF8bmH7ZlhnmjFgh0NI3/ZDwdaBJNbvrS7LZFVrBVtIE9KZ9s7vQ==", "dev": true, "license": "MIT", "dependencies": { @@ -29355,6 +29837,8 @@ }, "node_modules/unist-util-inspect/node_modules/@types/unist": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "dev": true, "license": "MIT" }, @@ -29587,6 +30071,8 @@ }, "node_modules/uvu": { "version": "0.5.6", + "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", + "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", "dev": true, "license": "MIT", "dependencies": { @@ -29602,16 +30088,10 @@ "node": ">=8" } }, - "node_modules/uvu/node_modules/diff": { - "version": "5.2.0", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/uvu/node_modules/kleur": { "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "dev": true, "license": "MIT", "engines": { @@ -29640,6 +30120,16 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/vary": { "version": "1.1.2", "dev": true, @@ -29650,6 +30140,8 @@ }, "node_modules/vfile": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", "dev": true, "license": "MIT", "dependencies": { @@ -29692,7 +30184,9 @@ } }, "node_modules/vfile-reporter": { - "version": "8.1.0", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-8.1.1.tgz", + "integrity": "sha512-qxRZcnFSQt6pWKn3PAk81yLK2rO2i7CDXpy8v8ZquiEOMLSnPw6BMSi9Y1sUCwGGl7a9b3CJT1CKpnRF7pp66g==", "dev": true, "license": "MIT", "dependencies": { @@ -29712,11 +30206,15 @@ }, "node_modules/vfile-reporter/node_modules/@types/unist": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "dev": true, "license": "MIT" }, "node_modules/vfile-reporter/node_modules/ansi-regex": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "license": "MIT", "engines": { @@ -29728,11 +30226,15 @@ }, "node_modules/vfile-reporter/node_modules/emoji-regex": { "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "dev": true, "license": "MIT" }, "node_modules/vfile-reporter/node_modules/string-width": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-6.1.0.tgz", + "integrity": "sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -29749,6 +30251,8 @@ }, "node_modules/vfile-reporter/node_modules/strip-ansi": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "license": "MIT", "dependencies": { @@ -29763,6 +30267,8 @@ }, "node_modules/vfile-reporter/node_modules/supports-color": { "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", "dev": true, "license": "MIT", "engines": { @@ -29774,6 +30280,8 @@ }, "node_modules/vfile-reporter/node_modules/unist-util-stringify-position": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "dev": true, "license": "MIT", "dependencies": { @@ -29786,6 +30294,8 @@ }, "node_modules/vfile-sort": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-4.0.0.tgz", + "integrity": "sha512-lffPI1JrbHDTToJwcq0rl6rBmkjQmMuXkAxsZPRS9DXbaJQvc642eCg6EGxcX2i1L+esbuhq+2l9tBll5v8AeQ==", "dev": true, "license": "MIT", "dependencies": { @@ -29799,6 +30309,8 @@ }, "node_modules/vfile-statistics": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-3.0.0.tgz", + "integrity": "sha512-/qlwqwWBWFOmpXujL/20P+Iuydil0rZZNglR+VNm6J0gpLHwuVM5s7g2TfVoswbXjZ4HuIhLMySEyIw5i7/D8w==", "dev": true, "license": "MIT", "dependencies": { @@ -29812,6 +30324,8 @@ }, "node_modules/vfile/node_modules/@types/unist": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "dev": true, "license": "MIT" }, @@ -29947,6 +30461,8 @@ }, "node_modules/walk-up-path": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", + "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==", "dev": true, "license": "ISC" }, @@ -30605,17 +31121,17 @@ }, "packages/react": { "name": "@primer/react", - "version": "37.0.0-rc.6", + "version": "37.0.0-rc.10", "license": "MIT", "dependencies": { "@github/relative-time-element": "^4.4.2", "@github/tab-container-element": "^4.8.0", "@lit-labs/react": "1.2.1", - "@oddbird/popover-polyfill": "^0.3.1", + "@oddbird/popover-polyfill": "^0.4.4", "@primer/behaviors": "^1.7.2", "@primer/live-region-element": "^0.7.1", "@primer/octicons-react": "^19.9.0", - "@primer/primitives": "^9.0.3", + "@primer/primitives": "^9.1.2", "@styled-system/css": "^5.1.5", "@styled-system/props": "^5.1.5", "@styled-system/theme-get": "^5.1.2", @@ -30670,7 +31186,7 @@ "@testing-library/react": "^16.0.0", "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.5.2", - "@types/lodash.groupby": "4.6.7", + "@types/lodash.groupby": "4.6.9", "@types/lodash.isempty": "4.4.9", "@types/lodash.isobject": "3.0.9", "@types/lodash.keyby": "4.6.7", @@ -30776,7 +31292,9 @@ } }, "packages/react/node_modules/@primer/primitives": { - "version": "9.1.1", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@primer/primitives/-/primitives-9.1.2.tgz", + "integrity": "sha512-KecRJpUdIf14J3gVpoyMMJeQD6Sh5kcHk93N5bYch4XGB0GOZP3ypxz+NByMjr/2HHPsRfCCO5EEgNjmeWYUGQ==", "license": "MIT", "dependencies": { "@prettier/sync": "^0.5.2", diff --git a/package.json b/package.json index 63a3c2fbc27..8980675ba4e 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "@github/markdownlint-github": "^0.6.0", "@github/prettier-config": "0.0.6", "@mdx-js/react": "1.6.22", - "@playwright/test": "1.43.0", + "@playwright/test": "^1.47.2", "@prettier/sync": "0.5.1", "@primer/stylelint-config": "^13.0.1-rc.5358628", "@size-limit/preset-big-lib": "11.0.2", @@ -60,7 +60,7 @@ "eslint-plugin-github": "5.0.1", "eslint-plugin-jest": "28.8.3", "eslint-plugin-jsx-a11y": "6.7.1", - "eslint-plugin-mdx": "3.0.0", + "eslint-plugin-mdx": "3.1.5", "eslint-plugin-playwright": "0.15.1", "eslint-plugin-prettier": "5.0.0", "eslint-plugin-primer-react": "5.4.0", @@ -69,7 +69,7 @@ "eslint-plugin-ssr-friendly": "1.3.0", "eslint-plugin-storybook": "0.8.0", "eslint-plugin-testing-library": "6.0.2", - "husky": "8.0.3", + "husky": "9.1.6", "jest": "29.7.0", "jest-watch-typeahead": "2.2.2", "lint-staged": "15.2.2", diff --git a/packages/react/.storybook/preview.jsx b/packages/react/.storybook/preview.jsx index b2dd26b9350..05be21801da 100644 --- a/packages/react/.storybook/preview.jsx +++ b/packages/react/.storybook/preview.jsx @@ -171,6 +171,19 @@ const primerThemes = [ {value: 'dark_high_contrast', left: '🌗', title: 'Dark High Contrast'}, ] +const defaultFeatureFlags = new Map(DefaultFeatureFlags.flags) +const featureFlagEnvList = new Set([ + 'PRIMER_REACT_CSS_MODULES_TEAM', + 'PRIMER_REACT_CSS_MODULES_STAFF', + 'PRIMER_REACT_CSS_MODULES_GA', +]) + +for (const flag of featureFlagEnvList) { + if (import.meta.env[`VITE_${flag}`] === '1') { + defaultFeatureFlags.set(flag.toLocaleLowerCase(), true) + } +} + export const globalTypes = { colorScheme: { name: 'Theme', @@ -187,7 +200,7 @@ export const globalTypes = { featureFlags: { name: 'Feature flags', description: 'Toggle feature flags', - defaultValue: Object.fromEntries(DefaultFeatureFlags.flags), + defaultValue: Object.fromEntries(defaultFeatureFlags), }, } diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index af5b072e756..a323b56b3ce 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,105 @@ # @primer/react +## 37.0.0-rc.10 + +### Minor Changes + +- [#5064](https://github.com/primer/react/pull/5064) [`29f33ce`](https://github.com/primer/react/commit/29f33ce93c6b7e573cca9f2c0a10bb12ec5245c3) Thanks [@broccolinisoup](https://github.com/broccolinisoup)! - Tooltip: Do not export all types publicly in the experimental bundle + +- [#5010](https://github.com/primer/react/pull/5010) [`8385c33`](https://github.com/primer/react/commit/8385c334df1f31aa810a8e6575986ca420a683f9) Thanks [@joshblack](https://github.com/joshblack)! - Promote Dialog, Tooltip, and Stack from `@primer/react/experimental` to `@primer/react` + +- [#5074](https://github.com/primer/react/pull/5074) [`e4965ed`](https://github.com/primer/react/commit/e4965ed773e32abc6fc49bff623dd79127047c93) Thanks [@joshblack](https://github.com/joshblack)! - Add the `useFeatureFlag` hook to `@primer/react/experimental` + +### Patch Changes + +- [#5059](https://github.com/primer/react/pull/5059) [`682e787`](https://github.com/primer/react/commit/682e787071d9bed26801202cf6823a96c1b39462) Thanks [@gwwar](https://github.com/gwwar)! - Fixes negative and invalid pages in data table pagination on re-render. + +- [#5078](https://github.com/primer/react/pull/5078) [`3b7bf41`](https://github.com/primer/react/commit/3b7bf411c60d5283eb2fba78e7ab1a26b707af5b) Thanks [@jonrohan](https://github.com/jonrohan)! - Set the `min-width` of `IconButton` to `unset` to resolve layout issues. + +- [#5062](https://github.com/primer/react/pull/5062) [`0f5d5e0`](https://github.com/primer/react/commit/0f5d5e05096b1b1599a92c90619cde6e11cb5808) Thanks [@jonrohan](https://github.com/jonrohan)! - Move CSS modules feature flag from staff to ga for Avatar component + +- [#5082](https://github.com/primer/react/pull/5082) [`212714c`](https://github.com/primer/react/commit/212714ccc005eb57e272b3f64e3736e198c555e8) Thanks [@langermank](https://github.com/langermank)! - Add focus styles to Pagination component + +- [#5077](https://github.com/primer/react/pull/5077) [`6490b27`](https://github.com/primer/react/commit/6490b27bde15e7687dcda48c444eb909dec2d5a7) Thanks [@jonrohan](https://github.com/jonrohan)! - Bug fix(Avatar): Changed rounded border calculation for the "square" Avatar to better align with existing border styles + +- [#5055](https://github.com/primer/react/pull/5055) [`73135c1`](https://github.com/primer/react/commit/73135c1c57a02e35d33ae6ffba16784043dcabb8) Thanks [@francinelucca](https://github.com/francinelucca)! - fix(Banner): rewrite PrimaryAction & SecondaryAction types + +- [#5068](https://github.com/primer/react/pull/5068) [`5f7bd0b`](https://github.com/primer/react/commit/5f7bd0b399073b2f22b8eaec548c37ff19a5ea86) Thanks [@jonrohan](https://github.com/jonrohan)! - fix for `toggleStyledComponent` utility, When the feature flag is enabled and sx prop is passed in use, Box + +- [#5091](https://github.com/primer/react/pull/5091) [`4218bef`](https://github.com/primer/react/commit/4218bef879ae70aab3cc30492bacfc9c506be8f7) Thanks [@jonrohan](https://github.com/jonrohan)! - Bug fix for `IconButton` to respect the `style` prop width when the feature flag is on. + +- [#5073](https://github.com/primer/react/pull/5073) [`472967a`](https://github.com/primer/react/commit/472967a712e9b81856b3b37088142b0ffbda5b15) Thanks [@siddharthkp](https://github.com/siddharthkp)! - SelectPanel: Fix items not being selected when defined within scope (track selection by item.id) + +- [#5066](https://github.com/primer/react/pull/5066) [`702ba5c`](https://github.com/primer/react/commit/702ba5ca59d42abc57a1d6da539935534edcd2ab) Thanks [@jonrohan](https://github.com/jonrohan)! - Use the IconButton for the close button on Dialog + +- [#5079](https://github.com/primer/react/pull/5079) [`a2e5671`](https://github.com/primer/react/commit/a2e5671e720e4d78a3f5a9b503fc841db100dc1d) Thanks [@jonrohan](https://github.com/jonrohan)! - Correctly pass styled system typography and common props to the `Box` component in the `Text` component when the CSS modules feature flag is enabled. + +## 37.0.0-rc.9 + +### Minor Changes + +- [#5021](https://github.com/primer/react/pull/5021) [`cff067a`](https://github.com/primer/react/commit/cff067afd997988fea9cec4ce9167c07a5d7acbc) Thanks [@joshblack](https://github.com/joshblack)! - Add ResponsiveValue type to `@primer/react` entrypoint + +### Patch Changes + +- [#5053](https://github.com/primer/react/pull/5053) [`2703d0c`](https://github.com/primer/react/commit/2703d0c659a71d3d0c6e307cb4d6dc2606c070d0) Thanks [@siddharthkp](https://github.com/siddharthkp)! - Banner: Fix margin for inline actions + +## 37.0.0-rc.8 + +### Major Changes + +- [#4992](https://github.com/primer/react/pull/4992) [`d1d911a`](https://github.com/primer/react/commit/d1d911ad739f4f766234e99afca4ced0ad966da2) Thanks [@joshblack](https://github.com/joshblack)! - Move Octicon, Pagehead, Dialog (v1), and Tooltip (v1) to `@primer/react/deprecated` + +### Patch Changes + +- [#5036](https://github.com/primer/react/pull/5036) [`6671a20`](https://github.com/primer/react/commit/6671a207066bebdd54939d0806fca89c7ab55137) Thanks [@langermank](https://github.com/langermank)! - ActionList.Group: Fix styles for description + +- [#5033](https://github.com/primer/react/pull/5033) [`0b83fe9`](https://github.com/primer/react/commit/0b83fe9772a8c2e71a2d2eb375a11849a6eabb9c) Thanks [@siddharthkp](https://github.com/siddharthkp)! - SelectPanel: Fix font weight from active styles for modern ActionList (behind feature flag) + +## 37.0.0-rc.7 + +### Major Changes + +- [#4784](https://github.com/primer/react/pull/4784) [`b518005`](https://github.com/primer/react/commit/b51800530e84520057b7517044ca611b409eaa57) Thanks [@joshblack](https://github.com/joshblack)! - Remove temporary folders for TypeScript resolution of sub-paths + +- [#4807](https://github.com/primer/react/pull/4807) [`055c9a7`](https://github.com/primer/react/commit/055c9a7150ac2761ee82998a45448d04129f781b) Thanks [@langermank](https://github.com/langermank)! - Remove deprecated `Button` component + +### Minor Changes + +- [#4965](https://github.com/primer/react/pull/4965) [`5426a9a`](https://github.com/primer/react/commit/5426a9a0b46d4f0a93bba985e248f8b1f775b6e7) Thanks [@joshblack](https://github.com/joshblack)! - Update CounterLabel to use CSS Modules behind feature flag + +- [#4956](https://github.com/primer/react/pull/4956) [`15cb90f`](https://github.com/primer/react/commit/15cb90fde3e59f41475b19daef0851a969885248) Thanks [@francinelucca](https://github.com/francinelucca)! - fix(PageHeader): add role prop and aria-label in top-level element + +- [#4962](https://github.com/primer/react/pull/4962) [`1977a68`](https://github.com/primer/react/commit/1977a682841267dc22ca49b5b05f56511f73764c) Thanks [@joshblack](https://github.com/joshblack)! - Update Checkbox component to use CSS Modules behind feature flag + +- [#4976](https://github.com/primer/react/pull/4976) [`f448b1b`](https://github.com/primer/react/commit/f448b1b3debd72a3a372f4083d656a4e235cbfc9) Thanks [@joshblack](https://github.com/joshblack)! - Add certain wildcard exports to named entry points + +- [#5007](https://github.com/primer/react/pull/5007) [`c909285`](https://github.com/primer/react/commit/c90928570c416f226f9bfdba25062131d406f687) Thanks [@lukasoppermann](https://github.com/lukasoppermann)! - ProgressBar: Add `bg` prop to `ProgressBar.Item` + +- [#4960](https://github.com/primer/react/pull/4960) [`21c3fce`](https://github.com/primer/react/commit/21c3fcea267c2a0f181310934ad34e548a1d605a) Thanks [@joshblack](https://github.com/joshblack)! - Add support for experimental IssueLabel component + +- [#5002](https://github.com/primer/react/pull/5002) [`9bd5c89`](https://github.com/primer/react/commit/9bd5c8936fa316c1216fb8fd22034b3355097431) Thanks [@jonrohan](https://github.com/jonrohan)! - chore(AvatarPair): Convert AvatarPair to CSS modules + +### Patch Changes + +- [#5026](https://github.com/primer/react/pull/5026) [`3302440`](https://github.com/primer/react/commit/33024402ccc9f739ebf358cea6e90f409e4e1188) Thanks [@siddharthkp](https://github.com/siddharthkp)! - Banner: Fix alignment of secondary action without primary action + +- [#5018](https://github.com/primer/react/pull/5018) [`8e4beae`](https://github.com/primer/react/commit/8e4beae98592c38a172aa0c2be604d7c06e941c7) Thanks [@jonrohan](https://github.com/jonrohan)! - Remove the CSS modules feature flag from `Heading` + +- [#5023](https://github.com/primer/react/pull/5023) [`1691e46`](https://github.com/primer/react/commit/1691e466a2749393af87ced37f4f72694582e0bb) Thanks [@jonrohan](https://github.com/jonrohan)! - Move Button component feature flag from primer_react_css_modules_team to primer_react_css_modules_staff + +- [#5020](https://github.com/primer/react/pull/5020) [`31f03fb`](https://github.com/primer/react/commit/31f03fbdcdcd1bfca6fee15443b0c0bd241a42df) Thanks [@jonrohan](https://github.com/jonrohan)! - Move Text component feature flag from primer_react_css_modules_staff to primer_react_css_modules_ga + +- [#5001](https://github.com/primer/react/pull/5001) [`597d285`](https://github.com/primer/react/commit/597d285a9cd876f52e7be56ba2dde1aed2c473f2) Thanks [@jonrohan](https://github.com/jonrohan)! - Migrate `ButtonGroup` component to use CSS modules behind the `primer_react_css_modules_team` feature flag + +- [#5022](https://github.com/primer/react/pull/5022) [`4395d16`](https://github.com/primer/react/commit/4395d162be1a80233bada149966b36a27f91ba51) Thanks [@jonrohan](https://github.com/jonrohan)! - Move Label component feature flag from primer_react_css_modules_staff to primer_react_css_modules_ga + +- [#4969](https://github.com/primer/react/pull/4969) [`0cd6151`](https://github.com/primer/react/commit/0cd6151c2b620f10a06921a88edf6d64e0a1bc1a) Thanks [@TylerJDev](https://github.com/TylerJDev)! - Add initial loading state to live region announcement in `TreeView` + +- [#5024](https://github.com/primer/react/pull/5024) [`45f3597`](https://github.com/primer/react/commit/45f359770ae830073f49aa23297aa9788809b46d) Thanks [@jonrohan](https://github.com/jonrohan)! - Move Avatar component feature flag from primer_react_css_modules_team to primer_react_css_modules_staff + +- [#5011](https://github.com/primer/react/pull/5011) [`7a5205d`](https://github.com/primer/react/commit/7a5205d88e6c1600e83232a102378d97639b4223) Thanks [@langermank](https://github.com/langermank)! - Bug fix: `Button` aria-expanded state (CSS Modules) + ## 37.0.0-rc.6 ### Major Changes diff --git a/packages/react/package.json b/packages/react/package.json index e2971d63705..f675aa3c155 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@primer/react", - "version": "37.0.0-rc.6", + "version": "37.0.0-rc.10", "description": "An implementation of GitHub's Primer Design System using React", "main": "lib/index.js", "module": "lib-esm/index.js", @@ -92,11 +92,11 @@ "@github/relative-time-element": "^4.4.2", "@github/tab-container-element": "^4.8.0", "@lit-labs/react": "1.2.1", - "@oddbird/popover-polyfill": "^0.3.1", + "@oddbird/popover-polyfill": "^0.4.4", "@primer/behaviors": "^1.7.2", "@primer/live-region-element": "^0.7.1", "@primer/octicons-react": "^19.9.0", - "@primer/primitives": "^9.0.3", + "@primer/primitives": "^9.1.2", "@styled-system/css": "^5.1.5", "@styled-system/props": "^5.1.5", "@styled-system/theme-get": "^5.1.2", @@ -151,7 +151,7 @@ "@testing-library/react": "^16.0.0", "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.5.2", - "@types/lodash.groupby": "4.6.7", + "@types/lodash.groupby": "4.6.9", "@types/lodash.isempty": "4.4.9", "@types/lodash.isobject": "3.0.9", "@types/lodash.keyby": "4.6.7", diff --git a/packages/react/rollup.config.mjs b/packages/react/rollup.config.mjs index 6b40253473f..0264079ae5b 100644 --- a/packages/react/rollup.config.mjs +++ b/packages/react/rollup.config.mjs @@ -11,7 +11,7 @@ import {importCSS} from 'rollup-plugin-import-css' import postcss from 'rollup-plugin-postcss' import postcssPresetPrimer from 'postcss-preset-primer' import MagicString from 'magic-string' -import packageJson from './package.json' assert {type: 'json'} +import packageJson from './package.json' with {type: 'json'} const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/packages/react/src/ActionBar/ActionBar.stories.tsx b/packages/react/src/ActionBar/ActionBar.stories.tsx index f2a85e5115e..f253a67d20e 100644 --- a/packages/react/src/ActionBar/ActionBar.stories.tsx +++ b/packages/react/src/ActionBar/ActionBar.stories.tsx @@ -18,7 +18,8 @@ import { ReplyIcon, ThreeBarsIcon, } from '@primer/octicons-react' -import {Box, Dialog, Button, Avatar, ActionMenu, IconButton, ActionList, Textarea} from '../' +import {Box, Button, Avatar, ActionMenu, IconButton, ActionList, Textarea} from '../' +import {Dialog} from '../DialogV1' import {Divider} from '../deprecated/ActionList/Divider' import mockData from '../experimental/SelectPanel2/mock-story-data' diff --git a/packages/react/src/ActionList/ActionList.features.stories.tsx b/packages/react/src/ActionList/ActionList.features.stories.tsx index c7e6c6be821..23e126409dd 100644 --- a/packages/react/src/ActionList/ActionList.features.stories.tsx +++ b/packages/react/src/ActionList/ActionList.features.stories.tsx @@ -643,21 +643,21 @@ export const InsideOverlay = () => { )} > - - + + Use your arrow keys ↓ - + keep going ↓ - + more more ↓ - + now go up! ↑ diff --git a/packages/react/src/ActionList/Group.tsx b/packages/react/src/ActionList/Group.tsx index f4c1e2e8105..da31c6830ef 100644 --- a/packages/react/src/ActionList/Group.tsx +++ b/packages/react/src/ActionList/Group.tsx @@ -1,8 +1,7 @@ import React from 'react' import {useId} from '../hooks/useId' import Box from '../Box' -import type {SxProp, BetterSystemStyleObject} from '../sx' -import {merge} from '../sx' +import type {SxProp} from '../sx' import {ListContext, type ActionListProps} from './shared' import type {AriaRole} from '../utils/types' import {default as Heading} from '../Heading' @@ -165,6 +164,20 @@ export const GroupHeading: React.FC> borderBottom: '1px solid', borderColor: 'neutral.muted', }), + + [`.ActionListGroupHeading`]: { + fontSize: 'var(--text-body-size-small), 12px', + fontWeight: 'var(--base-text-weight-semibold, 600)', + lineHeight: 'var(--text-body-lineHeight-small, 1.6666)', + color: 'var(--fgColor-muted)', + }, + + [`.ActionListGroupHeadingDescription`]: { + fontSize: 'var(--text-body-size-small, 12px)', + fontWeight: 'var(--base-text-weight-normal, 400)', + lineHeight: 'var(--text-body-lineHeight-small, 1.6666)', + color: 'var(--fgColor-muted)', + }, } return ( @@ -173,16 +186,16 @@ export const GroupHeading: React.FC> {listRole && listRole !== 'list' ? ( ) : ( // for explicit (role="list" is passed as prop) and implicit list roles (ActionList ins rendered as list by default), group titles are proper heading tags. - <> - (styles, sx)} {...props}> + + {_internalBackwardCompatibleTitle ?? children} - {auxiliaryText && {auxiliaryText}} - + {auxiliaryText &&
{auxiliaryText}
} +
)} ) diff --git a/packages/react/src/ActionList/Item.tsx b/packages/react/src/ActionList/Item.tsx index 629e1d3b5c1..53dae15b6a3 100644 --- a/packages/react/src/ActionList/Item.tsx +++ b/packages/react/src/ActionList/Item.tsx @@ -232,7 +232,7 @@ export const Item = React.forwardRef( /** Active styles */ ...(active ? activeStyles : {}), // NavList - '&[data-is-active-descendant]': activeStyles, // SelectPanel + '&[data-is-active-descendant]': {...activeStyles, fontWeight: 'normal'}, // SelectPanel ...(!buttonSemantics ? hoverStyles : {}), } diff --git a/packages/react/src/AnchoredOverlay/AnchoredOverlay.features.stories.tsx b/packages/react/src/AnchoredOverlay/AnchoredOverlay.features.stories.tsx index 78ff50b16c8..db336516af6 100644 --- a/packages/react/src/AnchoredOverlay/AnchoredOverlay.features.stories.tsx +++ b/packages/react/src/AnchoredOverlay/AnchoredOverlay.features.stories.tsx @@ -2,17 +2,49 @@ import React, {useEffect, useRef, useState} from 'react' import type {Args, Meta} from '@storybook/react' import {FocusKeys} from '@primer/behaviors' -import {Box, Button} from '..' +import {Avatar, Box, Text} from '..' import {AnchoredOverlay} from '../AnchoredOverlay' import Heading from '../Heading' +import Octicon from '../Octicon' +import {Button} from '../Button' import {registerPortalRoot} from '../Portal' import {Playground} from './AnchoredOverlay.stories' +import {LocationIcon, RepoIcon} from '@primer/octicons-react' +import {Stack} from '../Stack/Stack' export default { title: 'Components/AnchoredOverlay/Features', component: AnchoredOverlay, } as Meta +const hoverCard = ( + + + + + + + monalisa + + Monalisa Octocat + + + Former beach cat and champion swimmer. Now your friendly octapus with a normal face. + + + + Interwebs + + + + + + Owns this repository + + + +) + const HeaderAndLayout = ({children}: {children: JSX.Element}) => { const scrollingElementRef = useRef(null) useEffect(() => { @@ -70,9 +102,7 @@ export const CustomAnchorId = () => { renderAnchor={props => } anchorId="my-custom-anchor-id" > - - kitten - + {hoverCard} ) } @@ -88,9 +118,7 @@ export const Height = () => { renderAnchor={props => } height="large" > - - kitten - + {hoverCard} ) } @@ -106,9 +134,7 @@ export const Width = () => { renderAnchor={props => } width="large" > - - kitten - + {hoverCard} ) } @@ -128,9 +154,7 @@ export const AnchorAlignment = () => { )} align="center" > - - kitten - + {hoverCard} ) } @@ -146,9 +170,7 @@ export const AnchorSide = () => { renderAnchor={props => } side="outside-right" > - - kitten - + {hoverCard} ) } @@ -164,9 +186,7 @@ export const OffsetPositionFromAnchor = () => { renderAnchor={props => } anchorOffset={100} > - - kitten - + {hoverCard} ) } @@ -182,9 +202,7 @@ export const OffsetAlignmentFromAnchor = () => { renderAnchor={props => } alignmentOffset={100} > - - kitten - + {hoverCard} ) } @@ -247,9 +265,7 @@ export const OverlayPropsOverrides = () => {
  • overflow: `auto`
  • maxHeight: `xsmall`
  • - - kitten - + {hoverCard} ) } diff --git a/packages/react/src/AnchoredOverlay/AnchoredOverlay.stories.tsx b/packages/react/src/AnchoredOverlay/AnchoredOverlay.stories.tsx index deba2266964..5a7dcbf50da 100644 --- a/packages/react/src/AnchoredOverlay/AnchoredOverlay.stories.tsx +++ b/packages/react/src/AnchoredOverlay/AnchoredOverlay.stories.tsx @@ -1,16 +1,47 @@ import React, {useState} from 'react' import type {Args, Meta} from '@storybook/react' +import {LocationIcon, RepoIcon} from '@primer/octicons-react' -import {Box} from '..' +import {Avatar, Text} from '..' import {AnchoredOverlay} from '../AnchoredOverlay' import {Button} from '../Button' +import Octicon from '../Octicon' import {action} from '@storybook/addon-actions' +import {Stack} from '../Stack/Stack' export default { title: 'Components/AnchoredOverlay', component: AnchoredOverlay, } as Meta +const hoverCard = ( + + + + + + + monalisa + + Monalisa Octocat + + + Former beach cat and champion swimmer. Now your friendly octapus with a normal face. + + + + Interwebs + + + + + + Owns this repository + + + +) + export const Default = () => { const [open, setOpen] = useState(false) @@ -21,9 +52,7 @@ export const Default = () => { onClose={() => setOpen(false)} renderAnchor={props => } > - - kitten - + {hoverCard} ) } @@ -48,14 +77,12 @@ export const Playground = (args: Args) => { overlayProps={args.portalContainerName} side={args.side} > - - kitten - + {hoverCard} ) } Playground.args = { - width: 'small', + width: 'auto', height: 'auto', portalContainerName: 'Portal name', side: 'outside-bottom', diff --git a/packages/react/src/Autocomplete/Autocomplete.features.stories.tsx b/packages/react/src/Autocomplete/Autocomplete.features.stories.tsx index 548979ed971..db90164b260 100644 --- a/packages/react/src/Autocomplete/Autocomplete.features.stories.tsx +++ b/packages/react/src/Autocomplete/Autocomplete.features.stories.tsx @@ -2,7 +2,8 @@ import type {ChangeEventHandler, RefObject} from 'react' import React, {useCallback, useEffect, useRef, useState} from 'react' import type {Meta} from '@storybook/react' -import {BaseStyles, Box, Dialog, ThemeProvider, registerPortalRoot} from '..' +import {BaseStyles, Box, ThemeProvider, registerPortalRoot} from '..' +import {Dialog} from '../DialogV1' import TextInputTokens from '../TextInputWithTokens' import Autocomplete from './Autocomplete' import {AnchoredOverlay} from '../AnchoredOverlay' diff --git a/packages/react/src/Autocomplete/AutocompleteMenu.tsx b/packages/react/src/Autocomplete/AutocompleteMenu.tsx index fa566f3bbaf..cb09cdacc2c 100644 --- a/packages/react/src/Autocomplete/AutocompleteMenu.tsx +++ b/packages/react/src/Autocomplete/AutocompleteMenu.tsx @@ -12,12 +12,13 @@ import {AutocompleteContext} from './AutocompleteContext' import type {IconProps} from '@primer/octicons-react' import {PlusIcon} from '@primer/octicons-react' import VisuallyHidden from '../_VisuallyHidden' +import {isElement} from 'react-is' type OnSelectedChange = (item: T | T[]) => void export type AutocompleteMenuItem = MandateProps & { - leadingVisual?: React.FunctionComponent> + leadingVisual?: React.FunctionComponent> | React.ReactElement text?: string - trailingVisual?: React.FunctionComponent> + trailingVisual?: React.FunctionComponent> | React.ReactElement } const getDefaultSortFn = (isItemSelectedFn: (itemId: string) => boolean) => (itemIdA: string, itemIdB: string) => @@ -352,13 +353,13 @@ function AutocompleteMenu(props: AutocompleteMe onAction(item)} {...itemProps} id={id} data-id={id}> {LeadingVisual && ( - + {isElement(LeadingVisual) ? LeadingVisual : } )} {children ?? text} {TrailingVisual && ( - + {isElement(TrailingVisual) ? TrailingVisual : } )} diff --git a/packages/react/src/Avatar/Avatar.module.css b/packages/react/src/Avatar/Avatar.module.css index f20124dedfa..9edbe1cbdce 100644 --- a/packages/react/src/Avatar/Avatar.module.css +++ b/packages/react/src/Avatar/Avatar.module.css @@ -13,7 +13,8 @@ box-shadow: 0 0 0 1px var(--avatar-borderColor); &:where([data-square]) { - border-radius: var(--borderRadius-medium); + /* stylelint-disable-next-line primer/borders */ + border-radius: clamp(4px, calc(var(--avatarSize-regular) - 24px), var(--borderRadius-medium)); } &:where([data-responsive]) { diff --git a/packages/react/src/Avatar/Avatar.tsx b/packages/react/src/Avatar/Avatar.tsx index 79d7a1dfefb..4f5f066a147 100644 --- a/packages/react/src/Avatar/Avatar.tsx +++ b/packages/react/src/Avatar/Avatar.tsx @@ -48,7 +48,7 @@ const Avatar = React.forwardRef(function Avatar( {alt = '', size = DEFAULT_AVATAR_SIZE, square = false, sx: sxProp = defaultSxProp, className, ...rest}, ref, ) { - const enabled = useFeatureFlag('primer_react_css_modules_staff') + const enabled = useFeatureFlag('primer_react_css_modules_ga') const isResponsive = isResponsiveValue(size) const avatarSx = isResponsive ? merge( diff --git a/packages/react/src/AvatarStack/AvatarStack.tsx b/packages/react/src/AvatarStack/AvatarStack.tsx index 24667bbb69c..f07615f7214 100644 --- a/packages/react/src/AvatarStack/AvatarStack.tsx +++ b/packages/react/src/AvatarStack/AvatarStack.tsx @@ -183,17 +183,28 @@ export type AvatarStackProps = { alignRight?: boolean disableExpand?: boolean size?: number | ResponsiveValue + className?: string children: React.ReactNode } & SxProp -const AvatarStack = ({children, alignRight, disableExpand, size, sx: sxProp = defaultSxProp}: AvatarStackProps) => { +const AvatarStack = ({ + children, + alignRight, + disableExpand, + size, + className, + sx: sxProp = defaultSxProp, +}: AvatarStackProps) => { const count = React.Children.count(children) - const wrapperClassNames = clsx({ - 'pc-AvatarStack--two': count === 2, - 'pc-AvatarStack--three': count === 3, - 'pc-AvatarStack--three-plus': count > 3, - 'pc-AvatarStack--right': alignRight, - }) + const wrapperClassNames = clsx( + { + 'pc-AvatarStack--two': count === 2, + 'pc-AvatarStack--three': count === 3, + 'pc-AvatarStack--three-plus': count > 3, + 'pc-AvatarStack--right': alignRight, + }, + className, + ) const bodyClassNames = clsx('pc-AvatarStackBody', { 'pc-AvatarStack--disableExpand': disableExpand, }) diff --git a/packages/react/src/Banner/Banner.module.css b/packages/react/src/Banner/Banner.module.css index 5e20ad6cb73..2bef4bbe4ed 100644 --- a/packages/react/src/Banner/Banner.module.css +++ b/packages/react/src/Banner/Banner.module.css @@ -143,7 +143,7 @@ } } -.Banner[data-dismissible] .BannerActions { +.Banner[data-dismissible]:not([data-title-hidden]) .BannerActions { margin-block-end: var(--base-size-6); } diff --git a/packages/react/src/Banner/Banner.tsx b/packages/react/src/Banner/Banner.tsx index 2a9bbfd459b..d540b0c7b3f 100644 --- a/packages/react/src/Banner/Banner.tsx +++ b/packages/react/src/Banner/Banner.tsx @@ -1,14 +1,15 @@ import {clsx} from 'clsx' -import React, {useEffect} from 'react' +import React, {forwardRef, useEffect} from 'react' import styled from 'styled-components' import {AlertIcon, InfoIcon, StopIcon, CheckCircleIcon, XIcon} from '@primer/octicons-react' -import {Button, IconButton} from '../Button' +import {Button, IconButton, type ButtonProps} from '../Button' import {get} from '../constants' import {VisuallyHidden} from '../VisuallyHidden' import {useMergedRefs} from '../internal/hooks/useMergedRefs' import {useFeatureFlag} from '../FeatureFlags' import classes from './Banner.module.css' import {toggleStyledComponent} from '../internal/utils/toggleStyledComponent' +import type {ForwardRefComponent as PolymorphicForwardRefComponent} from '../utils/polymorphic' type BannerVariant = 'critical' | 'info' | 'success' | 'upsell' | 'warning' @@ -338,7 +339,7 @@ const StyledBanner = toggleStyledComponent( } } - &[data-dismissible] .BannerActions { + &[data-dismissible]:not([data-title-hidden]) .BannerActions { margin-block-end: var(--base-size-6, 0.375rem); } @@ -474,22 +475,28 @@ export function BannerActions({primaryAction, secondaryAction}: BannerActionsPro ) } -export type BannerPrimaryActionProps = Omit, 'variant'> +export type BannerPrimaryActionProps = Omit -export function BannerPrimaryAction({children, className, ...rest}: BannerPrimaryActionProps) { +const BannerPrimaryAction = forwardRef(({children, className, ...rest}, forwardedRef) => { return ( - ) -} +}) as PolymorphicForwardRefComponent<'button', BannerPrimaryActionProps> + +BannerPrimaryAction.displayName = 'BannerPrimaryAction' -export type BannerSecondaryActionProps = Omit, 'variant'> +export type BannerSecondaryActionProps = Omit -export function BannerSecondaryAction({children, className, ...rest}: BannerSecondaryActionProps) { +const BannerSecondaryAction = forwardRef(({children, className, ...rest}, forwardedRef) => { return ( - ) -} +}) as PolymorphicForwardRefComponent<'button', BannerSecondaryActionProps> + +BannerSecondaryAction.displayName = 'BannerSecondaryAction' + +export {BannerPrimaryAction, BannerSecondaryAction} diff --git a/packages/react/src/Button/ButtonBase.module.css b/packages/react/src/Button/ButtonBase.module.css index 8f8efabbda4..19464c3c4e4 100644 --- a/packages/react/src/Button/ButtonBase.module.css +++ b/packages/react/src/Button/ButtonBase.module.css @@ -68,22 +68,20 @@ /* IconButton */ - &:where(.IconButton) { + &.IconButton { display: inline-grid; width: var(--control-medium-size); - min-width: var(--control-medium-size); + min-width: unset; /* stylelint-disable-next-line primer/spacing */ padding: unset; place-content: center; &:where([data-size='small']) { width: var(--control-small-size); - min-width: var(--control-small-size); } &:where([data-size='large']) { width: var(--control-large-size); - min-width: var(--control-large-size); } } diff --git a/packages/react/src/Button/ButtonBase.tsx b/packages/react/src/Button/ButtonBase.tsx index 06f819dfe3b..562f6eaa5c1 100644 --- a/packages/react/src/Button/ButtonBase.tsx +++ b/packages/react/src/Button/ButtonBase.tsx @@ -19,24 +19,30 @@ import {AriaStatus} from '../live-region' import {clsx} from 'clsx' import classes from './ButtonBase.module.css' import {useFeatureFlag} from '../FeatureFlags' +import {isElement} from 'react-is' const iconWrapStyles = { display: 'flex', pointerEvents: 'none', } -const renderVisual = (Visual: React.ElementType, loading: boolean, visualName: string) => ( +const renderVisual = (Visual: React.ElementType | React.ReactElement, loading: boolean, visualName: string) => ( - {loading ? : } + {loading ? : isElement(Visual) ? Visual : } ) -const renderModuleVisual = (Visual: React.ElementType, loading: boolean, visualName: string, counterLabel: boolean) => ( +const renderModuleVisual = ( + Visual: React.ElementType | React.ReactElement, + loading: boolean, + visualName: string, + counterLabel: boolean, +) => ( - {loading ? : } + {loading ? : isElement(Visual) ? Visual : } ) @@ -141,6 +147,8 @@ const ButtonBase = forwardRef( {Icon ? ( loading ? ( + ) : isElement(Icon) ? ( + Icon ) : ( ) @@ -163,7 +171,7 @@ const ButtonBase = forwardRef( } { /* Render a leading visual unless the button is in a loading state. - Then replace the leading visual with a loading spinner. */ + Then replace the leading visual with a loading spinner. */ LeadingVisual && renderModuleVisual(LeadingVisual, Boolean(loading), 'leadingVisual', false) } {children && ( @@ -260,6 +268,8 @@ const ButtonBase = forwardRef( {Icon ? ( loading ? ( + ) : isElement(Icon) ? ( + Icon ) : ( ) @@ -369,6 +379,8 @@ const ButtonBase = forwardRef( {Icon ? ( loading ? ( + ) : isElement(Icon) ? ( + Icon ) : ( ) diff --git a/packages/react/src/Button/IconButton.dev.stories.tsx b/packages/react/src/Button/IconButton.dev.stories.tsx index dd0bffffbe5..bc772a04f28 100644 --- a/packages/react/src/Button/IconButton.dev.stories.tsx +++ b/packages/react/src/Button/IconButton.dev.stories.tsx @@ -1,6 +1,7 @@ -import {ChevronDownIcon} from '@primer/octicons-react' +import {BoldIcon, ChevronDownIcon} from '@primer/octicons-react' import React from 'react' import {IconButton} from '.' +import Box from '../Box' export default { title: 'Components/IconButton/DevOnly', @@ -25,3 +26,15 @@ export const CustomSizeWithMedia = () => { export const CustomIconColor = () => ( ) + +export const CustomSizeWithStyleProp = () => ( + + + +) diff --git a/packages/react/src/Button/IconButton.docs.json b/packages/react/src/Button/IconButton.docs.json index 6d606228e6d..dc357c85695 100644 --- a/packages/react/src/Button/IconButton.docs.json +++ b/packages/react/src/Button/IconButton.docs.json @@ -49,6 +49,13 @@ "required": false, "description": "Keyboard shortcuts that trigger the button. Keyboard shortcut will be appended to the accessible name or description (depending on the tooltip type) of the button with a comma (i.e. Bold, Command+B) and it will be displayed in the tooltip." }, + { + "name": "tooltipDirection", + "type": "'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw'", + "defaultValue": "'s'", + "description": "The direction of the tooltip. ", + "required": false + }, { "name": "sx", "type": "SystemStyleObject" diff --git a/packages/react/src/Button/__tests__/Button.types.test.tsx b/packages/react/src/Button/__tests__/Button.types.test.tsx index b50f0c51d24..23b0a084975 100644 --- a/packages/react/src/Button/__tests__/Button.types.test.tsx +++ b/packages/react/src/Button/__tests__/Button.types.test.tsx @@ -1,4 +1,4 @@ -import {StopIcon} from '@primer/octicons-react' +import {LogoGithubIcon, StopIcon} from '@primer/octicons-react' import React, {useRef} from 'react' import {Button, IconButton} from '../../Button' @@ -80,3 +80,11 @@ export function supportsLeadingVisual() { export function supportsTrailingVisual() { return } + +export function supportsLeadingVisualElement() { + return +} + +export function supportsTrailingVisualElement() { + return +} diff --git a/packages/react/src/Button/index.ts b/packages/react/src/Button/index.ts index 35ed7077460..7545aa6e576 100644 --- a/packages/react/src/Button/index.ts +++ b/packages/react/src/Button/index.ts @@ -3,3 +3,5 @@ import {LinkButton} from './LinkButton' export type {ButtonProps, IconButtonProps} from './types' export {IconButton, LinkButton} export {ButtonComponent as Button} from './Button' +export {ButtonBase} from './ButtonBase' +export type {ButtonBaseProps} from './ButtonBase' diff --git a/packages/react/src/Button/types.ts b/packages/react/src/Button/types.ts index 0d5dfb08e43..2d3fae5b07b 100644 --- a/packages/react/src/Button/types.ts +++ b/packages/react/src/Button/types.ts @@ -4,6 +4,7 @@ import type {SxProp} from '../sx' import sx from '../sx' import getGlobalFocusStyles from '../internal/utils/getGlobalFocusStyles' import type {TooltipDirection} from '../TooltipV2' +import type {IconProps} from '@primer/octicons-react' export const StyledButton = styled.button` ${getGlobalFocusStyles('-2px')}; @@ -66,17 +67,17 @@ export type ButtonProps = { /** * The icon for the IconButton */ - icon?: React.ElementType | null + icon?: React.FunctionComponent | React.ElementType | React.ReactElement | null /** * The leading visual which comes before the button content */ - leadingVisual?: React.ElementType | null + leadingVisual?: React.ElementType | React.ReactElement | null /** * The trailing visual which comes after the button content */ - trailingVisual?: React.ElementType | null + trailingVisual?: React.ElementType | React.ReactElement | null /** * Trailing action appears to the right of the trailing visual and is always locked to the end diff --git a/packages/react/src/DataTable/DataTable.stories.tsx b/packages/react/src/DataTable/DataTable.stories.tsx index f57b6843eba..7726463411d 100644 --- a/packages/react/src/DataTable/DataTable.stories.tsx +++ b/packages/react/src/DataTable/DataTable.stories.tsx @@ -195,6 +195,11 @@ export const Playground = (args: DataTableProps & ColWidthArgTypes) = const align = args.align as CellAlignment + const [pageIndex, setPageIndex] = React.useState(0) + const start = pageIndex * parseInt(args.pageSize, 10) + const end = start + parseInt(args.pageSize, 10) + const rows = data.slice(start, end) + return ( @@ -207,7 +212,7 @@ export const Playground = (args: DataTableProps & ColWidthArgTypes) = {...args} aria-labelledby="repositories" aria-describedby="repositories-subtitle" - data={data} + data={rows} columns={[ { header: 'Repository', @@ -276,12 +281,22 @@ export const Playground = (args: DataTableProps & ColWidthArgTypes) = }, ]} /> + { + setPageIndex(pageIndex) + }} + defaultPageIndex={parseInt(args.defaultPageIndex, 10)} + /> ) } Playground.args = { cellPadding: 'normal', + pageSize: 5, } Playground.argTypes = { @@ -318,6 +333,18 @@ Playground.argTypes = { disable: true, }, }, + pageSize: { + control: { + defaultValue: 5, + type: 'number', + min: 1, + }, + }, + defaultPageIndex: { + control: { + type: 'number', + }, + }, cellPadding: { control: { type: 'radio', diff --git a/packages/react/src/DataTable/Pagination.tsx b/packages/react/src/DataTable/Pagination.tsx index 938cb4fb3d4..7a3bfdfea70 100644 --- a/packages/react/src/DataTable/Pagination.tsx +++ b/packages/react/src/DataTable/Pagination.tsx @@ -192,9 +192,15 @@ export function Pagination({ totalCount, }) const truncatedPageCount = pageCount > 2 ? Math.min(pageCount - 2, MAX_TRUNCATED_STEP_COUNT) : 0 - const [offsetStartIndex, setOffsetStartIndex] = useState(() => { - return getDefaultOffsetStartIndex(pageIndex, pageCount, truncatedPageCount) - }) + const defaultOffset = getDefaultOffsetStartIndex(pageIndex, pageCount, truncatedPageCount) + const [defaultOffsetStartIndex, setDefaultOffsetStartIndex] = useState(defaultOffset) + const [offsetStartIndex, setOffsetStartIndex] = useState(defaultOffsetStartIndex) + + if (defaultOffsetStartIndex !== defaultOffset) { + setOffsetStartIndex(defaultOffset) + setDefaultOffsetStartIndex(defaultOffset) + } + const offsetEndIndex = offsetStartIndex + truncatedPageCount - 1 const hasLeadingTruncation = offsetStartIndex >= 2 const hasTrailingTruncation = pageCount - 1 - offsetEndIndex > 1 @@ -333,15 +339,15 @@ function getDefaultOffsetStartIndex(pageIndex: number, pageCount: number, trunca // When the current page is closer to the end of the list than the beginning if (pageIndex > pageCount - 1 - pageIndex) { if (pageCount - 1 - pageIndex >= truncatedPageCount) { - return pageIndex - 3 + return Math.max(pageIndex - 3, 1) } - return pageCount - 1 - truncatedPageCount + return Math.max(pageCount - 1 - truncatedPageCount, 1) } // When the current page is closer to the beginning of the list than the end if (pageIndex < pageCount - 1 - pageIndex) { if (pageIndex >= truncatedPageCount) { - return pageIndex - 3 + return Math.max(pageIndex - 3, 1) } return 1 } @@ -350,7 +356,7 @@ function getDefaultOffsetStartIndex(pageIndex: number, pageCount: number, trunca if (pageIndex < truncatedPageCount) { return pageIndex } - return pageIndex - 3 + return Math.max(pageIndex - 3, 1) } type RangeProps = { @@ -491,7 +497,7 @@ type PaginationResult = { function usePagination(config: PaginationConfig): PaginationResult { const {defaultPageIndex, onChange, pageSize, totalCount} = config const pageCount = Math.ceil(totalCount / pageSize) - const [pageIndex, setPageIndex] = useState(() => { + const [defaultIndex, setDefaultIndex] = useState(() => { if (defaultPageIndex !== undefined) { if (defaultPageIndex >= 0 && defaultPageIndex < pageCount) { return defaultPageIndex @@ -510,6 +516,13 @@ function usePagination(config: PaginationConfig): PaginationResult { return 0 }) + const [pageIndex, setPageIndex] = useState(defaultIndex) + const validDefaultPageCount = defaultPageIndex !== undefined && defaultPageIndex >= 0 && defaultPageIndex < pageCount + if (validDefaultPageCount && defaultIndex !== defaultPageIndex) { + setDefaultIndex(defaultPageIndex) + setPageIndex(defaultPageIndex) + onChange?.({pageIndex: defaultPageIndex}) + } const pageStart = pageIndex * pageSize const pageEnd = Math.min(pageIndex * pageSize + pageSize, totalCount - 1) const hasNextPage = pageIndex + 1 < pageCount diff --git a/packages/react/src/DataTable/__tests__/Pagination.test.tsx b/packages/react/src/DataTable/__tests__/Pagination.test.tsx index 0d5c93e1bb0..47338126fe9 100644 --- a/packages/react/src/DataTable/__tests__/Pagination.test.tsx +++ b/packages/react/src/DataTable/__tests__/Pagination.test.tsx @@ -84,6 +84,27 @@ describe('Table.Pagination', () => { await user.click(getPreviousPage()) expect(onChange).not.toHaveBeenCalled() }) + + it('should rerender many pages correctly', async () => { + const onChange = jest.fn() + + const {rerender} = render( + , + ) + expect(getPages()).toHaveLength(1) + expect(getCurrentPage()).toEqual(getPage(0)) + expect(getPageRange()).toEqual('1 through 25 of 25') + + rerender( + , + ) + expect(getPageRange()).toEqual('11 through 15 of 300') + expect(getCurrentPage()).toEqual(getPage(2)) + expect(getInvalidPages()).toHaveLength(0) + expect(onChange).toHaveBeenCalledWith({ + pageIndex: 2, + }) + }) }) describe('with two pages', () => { @@ -114,6 +135,32 @@ describe('Table.Pagination', () => { expect(getPageRange()).toEqual('1 through 25 of 50') }) + it('should rerender pager with correct page highlighted when clicking on pages and defaultPageIndex set', async () => { + const user = userEvent.setup() + const onChange = jest.fn() + + render( + , + ) + + expect(getPageRange()).toEqual('76 through 100 of 200') + expect(getCurrentPage()).toEqual(getPage(3)) + + await user.click(getPage(1)) + expect(onChange).toHaveBeenCalledWith({ + pageIndex: 1, + }) + expect(getPageRange()).toEqual('26 through 50 of 200') + expect(getCurrentPage()).toEqual(getPage(1)) + + await user.click(getPage(0)) + expect(onChange).toHaveBeenCalledWith({ + pageIndex: 0, + }) + expect(getPageRange()).toEqual('1 through 25 of 200') + expect(getCurrentPage()).toEqual(getPage(0)) + }) + it('should call `onChange` when using the keyboard to interact with pages', async () => { const user = userEvent.setup() const onChange = jest.fn() @@ -165,6 +212,31 @@ describe('Table.Pagination', () => { }) }) + it('should rerender pager with correct page highlighted when clicking on previous or next and defaultPageIndex set', async () => { + const user = userEvent.setup() + const onChange = jest.fn() + + render( + , + ) + + expect(getPageRange()).toEqual('76 through 100 of 200') + + await user.click(getNextPage()) + expect(onChange).toHaveBeenCalledWith({ + pageIndex: 4, + }) + expect(getPageRange()).toEqual('101 through 125 of 200') + expect(getCurrentPage()).toEqual(getPage(4)) + + await user.click(getPreviousPage()) + expect(onChange).toHaveBeenCalledWith({ + pageIndex: 3, + }) + expect(getPageRange()).toEqual('76 through 100 of 200') + expect(getCurrentPage()).toEqual(getPage(3)) + }) + it('should call `onChange` when using the keyboard to interact with previous or next', async () => { const user = userEvent.setup() const onChange = jest.fn() @@ -197,6 +269,27 @@ describe('Table.Pagination', () => { pageIndex: 0, }) }) + + it('should rerender many pages correctly', async () => { + const onChange = jest.fn() + + const {rerender} = render( + , + ) + expect(getPages()).toHaveLength(2) + expect(getCurrentPage()).toEqual(getPage(1)) + expect(getPageRange()).toEqual('26 through 50 of 50') + + rerender( + , + ) + expect(getPageRange()).toEqual('1 through 5 of 300') + expect(getCurrentPage()).toEqual(getPage(0)) + expect(getInvalidPages()).toHaveLength(0) + expect(onChange).toHaveBeenCalledWith({ + pageIndex: 0, + }) + }) }) describe('with three or more pages', () => { @@ -242,6 +335,34 @@ describe('Table.Pagination', () => { expect(pages).toHaveLength(7) }) }) + + it('should rerender many pages correctly', async () => { + const onChange = jest.fn() + const {rerender} = render( + , + ) + expect(getPages()).toHaveLength(8) + expect(getCurrentPage()).toEqual(getPage(1)) + expect(getPageRange()).toEqual('11 through 20 of 1000') + + rerender( + , + ) + expect(getPageRange()).toEqual('1 through 5 of 300') + expect(getFirstPage()).toEqual(getCurrentPage()) + expect(getInvalidPages()).toHaveLength(0) + expect(onChange).toHaveBeenCalledWith({ + pageIndex: 0, + }) + }) + + it('when rendering 3 pages and the second page is selected we should render a page number not ...', async () => { + const onChange = jest.fn() + render() + expect(getPageRange()).toEqual('3 through 4 of 6') + expect(getCurrentPage()).toEqual(getPage(1)) + expect(getInvalidPages()).toHaveLength(0) + }) }) function getPages() { @@ -288,6 +409,10 @@ function getLastPage() { return pages[pages.length - 1] } +function getInvalidPages() { + return getPages().filter(p => p.textContent?.match(/Page\s-/g) || p.textContent?.match(/Page\s0$/g)) +} + function getPageRange() { const element = document.querySelector('.TablePaginationRange') if (element && element.textContent) { diff --git a/packages/react/src/Dialog/Dialog.tsx b/packages/react/src/Dialog/Dialog.tsx index 1f5b9276a2f..50e30643c12 100644 --- a/packages/react/src/Dialog/Dialog.tsx +++ b/packages/react/src/Dialog/Dialog.tsx @@ -1,14 +1,13 @@ import React, {useCallback, useEffect, useRef, useState, type SyntheticEvent} from 'react' import styled from 'styled-components' import type {ButtonProps} from '../Button' -import {Button} from '../Button' +import {Button, IconButton} from '../Button' import Box from '../Box' import {get} from '../constants' import {useOnEscapePress, useProvidedRefOrCreate} from '../hooks' import {useFocusTrap} from '../hooks/useFocusTrap' import type {SxProp} from '../sx' import sx from '../sx' -import Octicon from '../Octicon' import {XIcon} from '@primer/octicons-react' import {useFocusZone} from '../hooks/useFocusZone' import {FocusKeys} from '@primer/behaviors' @@ -590,22 +589,11 @@ const Buttons: React.FC> ) } -const DialogCloseButton = styled(Button)` - border-radius: 4px; - background: transparent; - border: 0; - vertical-align: middle; - color: ${get('colors.fg.muted')}; - padding: ${get('space.2')}; - align-self: flex-start; - line-height: normal; - box-shadow: none; -` + const CloseButton: React.FC void}>> = ({onClose}) => { return ( - - - + // eslint-disable-next-line primer-react/a11y-remove-disable-tooltip + ) } diff --git a/packages/react/src/Dialog.docs.json b/packages/react/src/DialogV1/Dialog.docs.json similarity index 95% rename from packages/react/src/Dialog.docs.json rename to packages/react/src/DialogV1/Dialog.docs.json index c2efd78e70a..254859970d8 100644 --- a/packages/react/src/Dialog.docs.json +++ b/packages/react/src/DialogV1/Dialog.docs.json @@ -2,10 +2,10 @@ "id": "dialog", "docsId": "dialog", "name": "Dialog", - "status": "alpha", + "status": "deprecated", "a11yReviewed": false, "stories": [], - "importPath": "@primer/react", + "importPath": "@primer/react/deprecated", "props": [ { "name": "isOpen", diff --git a/packages/react/src/Dialog.stories.tsx b/packages/react/src/DialogV1/Dialog.stories.tsx similarity index 93% rename from packages/react/src/Dialog.stories.tsx rename to packages/react/src/DialogV1/Dialog.stories.tsx index 4f4cc41e280..3eb92101de6 100644 --- a/packages/react/src/Dialog.stories.tsx +++ b/packages/react/src/DialogV1/Dialog.stories.tsx @@ -1,8 +1,8 @@ import React, {useState, useRef} from 'react' import type {Meta} from '@storybook/react' -import {Button} from './Button' -import {Box, Link, Text} from '.' -import {Banner} from './Banner' +import {Button} from '../Button' +import {Box, Link, Text} from '..' +import {Banner} from '../Banner' import {default as Dialog} from './Dialog' /* Dialog Version 1*/ diff --git a/packages/react/src/__tests__/Dialog.test.tsx b/packages/react/src/DialogV1/Dialog.test.tsx similarity index 97% rename from packages/react/src/__tests__/Dialog.test.tsx rename to packages/react/src/DialogV1/Dialog.test.tsx index 0fed5ca5172..7df87bd2c75 100644 --- a/packages/react/src/__tests__/Dialog.test.tsx +++ b/packages/react/src/DialogV1/Dialog.test.tsx @@ -1,8 +1,9 @@ import React, {useState, useRef} from 'react' -import {Dialog, Box, Text, Button} from '..' +import {Box, Text, Button} from '..' +import {Dialog} from '../DialogV1' import {render as HTMLRender, fireEvent} from '@testing-library/react' import axe from 'axe-core' -import {behavesAsComponent, checkExports} from '../utils/testing' +import {behavesAsComponent} from '../utils/testing' /* Dialog Version 1*/ @@ -108,10 +109,6 @@ describe('Dialog', () => { options: {skipAs: true, skipSx: true}, }) - checkExports('Dialog', { - default: Dialog, - }) - describe('Dialog.Header', () => { behavesAsComponent({Component: Dialog.Header}) }) diff --git a/packages/react/src/Dialog.tsx b/packages/react/src/DialogV1/Dialog.tsx similarity index 90% rename from packages/react/src/Dialog.tsx rename to packages/react/src/DialogV1/Dialog.tsx index 2139792b545..3e565ba8d3d 100644 --- a/packages/react/src/Dialog.tsx +++ b/packages/react/src/DialogV1/Dialog.tsx @@ -1,14 +1,14 @@ import React, {forwardRef, useRef} from 'react' import styled from 'styled-components' -import {IconButton} from './Button' -import {get} from './constants' -import Box from './Box' -import useDialog from './hooks/useDialog' -import type {SxProp} from './sx' -import sx from './sx' -import Text from './Text' -import type {ComponentProps} from './utils/types' -import {useRefObjectAsForwardedRef} from './hooks/useRefObjectAsForwardedRef' +import {IconButton} from '../Button' +import {get} from '../constants' +import Box from '../Box' +import useDialog from '../hooks/useDialog' +import type {SxProp} from '../sx' +import sx from '../sx' +import Text from '../Text' +import type {ComponentProps} from '../utils/types' +import {useRefObjectAsForwardedRef} from '../hooks/useRefObjectAsForwardedRef' import {XIcon} from '@primer/octicons-react' // Dialog v1 diff --git a/packages/react/src/__tests__/Dialog.types.test.tsx b/packages/react/src/DialogV1/Dialog.types.test.tsx similarity index 87% rename from packages/react/src/__tests__/Dialog.types.test.tsx rename to packages/react/src/DialogV1/Dialog.types.test.tsx index de6b44c65ea..010f84f6fed 100644 --- a/packages/react/src/__tests__/Dialog.types.test.tsx +++ b/packages/react/src/DialogV1/Dialog.types.test.tsx @@ -1,5 +1,5 @@ import React from 'react' -import Dialog from '../Dialog' +import {Dialog} from '../DialogV1' export function shouldAcceptCallWithNoProps() { return diff --git a/packages/react/src/DialogV1/index.ts b/packages/react/src/DialogV1/index.ts new file mode 100644 index 00000000000..c12777c2acb --- /dev/null +++ b/packages/react/src/DialogV1/index.ts @@ -0,0 +1,2 @@ +export {default as Dialog} from './Dialog' +export type {DialogProps, DialogHeaderProps} from './Dialog' diff --git a/packages/react/src/FilteredActionList/FilteredActionListLoaders.tsx b/packages/react/src/FilteredActionList/FilteredActionListLoaders.tsx new file mode 100644 index 00000000000..61f2b904d24 --- /dev/null +++ b/packages/react/src/FilteredActionList/FilteredActionListLoaders.tsx @@ -0,0 +1,66 @@ +import React from 'react' +import Box from '../Box' +import Spinner from '../Spinner' +import {Stack} from '../Stack/Stack' +import {SkeletonBox} from '../experimental/Skeleton/SkeletonBox' + +export class FilteredActionListLoadingType { + public name: string + public appearsInBody: boolean + + constructor(name: string, appearsInBody: boolean) { + this.name = name + this.appearsInBody = appearsInBody + } +} + +export const FilteredActionListLoadingTypes = { + bodySpinner: new FilteredActionListLoadingType('body-spinner', true), + bodySkeleton: new FilteredActionListLoadingType('body-skeleton', true), + input: new FilteredActionListLoadingType('input', false), +} + +const SKELETON_ROW_HEIGHT = 24 +const SKELETON_MIN_ROWS = 3 + +export function FilteredActionListBodyLoader({ + loadingType, + height, +}: { + loadingType: FilteredActionListLoadingType + height: number +}): JSX.Element { + switch (loadingType) { + case FilteredActionListLoadingTypes.bodySpinner: + return + case FilteredActionListLoadingTypes.bodySkeleton: { + const rows = height < SKELETON_ROW_HEIGHT ? SKELETON_MIN_ROWS : height / SKELETON_ROW_HEIGHT + return + } + default: + return <> + } +} + +function LoadingSpinner({...props}): JSX.Element { + return ( + + + + ) +} + +function LoadingSkeleton({rows = 10, ...props}: {rows: number}): JSX.Element { + return ( + + + {Array.from({length: rows}, (_, i) => ( + + + + + ))} + + + ) +} diff --git a/packages/react/src/FilteredActionList/FilteredActionListWithDeprecatedActionList.tsx b/packages/react/src/FilteredActionList/FilteredActionListWithDeprecatedActionList.tsx index 0152247f387..64a4e481a9f 100644 --- a/packages/react/src/FilteredActionList/FilteredActionListWithDeprecatedActionList.tsx +++ b/packages/react/src/FilteredActionList/FilteredActionListWithDeprecatedActionList.tsx @@ -4,7 +4,6 @@ import type {KeyboardEventHandler} from 'react' import React, {useCallback, useEffect, useRef} from 'react' import styled from 'styled-components' import Box from '../Box' -import Spinner from '../Spinner' import type {TextInputProps} from '../TextInput' import TextInput from '../TextInput' import {get} from '../constants' @@ -17,6 +16,11 @@ import {useProvidedStateOrCreate} from '../hooks/useProvidedStateOrCreate' import useScrollFlash from '../hooks/useScrollFlash' import {VisuallyHidden} from '../VisuallyHidden' import type {SxProp} from '../sx' +import { + type FilteredActionListLoadingType, + FilteredActionListBodyLoader, + FilteredActionListLoadingTypes, +} from './FilteredActionListLoaders' const menuScrollMargins: ScrollIntoViewOptions = {startMargin: 0, endMargin: 8} @@ -25,9 +29,10 @@ export interface FilteredActionListProps ListPropsBase, SxProp { loading?: boolean + loadingType?: FilteredActionListLoadingType placeholderText?: string filterValue?: string - onFilterChange: (value: string, e: React.ChangeEvent) => void + onFilterChange: (value: string, e: React.ChangeEvent | null) => void textInputProps?: Partial> inputRef?: React.RefObject } @@ -39,6 +44,7 @@ const StyledHeader = styled.div` export function FilteredActionList({ loading = false, + loadingType = FilteredActionListLoadingTypes.bodySpinner, placeholderText, filterValue: externalFilterValue, onFilterChange, @@ -110,7 +116,7 @@ export function FilteredActionList({ useScrollFlash(scrollContainerRef) return ( - + Items will be filtered as you type - - {loading ? ( - - - + + {loading && scrollContainerRef.current && loadingType.appearsInBody ? ( + ) : ( )} diff --git a/packages/react/src/FilteredActionList/FilteredActionListWithModernActionList.tsx b/packages/react/src/FilteredActionList/FilteredActionListWithModernActionList.tsx index a3699cece07..0eca5708d86 100644 --- a/packages/react/src/FilteredActionList/FilteredActionListWithModernActionList.tsx +++ b/packages/react/src/FilteredActionList/FilteredActionListWithModernActionList.tsx @@ -4,7 +4,6 @@ import type {KeyboardEventHandler} from 'react' import React, {useCallback, useEffect, useRef} from 'react' import styled from 'styled-components' import Box from '../Box' -import Spinner from '../Spinner' import type {TextInputProps} from '../TextInput' import TextInput from '../TextInput' import {get} from '../constants' @@ -17,6 +16,8 @@ import {useProvidedStateOrCreate} from '../hooks/useProvidedStateOrCreate' import useScrollFlash from '../hooks/useScrollFlash' import {VisuallyHidden} from '../VisuallyHidden' import type {SxProp} from '../sx' +import type {FilteredActionListLoadingType} from './FilteredActionListLoaders' +import {FilteredActionListLoadingTypes, FilteredActionListBodyLoader} from './FilteredActionListLoaders' import {isValidElementType} from 'react-is' import type {RenderItemFn} from '../deprecated/ActionList/List' @@ -29,6 +30,7 @@ export interface FilteredActionListProps ListPropsBase, SxProp { loading?: boolean + loadingType?: FilteredActionListLoadingType placeholderText?: string filterValue?: string onFilterChange: (value: string, e: React.ChangeEvent) => void @@ -43,6 +45,7 @@ const StyledHeader = styled.div` export function FilteredActionList({ loading = false, + loadingType = FilteredActionListLoadingTypes.bodySpinner, placeholderText, filterValue: externalFilterValue, onFilterChange, @@ -146,17 +149,24 @@ export function FilteredActionList({ aria-controls={listId} aria-label={placeholderText} aria-describedby={inputDescriptionTextId} + loaderPosition={'leading'} + loading={loading && !loadingType.appearsInBody} {...textInputProps} /> Items will be filtered as you type - - {loading ? ( - - - + + {loading && scrollContainerRef.current && loadingType.appearsInBody ? ( + ) : ( - + {groupMetadata?.length ? groupMetadata.map((group, index) => { return ( diff --git a/packages/react/src/NavList/__snapshots__/NavList.test.tsx.snap b/packages/react/src/NavList/__snapshots__/NavList.test.tsx.snap index 837ba3e6eb9..a8eb41cec20 100644 --- a/packages/react/src/NavList/__snapshots__/NavList.test.tsx.snap +++ b/packages/react/src/NavList/__snapshots__/NavList.test.tsx.snap @@ -136,7 +136,7 @@ exports[`NavList renders a simple list 1`] = ` } .c2[data-is-active-descendant] { - font-weight: 600; + font-weight: 400; background-color: var(--control-transparent-bgColor-selected,var(--color-action-list-item-default-selected-bg,rgba(208,215,222,0.24))); } @@ -233,7 +233,7 @@ exports[`NavList renders a simple list 1`] = ` } .c7[data-is-active-descendant] { - font-weight: 600; + font-weight: 400; background-color: var(--control-transparent-bgColor-selected,var(--color-action-list-item-default-selected-bg,rgba(208,215,222,0.24))); } @@ -474,6 +474,20 @@ exports[`NavList renders with groups 1`] = ` color: var(--fgColor-muted,var(--color-fg-muted,#656d76)); } +.c3 .ActionListGroupHeading { + font-size: var(--text-body-size-small),12px; + font-weight: var(--base-text-weight-semibold,600); + line-height: var(--text-body-lineHeight-small,1.6666); + color: var(--fgColor-muted); +} + +.c3 .ActionListGroupHeadingDescription { + font-size: var(--text-body-size-small,12px); + font-weight: var(--base-text-weight-normal,400); + line-height: var(--text-body-lineHeight-small,1.6666); + color: var(--fgColor-muted); +} + .c4 { padding-inline-start: 0; } @@ -613,7 +627,7 @@ exports[`NavList renders with groups 1`] = ` } .c6[data-is-active-descendant] { - font-weight: 600; + font-weight: 400; background-color: var(--control-transparent-bgColor-selected,var(--color-action-list-item-default-selected-bg,rgba(208,215,222,0.24))); } @@ -710,7 +724,7 @@ exports[`NavList renders with groups 1`] = ` } .c11[data-is-active-descendant] { - font-weight: 600; + font-weight: 400; background-color: var(--control-transparent-bgColor-selected,var(--color-action-list-item-default-selected-bg,rgba(208,215,222,0.24))); } @@ -853,12 +867,16 @@ exports[`NavList renders with groups 1`] = `
  • -

    - Overview -

    +

    + Overview +

    +
      -

      - Components -

      +

      + Components +

      +
        = { - title: 'Components/Octicon', + title: 'Deprecated/Components/Octicon', component: Octicon, } export default meta diff --git a/packages/react/src/__tests__/Octicon.test.tsx b/packages/react/src/Octicon/Octicon.test.tsx similarity index 94% rename from packages/react/src/__tests__/Octicon.test.tsx rename to packages/react/src/Octicon/Octicon.test.tsx index 282ee99416b..173964c06e0 100644 --- a/packages/react/src/__tests__/Octicon.test.tsx +++ b/packages/react/src/Octicon/Octicon.test.tsx @@ -1,6 +1,6 @@ import React from 'react' import {XIcon} from '@primer/octicons-react' -import {Octicon} from '..' +import Octicon from '../Octicon' import {behavesAsComponent, checkExports} from '../utils/testing' import {render as HTMLRender} from '@testing-library/react' import axe from 'axe-core' diff --git a/packages/react/src/Octicon/Octicon.tsx b/packages/react/src/Octicon/Octicon.tsx index bd009a2792b..16df4c343b2 100644 --- a/packages/react/src/Octicon/Octicon.tsx +++ b/packages/react/src/Octicon/Octicon.tsx @@ -12,9 +12,15 @@ const Icon = React.forwardRef((props: StyledOcticonProps, ref: React.Ref }) +/** + * @deprecated + */ const Octicon = styled(Icon)` ${({color, sx: sxProp}) => sx({sx: {color, ...sxProp}})} ` +/** + * @deprecated + */ export type OcticonProps = ComponentProps export default Octicon diff --git a/packages/react/src/__tests__/Octicon.types.test.tsx b/packages/react/src/Octicon/Octicon.types.test.tsx similarity index 100% rename from packages/react/src/__tests__/Octicon.types.test.tsx rename to packages/react/src/Octicon/Octicon.types.test.tsx diff --git a/packages/react/src/PageHeader/PageHeader.examples.stories.tsx b/packages/react/src/PageHeader/PageHeader.examples.stories.tsx index ff4961563ad..ee066a61097 100644 --- a/packages/react/src/PageHeader/PageHeader.examples.stories.tsx +++ b/packages/react/src/PageHeader/PageHeader.examples.stories.tsx @@ -11,10 +11,10 @@ import { Box, PageLayout, Timeline, - Octicon, Heading, Token, } from '..' +import Octicon from '../Octicon' import { KebabHorizontalIcon, GitBranchIcon, diff --git a/packages/react/src/PageLayout/PageLayout.features.stories.tsx b/packages/react/src/PageLayout/PageLayout.features.stories.tsx index af5f5b18ef2..b75b0a9f63d 100644 --- a/packages/react/src/PageLayout/PageLayout.features.stories.tsx +++ b/packages/react/src/PageLayout/PageLayout.features.stories.tsx @@ -2,7 +2,8 @@ import React from 'react' import type {Meta, StoryFn} from '@storybook/react' import {PageLayout} from './PageLayout' import {Placeholder} from '../Placeholder' -import {Box, BranchName, Heading, Link, StateLabel, TabNav, Text} from '..' +import {Box, BranchName, Heading, Link, StateLabel, Text} from '..' +import TabNav from '../TabNav' export default { title: 'Components/PageLayout/Features', diff --git a/packages/react/src/Pagehead/Pagehead.docs.json b/packages/react/src/Pagehead/Pagehead.docs.json index 4eea4a5ba2c..c1f12fcda5b 100644 --- a/packages/react/src/Pagehead/Pagehead.docs.json +++ b/packages/react/src/Pagehead/Pagehead.docs.json @@ -1,10 +1,10 @@ { "id": "pagehead", "name": "Pagehead", - "status": "alpha", + "status": "deprecated", "a11yReviewed": false, "stories": [], - "importPath": "@primer/react", + "importPath": "@primer/react/deprecated", "props": [ { "name": "as", diff --git a/packages/react/src/Pagehead/Pagehead.stories.tsx b/packages/react/src/Pagehead/Pagehead.stories.tsx index f102b247631..ceea390c631 100644 --- a/packages/react/src/Pagehead/Pagehead.stories.tsx +++ b/packages/react/src/Pagehead/Pagehead.stories.tsx @@ -4,7 +4,7 @@ import Pagehead from './Pagehead' import Heading from '../Heading' export default { - title: 'Components/Pagehead', + title: 'Deprecated/Components/Pagehead', component: Pagehead, } as Meta diff --git a/packages/react/src/__tests__/Pagehead.test.tsx b/packages/react/src/Pagehead/Pagehead.test.tsx similarity index 94% rename from packages/react/src/__tests__/Pagehead.test.tsx rename to packages/react/src/Pagehead/Pagehead.test.tsx index 40a487afe3c..0c1fc8bad2b 100644 --- a/packages/react/src/__tests__/Pagehead.test.tsx +++ b/packages/react/src/Pagehead/Pagehead.test.tsx @@ -1,5 +1,5 @@ import React from 'react' -import {Pagehead} from '..' +import Pagehead from '../Pagehead' import theme from '../theme' import {behavesAsComponent, checkExports} from '../utils/testing' import {render as HTMLRender} from '@testing-library/react' diff --git a/packages/react/src/Pagehead/Pagehead.tsx b/packages/react/src/Pagehead/Pagehead.tsx index b32076f38fb..b4884414708 100644 --- a/packages/react/src/Pagehead/Pagehead.tsx +++ b/packages/react/src/Pagehead/Pagehead.tsx @@ -4,6 +4,9 @@ import type {SxProp} from '../sx' import sx from '../sx' import type {ComponentProps} from '../utils/types' +/** + * @deprecated + */ const Pagehead = styled.div` position: relative; padding-top: ${get('space.4')}; @@ -13,5 +16,8 @@ const Pagehead = styled.div` ${sx}; ` +/** + * @deprecated + */ export type PageheadProps = ComponentProps export default Pagehead diff --git a/packages/react/src/__tests__/Pagehead.types.test.tsx b/packages/react/src/Pagehead/Pagehead.types.test.tsx similarity index 100% rename from packages/react/src/__tests__/Pagehead.types.test.tsx rename to packages/react/src/Pagehead/Pagehead.types.test.tsx diff --git a/packages/react/src/Pagination/Pagination.tsx b/packages/react/src/Pagination/Pagination.tsx index 616272ffd5a..db3671c8dd8 100644 --- a/packages/react/src/Pagination/Pagination.tsx +++ b/packages/react/src/Pagination/Pagination.tsx @@ -4,7 +4,6 @@ import Box from '../Box' import {get} from '../constants' import type {SxProp} from '../sx' import sx from '../sx' -import getGlobalFocusStyles from '../internal/utils/getGlobalFocusStyles' import {buildComponentData, buildPaginationModel} from './model' import type {ResponsiveValue} from '../hooks/useResponsiveValue' import {viewportRanges} from '../hooks/useResponsiveValue' @@ -56,7 +55,10 @@ const Page = styled.a` transition-duration: 0.1s; } - ${getGlobalFocusStyles(0)}; + &:focus-visible { + outline: 2px solid ${get('colors.accent.emphasis')}; + outline-offset: -2px; + } &:active { border-color: ${get('colors.border.muted')}; @@ -74,6 +76,12 @@ const Page = styled.a` border-color: transparent; } + &[aria-current]:focus-visible { + outline: 2px solid ${get('colors.accent.emphasis')}; + outline-offset: -2px; + box-shadow: inset 0 0 0 3px ${get('colors.fg.onEmphasis')}; + } + &[aria-disabled], &[aria-disabled]:hover { margin: 0 2px; @@ -196,7 +204,7 @@ const PaginationContainer = styled.nav` .TablePaginationSteps[data-hidden-viewport-ranges*='${viewportRangeKey}'] > *:first-child { margin-inline-end: 0; } - + .TablePaginationSteps[data-hidden-viewport-ranges*='${viewportRangeKey}'] > *:last-child { margin-inline-start: 0; } diff --git a/packages/react/src/SegmentedControl/SegmentedControl.tsx b/packages/react/src/SegmentedControl/SegmentedControl.tsx index cf838c21b4a..fe9190e35dd 100644 --- a/packages/react/src/SegmentedControl/SegmentedControl.tsx +++ b/packages/react/src/SegmentedControl/SegmentedControl.tsx @@ -13,6 +13,7 @@ import {useResponsiveValue} from '../hooks/useResponsiveValue' import type {WidthOnlyViewportRangeKeys} from '../utils/types/ViewportRangeKeys' import styled from 'styled-components' import {defaultSxProp} from '../utils/defaultSxProp' +import {isElement} from 'react-is' // Needed because passing a ref to `Box` causes a type error const SegmentedControlList = styled.ul` @@ -80,16 +81,33 @@ const Root: React.FC> = ({ ) ? React.Children.toArray(children)[selectedIndex] : undefined - const getChildIcon = (childArg: React.ReactNode) => { + const getChildIcon = (childArg: React.ReactNode): React.ReactElement | null => { if ( React.isValidElement(childArg) && childArg.type === Button && childArg.props.leadingIcon ) { - return childArg.props.leadingIcon + if (isElement(childArg.props.leadingIcon)) { + return childArg.props.leadingIcon + } else { + const LeadingIcon = childArg.props.leadingIcon + return + } } - return React.isValidElement(childArg) ? childArg.props.icon : null + if ( + React.isValidElement(childArg) && + childArg.type === SegmentedControlIconButton + ) { + if (isElement(childArg.props.icon)) { + childArg.props.icon + } else { + const Icon = childArg.props.icon + return + } + } + + return null } const getChildText = (childArg: React.ReactNode) => { if (React.isValidElement(childArg) && childArg.type === Button) { @@ -140,7 +158,7 @@ const Root: React.FC> = ({ child.props.onClick && child.props.onClick(event as React.MouseEvent) }} > - {ChildIcon && } {getChildText(child)} + {ChildIcon} {getChildText(child)} ) })} diff --git a/packages/react/src/SegmentedControl/SegmentedControl.types.test.tsx b/packages/react/src/SegmentedControl/SegmentedControl.types.test.tsx new file mode 100644 index 00000000000..2d0dd73a461 --- /dev/null +++ b/packages/react/src/SegmentedControl/SegmentedControl.types.test.tsx @@ -0,0 +1,21 @@ +import {LogoGithubIcon} from '@primer/octicons-react' +import {SegmentedControl} from './SegmentedControl' +import React from 'react' + +export function buttonWithLeadingIconElement() { + return ( + + }>Button + + ) +} + +export function iconButtonWithIconElement() { + return ( + + }> + Button + + + ) +} diff --git a/packages/react/src/SegmentedControl/SegmentedControlButton.tsx b/packages/react/src/SegmentedControl/SegmentedControlButton.tsx index 58003d167f5..e295ce7f341 100644 --- a/packages/react/src/SegmentedControl/SegmentedControlButton.tsx +++ b/packages/react/src/SegmentedControl/SegmentedControlButton.tsx @@ -7,6 +7,8 @@ import type {SxProp} from '../sx' import sx, {merge} from '../sx' import {getSegmentedControlButtonStyles, getSegmentedControlListItemStyles} from './getSegmentedControlStyles' import {defaultSxProp} from '../utils/defaultSxProp' +import {isElement} from 'react-is' +import getGlobalFocusStyles from '../internal/utils/getGlobalFocusStyles' export type SegmentedControlButtonProps = { /** The visible label rendered in the button */ @@ -16,11 +18,12 @@ export type SegmentedControlButtonProps = { /** Whether the segment is selected. This is used for uncontrolled `SegmentedControls` to pick one `SegmentedControlButton` that is selected on the initial render. */ defaultSelected?: boolean /** The leading icon comes before item label */ - leadingIcon?: React.FunctionComponent> + leadingIcon?: React.FunctionComponent> | React.ReactElement } & SxProp & ButtonHTMLAttributes const SegmentedControlButtonStyled = styled.button` + ${getGlobalFocusStyles()}; ${sx}; ` @@ -42,11 +45,7 @@ const SegmentedControlButton: React.FC - {LeadingIcon && ( - - - - )} + {LeadingIcon && {isElement(LeadingIcon) ? LeadingIcon : }} {children} diff --git a/packages/react/src/SegmentedControl/SegmentedControlIconButton.tsx b/packages/react/src/SegmentedControl/SegmentedControlIconButton.tsx index 11970c0ab47..dbd8b13ca1b 100644 --- a/packages/react/src/SegmentedControl/SegmentedControlIconButton.tsx +++ b/packages/react/src/SegmentedControl/SegmentedControlIconButton.tsx @@ -7,11 +7,13 @@ import sx, {merge} from '../sx' import {getSegmentedControlButtonStyles, getSegmentedControlListItemStyles} from './getSegmentedControlStyles' import Box from '../Box' import {defaultSxProp} from '../utils/defaultSxProp' +import {isElement} from 'react-is' +import getGlobalFocusStyles from '../internal/utils/getGlobalFocusStyles' export type SegmentedControlIconButtonProps = { 'aria-label': string /** The icon that represents the segmented control item */ - icon: React.FunctionComponent> + icon: React.FunctionComponent> | React.ReactElement /** Whether the segment is selected. This is used for controlled SegmentedControls, and needs to be updated using the onChange handler on SegmentedControl. */ selected?: boolean /** Whether the segment is selected. This is used for uncontrolled SegmentedControls to pick one SegmentedControlButton that is selected on the initial render. */ @@ -20,6 +22,7 @@ export type SegmentedControlIconButtonProps = { ButtonHTMLAttributes const SegmentedControlIconButtonStyled = styled.button` + ${getGlobalFocusStyles()}; ${sx}; ` @@ -53,9 +56,7 @@ export const SegmentedControlIconButton: React.FC - - - + {isElement(Icon) ? Icon : } ) diff --git a/packages/react/src/SelectPanel/SelectPanel.examples.stories.tsx b/packages/react/src/SelectPanel/SelectPanel.examples.stories.tsx index 248432e0f9a..3f8c41fc254 100644 --- a/packages/react/src/SelectPanel/SelectPanel.examples.stories.tsx +++ b/packages/react/src/SelectPanel/SelectPanel.examples.stories.tsx @@ -137,7 +137,6 @@ export const HeightInitialWithUnderflowingItemsAfterFetch = () => { placeholderText="Filter Labels" open={open} onOpenChange={onOpenChange} - loading={filteredItems.length === 0} items={filteredItems} selected={selected} onSelectedChange={setSelected} @@ -309,3 +308,39 @@ export const CustomItemRenderer = () => { ) } + +export const ItemsInScope = () => { + // items are defined in the same scope as selection, so they could rerender and create new object references + // We use item.id to track selection + // Reported in: https://github.com/primer/react/issues/4315 + const items = [ + {text: 'enhancement', id: 1}, + {text: 'bug', id: 2}, + {text: 'good first issue', id: 3}, + {text: 'design', id: 4}, + {text: 'blocker', id: 5}, + {text: 'backend', id: 6}, + {text: 'frontend', id: 7}, + ] + + const [selected, setSelected] = React.useState([items[0], items[1]]) + const [open, setOpen] = useState(false) + const [filter, setFilter] = React.useState('') + const filteredItems = items.filter(item => item.text.toLowerCase().startsWith(filter.toLowerCase())) + + return ( + <> +

        Items in component scope

        + + + ) +} diff --git a/packages/react/src/SelectPanel/SelectPanel.features.stories.tsx b/packages/react/src/SelectPanel/SelectPanel.features.stories.tsx index da4bb2084be..af59b621ba0 100644 --- a/packages/react/src/SelectPanel/SelectPanel.features.stories.tsx +++ b/packages/react/src/SelectPanel/SelectPanel.features.stories.tsx @@ -1,5 +1,5 @@ import React, {useState, useRef, useMemo} from 'react' -import type {Meta} from '@storybook/react' +import type {Meta, StoryObj} from '@storybook/react' import Box from '../Box' import {Button} from '../Button' import type {ItemInput, GroupedListProps} from '../deprecated/ActionList/List' @@ -14,6 +14,7 @@ import { TypographyIcon, VersionsIcon, } from '@primer/octicons-react' +import useSafeTimeout from '../hooks/useSafeTimeout' const meta = { title: 'Components/SelectPanel/Features', @@ -369,3 +370,63 @@ export const WithGroups = () => { /> ) } + +export const AsyncFetch: StoryObj = { + render: ({initialLoadingType, height}) => { + const [selected, setSelected] = React.useState([]) + const [filteredItems, setFilteredItems] = React.useState([]) + const [open, setOpen] = useState(false) + const filterTimerId = useRef(null) + const {safeSetTimeout, safeClearTimeout} = useSafeTimeout() + const onFilterChange = (value: string) => { + if (filterTimerId.current) { + safeClearTimeout(filterTimerId.current) + } + + filterTimerId.current = safeSetTimeout(() => { + setFilteredItems(items.filter(item => item.text.toLowerCase().startsWith(value.toLowerCase()))) + }, 2000) as unknown as number + } + + return ( + ( + + )} + placeholderText="Filter labels" + open={open} + onOpenChange={setOpen} + items={filteredItems} + selected={selected} + onSelectedChange={setSelected} + onFilterChange={onFilterChange} + showItemDividers={true} + initialLoadingType={initialLoadingType} + height={height} + /> + ) + }, + args: { + initialLoadingType: 'spinner', + height: 'medium', + }, + argTypes: { + initialLoadingType: { + control: 'select', + options: ['spinner', 'skeleton'], + }, + height: { + control: 'select', + options: ['auto', 'xsmall', 'small', 'medium', 'large', 'xlarge'], + }, + }, +} diff --git a/packages/react/src/SelectPanel/SelectPanel.stories.tsx b/packages/react/src/SelectPanel/SelectPanel.stories.tsx index a8951c1211a..a52757c539b 100644 --- a/packages/react/src/SelectPanel/SelectPanel.stories.tsx +++ b/packages/react/src/SelectPanel/SelectPanel.stories.tsx @@ -33,20 +33,20 @@ function getColorCircle(color: string) { } } -const items = [ - {leadingVisual: getColorCircle('#a2eeef'), text: 'enhancement', id: 1}, - {leadingVisual: getColorCircle('#d73a4a'), text: 'bug', id: 2}, - {leadingVisual: getColorCircle('#0cf478'), text: 'good first issue', id: 3}, +const items: ItemInput[] = [ + {leadingVisual: getColorCircle('#a2eeef'), text: 'enhancement', description: 'New feature or request', id: 1}, + {leadingVisual: getColorCircle('#d73a4a'), text: 'bug', description: "Something isn't working", id: 2}, + {leadingVisual: getColorCircle('#0cf478'), text: 'good first issue', description: 'Good for newcomers', id: 3}, {leadingVisual: getColorCircle('#ffd78e'), text: 'design', id: 4}, {leadingVisual: getColorCircle('#ff0000'), text: 'blocker', id: 5}, {leadingVisual: getColorCircle('#a4f287'), text: 'backend', id: 6}, {leadingVisual: getColorCircle('#8dc6fc'), text: 'frontend', id: 7}, -] +].map(item => ({...item, descriptionVariant: 'block'})) export const Default = () => { const [selected, setSelected] = React.useState([items[0], items[1]]) const [filter, setFilter] = React.useState('') - const filteredItems = items.filter(item => item.text.toLowerCase().startsWith(filter.toLowerCase())) + const filteredItems = items.filter(item => item.text?.toLowerCase().startsWith(filter.toLowerCase())) const [open, setOpen] = useState(false) return ( diff --git a/packages/react/src/SelectPanel/SelectPanel.test.tsx b/packages/react/src/SelectPanel/SelectPanel.test.tsx index 936f3b544fc..6a23226cc3d 100644 --- a/packages/react/src/SelectPanel/SelectPanel.test.tsx +++ b/packages/react/src/SelectPanel/SelectPanel.test.tsx @@ -5,6 +5,7 @@ import type {ItemInput, GroupedListProps} from '../deprecated/ActionList/List' import {userEvent} from '@testing-library/user-event' import ThemeProvider from '../ThemeProvider' import {FeatureFlags} from '../FeatureFlags' +import type {InitialLoadingType} from './SelectPanel' import {getLiveRegion} from '../utils/testing' const renderWithFlag = (children: React.ReactNode, flag: boolean) => { @@ -335,6 +336,53 @@ for (const useModernActionList of [false, true]) { screen.getByRole('option', {name: 'item one'}).id, ) }) + + it('should select an item (by item.id) even when items are defined in the component', async () => { + const user = userEvent.setup() + + function Fixture() { + // items are defined in the same scope as selection, so they could rerender and create new object references + // We use item.id to track selection + const items: SelectPanelProps['items'] = [ + {id: 'one', text: 'item one'}, + {id: 'two', text: 'item two'}, + {id: 'three', text: 'item three'}, + ] + + const [open, setOpen] = React.useState(false) + const [selected, setSelected] = React.useState([]) + const [filter, setFilter] = React.useState('') + + return ( + + + + ) + } + + renderWithFlag(, useModernActionList) + + await user.click(screen.getByText('Select items')) + + await user.click(screen.getByText('item one')) + expect(screen.getByRole('option', {name: 'item one'})).toHaveAttribute('aria-selected', 'true') + + await user.click(screen.getByText('item two')) + expect(screen.getByRole('option', {name: 'item two'})).toHaveAttribute('aria-selected', 'true') + + await user.click(screen.getByRole('option', {name: 'item one'})) + expect(screen.getByRole('option', {name: 'item one'})).toHaveAttribute('aria-selected', 'false') + }) }) function FilterableSelectPanel() { @@ -388,6 +436,71 @@ for (const useModernActionList of [false, true]) { // this is only implemented with the feature flag if (!useModernActionList) return + function LoadingSelectPanel({ + initialLoadingType = 'spinner', + items = [], + }: { + initialLoadingType?: InitialLoadingType + items?: SelectPanelProps['items'] + }) { + const [open, setOpen] = React.useState(false) + + return ( + + {}} + selected={[]} + onSelectedChange={() => {}} + onOpenChange={isOpen => { + setOpen(isOpen) + }} + initialLoadingType={initialLoadingType} + /> + + ) + } + + it('displays a loading spinner on first open', async () => { + const user = userEvent.setup() + + renderWithFlag(, useModernActionList) + + await user.click(screen.getByText('Select items')) + + expect(screen.getByTestId('filtered-action-list-spinner')).toBeTruthy() + }) + + it('displays a loading skeleton on first open', async () => { + const user = userEvent.setup() + + renderWithFlag(, useModernActionList) + + await user.click(screen.getByText('Select items')) + + expect(screen.getByTestId('filtered-action-list-skeleton')).toBeTruthy() + }) + + it('displays a loading spinner in the text input if items are already loaded', async () => { + const user = userEvent.setup() + + renderWithFlag(, useModernActionList) + + await user.click(screen.getByText('Select items')) + + expect(screen.getAllByRole('option')).toHaveLength(3) + + // since the test never repopulates the panel's list of items, the panel will enter + // the loading state after the following line executes and stay there indefinitely + await user.type(document.activeElement!, 'two') + + expect(screen.getByTestId('text-input-leading-visual')).toBeTruthy() + }) + it('should announce initial focused item', async () => { const user = userEvent.setup() renderWithFlag(, useModernActionList) diff --git a/packages/react/src/SelectPanel/SelectPanel.tsx b/packages/react/src/SelectPanel/SelectPanel.tsx index efae1b5a7e1..73b09f0491d 100644 --- a/packages/react/src/SelectPanel/SelectPanel.tsx +++ b/packages/react/src/SelectPanel/SelectPanel.tsx @@ -1,5 +1,5 @@ import {SearchIcon, TriangleDownIcon} from '@primer/octicons-react' -import React, {useCallback, useMemo} from 'react' +import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react' import type {AnchoredOverlayProps} from '../AnchoredOverlay' import {AnchoredOverlay} from '../AnchoredOverlay' import type {AnchoredOverlayWrapperAnchorProps} from '../AnchoredOverlay/AnchoredOverlay' @@ -17,6 +17,9 @@ import type {FocusZoneHookSettings} from '../hooks/useFocusZone' import {useId} from '../hooks/useId' import {useProvidedStateOrCreate} from '../hooks/useProvidedStateOrCreate' import {LiveRegion, LiveRegionOutlet, Message} from '../internal/components/LiveRegion' +import useSafeTimeout from '../hooks/useSafeTimeout' +import type {FilteredActionListLoadingType} from '../FilteredActionList/FilteredActionListLoaders' +import {FilteredActionListLoadingTypes} from '../FilteredActionList/FilteredActionListLoaders' import {useFeatureFlag} from '../FeatureFlags' interface SelectPanelSingleSelection { @@ -29,6 +32,8 @@ interface SelectPanelMultiSelection { onSelectedChange: (selected: ItemInput[]) => void } +export type InitialLoadingType = 'spinner' | 'skeleton' + interface SelectPanelBaseProps { // TODO: Make `title` required in the next major version title?: string | React.ReactElement @@ -42,11 +47,12 @@ interface SelectPanelBaseProps { inputLabel?: string overlayProps?: Partial footer?: string | React.ReactElement + initialLoadingType?: InitialLoadingType } export type SelectPanelProps = SelectPanelBaseProps & Omit & - Pick & + Pick & AnchoredOverlayWrapperAnchorProps & (SelectPanelSingleSelection | SelectPanelMultiSelection) @@ -61,6 +67,16 @@ const focusZoneSettings: Partial = { disabled: true, } +const areItemsEqual = (itemA: ItemInput, itemB: ItemInput) => { + // prefer checking equivality by item.id + if (typeof itemA.id !== 'undefined') return itemA.id === itemB.id + else return itemA === itemB +} + +const doesItemsIncludeItem = (items: ItemInput[], item: ItemInput) => { + return items.some(i => areItemsEqual(i, item)) +} + export function SelectPanel({ open, onOpenChange, @@ -87,19 +103,78 @@ export function SelectPanel({ textInputProps, overlayProps, sx, + loading, + initialLoadingType = 'spinner', + height, ...listProps }: SelectPanelProps): JSX.Element { + const inputRef = React.useRef(null) const titleId = useId() const subtitleId = useId() + const [dataLoadedOnce, setDataLoadedOnce] = useState(false) + const [isLoading, setIsLoading] = useProvidedStateOrCreate(loading, undefined, false) const [filterValue, setInternalFilterValue] = useProvidedStateOrCreate(externalFilterValue, undefined, '') + const {safeSetTimeout, safeClearTimeout} = useSafeTimeout() + const loadingDelayTimeoutId = useRef(null) const onFilterChange: FilteredActionListProps['onFilterChange'] = useCallback( (value, e) => { + if (dataLoadedOnce) { + // If data has already been loaded once, delay the spinner a bit. This also helps + // not show and then immediately hide the spinner if items are loaded quickly, i.e. + // not async. + + if (loadingDelayTimeoutId.current) { + safeClearTimeout(loadingDelayTimeoutId.current) + } + + loadingDelayTimeoutId.current = safeSetTimeout(() => setIsLoading(true), 1000) + } else { + // If this is the first data load and there are no items, show the loading spinner + // immediately + + if (items.length === 0) { + setIsLoading(true) + } + } + externalOnFilterChange(value, e) setInternalFilterValue(value) }, - [externalOnFilterChange, setInternalFilterValue], + [ + dataLoadedOnce, + externalOnFilterChange, + setInternalFilterValue, + safeSetTimeout, + safeClearTimeout, + setIsLoading, + items.length, + ], ) + useEffect(() => { + if (isLoading) { + setIsLoading(false) + setDataLoadedOnce(true) + } + // Only fire this effect if items have changed + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [items]) + + // Populate panel with items on first open + useEffect(() => { + // If data was already loaded once, do nothing + if (dataLoadedOnce) return + + // Only load data when the panel is open + if (open) { + // Only trigger filter change event if there are no items + if (items.length === 0) { + // Trigger filter event to populate panel on first open + onFilterChange(filterValue, null) + } + } + }, [open, dataLoadedOnce, onFilterChange, filterValue, items]) + const anchorRef = useProvidedRefOrCreate(externalAnchorRef) const onOpen: AnchoredOverlayProps['onOpen'] = useCallback( (gesture: Parameters>[0]) => onOpenChange(true, gesture), @@ -129,7 +204,7 @@ export function SelectPanel({ const itemsToRender = useMemo(() => { return items.map(item => { - const isItemSelected = isMultiSelectVariant(selected) ? selected.includes(item) : selected === item + const isItemSelected = isMultiSelectVariant(selected) ? doesItemsIncludeItem(selected, item) : selected === item return { ...item, @@ -143,8 +218,10 @@ export function SelectPanel({ } if (isMultiSelectVariant(selected)) { - const otherSelectedItems = selected.filter(selectedItem => selectedItem !== item) - const newSelectedItems = selected.includes(item) ? otherSelectedItems : [...otherSelectedItems, item] + const otherSelectedItems = selected.filter(selectedItem => !areItemsEqual(selectedItem, item)) + const newSelectedItems = doesItemsIncludeItem(selected, item) + ? otherSelectedItems + : [...otherSelectedItems, item] const multiSelectOnChange = onSelectedChange as SelectPanelMultiSelection['onSelectedChange'] multiSelectOnChange(newSelectedItems) @@ -160,7 +237,6 @@ export function SelectPanel({ }) }, [onClose, onSelectedChange, items, selected]) - const inputRef = React.useRef(null) const focusTrapSettings = { initialFocusRef: inputRef, } @@ -175,6 +251,17 @@ export function SelectPanel({ } }, [inputLabel, textInputProps]) + const loadingType = (): FilteredActionListLoadingType => { + if (dataLoadedOnce) { + return FilteredActionListLoadingTypes.input + } else { + if (initialLoadingType === 'spinner') { + return FilteredActionListLoadingTypes.bodySpinner + } else { + return FilteredActionListLoadingTypes.bodySkeleton + } + } + } const usingModernActionList = useFeatureFlag('primer_react_select_panel_with_modern_action_list') return ( @@ -193,6 +280,7 @@ export function SelectPanel({ }} focusTrapSettings={focusTrapSettings} focusZoneSettings={focusZoneSettings} + height={height} > {usingModernActionList ? null : ( @@ -231,6 +319,8 @@ export function SelectPanel({ items={itemsToRender} textInputProps={extendedTextInputProps} inputRef={inputRef} + loading={isLoading} + loadingType={loadingType()} // inheriting height and maxHeight ensures that the FilteredActionList is never taller // than the Overlay (which would break scrolling the items) sx={{...sx, height: 'inherit', maxHeight: 'inherit'}} diff --git a/packages/react/src/TabNav/TabNav.docs.json b/packages/react/src/TabNav/TabNav.docs.json index afd1169fdba..86afe4816cb 100644 --- a/packages/react/src/TabNav/TabNav.docs.json +++ b/packages/react/src/TabNav/TabNav.docs.json @@ -1,10 +1,10 @@ { "id": "tab_nav", "name": "TabNav", - "status": "alpha", + "status": "deprecated", "a11yReviewed": false, "stories": [], - "importPath": "@primer/react", + "importPath": "@primer/react/deprecated", "props": [ { "name": "aria-label", diff --git a/packages/react/src/TabNav/TabNav.features.stories.tsx b/packages/react/src/TabNav/TabNav.features.stories.tsx index 994d1d3ccdf..e885a723f69 100644 --- a/packages/react/src/TabNav/TabNav.features.stories.tsx +++ b/packages/react/src/TabNav/TabNav.features.stories.tsx @@ -4,7 +4,7 @@ import TabNav from './TabNav' import type {ComponentProps} from '../utils/types' export default { - title: 'Components/TabNav/Features', + title: 'Deprecated/Components/TabNav/Features', component: TabNav, subcomponents: { 'TabNav.Link': TabNav.Link, diff --git a/packages/react/src/TabNav/TabNav.stories.tsx b/packages/react/src/TabNav/TabNav.stories.tsx index a8ce31c167a..d0e5cdb3920 100644 --- a/packages/react/src/TabNav/TabNav.stories.tsx +++ b/packages/react/src/TabNav/TabNav.stories.tsx @@ -4,7 +4,7 @@ import TabNav from './TabNav' import type {ComponentProps} from '../utils/types' export default { - title: 'Components/TabNav', + title: 'Deprecated/Components/TabNav', component: TabNav, subcomponents: { 'TabNav.Link': TabNav.Link, diff --git a/packages/react/src/TabNav/TabNav.tsx b/packages/react/src/TabNav/TabNav.tsx index 26f94497440..b634e89c264 100644 --- a/packages/react/src/TabNav/TabNav.tsx +++ b/packages/react/src/TabNav/TabNav.tsx @@ -28,8 +28,14 @@ const TabNavNav = styled.nav` border-bottom: 1px solid ${get('colors.border.default')}; ` +/** + * @deprecated + */ export type TabNavProps = ComponentProps +/** + * @deprecated + */ function TabNav({children, 'aria-label': ariaLabel, ...rest}: TabNavProps) { const customContainerRef = useRef(null) @@ -75,12 +81,18 @@ function TabNav({children, 'aria-label': ariaLabel, ...rest}: TabNavProps) { ) } +/** + * @deprecated + */ export type TabNavLinkProps = React.DetailedHTMLProps, HTMLAnchorElement> & { to?: To selected?: boolean href?: string } & SxProp +/** + * @deprecated + */ const TabNavLink = styled.a.attrs(props => ({ className: clsx(ITEM_CLASS, props.selected && SELECTED_CLASS, props.className), role: 'tab', diff --git a/packages/react/src/Text/Text.tsx b/packages/react/src/Text/Text.tsx index 3f7ee333b97..9bad8d5d923 100644 --- a/packages/react/src/Text/Text.tsx +++ b/packages/react/src/Text/Text.tsx @@ -58,14 +58,27 @@ const StyledText = styled.span` ${sx}; ` +const COMMON_PROP_NAMES = new Set(Object.keys(COMMON)) +const TYPOGRAPHY_PROP_NAMES = new Set(Object.keys(TYPOGRAPHY)) + +const includesSystemProps = (props: StyledTextProps) => { + if (props.sx) { + return true + } + + return Object.keys(props).some(prop => { + return TYPOGRAPHY_PROP_NAMES.has(prop) || COMMON_PROP_NAMES.has(prop) + }) +} + const Text = forwardRef(({as: Component = 'span', className, size, weight, ...props}, forwardedRef) => { const enabled = useFeatureFlag('primer_react_css_modules_ga') const innerRef = React.useRef(null) useRefObjectAsForwardedRef(forwardedRef, innerRef) - if (enabled) { - if (props.sx) { + // If props includes TYPOGRAPHY or COMMON props, pass them to the Box component + if (includesSystemProps(props)) { return ( // @ts-ignore shh ( + + + First name + + + + Last name + + + +) diff --git a/packages/react/src/TextInput/TextInput.tsx b/packages/react/src/TextInput/TextInput.tsx index e2d2acd0736..5c48174ce49 100644 --- a/packages/react/src/TextInput/TextInput.tsx +++ b/packages/react/src/TextInput/TextInput.tsx @@ -137,6 +137,7 @@ const TextInput = React.forwardRef( visualPosition="leading" showLoadingIndicator={showLeadingLoadingIndicator} hasLoadingIndicator={typeof loading === 'boolean'} + data-testid="text-input-leading-visual" > {typeof LeadingVisual !== 'string' && isValidElementType(LeadingVisual) ? : LeadingVisual} @@ -155,6 +156,7 @@ const TextInput = React.forwardRef( visualPosition="trailing" showLoadingIndicator={showTrailingLoadingIndicator} hasLoadingIndicator={typeof loading === 'boolean'} + data-testid="text-input-trailing-visual" > {typeof TrailingVisual !== 'string' && isValidElementType(TrailingVisual) ? ( diff --git a/packages/react/src/Timeline/Timeline.features.stories.tsx b/packages/react/src/Timeline/Timeline.features.stories.tsx index fd9815595d3..0a6731096ff 100644 --- a/packages/react/src/Timeline/Timeline.features.stories.tsx +++ b/packages/react/src/Timeline/Timeline.features.stories.tsx @@ -76,7 +76,11 @@ export const WithInlineLinks = () => ( - + Monalisa enabled auto-merge (squash) diff --git a/packages/react/src/Tooltip/Tooltip.docs.json b/packages/react/src/Tooltip/Tooltip.docs.json index f789ac60bb0..f58dca45119 100644 --- a/packages/react/src/Tooltip/Tooltip.docs.json +++ b/packages/react/src/Tooltip/Tooltip.docs.json @@ -2,10 +2,10 @@ "id": "tooltip", "name": "Tooltip", "docsId": "tooltip", - "status": "alpha", + "status": "deprecated", "a11yReviewed": false, "stories": [], - "importPath": "@primer/react", + "importPath": "@primer/react/deprecated", "props": [ { "name": "align", diff --git a/packages/react/src/Tooltip/Tooltip.features.stories.tsx b/packages/react/src/Tooltip/Tooltip.features.stories.tsx index a977be340db..cbff56035a9 100644 --- a/packages/react/src/Tooltip/Tooltip.features.stories.tsx +++ b/packages/react/src/Tooltip/Tooltip.features.stories.tsx @@ -8,7 +8,7 @@ import {SearchIcon} from '@primer/octicons-react' /* Tooltip v1 */ export default { - title: 'Components/Tooltip/Features', + title: 'Deprecated/Components/Tooltip/Features', component: Tooltip, decorators: [ diff --git a/packages/react/src/Tooltip/Tooltip.stories.tsx b/packages/react/src/Tooltip/Tooltip.stories.tsx index 02b00559a56..39615cc9f7c 100644 --- a/packages/react/src/Tooltip/Tooltip.stories.tsx +++ b/packages/react/src/Tooltip/Tooltip.stories.tsx @@ -9,7 +9,7 @@ import Tooltip from './Tooltip' /* Tooltip v1 */ export default { - title: 'Components/Tooltip', + title: 'Deprecated/Components/Tooltip', component: Tooltip, decorators: [ diff --git a/packages/react/src/Tooltip/Tooltip.tsx b/packages/react/src/Tooltip/Tooltip.tsx index 70d8f624033..06a17b47941 100644 --- a/packages/react/src/Tooltip/Tooltip.tsx +++ b/packages/react/src/Tooltip/Tooltip.tsx @@ -186,6 +186,9 @@ const TooltipBase = styled.span` ${sx}; ` +/** + * @deprecated + */ export type TooltipProps = { direction?: 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw' text?: string @@ -195,6 +198,10 @@ export type TooltipProps = { } & ComponentProps export const TooltipContext = React.createContext<{tooltipId?: string}>({}) + +/** + * @deprecated + */ function Tooltip({direction = 'n', children, className, text, noDelay, align, wrap, id, ...rest}: TooltipProps) { const tooltipId = useId(id) const classes = clsx( diff --git a/packages/react/src/TooltipV2/Tooltip.features.stories.tsx b/packages/react/src/TooltipV2/Tooltip.features.stories.tsx index 59cda469fc6..2819aef6dd3 100644 --- a/packages/react/src/TooltipV2/Tooltip.features.stories.tsx +++ b/packages/react/src/TooltipV2/Tooltip.features.stories.tsx @@ -1,5 +1,6 @@ import React from 'react' -import {IconButton, Button, Box, Link, Octicon, ActionMenu, ActionList} from '..' +import {IconButton, Button, Box, Link, ActionMenu, ActionList} from '..' +import Octicon from '../Octicon' import {Tooltip} from './Tooltip' import {SearchIcon, BookIcon, CheckIcon, TriangleDownIcon, GitBranchIcon} from '@primer/octicons-react' diff --git a/packages/react/src/TooltipV2/Tooltip.tsx b/packages/react/src/TooltipV2/Tooltip.tsx index ab5c5fe6648..4c574664b31 100644 --- a/packages/react/src/TooltipV2/Tooltip.tsx +++ b/packages/react/src/TooltipV2/Tooltip.tsx @@ -133,7 +133,7 @@ export type TooltipProps = React.PropsWithChildren< ComponentProps > -export type TriggerPropsType = { +type TriggerPropsType = { 'aria-describedby'?: string 'aria-labelledby'?: string 'aria-label'?: string @@ -328,8 +328,8 @@ export const Tooltip = React.forwardRef( {...rest} // Only need tooltip role if the tooltip is a description for supplementary information role={type === 'description' ? 'tooltip' : undefined} - // stop AT from announcing the tooltip twice when it is a label type because it will be announced with "aria-labelledby" - aria-hidden={type === 'label' ? true : undefined} + // stop AT from announcing the tooltip twice: when it is a label type it will be announced with "aria-labelledby",when it is a description type it will be announced with "aria-describedby" + aria-hidden={true} id={tooltipId} // mouse leave and enter on the tooltip itself is needed to keep the tooltip open when the mouse is over the tooltip onMouseEnter={openTooltip} diff --git a/packages/react/src/TooltipV2/__tests__/Tooltip.test.tsx b/packages/react/src/TooltipV2/__tests__/Tooltip.test.tsx index 0bf8c8b3149..a088914a114 100644 --- a/packages/react/src/TooltipV2/__tests__/Tooltip.test.tsx +++ b/packages/react/src/TooltipV2/__tests__/Tooltip.test.tsx @@ -51,6 +51,10 @@ describe('Tooltip', () => { const {getByText} = HTMLRender() expect(getByText('Tooltip text')).toHaveAttribute('aria-hidden', 'true') }) + it('should render aria-hidden on the tooltip element when the tooltip is description type', () => { + const {getByText} = HTMLRender() + expect(getByText('Tooltip text')).toHaveAttribute('aria-hidden', 'true') + }) it('should describe the trigger element by its tooltip when the tooltip type is description (by default)', () => { const {getByRole, getByText} = HTMLRender() const triggerEL = getByRole('button') diff --git a/packages/react/src/TooltipV2/index.ts b/packages/react/src/TooltipV2/index.ts index ba15f407377..9a336ded38c 100644 --- a/packages/react/src/TooltipV2/index.ts +++ b/packages/react/src/TooltipV2/index.ts @@ -1 +1,2 @@ -export * from './Tooltip' +export {Tooltip} from './Tooltip' +export type {TooltipProps, TooltipDirection} from './Tooltip' diff --git a/packages/react/src/UnderlineNav/UnderlineNav.examples.stories.tsx b/packages/react/src/UnderlineNav/UnderlineNav.examples.stories.tsx index 1435bcd0442..cc272ebaa3c 100644 --- a/packages/react/src/UnderlineNav/UnderlineNav.examples.stories.tsx +++ b/packages/react/src/UnderlineNav/UnderlineNav.examples.stories.tsx @@ -22,7 +22,8 @@ import { } from '@primer/octicons-react' import type {Meta} from '@storybook/react' import {UnderlineNav} from './index' -import {Avatar, Octicon, Button, Box, Heading, Link, Text, StateLabel, BranchName} from '..' +import {Avatar, Button, Box, Heading, Link, Text, StateLabel, BranchName} from '..' +import Octicon from '../Octicon' export default { title: 'Components/UnderlineNav/Examples', diff --git a/packages/react/src/__tests__/ActionMenu.test.tsx b/packages/react/src/__tests__/ActionMenu.test.tsx index 4b067fda8be..8c8d372e403 100644 --- a/packages/react/src/__tests__/ActionMenu.test.tsx +++ b/packages/react/src/__tests__/ActionMenu.test.tsx @@ -3,7 +3,8 @@ import userEvent from '@testing-library/user-event' import axe from 'axe-core' import React from 'react' import theme from '../theme' -import {ActionMenu, ActionList, BaseStyles, ThemeProvider, Tooltip, Button, IconButton} from '..' +import {ActionMenu, ActionList, BaseStyles, ThemeProvider, Button, IconButton} from '..' +import Tooltip from '../Tooltip' import {Tooltip as TooltipV2} from '../TooltipV2/Tooltip' import {behavesAsComponent, checkExports} from '../utils/testing' import {SingleSelect} from '../ActionMenu/ActionMenu.features.stories' @@ -401,7 +402,7 @@ describe('ActionMenu', () => { button.focus() }) - expect(component.getByRole('tooltip')).toBeInTheDocument() + expect(component.getByRole('tooltip', {hidden: true})).toBeInTheDocument() }) it('should open menu on menu anchor click and it is wrapped with tooltip v2', async () => { @@ -437,7 +438,7 @@ describe('ActionMenu', () => { button.focus() }) - expect(component.getByRole('tooltip')).toBeInTheDocument() + expect(component.getByRole('tooltip', {hidden: true})).toBeInTheDocument() }) it('should pass the "id" prop from ActionMenu.Button to the HTML button', async () => { diff --git a/packages/react/src/__tests__/Autocomplete.types.test.tsx b/packages/react/src/__tests__/Autocomplete.types.test.tsx new file mode 100644 index 00000000000..185480459cd --- /dev/null +++ b/packages/react/src/__tests__/Autocomplete.types.test.tsx @@ -0,0 +1,24 @@ +import {LogoGithubIcon} from '@primer/octicons-react' +import {Autocomplete} from '..' +import React from 'react' + +export function itemWithIconElements() { + return ( + <> + + + + , trailingVisual: }, + ]} + > + + + + ) +} diff --git a/packages/react/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap b/packages/react/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap index 92301474008..860d10e595d 100644 --- a/packages/react/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap +++ b/packages/react/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap @@ -796,7 +796,7 @@ exports[`snapshots renders a menu that contains an item to add to the menu 1`] = } .c3[data-is-active-descendant] { - font-weight: 600; + font-weight: 400; background-color: var(--control-transparent-bgColor-selected,var(--color-action-list-item-default-selected-bg,rgba(208,215,222,0.24))); } @@ -1603,7 +1603,7 @@ exports[`snapshots renders a multiselect input 1`] = ` } .c3[data-is-active-descendant] { - font-weight: 600; + font-weight: 400; background-color: var(--control-transparent-bgColor-selected,var(--color-action-list-item-default-selected-bg,rgba(208,215,222,0.24))); } @@ -2382,7 +2382,7 @@ exports[`snapshots renders a multiselect input with selected menu items 1`] = ` } .c3[data-is-active-descendant] { - font-weight: 600; + font-weight: 400; background-color: var(--control-transparent-bgColor-selected,var(--color-action-list-item-default-selected-bg,rgba(208,215,222,0.24))); } @@ -2479,7 +2479,7 @@ exports[`snapshots renders a multiselect input with selected menu items 1`] = ` } .c8[data-is-active-descendant] { - font-weight: 600; + font-weight: 400; background-color: var(--control-transparent-bgColor-selected,var(--color-action-list-item-default-selected-bg,rgba(208,215,222,0.24))); } @@ -3202,7 +3202,7 @@ exports[`snapshots renders a single select input 1`] = ` } .c3[data-is-active-descendant] { - font-weight: 600; + font-weight: 400; background-color: var(--control-transparent-bgColor-selected,var(--color-action-list-item-default-selected-bg,rgba(208,215,222,0.24))); } @@ -3689,7 +3689,7 @@ exports[`snapshots renders with a custom text input component 1`] = ` } .c3[data-is-active-descendant] { - font-weight: 600; + font-weight: 400; background-color: var(--control-transparent-bgColor-selected,var(--color-action-list-item-default-selected-bg,rgba(208,215,222,0.24))); } diff --git a/packages/react/src/__tests__/__snapshots__/TextInput.test.tsx.snap b/packages/react/src/__tests__/__snapshots__/TextInput.test.tsx.snap index f5f5c3e315b..c8cce954101 100644 --- a/packages/react/src/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/packages/react/src/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -3401,6 +3401,7 @@ exports[`TextInput renders trailingAction text button with a tooltip 1`] = `
        ` animation: ${shimmer}; display: block; - background-color: var(--bgColor-muted, ${get('colors.canvas.subtle')}); + background-color: var(--skeletonLoader-bgColor, ${get('colors.canvas.subtle')}); border-radius: 3px; height: ${props => props.height || '1rem'}; width: ${props => props.width}; diff --git a/packages/react/src/experimental/index.ts b/packages/react/src/experimental/index.ts index f131cf11e6b..19ebadec41a 100644 --- a/packages/react/src/experimental/index.ts +++ b/packages/react/src/experimental/index.ts @@ -11,6 +11,9 @@ export {Blankslate} from '../Blankslate' export type {BlankslateProps} from '../Blankslate' +export {ButtonBase} from '../Button' +export type {ButtonBaseProps} from '../Button' + export {Banner} from '../Banner' export type {BannerProps} from '../Banner' @@ -52,7 +55,8 @@ export type { NavListDividerProps, } from '../NavList' export * from './SelectPanel2' -export * from '../TooltipV2' +export {Tooltip} from '../TooltipV2' +export type {TooltipProps} from '../TooltipV2' export * from '../ActionBar' export {ScrollableRegion} from '../ScrollableRegion' @@ -68,7 +72,7 @@ export {UnderlinePanels} from './UnderlinePanels' export type {UnderlinePanelsProps, UnderlinePanelsTabProps, UnderlinePanelsPanelProps} from './UnderlinePanels' export {SkeletonBox, SkeletonText, SkeletonAvatar} from './Skeleton' -export {FeatureFlags, DefaultFeatureFlags} from '../FeatureFlags' +export {FeatureFlags, DefaultFeatureFlags, useFeatureFlag} from '../FeatureFlags' export type {FeatureFlagsProps} from '../FeatureFlags' export {FilteredActionList} from '../FilteredActionList' diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index c4d89da90d9..a6188c13cee 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -43,7 +43,7 @@ export {useFocusZone} from './hooks/useFocusZone' export type {FocusZoneHookSettings} from './hooks/useFocusZone' export {useRefObjectAsForwardedRef} from './hooks/useRefObjectAsForwardedRef' export {useResizeObserver} from './hooks/useResizeObserver' -export {useResponsiveValue} from './hooks/useResponsiveValue' +export {useResponsiveValue, type ResponsiveValue} from './hooks/useResponsiveValue' export {default as useIsomorphicLayoutEffect} from './utils/useIsomorphicLayoutEffect' export {useProvidedRefOrCreate} from './hooks/useProvidedRefOrCreate' @@ -93,8 +93,8 @@ export {default as CounterLabel} from './CounterLabel' export type {CounterLabelProps} from './CounterLabel' export {default as Details} from './Details' export type {DetailsProps} from './Details' -export {default as Dialog} from './Dialog' -export type {DialogProps, DialogHeaderProps} from './Dialog' +export {Dialog} from './Dialog/Dialog' +export type {DialogProps, DialogHeaderProps, DialogButtonProps, DialogWidth, DialogHeight} from './Dialog/Dialog' export type {ConfirmationDialogProps} from './ConfirmationDialog/ConfirmationDialog' export {ConfirmationDialog} from './ConfirmationDialog/ConfirmationDialog' export {default as Flash} from './Flash' @@ -121,12 +121,8 @@ export type { NavListTrailingVisualProps, NavListDividerProps, } from './NavList' -export {default as Octicon} from './Octicon' -export type {OcticonProps} from './Octicon' export {default as Overlay} from './Overlay' export type {OverlayProps} from './Overlay' -export {default as Pagehead} from './Pagehead' -export type {PageheadProps} from './Pagehead' export {default as Pagination} from './Pagination' export type {PaginationProps} from './Pagination' export {default as PointerBox} from './PointerBox' @@ -154,8 +150,6 @@ export type {StateLabelProps} from './StateLabel' export {default as SubNav} from './SubNav' export type {SubNavProps, SubNavLinkProps, SubNavLinksProps} from './SubNav' export {default as ToggleSwitch} from './ToggleSwitch' -export {default as TabNav} from './TabNav' -export type {TabNavProps, TabNavLinkProps} from './TabNav' export {default as TextInput} from './TextInput' export type {TextInputProps} from './TextInput' export {default as TextInputWithTokens} from './TextInputWithTokens' @@ -172,8 +166,8 @@ export type { } from './Timeline' export {default as Token, IssueLabelToken, AvatarToken} from './Token' export type {TokenProps, IssueLabelTokenProps} from './Token' -export {default as Tooltip} from './Tooltip/Tooltip' -export type {TooltipProps} from './Tooltip/Tooltip' +export {Tooltip} from './TooltipV2' +export type {TooltipProps} from './TooltipV2' export {default as Truncate} from './Truncate' export type {TruncateProps} from './Truncate' diff --git a/packages/react/src/internal/components/TextInputInnerVisualSlot.tsx b/packages/react/src/internal/components/TextInputInnerVisualSlot.tsx index b8370ac12fe..ca43cf800c4 100644 --- a/packages/react/src/internal/components/TextInputInnerVisualSlot.tsx +++ b/packages/react/src/internal/components/TextInputInnerVisualSlot.tsx @@ -12,7 +12,7 @@ const TextInputInnerVisualSlot: React.FC< /** Which side of this visual is being rendered */ visualPosition: 'leading' | 'trailing' }> -> = ({children, hasLoadingIndicator, showLoadingIndicator, visualPosition}) => { +> = ({children, hasLoadingIndicator, showLoadingIndicator, visualPosition, ...props}) => { if ((!children && !hasLoadingIndicator) || (visualPosition === 'leading' && !children && !showLoadingIndicator)) { return null } @@ -22,7 +22,7 @@ const TextInputInnerVisualSlot: React.FC< } return ( - + {children && {children}} { + test('renders the `as` prop when flag is enabled', () => { + const TestComponent = toggleStyledComponent('testFeatureFlag', () =>
        ) + const {container} = render( + + + , + ) + expect(container.firstChild).toBeInstanceOf(HTMLButtonElement) + }) + + test('renders a div as fallback when flag is enabled and no `as` prop is provided', () => { + const TestComponent = toggleStyledComponent('testFeatureFlag', () =>
        ) + const {container} = render( + + + , + ) + expect(container.firstChild).toBeInstanceOf(HTMLDivElement) + }) + + test('renders Box with `as` if `sx` is provided and flag is enabled', () => { + const TestComponent = toggleStyledComponent('testFeatureFlag', () => styled.div``) + const {container} = render( + + + , + ) + + expect(container.firstChild).toBeInstanceOf(HTMLButtonElement) + expect(container.firstChild).toHaveStyle('color: red') + }) + + test('renders styled component when flag is disabled', () => { + const StyledComponent = toggleStyledComponent('testFeatureFlag', styled.div.attrs({['data-styled']: true})``) + const {container} = render( + + + , + ) + expect(container.firstChild).toHaveAttribute('data-styled') + }) +}) diff --git a/packages/react/src/internal/utils/toggleStyledComponent.tsx b/packages/react/src/internal/utils/toggleStyledComponent.tsx index 4a9bbd0e00a..7b366cb0eb0 100644 --- a/packages/react/src/internal/utils/toggleStyledComponent.tsx +++ b/packages/react/src/internal/utils/toggleStyledComponent.tsx @@ -1,9 +1,12 @@ import React from 'react' import {useFeatureFlag} from '../../FeatureFlags' +import Box from '../../Box' +import {defaultSxProp} from '../../utils/defaultSxProp' type CSSModulesProps = { // eslint-disable-next-line @typescript-eslint/no-explicit-any as?: string | React.ComponentType + sx?: React.CSSProperties } /** @@ -18,12 +21,18 @@ type CSSModulesProps = { * is disabled */ export function toggleStyledComponent(flag: string, Component: React.ComponentType

        ) { - const Wrapper = React.forwardRef(function Wrapper({as: BaseComponent = 'div', ...rest}, ref) { + const Wrapper = React.forwardRef(function Wrapper( + {as: BaseComponent = 'div', sx: sxProp = defaultSxProp, ...rest}, + ref, + ) { const enabled = useFeatureFlag(flag) if (enabled) { + if (sxProp !== defaultSxProp) { + return + } return } - return + return }) return Wrapper diff --git a/packages/react/src/next/index.ts b/packages/react/src/next/index.ts index cafa67c9ab8..4b07c532265 100644 --- a/packages/react/src/next/index.ts +++ b/packages/react/src/next/index.ts @@ -1,4 +1,5 @@ 'use client' // next entrypoint is used to export the latest version of the components that have conflicts with the main bundle. -export * from '../TooltipV2' +export {Tooltip} from '../TooltipV2' +export type {TooltipProps} from '../TooltipV2' diff --git a/packages/rollup-plugin-import-css/rollup.config.js b/packages/rollup-plugin-import-css/rollup.config.js index bd170e7977f..da639769421 100644 --- a/packages/rollup-plugin-import-css/rollup.config.js +++ b/packages/rollup-plugin-import-css/rollup.config.js @@ -2,7 +2,7 @@ import {nodeResolve} from '@rollup/plugin-node-resolve' import commonjs from '@rollup/plugin-commonjs' import typescript from 'rollup-plugin-typescript2' import esbuild from 'rollup-plugin-esbuild' -import packageJson from './package.json' assert {type: 'json'} +import packageJson from './package.json' with {type: 'json'} const dependencyTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'] const dependencies = new Set( diff --git a/script/test-e2e b/script/test-e2e index 8ffffd42274..462fd5d625e 100755 --- a/script/test-e2e +++ b/script/test-e2e @@ -1,12 +1,26 @@ #!/bin/bash +set -e set -x PLAYWRIGHT_VERSION=$(npm --json list @playwright/test | jq --raw-output '.dependencies["@playwright/test"].version') +if [ -z "$PLAYWRIGHT_VERSION" ]; then + echo "Unable to find Playwright version. Make sure @playwright/test is installed." + exit 1 +fi + +echo "Using Playwright version $PLAYWRIGHT_VERSION" + +if [ -z "$STORYBOOK_URL" ]; then + STORYBOOK_URL="http://host.docker.internal:6006" +fi + +echo "Using Storybook at: $STORYBOOK_URL" + docker run --rm \ --network host \ -v $(pwd):/workspace \ -w /workspace \ -it "mcr.microsoft.com/playwright:v$PLAYWRIGHT_VERSION-jammy" \ - /bin/bash -c "npm install && STORYBOOK_URL=http://host.docker.internal:6006 npx playwright test $@" + /bin/bash -c "npm install && STORYBOOK_URL=$STORYBOOK_URL npx playwright test $@"