|
3 | 3 | * Licensed under the MIT License. See License.txt in the project root for license information. |
4 | 4 | *--------------------------------------------------------------------------------------------*/ |
5 | 5 |
|
6 | | -import React, { useContext, useRef, useState } from 'react'; |
| 6 | +import React, { useContext, useEffect, useRef, useState } from 'react'; |
7 | 7 | import { COPILOT_LOGINS } from '../../src/common/copilot'; |
8 | 8 | import { gitHubLabelColor } from '../../src/common/utils'; |
9 | 9 | import { IAccount, IMilestone, IProjectItem, reviewerId, reviewerLabel, ReviewState } from '../../src/github/interface'; |
@@ -255,7 +255,7 @@ export function CollapsibleSidebar(props: PullRequest) { |
255 | 255 | > |
256 | 256 | <Sidebar {...props} /> |
257 | 257 | </div> |
258 | | - <a className='collapsible-label-see-more' onClick={() => setExpanded(e => !e)}>{expanded ? 'See less' : 'See more...'}</a> |
| 258 | + <a className='collapsible-label-see-more' onClick={() => setExpanded(e => !e)}>{expanded ? 'See less' : 'See more'}</a> |
259 | 259 | </div> |
260 | 260 | ); |
261 | 261 | } |
@@ -283,28 +283,61 @@ function CollapsedLabel(props: PullRequest) { |
283 | 283 | getColor: (item: any) => { backgroundColor: string; textColor: string; borderColor: string }, |
284 | 284 | getText: (item: any) => string |
285 | 285 | }) => { |
286 | | - return <span className="pill-stack"> |
287 | | - {items.slice(0, 5).map((item, i) => { |
| 286 | + const containerRef = useRef<HTMLSpanElement>(null); |
| 287 | + const [visibleCount, setVisibleCount] = useState(items.length); |
| 288 | + |
| 289 | + useEffect(() => { |
| 290 | + if (!containerRef.current || items.length === 0) return; |
| 291 | + |
| 292 | + const resizeObserver = new ResizeObserver(() => { |
| 293 | + const container = containerRef.current; |
| 294 | + if (!container) return; |
| 295 | + |
| 296 | + const containerWidth = container.offsetWidth; |
| 297 | + const overflowTextWidth = 60; // "+N more" text width estimate |
| 298 | + |
| 299 | + // Start with all items and reduce until they fit |
| 300 | + let testCount = items.length; |
| 301 | + while (testCount > 0) { |
| 302 | + const testWidth = testCount * 50 + (testCount < items.length ? overflowTextWidth : 0); |
| 303 | + if (testWidth <= containerWidth) { |
| 304 | + break; |
| 305 | + } |
| 306 | + testCount--; |
| 307 | + } |
| 308 | + |
| 309 | + setVisibleCount(Math.max(1, testCount)); |
| 310 | + }); |
| 311 | + |
| 312 | + resizeObserver.observe(containerRef.current); |
| 313 | + return () => resizeObserver.disconnect(); |
| 314 | + }, [items.length]); |
| 315 | + |
| 316 | + const visibleItems = items.slice(0, visibleCount); |
| 317 | + const hiddenCount = items.length - visibleCount; |
| 318 | + |
| 319 | + return <span className="pill-container" ref={containerRef}> |
| 320 | + {visibleItems.map((item) => { |
288 | 321 | const color = getColor(item); |
289 | | - const pill = ( |
| 322 | + return ( |
290 | 323 | <span |
291 | 324 | key={getKey(item)} |
292 | | - className="stacked-pill" |
| 325 | + className="pill-item" |
293 | 326 | style={{ |
294 | 327 | backgroundColor: color.backgroundColor, |
295 | 328 | color: color.textColor, |
296 | 329 | borderRadius: '20px', |
297 | | - left: `${(i * 20)}px`, |
298 | 330 | }} |
299 | 331 | title={getText(item)} |
300 | 332 | > |
301 | 333 | {getText(item)} |
302 | 334 | </span> |
303 | 335 | ); |
304 | | - return pill; |
305 | 336 | })} |
| 337 | + {hiddenCount > 0 && ( |
| 338 | + <span className="pill-overflow">+{hiddenCount}</span> |
| 339 | + )} |
306 | 340 | </span>; |
307 | | - |
308 | 341 | }; |
309 | 342 |
|
310 | 343 | // Collect non-empty sections in order, with custom rendering |
|
0 commit comments