Skip to content

feat: Redesign Compare Environments page#7965

Open
kyle-ssg wants to merge 7 commits into
mainfrom
feat/compare-environments-redesign
Open

feat: Redesign Compare Environments page#7965
kyle-ssg wants to merge 7 commits into
mainfrom
feat/compare-environments-redesign

Conversation

@kyle-ssg

@kyle-ssg kyle-ssg commented Jul 8, 2026

Copy link
Copy Markdown
Member

Thanks for submitting a PR! Please check the boxes below:

  • I have read the Contributing Guide.
  • I have added information to docs/ if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

  • Convert CompareEnvironments from JS to TypeScript
  • Add expandable rows with full diff view (segments, variations)
  • Add standard table filters (search, tags, owners, groups, sort)
  • Split results into "Changed features" and "Unchanged features" tables
  • Add column headers for source/target environments and segment changes
  • Show environment names in diff view dropdown instead of "Old/New Value"
  • Add environment name legend with +/- indicators in diff colours
  • Style improvements: proper table header styling, badge counts
    Please describe.

How did you test this code?

Compared features in production

- Convert CompareEnvironments from JS to TypeScript
- Add expandable rows with full diff view (segments, variations)
- Add standard table filters (search, tags, owners, groups, sort)
- Split results into "Changed features" and "Unchanged features" tables
- Add column headers for source/target environments and segment changes
- Show environment names in diff view dropdown instead of "Old/New Value"
- Add environment name legend with +/- indicators in diff colours
- Style improvements: proper table header styling, badge counts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@kyle-ssg kyle-ssg requested a review from a team as a code owner July 8, 2026 10:04
@kyle-ssg kyle-ssg requested review from talissoncosta and removed request for a team July 8, 2026 10:04
@vercel

vercel Bot commented Jul 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
flagsmith-frontend-preview Ready Ready Preview, Comment Jul 15, 2026 1:05pm
flagsmith-frontend-staging Ready Ready Preview, Comment Jul 15, 2026 1:05pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview Jul 15, 2026 1:05pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The legacy environment comparison module is replaced by a TypeScript comparison flow with typed comparison data, paginated feature-state fetching, filtering and sorting, expandable feature rows, editing, and environment-specific diff rendering. The page compares changed and unchanged features across two selected environments, while DiffFeature displays optional environment names and matching added or removed headers.

Estimated code review effort: 4 (Complex) | ~60 minutes


Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the front-end Issue related to the React Front End Dashboard label Jul 8, 2026
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Docker builds report

Image Build Status Security report
ghcr.io/flagsmith/flagsmith-api-test:pr-7965 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-e2e:pr-7965 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith:pr-7965 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-api:pr-7965 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-private-cloud:pr-7965 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-frontend:pr-7965 Finished ✅ Results

@github-actions github-actions Bot added the feature New feature or request label Jul 8, 2026
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  5 passed

Details

stats  5 tests across 3 suites
duration  42.9 seconds
commit  2aaa93c
info  🔄 Run: #18083 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  4 passed

Details

stats  4 tests across 3 suites
duration  45.2 seconds
commit  2aaa93c
info  🔄 Run: #18083 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  5 passed

Details

stats  5 tests across 5 suites
duration  35.9 seconds
commit  2aaa93c
info  🔄 Run: #18083 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  4 passed

Details

stats  4 tests across 4 suites
duration  12.4 seconds
commit  2aaa93c
info  🔄 Run: #18083 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  4 passed

Details

stats  4 tests across 3 suites
duration  33.9 seconds
commit  511d3ff
info  🔄 Run: #18084 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  5 passed

Details

stats  5 tests across 4 suites
duration  4.5 seconds
commit  511d3ff
info  🔄 Run: #18084 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  3 passed

Details

stats  3 tests across 3 suites
duration  43 seconds
commit  511d3ff
info  🔄 Run: #18084 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  54.5 seconds
commit  511d3ff
info  🔄 Run: #18084 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  4 passed

Details

stats  4 tests across 3 suites
duration  12.1 seconds
commit  a0169a8
info  🔄 Run: #18102 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  3 passed

Details

stats  3 tests across 3 suites
duration  59.9 seconds
commit  a0169a8
info  🔄 Run: #18102 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  6 passed

Details

stats  6 tests across 5 suites
duration  42.7 seconds
commit  a0169a8
info  🔄 Run: #18102 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  5 passed

Details

stats  5 tests across 3 suites
duration  37.8 seconds
commit  a0169a8
info  🔄 Run: #18102 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  4 passed

Details

stats  4 tests across 2 suites
duration  12.2 seconds
commit  c6df7d3
info  🔄 Run: #18103 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  5 passed

Details

stats  5 tests across 5 suites
duration  1 minute
commit  c6df7d3
info  🔄 Run: #18103 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

failed  2 failed

Details

stats  2 tests across 2 suites
duration  55.2 seconds
commit  c6df7d3
info  📦 Artifacts: View test results and HTML report
🔄 Run: #18103 (attempt 1)

Failed tests

firefox › tests/environment-permission-test.pw.ts › Environment Permission Tests › Environment-level permissions control access to features, identities, and segments @enterprise
firefox › tests/project-permission-test.pw.ts › Project Permission Tests › Project-level permissions control access to features, environments, audit logs, and segments @enterprise

### Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  4 passed

Details

stats  4 tests across 3 suites
duration  43.2 seconds
commit  c6df7d3
info  🔄 Run: #18103 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  6 passed

Details

stats  6 tests across 4 suites
duration  55.9 seconds
commit  c6df7d3
info  🔄 Run: #18103 (attempt 2)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  4 passed

Details

stats  4 tests across 3 suites
duration  18.3 seconds
commit  7fbd8b3
info  🔄 Run: #18279 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  4 passed

Details

stats  4 tests across 3 suites
duration  42.9 seconds
commit  7fbd8b3
info  🔄 Run: #18279 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  6 passed

Details

stats  6 tests across 5 suites
duration  36.1 seconds
commit  7fbd8b3
info  🔄 Run: #18279 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  5 passed

Details

stats  5 tests across 4 suites
duration  59.1 seconds
commit  7fbd8b3
info  🔄 Run: #18279 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  18.9 seconds
commit  82764e1
info  🔄 Run: #18297 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  5 passed

Details

stats  5 tests across 4 suites
duration  53.9 seconds
commit  82764e1
info  🔄 Run: #18297 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  3 passed

Details

stats  3 tests across 2 suites
duration  38.5 seconds
commit  82764e1
info  🔄 Run: #18297 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  5 passed

Details

stats  5 tests across 4 suites
duration  33 seconds
commit  82764e1
info  🔄 Run: #18297 (attempt 1)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d35e7802-5b0d-4d36-a807-ab7858d6883c

📥 Commits

Reviewing files that changed from the base of the PR and between fd438ba and 2aaa93c.

📒 Files selected for processing (4)
  • frontend/web/components/CompareEnvironments.js
  • frontend/web/components/CompareEnvironments.tsx
  • frontend/web/components/diff/DiffFeature.tsx
  • frontend/web/styles/3rdParty/_react-diff.scss
💤 Files with no reviewable changes (1)
  • frontend/web/components/CompareEnvironments.js

Comment thread frontend/web/components/CompareEnvironments.tsx Outdated
Comment thread frontend/web/components/CompareEnvironments.tsx Outdated
Comment thread frontend/web/components/CompareEnvironments.tsx Outdated
Comment thread frontend/web/components/CompareEnvironments.tsx Outdated
Comment thread frontend/web/components/CompareEnvironments.tsx Outdated
Comment thread frontend/web/components/CompareEnvironments.tsx Outdated
Comment thread frontend/web/styles/3rdParty/_react-diff.scss Outdated
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Visual Regression

19 screenshots compared. See report for details.
View full report

Add Edit buttons to each environment column that open the
CreateFlagModal for editing features directly from the comparison view.
The modal handles change requests automatically when required.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2e5c607a-0133-4beb-977e-e3136eda0457

📥 Commits

Reviewing files that changed from the base of the PR and between 2aaa93c and 511d3ff.

📒 Files selected for processing (1)
  • frontend/web/components/CompareEnvironments.tsx

Comment thread frontend/web/components/CompareEnvironments.tsx Outdated
Comment thread frontend/web/components/CompareEnvironments.tsx Outdated
talissoncosta
talissoncosta previously approved these changes Jul 8, 2026

@talissoncosta talissoncosta left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good @kyle-ssg ! Thanks for that!

I just left some suggestions.

If we can break it into small components and get rid of the _data import would be amazing.

Comment thread frontend/web/components/CompareEnvironments.tsx Outdated
Comment thread frontend/web/components/CompareEnvironments.tsx Outdated
Address PR review feedback on the Compare Environments redesign:

- Move the single 607-line component into a CompareEnvironments/ folder
  with a barrel: types.ts, useEnvironmentComparison hook (fetch + diff
  derivation, now unit-testable), ExpandedRow, CompareFeatureRow, and the
  layout component.
- Replace relative imports with components/ and common/ aliases.
- Reuse the shared FlagsmithValue type instead of an inline union.
- Surface a fetch error state with a retry action instead of silently
  swallowing failures and rendering "No differences found".
- Guard against stale overlapping comparisons with a request-id check so a
  slow earlier response can't overwrite a newer one.
- Make the row expand toggle keyboard accessible (role, tabIndex,
  aria-expanded, Enter/Space handling).
- Pass the numeric projectId into CreateFlagModal.
- Fall back to the left project flag for the right-side edit action so the
  modal edits the existing feature instead of switching to create mode.
- Consolidate duplicated diff header styles into a shared base rule.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9358fdf4-3fea-4572-8fe1-3a268386a44c

📥 Commits

Reviewing files that changed from the base of the PR and between 511d3ff and a0169a8.

📒 Files selected for processing (7)
  • frontend/web/components/CompareEnvironments/CompareEnvironments.tsx
  • frontend/web/components/CompareEnvironments/CompareFeatureRow.tsx
  • frontend/web/components/CompareEnvironments/ExpandedRow.tsx
  • frontend/web/components/CompareEnvironments/index.ts
  • frontend/web/components/CompareEnvironments/types.ts
  • frontend/web/components/CompareEnvironments/useEnvironmentComparison.ts
  • frontend/web/styles/3rdParty/_react-diff.scss

Comment thread frontend/web/components/CompareEnvironments/CompareFeatureRow.tsx
Comment thread frontend/web/components/CompareEnvironments/CompareFeatureRow.tsx
Comment thread frontend/web/components/CompareEnvironments/ExpandedRow.tsx
Comment thread frontend/web/components/CompareEnvironments/ExpandedRow.tsx Outdated
Comment thread frontend/web/components/CompareEnvironments/useEnvironmentComparison.ts Outdated
Comment thread frontend/web/components/CompareEnvironments/useEnvironmentComparison.ts Outdated
…PageGet

Export the existing recursivePageGet helper and reuse it in the comparison
hook so every list is fetched across all pages, replacing the page_size=999
calls that silently capped results at 999. A small _data.get adapter bridges
it to the baseQuery contract the helper expects.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/common/services/useProjectFlag.ts (1)

12-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Make recursivePageGet generic
It’s reused for both ProjectFlag and FeatureState, so parameterising the response type will remove the cast in useEnvironmentComparison and keep callers type-safe.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e7b13097-571d-4572-a88c-8cca942142a7

📥 Commits

Reviewing files that changed from the base of the PR and between a0169a8 and c6df7d3.

📒 Files selected for processing (2)
  • frontend/common/services/useProjectFlag.ts
  • frontend/web/components/CompareEnvironments/useEnvironmentComparison.ts

@github-actions github-actions Bot added feature New feature or request and removed feature New feature or request labels Jul 8, 2026
talissoncosta
talissoncosta previously approved these changes Jul 8, 2026

@talissoncosta talissoncosta left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing the changes.

It looks good!

kyle-ssg and others added 2 commits July 15, 2026 11:32
- Add getAllEnvironmentFeatureStates endpoint for bulk
  environments/{key}/featurestates/ (default states only, all pages)
- Rewrite useEnvironmentComparison to use RTK Query hooks, dropping the
  manual race guard in favour of currentData semantics
- Fix recursivePageGet: it read results/next off the RTK baseQuery
  {data} wrapper, so pagination silently stopped after the first page
- Move recursivePageGet to common/utils as it is now shared by the
  project flag and feature state services
- Surface feature state fetch errors in ExpandedRow instead of showing
  "No differences between environments"

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ading UX

- Remove Edit buttons; clicking the switch or value chip opens the edit
  modal (keyboard accessible via Enter/Space on the cell)
- Share column width constants between header and rows, and clamp
  overflowing value chips so wide values no longer break alignment
- Keep the table visible and dimmed during refreshes instead of
  replacing it with a loader
- Refetch when the edit modal saves (FeatureListStore events) rather
  than on every modal close

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
frontend/common/utils/recursivePageGet.ts (1)

1-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

No unit tests for this new shared pagination helper.

recursivePageGet is a pure, easily testable function now shared by two service files; a couple of tests (single page, multi-page merge via next, error passthrough) would guard against regressions.

frontend/web/components/CompareEnvironments/CompareFeatureRow.tsx (1)

82-86: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use a real segment-difference metricMath.max(leftOverrides, rightOverrides) shows the larger override count, not the number of changed segments, so the “Segment changes” chip can be non-zero even when both environments have the same overrides. Either compare the override sets or relabel the chip to match the metric.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d54db1e4-94fc-4c56-af47-fe10cf5e6c4b

📥 Commits

Reviewing files that changed from the base of the PR and between c6df7d3 and 7fbd8b3.

📒 Files selected for processing (9)
  • frontend/common/services/useFeatureState.ts
  • frontend/common/services/useProjectFlag.ts
  • frontend/common/types/requests.ts
  • frontend/common/utils/recursivePageGet.ts
  • frontend/web/components/CompareEnvironments/CompareEnvironments.tsx
  • frontend/web/components/CompareEnvironments/CompareFeatureRow.tsx
  • frontend/web/components/CompareEnvironments/ExpandedRow.tsx
  • frontend/web/components/CompareEnvironments/constants.ts
  • frontend/web/components/CompareEnvironments/useEnvironmentComparison.ts

Comment on lines +26 to +37
getAllEnvironmentFeatureStates: builder.query<
Res['featureStates'],
Req['getAllEnvironmentFeatureStates']
>({
providesTags: [{ id: 'LIST', type: 'FeatureState' }],
queryFn: async (query, _baseQueryApi, _extraOptions, baseQuery) =>
recursivePageGet<FeatureState>(
`environments/${query.environmentKey}/featurestates/?page_size=999`,
null,
baseQuery,
),
}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

ast-grep outline frontend/common/services/useFeatureState.ts --view expanded

Repository: Flagsmith/flagsmith

Length of output: 291


🏁 Script executed:

sed -n '1,180p' frontend/common/services/useFeatureState.ts

Repository: Flagsmith/flagsmith

Length of output: 3609


🏁 Script executed:

rg -n "type FeatureState|interface FeatureState|featureStates|getAllEnvironmentFeatureStates|addFeatureSegmentsToFeatureStates|feature_segment" frontend/common/types frontend/common -g '!**/dist/**'

Repository: Flagsmith/flagsmith

Length of output: 11938


🏁 Script executed:

sed -n '760,810p' frontend/common/types/responses.ts && printf '\n---\n' && sed -n '750,790p' frontend/common/types/requests.ts && printf '\n---\n' && rg -n "useGetAllEnvironmentFeatureStatesQuery|getAllEnvironmentFeatureStates" frontend/common -g '!**/dist/**'

Repository: Flagsmith/flagsmith

Length of output: 2975


🏁 Script executed:

rg -n "environments/.*/featurestates|featurestates/\?page_size=999|getAllEnvironmentFeatureStatesQuery|useGetAllEnvironmentFeatureStatesQuery" . -g '!**/dist/**' -g '!**/node_modules/**'

Repository: Flagsmith/flagsmith

Length of output: 4003


🏁 Script executed:

sed -n '1,180p' frontend/web/components/CompareEnvironments/useEnvironmentComparison.ts && printf '\n---\n' && rg -n "feature_segment.*Serializer|FeatureState.*Serializer|featurestates" api -g '!**/migrations/**' -g '!**/node_modules/**'

Repository: Flagsmith/flagsmith

Length of output: 39867


🏁 Script executed:

sed -n '1,220p' api/environments/serializers.py && printf '\n---\n' && sed -n '1,240p' api/environments/views.py && printf '\n---\n' && sed -n '1,220p' api/features/serializers.py

Repository: Flagsmith/flagsmith

Length of output: 25232


🏁 Script executed:

rg -n "environment-featurestates|featurestates-list|FeatureStateSerializerFull|FeatureStateSerializerBasic|IdentityAllFeatureStatesSerializer" api/environments api/features -g '!**/migrations/**'

Repository: Flagsmith/flagsmith

Length of output: 2077


🏁 Script executed:

sed -n '1,220p' api/environments/urls.py && printf '\n---\n' && sed -n '1,260p' api/features/views.py

Repository: Flagsmith/flagsmith

Length of output: 16009


🏁 Script executed:

sed -n '620,760p' api/features/views.py && printf '\n---\n' && sed -n '540,640p' api/features/serializers.py

Repository: Flagsmith/flagsmith

Length of output: 8873


🏁 Script executed:

sed -n '660,840p' api/features/serializers.py && printf '\n---\n' && sed -n '1,220p' api/features/features_service.py

Repository: Flagsmith/flagsmith

Length of output: 11729


getAllEnvironmentFeatureStates returns a different feature_segment shape than FeatureState expects. Either resolve segment refs here like getFeatureStates does, or narrow the endpoint type to the raw environment-feature-state shape so consumers don’t assume the nested object is present.

Comment thread frontend/common/utils/recursivePageGet.ts Outdated
Comment thread frontend/web/components/CompareEnvironments/CompareEnvironments.tsx
Comment thread frontend/web/components/CompareEnvironments/CompareEnvironments.tsx
Comment thread frontend/web/components/CompareEnvironments/CompareFeatureRow.tsx
Comment on lines +34 to +66
type EnvironmentStateCellProps = {
enabled: boolean
value: FeatureChange['leftValue']
onEdit: () => void
}

// The switch and value are read-only representations — clicking either opens
// the edit modal rather than toggling in place
const EnvironmentStateCell: FC<EnvironmentStateCellProps> = ({
enabled,
onEdit,
value,
}) => (
<div
className='clickable d-flex align-items-center gap-2 overflow-hidden'
role='button'
tabIndex={0}
onClick={(e: React.MouseEvent) => {
e.stopPropagation()
onEdit()
}}
onKeyDown={(e: React.KeyboardEvent) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
e.stopPropagation()
onEdit()
}
}}
>
<Switch className='flex-shrink-0 pe-none' checked={enabled} disabled />
<FeatureValue className='overflow-hidden' value={value} />
</div>
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

EnvironmentStateCell lacks an accessible label describing its action.

The cell exposes role='button' but no aria-label; its accessible name falls back to the rendered FeatureValue text (e.g. a raw value), giving no indication that activating it opens the edit modal. Consider an aria-label such as Edit feature state.

♻️ Proposed fix
   <div
     className='clickable d-flex align-items-center gap-2 overflow-hidden'
     role='button'
+    aria-label='Edit feature state'
     tabIndex={0}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type EnvironmentStateCellProps = {
enabled: boolean
value: FeatureChange['leftValue']
onEdit: () => void
}
// The switch and value are read-only representations — clicking either opens
// the edit modal rather than toggling in place
const EnvironmentStateCell: FC<EnvironmentStateCellProps> = ({
enabled,
onEdit,
value,
}) => (
<div
className='clickable d-flex align-items-center gap-2 overflow-hidden'
role='button'
tabIndex={0}
onClick={(e: React.MouseEvent) => {
e.stopPropagation()
onEdit()
}}
onKeyDown={(e: React.KeyboardEvent) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
e.stopPropagation()
onEdit()
}
}}
>
<Switch className='flex-shrink-0 pe-none' checked={enabled} disabled />
<FeatureValue className='overflow-hidden' value={value} />
</div>
)
type EnvironmentStateCellProps = {
enabled: boolean
value: FeatureChange['leftValue']
onEdit: () => void
}
// The switch and value are read-only representations — clicking either opens
// the edit modal rather than toggling in place
const EnvironmentStateCell: FC<EnvironmentStateCellProps> = ({
enabled,
onEdit,
value,
}) => (
<div
className='clickable d-flex align-items-center gap-2 overflow-hidden'
role='button'
aria-label='Edit feature state'
tabIndex={0}
onClick={(e: React.MouseEvent) => {
e.stopPropagation()
onEdit()
}}
onKeyDown={(e: React.KeyboardEvent) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
e.stopPropagation()
onEdit()
}
}}
>
<Switch className='flex-shrink-0 pe-none' checked={enabled} disabled />
<FeatureValue className='overflow-hidden' value={value} />
</div>
)

Comment on lines +1 to +5
// Shared column widths so the header and rows stay aligned. The environment
// column must fit a Switch, the widest possible FeatureValue chip (20
// truncated characters plus quotes) and an Edit button.
export const ENV_COLUMN_WIDTH = 320
export const SEGMENTS_COLUMN_WIDTH = 140

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Comment references a removed "Edit button".

The width rationale mentions fitting "an Edit button", but CompareFeatureRow.tsx replaced the standalone Edit button with the clickable EnvironmentStateCell (Switch + FeatureValue chip only). Update the comment to reflect the current layout so future width changes aren't based on stale assumptions.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request front-end Issue related to the React Front End Dashboard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants