@flamingo-stack/openframe-frontend-core 0.0.192 → 0.0.193-snapshot.20260518191824

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,6 +17,7 @@ import {
17
17
  type DragStartEvent,
18
18
  } from '@dnd-kit/core'
19
19
  import { arrayMove, sortableKeyboardCoordinates } from '@dnd-kit/sortable'
20
+ import { useHorizontalScrollbar } from '@/hooks/ui/use-horizontal-scrollbar'
20
21
  import { cn } from '../../../utils/cn'
21
22
  import { BoardColumn } from './board-column'
22
23
  import { TicketCard } from './ticket-card'
@@ -48,6 +49,19 @@ export function Board({
48
49
  }: BoardProps) {
49
50
  const { collapsed, toggle } = useBoardCollapse(collapseStorageKey)
50
51
 
52
+ const {
53
+ scrollRef,
54
+ trackRef,
55
+ thumbRef,
56
+ thumbRatio,
57
+ onScroll,
58
+ onTrackClick,
59
+ onTrackWheel,
60
+ onThumbPointerDown,
61
+ onThumbPointerMove,
62
+ onThumbPointerUp,
63
+ } = useHorizontalScrollbar()
64
+
51
65
  const [items, setItems] = React.useState<BoardColumnDef[]>(columns)
52
66
  const isDraggingRef = React.useRef(false)
53
67
 
@@ -232,31 +246,56 @@ export function Board({
232
246
  onDragEnd={handleDragEnd}
233
247
  onDragCancel={handleDragCancel}
234
248
  >
235
- <div className={cn('flex h-full overflow-x-auto', className)}>
236
- {items.map((column, i) => {
237
- const prev = items[i - 1]
238
- const next = items[i + 1]
239
- const joinLeft = !!(column.system && prev?.system)
240
- const joinRight = !!(column.system && next?.system)
241
- const showGap = i > 0 && !joinLeft
242
- return (
243
- <React.Fragment key={column.id}>
244
- {showGap && <div aria-hidden className="w-[var(--spacing-system-mf)] shrink-0" />}
245
- <BoardColumn
246
- column={column}
247
- collapsed={!!collapsed[column.id]}
248
- onToggleCollapse={() => toggle(column.id)}
249
- onAddTicket={onAddTicket}
250
- getTicketHref={getTicketHref}
251
- renderAssignSlot={renderAssignSlot}
252
- onLoadMore={onLoadMore}
253
- loadMoreRootMargin={loadMoreRootMargin}
254
- joinLeft={joinLeft}
255
- joinRight={joinRight}
256
- />
257
- </React.Fragment>
258
- )
259
- })}
249
+ <div className={cn('flex flex-col h-full', className)}>
250
+ <div
251
+ ref={scrollRef}
252
+ onScroll={onScroll}
253
+ className="flex flex-1 min-h-0 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
254
+ >
255
+ {items.map((column, i) => {
256
+ const prev = items[i - 1]
257
+ const next = items[i + 1]
258
+ const joinLeft = !!(column.system && prev?.system)
259
+ const joinRight = !!(column.system && next?.system)
260
+ const showGap = i > 0 && !joinLeft
261
+ return (
262
+ <React.Fragment key={column.id}>
263
+ {showGap && <div aria-hidden className="w-[var(--spacing-system-mf)] shrink-0" />}
264
+ <BoardColumn
265
+ column={column}
266
+ collapsed={!!collapsed[column.id]}
267
+ onToggleCollapse={() => toggle(column.id)}
268
+ onAddTicket={onAddTicket}
269
+ getTicketHref={getTicketHref}
270
+ renderAssignSlot={renderAssignSlot}
271
+ onLoadMore={onLoadMore}
272
+ loadMoreRootMargin={loadMoreRootMargin}
273
+ joinLeft={joinLeft}
274
+ joinRight={joinRight}
275
+ />
276
+ </React.Fragment>
277
+ )
278
+ })}
279
+ </div>
280
+
281
+ {thumbRatio > 0 && (
282
+ <div
283
+ ref={trackRef}
284
+ onClick={onTrackClick}
285
+ onWheel={onTrackWheel}
286
+ className="relative h-2 mt-[var(--spacing-system-mf)] rounded-full bg-ods-border cursor-pointer shrink-0"
287
+ >
288
+ <div
289
+ ref={thumbRef}
290
+ data-scrollbar-thumb
291
+ className="absolute top-0 h-full rounded-full bg-ods-text-secondary transition-colors"
292
+ style={{ width: `${thumbRatio * 100}%`, cursor: 'grab' }}
293
+ onPointerDown={onThumbPointerDown}
294
+ onPointerMove={onThumbPointerMove}
295
+ onPointerUp={onThumbPointerUp}
296
+ />
297
+ </div>
298
+ )}
260
299
  </div>
261
300
  <DragOverlay dropAnimation={null}>
262
301
  {activeTicket ? (