fix(ui): Size Select popups to the widest option and truncate the PR repo name

Virtualised list rows are absolutely positioned, so the popup only took the
trigger's width and cut short labels like "Merged". The Pull Requests header
now keeps the repository on one line with an ellipsis and a tooltip.
This commit is contained in:
l0ng-ai
2026-10-24 10:02:13 +08:00
parent 1309ce10e4
commit 4f74f22624
4 changed files with 38 additions and 4 deletions
+4
View File
@@ -37,7 +37,11 @@
white-space: nowrap;
}
.repo {
min-width: 0;
margin-left: 8px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--fg-subtle);
font-size: var(--fs-small);
}
+6 -1
View File
@@ -591,5 +591,10 @@ export function PullRequestsView() {
export function PullRequestsHeader() {
const availability = useGithub((s) => s.availability);
if (availability?.kind !== "ready") return null;
return <span className={styles.repo}>{availability.repo.nameWithOwner}</span>;
const name = availability.repo.nameWithOwner;
return (
<span className={styles.repo} title={name}>
{name}
</span>
);
}
+17 -2
View File
@@ -72,14 +72,29 @@
flex: none;
color: var(--fg-muted);
}
/* The label keeps its width (up to most of the row); a long detail (a path) is cut instead. */
.sizer {
height: 0;
overflow: hidden;
visibility: hidden;
}
/* Mirrors a List row: inset, padding and gap. */
.sizerRow {
display: flex;
gap: 6px;
margin: 0 var(--list-inset, 6px);
padding: 0 8px;
white-space: nowrap;
}
.optionLabel {
flex: 1 0 auto;
max-width: 70%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* The label keeps its width (up to most of the row); a long detail (a path) is cut instead. */
.withDetail {
max-width: 70%;
}
.detail {
flex: 0 1 auto;
min-width: 0;
+11 -1
View File
@@ -127,6 +127,16 @@ export function Select<V extends string = string>({
className={styles.popup}
>
<div tabIndex={-1} data-autofocus onKeyDown={onPopupKey} className={styles.popupInner}>
{/* Virtualised rows are absolutely positioned; this sizes the popup to the widest label. */}
<div aria-hidden className={styles.sizer}>
{options.map((o) => (
<div key={o.value} className={styles.sizerRow}>
<span className={styles.check} />
{o.icon && <Icon name={o.icon} size={14} />}
<span>{tx(o.label)}</span>
</div>
))}
</div>
<List
items={options}
getKey={(o) => o.value}
@@ -144,7 +154,7 @@ export function Select<V extends string = string>({
<>
<span className={styles.check}>{o.value === value && <Icon name="check" size={12} />}</span>
{o.icon && <Icon name={o.icon} size={14} />}
<span className={styles.optionLabel}>{tx(o.label)}</span>
<span className={clsx(styles.optionLabel, o.detail && styles.withDetail)}>{tx(o.label)}</span>
{o.detail && (
<span className={styles.detail} title={o.detail}>
{tx(o.detail)}