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/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/pre.json b/.changeset/pre.json index 11d13a9c9a3..7d1b0cf362e 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -24,15 +24,19 @@ "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", @@ -48,6 +52,9 @@ "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", @@ -55,6 +62,7 @@ "lovely-days-march", "lucky-oranges-camp", "mighty-parrots-carry", + "modern-cooks-invite", "moody-rivers-impress", "nervous-llamas-ring", "new-shirts-beam", @@ -63,6 +71,7 @@ "olive-donkeys-exercise", "orange-steaks-do", "pink-actors-cross", + "plenty-books-agree", "purple-apricots-relax", "quick-adults-buy", "quick-feet-sip", @@ -73,8 +82,10 @@ "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", @@ -87,6 +98,7 @@ "stale-lizards-report", "stale-pets-tan", "strong-tables-rest", + "stupid-monkeys-beg", "tall-wasps-end", "tame-boats-hide", "ten-gifts-own", @@ -98,11 +110,13 @@ "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", 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/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/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/.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/ci.yml b/.github/workflows/ci.yml index 098af6b11c3..fd6e8942875 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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: @@ -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 @@ -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.43.0-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: @@ -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 @@ -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.43.0-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: 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/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/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/examples/app-router/package.json b/examples/app-router/package.json index 77ed05ce4e5..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.9", + "@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 dd56088ae5c..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.9", + "@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 10461a46255..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.9", + "@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 097ba5772ed..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.9", + "@primer/react": "37.0.0-rc.10", "clsx": "^1.2.1", "next": "^14.2.10", "react": "^18.3.1", 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 a0387a904ab..a323b56b3ce 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,39 @@ # @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 diff --git a/packages/react/package.json b/packages/react/package.json index 24182f767ee..aff5a7b1bb4 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@primer/react", - "version": "37.0.0-rc.9", + "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", 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/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/Banner/Banner.tsx b/packages/react/src/Banner/Banner.tsx index d1061e966ed..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' @@ -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/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/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/SegmentedControlButton.tsx b/packages/react/src/SegmentedControl/SegmentedControlButton.tsx index 58003d167f5..0474323ab43 100644 --- a/packages/react/src/SegmentedControl/SegmentedControlButton.tsx +++ b/packages/react/src/SegmentedControl/SegmentedControlButton.tsx @@ -7,6 +7,7 @@ import type {SxProp} from '../sx' import sx, {merge} from '../sx' import {getSegmentedControlButtonStyles, getSegmentedControlListItemStyles} from './getSegmentedControlStyles' import {defaultSxProp} from '../utils/defaultSxProp' +import getGlobalFocusStyles from '../internal/utils/getGlobalFocusStyles' export type SegmentedControlButtonProps = { /** The visible label rendered in the button */ @@ -21,6 +22,7 @@ export type SegmentedControlButtonProps = { ButtonHTMLAttributes const SegmentedControlButtonStyled = styled.button` + ${getGlobalFocusStyles()}; ${sx}; ` diff --git a/packages/react/src/SegmentedControl/SegmentedControlIconButton.tsx b/packages/react/src/SegmentedControl/SegmentedControlIconButton.tsx index 11970c0ab47..1986bf92a3f 100644 --- a/packages/react/src/SegmentedControl/SegmentedControlIconButton.tsx +++ b/packages/react/src/SegmentedControl/SegmentedControlIconButton.tsx @@ -7,6 +7,7 @@ import sx, {merge} from '../sx' import {getSegmentedControlButtonStyles, getSegmentedControlListItemStyles} from './getSegmentedControlStyles' import Box from '../Box' import {defaultSxProp} from '../utils/defaultSxProp' +import getGlobalFocusStyles from '../internal/utils/getGlobalFocusStyles' export type SegmentedControlIconButtonProps = { 'aria-label': string @@ -20,6 +21,7 @@ export type SegmentedControlIconButtonProps = { ButtonHTMLAttributes const SegmentedControlIconButtonStyled = styled.button` + ${getGlobalFocusStyles()}; ${sx}; ` diff --git a/packages/react/src/SelectPanel/SelectPanel.examples.stories.tsx b/packages/react/src/SelectPanel/SelectPanel.examples.stories.tsx index 248432e0f9a..3e261c6bce3 100644 --- a/packages/react/src/SelectPanel/SelectPanel.examples.stories.tsx +++ b/packages/react/src/SelectPanel/SelectPanel.examples.stories.tsx @@ -309,3 +309,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.test.tsx b/packages/react/src/SelectPanel/SelectPanel.test.tsx index 936f3b544fc..a047507fb7e 100644 --- a/packages/react/src/SelectPanel/SelectPanel.test.tsx +++ b/packages/react/src/SelectPanel/SelectPanel.test.tsx @@ -335,6 +335,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() { diff --git a/packages/react/src/SelectPanel/SelectPanel.tsx b/packages/react/src/SelectPanel/SelectPanel.tsx index efae1b5a7e1..c862950deb3 100644 --- a/packages/react/src/SelectPanel/SelectPanel.tsx +++ b/packages/react/src/SelectPanel/SelectPanel.tsx @@ -61,6 +61,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, @@ -129,7 +139,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 +153,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) 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 ( - + Monalisa enabled auto-merge (squash) diff --git a/packages/react/src/TooltipV2/Tooltip.tsx b/packages/react/src/TooltipV2/Tooltip.tsx index ab5c5fe6648..3f613d340a2 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 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/__tests__/__snapshots__/exports.test.ts.snap b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap index dd5d8d91184..3651ddc6fbe 100644 --- a/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap +++ b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap @@ -65,6 +65,12 @@ exports[`@primer/react should not update exports without a semver change 1`] = ` "createComponent", "Details", "type DetailsProps", + "Dialog", + "type DialogButtonProps", + "type DialogHeaderProps", + "type DialogHeight", + "type DialogProps", + "type DialogWidth", "Flash", "type FlashProps", "type FocusTrapHookSettings", @@ -173,6 +179,8 @@ exports[`@primer/react should not update exports without a semver change 1`] = ` "ToggleSwitch", "Token", "type TokenProps", + "Tooltip", + "type TooltipProps", "type TouchOrMouseEvent", "TreeView", "type TreeViewErrorDialogProps", @@ -316,14 +324,12 @@ exports[`@primer/react/experimental should not update exports without a semver c "type TableTitleProps", "type TitleProps", "Tooltip", - "TooltipContext", - "type TooltipDirection", "type TooltipProps", - "type TriggerPropsType", "UnderlinePanels", "type UnderlinePanelsPanelProps", "type UnderlinePanelsProps", "type UnderlinePanelsTabProps", + "useFeatureFlag", "useOverflow", "useSlots", ] diff --git a/packages/react/src/experimental/index.ts b/packages/react/src/experimental/index.ts index f131cf11e6b..7cafc776d18 100644 --- a/packages/react/src/experimental/index.ts +++ b/packages/react/src/experimental/index.ts @@ -52,7 +52,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 +69,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 cbc739faf4b..a6188c13cee 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -93,6 +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 {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' @@ -164,6 +166,8 @@ export type { } from './Timeline' export {default as Token, IssueLabelToken, AvatarToken} from './Token' export type {TokenProps, IssueLabelTokenProps} from './Token' +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/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'