@@ -205,6 +205,15 @@ export interface PopoverContentProps
205205 * Maximum height for the popover content in pixels
206206 */
207207 maxHeight ?: number
208+ /**
209+ * Maximum width for the popover content in pixels.
210+ * When provided, Popover will also enable default truncation for inner text and section headers.
211+ */
212+ maxWidth ?: number
213+ /**
214+ * Minimum width for the popover content in pixels
215+ */
216+ minWidth ?: number
208217 /**
209218 * Preferred side to display the popover
210219 * @default 'bottom'
@@ -249,6 +258,8 @@ const PopoverContent = React.forwardRef<
249258 style,
250259 children,
251260 maxHeight,
261+ maxWidth,
262+ minWidth,
252263 side = 'bottom' ,
253264 align = 'start' ,
254265 sideOffset,
@@ -264,7 +275,11 @@ const PopoverContent = React.forwardRef<
264275 // When present, we enable default text truncation behavior for inner flexible items,
265276 // so callers don't need to manually pass 'truncate' to every label.
266277 const hasUserWidthConstraint =
267- style ?. minWidth !== undefined || style ?. maxWidth !== undefined || style ?. width !== undefined
278+ maxWidth !== undefined ||
279+ minWidth !== undefined ||
280+ style ?. minWidth !== undefined ||
281+ style ?. maxWidth !== undefined ||
282+ style ?. width !== undefined
268283
269284 return (
270285 < PopoverPrimitive . Portal >
@@ -278,15 +293,21 @@ const PopoverContent = React.forwardRef<
278293 sticky = 'partial'
279294 { ...restProps }
280295 className = { cn (
281- 'z-[10000001] flex flex-col overflow-hidden rounded-[8px] bg-[var(--surface-3)] px-[5.5px] py-[5px] text-foreground outline-none dark:bg-[var(--surface-3)]' ,
282- // If width is constrained by the caller, ensure inner flexible text truncates by default.
283- hasUserWidthConstraint && '[&_.flex-1]: truncate' ,
284- className
296+ 'z-[10000001] flex flex-col overflow-auto rounded-[8px] bg-[var(--surface-3)] px-[5.5px] py-[5px] text-foreground outline-none dark:bg-[var(--surface-3)]' ,
297+ // If width is constrained by the caller (prop or style) , ensure inner flexible text truncates by default,
298+ // and also truncate section headers.
299+ hasUserWidthConstraint && '[&_.flex-1]:truncate [&_[data-popover-section]]:truncate' ,
285300 ) }
286301 style = { {
287302 maxHeight : `${ maxHeight || 400 } px` ,
288- maxWidth : 'calc(100vw - 16px)' ,
289- minWidth : '160px' ,
303+ maxWidth : maxWidth !== undefined ? `${ maxWidth } px` : 'calc(100vw - 16px)' ,
304+ // Only enforce default min width when the user hasn't set width constraints
305+ minWidth :
306+ minWidth !== undefined
307+ ? `${ minWidth } px`
308+ : hasUserWidthConstraint
309+ ? undefined
310+ : '160px' ,
290311 ...style ,
291312 } }
292313 >
@@ -319,7 +340,7 @@ const PopoverScrollArea = React.forwardRef<HTMLDivElement, PopoverScrollAreaProp
319340 ( { className, ...props } , ref ) => {
320341 return (
321342 < div
322- className = { cn ( 'min-h-0 flex-1 overflow-auto overscroll-contain' , className ) }
343+ className = { cn ( 'min-h-0 overflow-auto overscroll-contain' , className ) }
323344 ref = { ref }
324345 { ...props }
325346 />
@@ -415,9 +436,10 @@ const PopoverSection = React.forwardRef<HTMLDivElement, PopoverSectionProps>(
415436 return (
416437 < div
417438 className = { cn (
418- 'px-[6px] py-[4px] font-base text-[12px] text-[var(--text-tertiary)] dark:text-[var(--text-tertiary)]' ,
439+ 'min-w-0 px-[6px] py-[4px] font-base text-[12px] text-[var(--text-tertiary)] dark:text-[var(--text-tertiary)]' ,
419440 className
420441 ) }
442+ data-popover-section = ''
421443 ref = { ref }
422444 { ...props }
423445 />
0 commit comments