88} from "@heroicons/react/20/solid" ;
99import { StarIcon as StarIconOutline } from "@heroicons/react/24/outline" ;
1010import { GripVerticalIcon } from "lucide-react" ;
11- import { useMemo , useState } from "react" ;
11+ import { useMemo , useRef , useState } from "react" ;
1212import { ColumnsIcon } from "~/assets/icons/ColumnsIcon" ;
1313import { useFavoritePageToggle } from "~/components/navigation/favoritePages" ;
1414import { Button } from "~/components/primitives/Buttons" ;
@@ -19,10 +19,13 @@ import {
1919 PopoverMenuItem ,
2020 PopoverTrigger ,
2121} from "~/components/primitives/Popover" ;
22+ import { ShortcutKey } from "~/components/primitives/ShortcutKey" ;
23+ import { SimpleTooltip } from "~/components/primitives/Tooltip" ;
2224import { useEnvironment } from "~/hooks/useEnvironment" ;
2325import { useFeatures } from "~/hooks/useFeatures" ;
2426import { useOptimisticLocation } from "~/hooks/useOptimisticLocation" ;
2527import { useSearchParams } from "~/hooks/useSearchParam" ;
28+ import { useShortcutKeys } from "~/hooks/useShortcutKeys" ;
2629import { cn } from "~/utils/cn" ;
2730import {
2831 encodeColumnLayout ,
@@ -41,6 +44,9 @@ function keyFor(col: ResolvedColumn): string {
4144
4245type SmartEditTarget = { index : number ; def : SmartColumnDef } ;
4346
47+ /** Opens the Columns popover. "l" is free on every list this control appears on. */
48+ export const COLUMNS_SHORTCUT = { key : "l" as const } ;
49+
4450export function RunsDisplayOptions ( {
4551 sampleFilters,
4652} : {
@@ -56,6 +62,16 @@ export function RunsDisplayOptions({
5662 const [ editing , setEditing ] = useState < SmartEditTarget | null > ( null ) ;
5763 const [ dragKey , setDragKey ] = useState < string | null > ( null ) ;
5864 const [ overKey , setOverKey ] = useState < string | null > ( null ) ;
65+ const triggerRef = useRef < HTMLButtonElement > ( null ) ;
66+
67+ useShortcutKeys ( {
68+ shortcut : COLUMNS_SHORTCUT ,
69+ action : ( event ) => {
70+ event . preventDefault ( ) ;
71+ event . stopPropagation ( ) ;
72+ triggerRef . current ?. click ( ) ;
73+ } ,
74+ } ) ;
5975
6076 const runtime : RunColumnRuntime = {
6177 isManagedCloud,
@@ -141,11 +157,28 @@ export function RunsDisplayOptions({
141157 return (
142158 < >
143159 < Popover >
144- < PopoverTrigger asChild >
145- < Button variant = "secondary/small" LeadingIcon = { ColumnsIcon } >
146- Columns
147- </ Button >
148- </ PopoverTrigger >
160+ < SimpleTooltip
161+ asChild
162+ side = "bottom"
163+ disableHoverableContent
164+ button = {
165+ // Plain wrapper: Button drops the pointer-event props Radix injects via asChild,
166+ // so the tooltip anchor can't be the Button itself (same as NotificationPanel).
167+ < div className = "flex" >
168+ < PopoverTrigger asChild >
169+ < Button ref = { triggerRef } variant = "secondary/small" LeadingIcon = { ColumnsIcon } >
170+ Columns
171+ </ Button >
172+ </ PopoverTrigger >
173+ </ div >
174+ }
175+ content = {
176+ < span className = "flex items-center gap-2" >
177+ Customize columns
178+ < ShortcutKey shortcut = { COLUMNS_SHORTCUT } variant = "small" />
179+ </ span >
180+ }
181+ />
149182 < PopoverContent
150183 align = "end"
151184 className = "w-64 p-0"
@@ -194,6 +227,7 @@ export function RunsDisplayOptions({
194227 icon = { PlusIcon }
195228 title = "Add smart column…"
196229 onClick = { ( ) => setAddOpen ( true ) }
230+ className = "h-8"
197231 />
198232 { canFavorite && (
199233 < PopoverMenuItem
@@ -206,13 +240,15 @@ export function RunsDisplayOptions({
206240 }
207241 title = { isFavorited ? "Remove from favorites" : "Save to favorites" }
208242 onClick = { toggleFavorite }
243+ className = "h-8"
209244 />
210245 ) }
211246 < PopoverMenuItem
212247 icon = { ArrowUturnLeftIcon }
213248 title = "Reset to default"
214249 onClick = { reset }
215250 disabled = { ! layout . isCustomized }
251+ className = "h-8"
216252 />
217253 </ div >
218254 </ PopoverContent >
@@ -268,7 +304,7 @@ function ColumnRow({
268304 return (
269305 < div
270306 className = { cn (
271- "group relative flex h-[1.8rem] items-center rounded-sm transition-colors hover:bg-background-hover" ,
307+ "group relative flex h-8 items-center rounded-sm transition-colors hover:bg-background-hover" ,
272308 dragging && "opacity-40"
273309 ) }
274310 draggable
@@ -289,7 +325,7 @@ function ColumnRow({
289325 { /* Native label so the whole name area toggles the column, matching CheckboxWithLabel. */ }
290326 < label
291327 className = { cn (
292- "flex h-full min-w-0 flex-1 items-center gap-x-1.5 pl-[0.4rem] " ,
328+ "flex h-full min-w-0 flex-1 items-center gap-x-2 pl-2 " ,
293329 locked ? "cursor-default" : "cursor-pointer"
294330 ) }
295331 >
@@ -305,13 +341,13 @@ function ColumnRow({
305341 </ span >
306342 { isSmart && < BoltIcon className = "size-3.5 flex-none text-text-dimmed" /> }
307343 </ label >
308- < div className = "flex flex-none items-center gap-0.5 pr-[0.4rem] " >
344+ < div className = "flex flex-none items-center gap-0.5 pr-1 " >
309345 { onEdit && (
310346 < button
311347 type = "button"
312348 onClick = { onEdit }
313349 aria-label = { `Edit ${ col . def . label } ` }
314- className = "flex size-6 cursor-pointer items-center justify-center rounded-sm text-text-dimmed opacity-0 transition hover:bg-charcoal-700 hover:text-text-bright focus-custom group-hover :opacity-100 group-focus-within :opacity-100"
350+ className = "flex size-6 cursor-pointer items-center justify-center rounded-sm text-text-dimmed opacity-0 transition hover:bg-charcoal-700 hover:text-text-bright focus-custom focus-visible :opacity-100 group-hover :opacity-100"
315351 >
316352 < PencilSquareIcon className = "size-4" />
317353 </ button >
@@ -321,7 +357,7 @@ function ColumnRow({
321357 type = "button"
322358 onClick = { onRemove }
323359 aria-label = { `Remove ${ col . def . label } ` }
324- className = "flex size-6 cursor-pointer items-center justify-center rounded-sm text-text-dimmed opacity-0 transition hover:bg-charcoal-700 hover:text-error focus-custom group-hover :opacity-100 group-focus-within :opacity-100"
360+ className = "flex size-6 cursor-pointer items-center justify-center rounded-sm text-text-dimmed opacity-0 transition hover:bg-charcoal-700 hover:text-error focus-custom focus-visible :opacity-100 group-hover :opacity-100"
325361 >
326362 < XMarkIcon className = "size-4" />
327363 </ button >
@@ -338,7 +374,7 @@ function ColumnRow({
338374 onMove ( 1 ) ;
339375 }
340376 } }
341- className = "flex size-6 cursor-grab items-center justify-center rounded-sm text-text-dimmed opacity-0 transition hover:bg-charcoal-700 hover:text-text-bright focus-custom group-hover :opacity-100 group-focus-within :opacity-100 active:cursor-grabbing"
377+ className = "flex size-6 cursor-grab items-center justify-center rounded-sm text-text-dimmed opacity-0 transition hover:bg-charcoal-700 hover:text-text-bright focus-custom focus-visible :opacity-100 group-hover :opacity-100 active:cursor-grabbing"
342378 >
343379 < GripVerticalIcon className = "size-4" />
344380 </ button >
0 commit comments