Skip to content

fix(ui,checks): clip Select picker rows through a shared helper - #259

Merged
theBGuy merged 3 commits into
masterfrom
fix/select-picker-clip-tooltips
Aug 26, 2026
Merged

theBGuy merged 3 commits into
masterfrom
fix/select-picker-clip-tooltips

Conversation

@theBGuy

@theBGuy theBGuy commented Aug 26, 2026 •

Copy link
Copy Markdown
Owner

Long branch, workflow, and environment names in Select popups ran past the row instead of ellipsizing, and the per-site attempts to fix that never engaged: the popup hard-clips overflow while ItemText's min-width: auto floor grows with its nowrap content, so a bare truncate child can't shrink and an item-level clipTitle handler measures an element that never overflows. This replaces both dead shapes with one SelectClipText component, routes every picker through it, and adds a checks guard so the superseded shapes can't come back.

Shared helper

  • Adds SelectClipText in src/components/select-clip-text.tsx — a w-0 min-w-full truncate span with onMouseEnter={clipTitleFromText}, so the row collapses the min-width floor, re-expands to the row's real width (including under call-site popup max-w overrides), and titles on hover only when actually clipped. The doc comment records the sole-child constraint: min-w-full claims ItemText's whole content box, so a sibling icon or badge would be pushed past the clip edge.

Picker call sites

  • Converts the popup rows and adds onMouseEnter={clipTitleFromText} to the closed field's SelectValue across the branch pickers: BranchMergePickerDialog.tsx, RebaseOntoDialog.tsx (both new-base and old-base), WorktreesDialog.tsx (base and existing-branch), and HistoryDialogs.tsx (cherry-pick destination).
  • Same conversion across repository settings — GeneralSettingsSection.tsx (commit-message template and default branch), BitbucketGeneralSection.tsx, BitbucketSchedulesSection.tsx, GitLabGeneralSection.tsx, PagesSection.tsx (both the disabled and enabled branch pickers), and SecretsSection.tsx (environment scope) — plus RunWorkflowDialog.tsx (workflow and pipeline) and settings/GitSection.tsx (line endings).
  • Deletes the superseded item-level clipTitle handlers and their explanatory comments in GeneralSettingsSection.tsx, SecretsSection.tsx, and WorktreesDialog.tsx, and the inert <span className="block truncate"> children in GeneralSettingsSection.tsx, PagesSection.tsx, and GitSection.tsx.

Guard and tests

  • Adds the select-item-clip-title check to scripts/check-banned-patterns.mjs with two PAIR_GAP-bounded patterns — a clipTitle token following a <SelectItem, and a block truncate child of one — with the message pointing at SelectClipText and an allowlist escape hatch for stacked pickers. The comment records why the gap is [\s\S] (prop expressions carry => arrows) and that the closest real forward gap today measures 379 normalized chars.
  • Covers both arms in scripts/checks.test.mjs: the wrapped-props and inner-span variants flag, while the converted SelectClipText idiom, SelectValue trigger handlers, non-Select row clipTitle, and a self-bounded max-w-64 truncate span stay clean; a third test pins the vendored-ui exemption.

Documentation

  • Rewrites the Select bullet in .claude/skills/gd-conventions/SKILL.md so it names SelectClipText, both failure shapes the guard catches, and the SelectValue handler for the closed field.
  • Adds changelog.d/changed-select-picker-clip-affordances.md describing the hover-to-see-full-name behavior across the merge, rebase, worktree, settings, workflow, pipeline, and environment pickers.

Summary by CodeRabbit

  • New Features

    • Improved select fields across branch, workflow, pipeline, environment, and repository settings pickers.
    • Long option labels now display with ellipses while remaining constrained to the available space.
    • Hovering over clipped selected values or options reveals their full names.
  • Documentation

    • Added guidance documenting the updated select-label display behavior.

Long branch, workflow, and environment names ran past the Select popup edge
instead of ellipsizing: a bare `truncate` child never engages because
ItemText's `min-width: auto` floor grows with its nowrap content, and the
item-level `clipTitle` workaround measured an element that never overflows.

- `src/components/select-clip-text.tsx`: new `SelectClipText` wraps popup-row
  text in a `w-0 min-w-full truncate` span and titles it on hover only when
  the text is actually clipped.
- Call sites converted: the merge, rebase-onto, cherry-pick-onto and worktree
  branch pickers; repo settings (general, GitLab, Bitbucket, Pages, secrets
  scope); the run workflow/pipeline dialog; and the line-endings select. Each
  closed field now carries `onMouseEnter={clipTitleFromText}` on its
  `SelectValue`.
- `scripts/check-banned-patterns.mjs`: new `select-item-clip-title` guard
  fails on both superseded shapes (a `clipTitle` handler under a `SelectItem`,
  a bare `block truncate` child), covered by `scripts/checks.test.mjs`.
- `.claude/skills/gd-conventions/SKILL.md` records the idiom, plus a changelog
  fragment for the picker behavior change.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 26, 2026 •

Copy link
Copy Markdown

Deploying gitdesktop with  Cloudflare Pages  Cloudflare Pages

Latest commit: c6cb7ca
Status: ✅  Deploy successful!
Preview URL: https://4a5e34bd.gitdesktop.pages.dev
Branch Preview URL: https://fix-select-picker-clip-toolt.gitdesktop.pages.dev

View logs

@theBGuy theBGuy added the enhancement New feature or request label Aug 26, 2026
@theBGuy theBGuy self-assigned this Aug 26, 2026
@theBGuy

theBGuy commented Aug 26, 2026

Copy link
Copy Markdown
Owner Author

Context for reviewers — author notes, on the record before review fires:

  1. What this does: every Select picker holding repo-content names (branches, workflows, pipelines, environments — 18 popup rows across 13 files) now ellipsizes rows that clip and shows the full name in a hover title, on the rows and on the closed field. The five sites that shipped clipTitle-on-SelectItem in fix(ui,checks): route clip-measured tooltips through a shared helper #256 (GeneralSettings, Secrets, Worktrees ×3) convert to the same idiom, so one idiom exists, not two.

  2. The row mechanism is runtime-measured, not inferred. SelectClipText's w-0 min-w-full truncate: the vendored ItemText is shrink-0 with a min-width: auto floor that grows it with its nowrap content — w-0 collapses that floor (the span contributes ~0 intrinsic width), min-w-full re-expands it to the row's real width. Verified in a Chromium repro of the exact vendored structure, independently re-measured by a second review pass, then live in the app.

  3. Why not max-w-[calc(var(--anchor-width)-…)]: measured broken — GeneralSettingsSection caps its popup with max-w-[min(20rem,80vw)], and an anchor-based span renders 360px wide inside the 320px popup, pushing its ellipsis past the clip edge (invisible). A suggestion to switch to the var form should meet this measurement.

  4. The closed field does not ellipsize — deliberate wording. In the built stylesheet the value slot's display:flex beats line-clamp-1's -webkit-box (same specificity, later order), so the trigger hard-clips; what this PR adds there is the hover title only (clipTitleFromText on SelectValue — its scrollWidth axis fires under both display resolutions). The changelog fragment says exactly that.

  5. Live-verified on this exact tree (cold-start worktree instance): trigger tooltip with the full name; rows ellipsize only when clipped, check-indicator gutter clear; row hover tooltip; a 1.8s rested hover on a short row shows no tooltip (the removeAttribute branch); and the w-fit Worktrees "Based on" trigger — popup at its min-w-36 floor — ellipsizes and tooltips correctly at 144px.

  6. Tripwire: select-item-clip-title in scripts/check-banned-patterns.mjs, two arms — a clipTitle handler on/inside a SelectItem, and the pre-fix(ui,checks): route clip-measured tooltips through a shared helper #256 dead block truncate child — plus 5 pinned tests. Accepted evasions are named in the comment (aliased handler, reordered class string, wrapper component). Closest real forward pairing gap today is 379 normalized chars vs the 160 window; a stacked-picker false positive is loud, with the allowlist as remedy.

  7. SelectClipText must be the row's sole child — min-w-full claims ItemText's whole content box, so a sibling icon/badge would be pushed past the popup clip. Documented in the component; children: string types the common case away.

  8. Hover-surface trade at the converted sites: the tooltip moved from the whole row (including the pr-8 indicator gutter) to the text span. Deliberate — that is what buys the visible ellipsis.

  9. Deferred with a home — fields.tsx SelectControl: its rich row (min-w-0 flex-1 truncate) is measured-dead the same way, and sizeToContent hard-clips past its 28rem cap — consumers include the PR-create base/head pickers. It is a shared two-child primitive (the annotations sibling breaks the min-w-full math), so it is its own change with its own verification round; tracked in the project backlog. This PR's fragment deliberately does not claim those surfaces.

  10. Exclusions: fixed-enum pickers keep bare labels (short, never clip meaningfully) — except GitSection's autocrlf picker and the repo-settings AI-target picker, which carry deliberately capped popups and authored-but-dead truncate spans; both converted. Tooltips remain mouse-only (the repo-wide clipTitle trade); the ellipsis is the new signal keyboard users get.

  11. Release-note overlap: fix(ui,checks): route clip-measured tooltips through a shared helper #256's pending fixed-default-branch-select-tooltip fragment is now partially subsumed by this PR's fragment — merging the bullets at release-cut is an owner call, not done here.

Verification: pnpm build ✓ · pnpm run checks 62/62 (new guard clean over 493 files) ✓ · LF-copy biome ci on all 13 touched ts/tsx + a red planted negative control ✓ · NUL scan ✓.


Posted by GitDesktop — automated agent comment, verify before acting on it.

@theBGuy
theBGuy marked this pull request as ready for review August 26, 2026 17:29
Copilot AI lite review requested due to automatic review settings August 26, 2026 17:29

Copilot AI 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.

🟢 Approval recommended

The changes consistently apply a single verified clipping strategy across call sites and add a guard + tests to prevent regressions.

Pull request overview

This pull request fixes long labels overflowing (instead of truncating) in Base UI Select popups and triggers by introducing a single, reliable clipping + hover-title helper and routing all affected picker call sites through it. It also adds a guard + tests to prevent the two previously “dead” truncation/tooltip patterns from being reintroduced.

Changes:

  • Added SelectClipText to make Select popup row text actually ellipsize and only set a title when clipped.
  • Updated Select picker call sites to use SelectClipText for rows and onMouseEnter={clipTitleFromText} on SelectValue for the closed field.
  • Added a banned-patterns guard (select-item-clip-title) with unit tests, plus updated conventions docs and a changelog fragment.
File summaries
File Description
src/components/select-clip-text.tsx Introduces the shared SelectClipText helper that self-bounds row text and sets hover title only when clipped.
src/features/settings/GitSection.tsx Converts line endings picker row text + closed-field hover title to the shared helper/handler.
src/features/repository/WorktreesDialog.tsx Replaces item-level tooltip logic with SelectClipText and adds closed-field hover title handling.
src/features/repository/RebaseOntoDialog.tsx Routes both base pickers’ rows through SelectClipText and adds SelectValue hover title handling.
src/features/repository/BranchMergePickerDialog.tsx Converts merge branch picker rows to SelectClipText and adds SelectValue hover title handling.
src/features/repo-settings/SecretsSection.tsx Switches environment scope picker rows to SelectClipText and adds closed-field hover title handling.
src/features/repo-settings/PagesSection.tsx Converts both Pages branch pickers’ rows to SelectClipText and adds closed-field hover title handling.
src/features/repo-settings/GitLabGeneralSection.tsx Converts default-branch picker rows to SelectClipText and adds closed-field hover title handling.
src/features/repo-settings/GeneralSettingsSection.tsx Converts commit template/default branch picker rows to SelectClipText and adds closed-field hover title handling.
src/features/repo-settings/BitbucketSchedulesSection.tsx Converts schedule branch picker rows to SelectClipText and adds closed-field hover title handling.
src/features/repo-settings/BitbucketGeneralSection.tsx Converts main branch picker rows to SelectClipText and adds closed-field hover title handling.
src/features/history/HistoryDialogs.tsx Converts cherry-pick destination rows to SelectClipText and adds closed-field hover title handling.
src/features/actions/RunWorkflowDialog.tsx Converts workflow/pipeline picker rows to SelectClipText and adds closed-field hover title handling.
scripts/check-banned-patterns.mjs Adds the select-item-clip-title check to prevent reintroducing the two superseded Select truncation/tooltip shapes.
scripts/checks.test.mjs Adds tests covering both matching arms and the intended non-matches/exemptions for the new guard.
.claude/skills/gd-conventions/SKILL.md Updates the repo conventions doc to point contributors at SelectClipText + the SelectValue hover handler.
changelog.d/changed-select-picker-clip-affordances.md Documents the user-visible behavior change (ellipsis + hover-to-see-full-name) across the affected pickers.
Review details
  • Files reviewed: 17/17 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@theBGuy

theBGuy commented Aug 26, 2026

Copy link
Copy Markdown
Owner Author

🤖 GitDesktop AI security audit · opus · automated


No security issues found in these changes. The diff is UI-only: SelectClipText renders its children as escaped JSX text and clipTitleFromText writes to the title property (text sink, not HTML), so repo-derived names (branches, workflows, environments) reach no injection sink; the new check-banned-patterns.mjs arms are build-time regex scans over first-party source with no untrusted input or execution.


Posted by GitDesktop — AI output, verify before acting on it.

@coderabbitai

coderabbitai Bot commented Aug 26, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 26 minutes.

View limit details

Limit details: You’ve used all 2 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: de1a8186-4705-4ff9-baa2-84a9666532f7

📥 Commits

Reviewing files that changed from the base of the PR and between 7ea8c6c and c6cb7ca.

📒 Files selected for processing (4)
  • .claude/skills/gd-conventions/SKILL.md
  • changelog.d/changed-select-picker-clip-affordances.md
  • scripts/check-banned-patterns.mjs
  • scripts/checks.test.mjs
📝 Walkthrough

Walkthrough

The change adds SelectClipText for clipped select rows, applies clipTitleFromText to selected values, updates picker and settings selectors, documents the convention, and adds checks for obsolete clipping patterns.

Changes

Select picker clipping

Layer / File(s) Summary
Shared clipping contract
.claude/skills/gd-conventions/SKILL.md, changelog.d/changed-select-picker-clip-affordances.md, src/components/select-clip-text.tsx
Defines SelectClipText, documents hover title behavior, and records the picker updates.
Dialog picker migration
src/features/actions/RunWorkflowDialog.tsx, src/features/history/HistoryDialogs.tsx, src/features/repository/*
Updates workflow, pipeline, history, merge, rebase, and worktree selectors.
Repository settings migration
src/features/repo-settings/*
Updates branch, environment, commit-message, and Pages selectors.
Application settings migration
src/features/settings/GitSection.tsx
Updates the line-ending selector.
Obsolete pattern enforcement
scripts/check-banned-patterns.mjs, scripts/checks.test.mjs
Detects obsolete SelectItem clipping patterns and tests valid and invalid cases.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: 🔵 Low · up to 7ea8c

This PR centralizes Select clipping and hover titles across picker rows and closed fields. A bounded source-check false positive and stale closed-field titles after selection changes still require owner follow-up, so the change is mergeable with explicit awareness.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 15 files. (2 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: shared clipping for Select picker rows, with related checks included in the scope.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 46.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 15 files. (2 skipped: 2 unsupported.)

✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/select-picker-clip-tooltips

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a63fe56-621e-424a-bc81-22d2addda28e

📥 Commits

Reviewing files that changed from the base of the PR and between 0cd33f3 and 7ea8c6c.

📒 Files selected for processing (17)
  • .claude/skills/gd-conventions/SKILL.md
  • changelog.d/changed-select-picker-clip-affordances.md
  • scripts/check-banned-patterns.mjs
  • scripts/checks.test.mjs
  • src/components/select-clip-text.tsx
  • src/features/actions/RunWorkflowDialog.tsx
  • src/features/history/HistoryDialogs.tsx
  • src/features/repo-settings/BitbucketGeneralSection.tsx
  • src/features/repo-settings/BitbucketSchedulesSection.tsx
  • src/features/repo-settings/GeneralSettingsSection.tsx
  • src/features/repo-settings/GitLabGeneralSection.tsx
  • src/features/repo-settings/PagesSection.tsx
  • src/features/repo-settings/SecretsSection.tsx
  • src/features/repository/BranchMergePickerDialog.tsx
  • src/features/repository/RebaseOntoDialog.tsx
  • src/features/repository/WorktreesDialog.tsx
  • src/features/settings/GitSection.tsx

Included review availability: Your plan provides up to 2 included reviews per hour; 1 remains after this review.

📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: copilot-pull-request-reviewer
  • GitHub Check: Cloudflare Pages
⚠️ CI failures not shown inline (2)

GitHub Actions: changelog / 0_fragment.txt: fix(ui,checks): clip Select picker rows through a shared helper

Conclusion: failure

View job details

##[group]Run node scripts/changelog-draft.mjs --check
 �[36;1mnode scripts/changelog-draft.mjs --check�[0m
 shell: /usr/bin/bash -e {0}
 ##[endgroup]
 ##[error]two or more em-dashes in one bullet reads as a paired "— aside —" interrupter — recast with commas or parentheses; quoted UI copy is exempt inside backticks, **bold**, or "quotes" (see CLAUDE.md "Reader-facing prose outside the blog")

GitHub Actions: changelog / fragment: fix(ui,checks): clip Select picker rows through a shared helper

Conclusion: failure

View job details

##[group]Run node scripts/changelog-draft.mjs --check
 �[36;1mnode scripts/changelog-draft.mjs --check�[0m
 shell: /usr/bin/bash -e {0}
 ##[endgroup]
 ##[error]two or more em-dashes in one bullet reads as a paired "— aside —" interrupter — recast with commas or parentheses; quoted UI copy is exempt inside backticks, **bold**, or "quotes" (see CLAUDE.md "Reader-facing prose outside the blog")
🧰 Additional context used
📓 Path-based instructions (2)
- **Keyboard-first, WCAG AA** — wire arrow-key nav for any new selectable list in the

📄 CodeRabbit inference engine (CLAUDE.md)

Files:

  • src/components/select-clip-text.tsx
  • src/features/settings/GitSection.tsx
  • src/features/repo-settings/BitbucketSchedulesSection.tsx
  • src/features/repository/RebaseOntoDialog.tsx
  • src/features/repository/BranchMergePickerDialog.tsx
  • src/features/history/HistoryDialogs.tsx
  • src/features/actions/RunWorkflowDialog.tsx
  • src/features/repo-settings/BitbucketGeneralSection.tsx
  • src/features/repo-settings/GitLabGeneralSection.tsx
  • src/features/repo-settings/GeneralSettingsSection.tsx
  • src/features/repo-settings/SecretsSection.tsx
  • src/features/repository/WorktreesDialog.tsx
  • src/features/repo-settings/PagesSection.tsx
- **Conventional Commits** with a scope: `feat(github,issues): …`, `fix(diff): …`.

📄 CodeRabbit inference engine (CLAUDE.md)

Files:

  • changelog.d/changed-select-picker-clip-affordances.md
  • src/components/select-clip-text.tsx
  • src/features/settings/GitSection.tsx
  • src/features/repo-settings/BitbucketSchedulesSection.tsx
  • src/features/repository/RebaseOntoDialog.tsx
  • src/features/repository/BranchMergePickerDialog.tsx
  • src/features/history/HistoryDialogs.tsx
  • src/features/actions/RunWorkflowDialog.tsx
  • src/features/repo-settings/BitbucketGeneralSection.tsx
  • src/features/repo-settings/GitLabGeneralSection.tsx
  • src/features/repo-settings/GeneralSettingsSection.tsx
  • src/features/repo-settings/SecretsSection.tsx
  • scripts/checks.test.mjs
  • scripts/check-banned-patterns.mjs
  • src/features/repository/WorktreesDialog.tsx
  • src/features/repo-settings/PagesSection.tsx
🧠 Learnings (3)
📚 Learning: 2026-08-17T06:37:10.176Z
Learnt from: theBGuy
Repo: theBGuy/GitDesktop PR: 214
File: changelog.d/fixed-worktree-removal-stays-visible.md:0-0
Timestamp: 2026-08-17T06:37:10.176Z
Learning: In GitDesktop changelog fragments, describe the current user-visible behavior and any intentional control exceptions. Do not narrate prior defects or internal implementation history, including wording about what a previous UI state “used to” do.

Applied to files:

  • changelog.d/changed-select-picker-clip-affordances.md
📚 Learning: 2026-08-15T16:52:49.221Z
Learnt from: theBGuy
Repo: theBGuy/GitDesktop PR: 209
File: changelog.d/fixed-stash-mid-op-guard.md:1-5
Timestamp: 2026-08-15T16:52:49.221Z
Learning: GitDesktop changelog entries should describe the user-facing benefit or behavior change concisely, without implementation-level epistemic hedging or internal details such as best-effort detection caveats. Document technical limitations and guarantees in the relevant source-code comments instead.

Applied to files:

  • changelog.d/changed-select-picker-clip-affordances.md
📚 Learning: 2026-08-16T06:23:57.614Z
Learnt from: theBGuy
Repo: theBGuy/GitDesktop PR: 212
File: changelog.d/fixed-update-branch-async.md:0-0
Timestamp: 2026-08-16T06:23:57.614Z
Learning: In GitDesktop changelog fragments, retain visible UI details—such as control states, hover text, tabs, and header placement—when they clarify intentional user-facing behavior. Omit internal implementation mechanisms, including polling details and query comparisons.

Applied to files:

  • changelog.d/changed-select-picker-clip-affordances.md
🔇 Additional comments (14)
src/components/select-clip-text.tsx (1)

1-19: LGTM!

.claude/skills/gd-conventions/SKILL.md (1)

98-103: LGTM!

src/features/actions/RunWorkflowDialog.tsx (1)

4-4: LGTM!

Also applies to: 23-23, 201-207, 231-236

src/features/history/HistoryDialogs.tsx (1)

4-4: LGTM!

Also applies to: 24-24, 270-275

src/features/repository/BranchMergePickerDialog.tsx (1)

8-8: LGTM!

Also applies to: 28-28, 217-222

src/features/repository/RebaseOntoDialog.tsx (1)

3-3: LGTM!

Also applies to: 22-22, 175-180, 197-202

src/features/repository/WorktreesDialog.tsx (1)

18-18: LGTM!

Also applies to: 45-45, 883-894, 915-923

src/features/settings/GitSection.tsx (1)

3-3: LGTM!

Also applies to: 12-12, 237-242

src/features/repo-settings/BitbucketGeneralSection.tsx (1)

4-4: LGTM!

Also applies to: 17-17, 274-276

src/features/repo-settings/BitbucketSchedulesSection.tsx (1)

6-6: LGTM!

Also applies to: 19-19, 342-344

src/features/repo-settings/GeneralSettingsSection.tsx (1)

5-5: LGTM!

Also applies to: 20-20, 183-185, 361-363

src/features/repo-settings/GitLabGeneralSection.tsx (1)

4-4: LGTM!

Also applies to: 17-17, 297-299

src/features/repo-settings/PagesSection.tsx (1)

5-5: LGTM!

Also applies to: 20-20, 146-148, 299-301

src/features/repo-settings/SecretsSection.tsx (1)

5-5: LGTM!

Also applies to: 17-17, 146-148

Comment thread changelog.d/changed-select-picker-clip-affordances.md Outdated
Comment thread scripts/check-banned-patterns.mjs
Comment thread src/features/repo-settings/BitbucketGeneralSection.tsx
@theBGuy

theBGuy commented Aug 26, 2026

Copy link
Copy Markdown
Owner Author

🤖 GitDesktop AI review · opus · automated


Summary

Routes every repo-content Select popup row through a new shared SelectClipText span (w-0 min-w-full truncate + clipTitleFromText), adds clipTitleFromText to the closed field's SelectValue at 18 sites, converts the five clipTitle-on-SelectItem sites from #256, and ships a select-item-clip-title tripwire with tests. The mechanism and the conversion sweep look sound — I checked the vendored SelectItem/ItemText structure, every remaining <SelectItem site under src/ (the unconverted ones are fixed-enum labels or the deferred multi-child rows), and the new guard's pairing distances against the real tree; the guard is clean today. Nothing blocking. One real problem in the guard's false-positive envelope and its test fixture, plus copy/doc gaps.

Guard & tests

  • should-fix — scripts/check-banned-patterns.mjs:213-216 (SELECT_ITEM_CLIP_TITLE_RE) together with the bounded fixture in scripts/checks.test.mjs ("select-item-clip-title leaves the SelectClipText idiom and trigger handlers alone"). The arm bans any clipTitle token within PAIR_GAP of a <SelectItem, but a legal, live instance of exactly that pairing exists: src/features/scripts/TaskDialog.tsx:334-347 puts onMouseEnter={clipTitle(found)} on a self-bounded max-w-64 truncate span inside a SelectItem — a span that really does measure clipped, so the handler is not dead. It passes only because the rich row's markup leaves ~320 normalized chars between <SelectItem and clipTitle (2× the 160 window); shortening that row (dropping the missing branch, trimming the class list, hoisting the span into a helper) turns a correct pattern red. The test that claims to pin this shape as legal omits the handler entirely (<span className="max-w-64 truncate font-mono">{path}</span>), so it pins a shape that does not exist in the tree and the suite reports coverage it doesn't have. Concretely: change bounded to carry the real onMouseEnter={clipTitle(found)} on the self-bounded span and assert what the guard actually does with it at close range (it matches — so assert [1] and rename the test comment from "stays legal" to "a self-bounded span still pairs — known false positive, allowlist is the remedy"); and extend the block comment's false-positive paragraph at check-banned-patterns.mjs:206-212 to name TaskDialog's ~320-char legal-clip-span collision alongside the 379-char stacked-picker one, since it is the closer of the two and the comment currently presents stacked pickers as the only route. Do not pre-add src/features/scripts/TaskDialog.tsx to the check's allowlist as a hedge — runCheck reports an entry that produces no hit as a stale-entry failure, so that would turn pnpm run checks red immediately.
  • nit — check-banned-patterns.mjs:211-212: the "Accepted evasions" list omits the shape 8 of the 13 converted files actually had before this PR — a bare {b.name} text child, which no arm can catch and which is how the fixed class will re-open. Name it so a later reader doesn't read the tripwire as covering the whole class.

Docs & copy

  • should-fix — changelog.d/changed-select-picker-clip-affordances.md: the bullet enumerates surfaces, but three converted pickers fall outside every clause — the cherry-pick-onto branch picker (src/features/history/HistoryDialogs.tsx:270-277), the Settings → Git line-endings picker (src/features/settings/GitSection.tsx:237-243), and the commit-message model picker in repo settings (src/features/repo-settings/GeneralSettingsSection.tsx:180-186; "Branch pickers … across repository settings" doesn't reach it, and neither does "workflow, pipeline, and environment pickers"). The same sentence also uses a paired em-dash interrupter (— plus workflow, pipeline, and environment pickers —), which CLAUDE.md bans for reader-facing prose including changelog.d/ fragments. One rewrite fixes both:

    - Long names in the app's dropdown pickers now ellipsize when they don't fit
      the open list, and show the full name on hover on both the rows and the
      closed field: branch pickers in the merge, rebase, rebase-onto, cherry-pick,
      and worktree dialogs and across repository settings, plus the workflow,
      pipeline, environment, commit-message-model, and line-endings pickers.
  • nit — documentation surfaces: the diff adds the changelog fragment (and correctly leaves CHANGELOG.md alone) but touches none of README.md, site/src/data/capabilities.ts / site/src/pages/index.astro, or src/features/help/content.ts. For a clip-affordance polish, fragment-only is plausibly the right call — but the repo convention asks for that call to be stated, and none of the 11 reviewer notes covers it; add a line saying so (the notes cover the fix(ui,checks): route clip-measured tooltips through a shared helper #256 fragment overlap, not this).

Readability

  • nit — .claude/skills/gd-conventions/SKILL.md:98-103: the new sentence stacks three clauses inside a paired "— … —" interrupter, and it omits the invariant an agent is most likely to break — SelectClipText must be the row's sole child (documented only in src/components/select-clip-text.tsx:9-10, enforced by nothing mechanical, so an added icon/badge silently pushes past the popup's clip edge). Recast as two sentences and carry the invariant, e.g.: "Base UI Select popup rows route through SelectClipText (src/components/select-clip-text.tsx), which must be the row's sole child. A bare truncate child never engages there and an item-level handler is dead once the row span self-bounds (the select-item-clip-title guard fails on both); the closed field takes onMouseEnter={clipTitleFromText} on its SelectValue."

Recorded decisions I'm not re-flagging: the --anchor-width alternative (measured broken under call-site max-w), the hover-surface trade at converted sites, mouse-only tooltips with the ellipsis as the keyboard signal, the fields.tsx/SelectControl deferral, and the #256 fragment overlap left as an owner call at release cut.


Posted by GitDesktop — AI output, verify before acting on it.

@theBGuy

theBGuy commented Aug 26, 2026

Copy link
Copy Markdown
Owner Author

Dispositions for the AI review (each verified against source; changes land in the next push):

  1. Guard fixture + comment (should-fix) — accepted, with an upgrade. bounded did pin a phantom: the real TaskDialog span carries onMouseEnter={clipTitle(found)} (verified at TaskDialog.tsx:347). Beyond documenting the collision, both guard arms now take CodeRabbit's tempered step — (?!</SelectItem\b) stops each scan at the item's closing tag — which kills the stacked-picker false-positive class outright (a compact stacked fixture that fired pre-tempering is pinned as a regression test). The comment now names the one remaining known false positive: TaskDialog's legal self-bounded span, ~2× outside the window today, allowlist as remedy. TaskDialog is not pre-allowlisted — your stale-entry point is exactly right.

  2. Fragment surfaces (should-fix) — accepted, with a correction of my own record. HistoryDialogs is indeed the cherry-pick dialog (DialogTitle "Cherry-pick to branch" — my context-comment item 1 carried the mislabel forward from the task notes). Rewritten to name merge, rebase, rebase-onto, cherry-pick, and worktree dialogs, repository settings, and the workflow, pipeline, environment, line-endings, and commit-message model pickers — split into two sentences so the rows-vs-closed-field behaviors can't blur (CodeRabbit's ask too), paired em-dash gone (the CI red). One deviation from your proposed wording: "the app's dropdown pickers" would over-claim while the SelectControl consumers (PR-create base/head) stay deferred, so the enumeration stays explicit.

  3. Evasions list (nit) — accepted: the bare no-affordance text child is now named as the shape no arm can see.

  4. Doc surfaces (nit) — accepted; stating the call here for the record: README, the site capabilities list, and the in-app help guide are deliberately untouched — this is affordance polish on existing surfaces, not a feature. The changelog fragment is the only user-facing doc surface; gd-conventions and the guard are the dev-facing ones, both updated in-diff.

  5. Conventions sentence (nit) — accepted: recast as two sentences, carrying the sole-child invariant.


Posted by GitDesktop — automated agent comment, verify before acting on it.

- `scripts/check-banned-patterns.mjs`: temper both `select-item-clip-title`
  patterns with `(?!</SelectItem\b)` so each scan stops at the item's closing
  tag. Previously a stacked picker could pair one Select's last item with the
  next Select's `SelectValue` trigger handler once the gap tightened; the
  comment now records the one remaining false positive (a self-bounded
  `max-w` clip span inside an item) and points at the allowlist as its remedy.
- `scripts/checks.test.mjs`: the stacked-picker fixture, which fired before
  the tempered step, now asserts clean, and the self-bounded span is asserted
  as the known false positive instead of as legal.
- `changelog.d/changed-select-picker-clip-affordances.md`: lead with the
  behavior, note the closed-field hover, and add the sites the first draft
  missed (cherry-pick, line-endings, commit-message model pickers).
- `gd-conventions` skill: state that `SelectClipText` must be the row's sole
  child, since a sibling child reintroduces the shrink-refusing layout.
@theBGuy

theBGuy commented Aug 26, 2026

Copy link
Copy Markdown
Owner Author

🤖 GitDesktop AI review · opus · automated


Fix round verified: the tempered (?!</SelectItem\b) step is correct (each scan really does stop at the item's closing tag, so the stacked fixture can't pair), the bounded fixture now carries TaskDialog's real onMouseEnter={clipTitle(found)} and asserts the true [1] behavior, and I re-measured TaskDialog's live gap (~300 normalized chars from <SelectItem at :334 to clipTitle at :347) so the guard stays clean today. One piece of collateral from the tempering fix is left behind.

Guard

  • should-fix — scripts/check-banned-patterns.mjs:347 (the select-item-clip-title message): it still ends "if the pairing is a false positive (stacked pickers), add an allowlist entry with rationale", but the tempered step this push added makes the stacked-picker pairing impossible — that is exactly what the new stacked fixture (scripts/checks.test.mjs:255-266) pins, and the block comment at :202-217 now names a different FP entirely. Concretely: the one shape that can still fire falsely is a legal self-bounded clip span inside a compacted rich row (TaskDialog's max-w-64 truncate sub-span, today ~2× outside the window), and a dev who hits that red is pointed at a class that can no longer occur while the real one goes unnamed. Fix: replace the parenthetical with the surviving case, e.g. "…; if the pairing is a false positive (a self-bounded clip span inside a rich row — its own max-w keeps the handler live), add an allowlist entry with rationale", so the message and the block comment name the same remaining FP. No other change is owed: the grep for stacked picker shows this line is the last reference, the allowlist: [] stays empty (pre-adding TaskDialog would fail runCheck's stale-entry arm at :489), and the tests need no edit.

Resolved since last review

  • bounded no longer pins a phantom — it carries the real handler and asserts [1], and the comment at :210-213 names TaskDialog's collision as the known FP. The tempered step is a genuine upgrade over what I asked for (also flagged by CodeRabbit); I checked it does not fail open on the shapes the other fixtures cover.
  • Changelog fragment: cherry-pick, line-endings, and commit-message model pickers now named, the rows-vs-closed-field behaviors split into separate clauses, paired em-dash gone. "rebase" checks out — BranchMergePickerDialog is the merge/squash/rebase picker (PickerMode at :34).
  • Evasions list now names the bare no-affordance text child.
  • gd-conventions/SKILL.md:98-103 recast as two sentences carrying the sole-child invariant.
  • Doc-surface call (README / site / help untouched) is now stated on the record rather than silent.

CodeRabbit's stale-title-on-controlled-value-change point remains a recorded, declined decision; clipTitleFromText re-measures and removes on every mouseenter, so the residual is bounded to a pointer resting on a closed trigger — non-blocking either way.

Verdict: no blocking issues — remaining items are non-blocking; merge when ready


Posted by GitDesktop — AI output, verify before acting on it.

@theBGuy

theBGuy commented Aug 26, 2026

Copy link
Copy Markdown
Owner Author

Fix-round disposition: the message-string collateral is accepted — with the tempered step in, "(stacked pickers)" named a false-positive class that can no longer occur while the surviving one went unnamed. The select-item-clip-title message now names the self-bounded-clip-span case, matching the block comment, exactly as suggested; allowlist stays empty per the stale-entry semantics. One line, checks 62/62 — ready in the tree for the next push, which should close the board.


Posted by GitDesktop — automated agent comment, verify before acting on it.

The banned-pattern message told authors to allowlist "stacked pickers"
without saying what makes such a pairing legitimate. Point instead at the
real shape — a self-bounded clip span inside a rich row, whose own max-w
keeps the item-level handler live — so the allowlist rationale can be
judged rather than guessed at.
@theBGuy

theBGuy commented Aug 26, 2026

Copy link
Copy Markdown
Owner Author

🤖 GitDesktop AI review · opus · automated


The one-line delta since my last review applies the select-item-clip-title message fix exactly as scoped; I re-verified it against the guard's block comment and the check machinery, and nothing new was disturbed.

Resolved since last review

  • scripts/check-banned-patterns.mjs:347 — the message parenthetical no longer names the now-impossible stacked-picker pairing; it names the surviving false positive (a self-bounded clip span inside a rich row), matching the block comment at :210-213 verbatim in substance. The fix is a pure string edit with no collateral: allowlist stays [] (so runCheck's stale-entry arm at :489 has nothing to trip on), the two regexes at :218-225 are untouched, and no fixture in scripts/checks.test.mjs asserts on message text. I also confirmed the guard can't self-trip on its own fixtures — main() walks SRC only (:494), so scripts/checks.test.mjs is never scanned — and that WorktreesDialog.tsx's widened import is still justified (clipTitle remains in use at :380).

Nothing further to raise. CodeRabbit's stale-title-on-controlled-value-change comment on BitbucketGeneralSection.tsx:271 is still open on the PR but remains a recorded, declined decision, non-blocking either way.

Verdict: no blocking issues — remaining items are non-blocking; merge when ready


Posted by GitDesktop — AI output, verify before acting on it.

@theBGuy
theBGuy merged commit 49105ad into master Aug 26, 2026
6 checks passed
@theBGuy
theBGuy deleted the fix/select-picker-clip-tooltips branch August 26, 2026 18:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants