@@ -20,6 +20,7 @@ import isEqual from 'fast-deep-equal';
2020import { useIntersectionObserver } from 'usehooks-ts' ;
2121
2222import { LabelSet } from '@parca/client' ;
23+ import { Button } from '@parca/components' ;
2324
2425import { TimelineGuide } from '../../TimelineGuide' ;
2526import { NumberDuo } from '../../utils' ;
@@ -69,6 +70,7 @@ export const labelSetToString = (labelSet?: LabelSet): string => {
6970} ;
7071
7172const STRIP_HEIGHT = 24 ;
73+ const MAX_VISIBLE_STRIPS = 20 ;
7274
7375const getTimelineGuideHeight = ( cpusCount : number , collapsedCount : number ) : number => {
7476 return ( STRIP_HEIGHT + 4 ) * ( cpusCount - collapsedCount ) + 20 * collapsedCount + 24 - 6 ;
@@ -169,6 +171,7 @@ export const SamplesStrip = ({
169171 stepMs,
170172} : Props ) : JSX . Element => {
171173 const [ collapsedLabels , setCollapsedLabels ] = useState < Set < string > > ( new Set ( ) ) ;
174+ const [ showAll , setShowAll ] = useState ( false ) ;
172175 const [ dragState , setDragState ] = useState < DragState | undefined > ( undefined ) ;
173176 const containerRef = useRef < HTMLDivElement > ( null ) ;
174177
@@ -184,6 +187,12 @@ export const SamplesStrip = ({
184187 return items . sort ( ( a , b ) => a . label . localeCompare ( b . label ) ) ;
185188 } , [ cpus , data ] ) ;
186189
190+ const hasMore = useMemo ( ( ) => sortedItems . length > MAX_VISIBLE_STRIPS , [ sortedItems ] ) ;
191+ const visibleItems = useMemo (
192+ ( ) => ( showAll || ! hasMore ? sortedItems : sortedItems . slice ( 0 , MAX_VISIBLE_STRIPS ) ) ,
193+ [ sortedItems , showAll , hasMore ]
194+ ) ;
195+
187196 // Deterministic color: hash the label string so the same label always gets the same color
188197 // regardless of render order.
189198 const color = useMemo ( ( ) => {
@@ -227,8 +236,7 @@ export const SamplesStrip = ({
227236 const innerWidth = width ?? rect . width ;
228237 const startTs = bounds [ 0 ] + ( start / innerWidth ) * ( bounds [ 1 ] - bounds [ 0 ] ) ;
229238 const endTs = bounds [ 0 ] + ( end / innerWidth ) * ( bounds [ 1 ] - bounds [ 0 ] ) ;
230- // Use sortedItems to get the correct cpu for the strip index
231- onSelectedTimeframe ( sortedItems [ stripIndex ] . cpu , [ startTs , endTs ] ) ;
239+ onSelectedTimeframe ( visibleItems [ stripIndex ] . cpu , [ startTs , endTs ] ) ;
232240 }
233241
234242 setDragState ( undefined ) ;
@@ -258,10 +266,13 @@ export const SamplesStrip = ({
258266 < TimelineGuide
259267 bounds = { [ BigInt ( 0 ) , BigInt ( bounds [ 1 ] - bounds [ 0 ] ) ] }
260268 width = { width ?? 1468 }
261- height = { getTimelineGuideHeight ( sortedItems . length , collapsedLabels . size ) }
269+ height = { getTimelineGuideHeight (
270+ visibleItems . length ,
271+ [ ...collapsedLabels ] . filter ( l => visibleItems . some ( item => item . label === l ) ) . length
272+ ) }
262273 margin = { 1 }
263274 />
264- { sortedItems . map ( ( item , i ) => {
275+ { visibleItems . map ( ( item , i ) => {
265276 const isCollapsed = collapsedLabels . has ( item . label ) ;
266277 const isSelected = isEqual ( item . cpu , selectedTimeframe ?. labels ) ;
267278
@@ -296,6 +307,11 @@ export const SamplesStrip = ({
296307 />
297308 ) ;
298309 } ) }
310+ { hasMore && ! showAll && (
311+ < Button variant = "secondary" onClick = { ( ) => setShowAll ( true ) } className = "w-fit mx-auto mt-2" >
312+ Show all { sortedItems . length } rows
313+ </ Button >
314+ ) }
299315 </ div >
300316 ) ;
301317} ;
0 commit comments