Page Ribbon
retab-ui/page-ribbonFreeComponent
A page-axis ribbon: segments drawn as blocks spanning their pages. One vertical lane = a split sidebar; many horizontal rows (consensus + votes) = a partition waterfall. Shared hover/focus/selection + click-to-jump.
Install it
npx shadcn@latest add https://ui.retab.com/r/page-ribbon.jsonSource
1"use client";23import * as React from "react";45import {6 getSegmentInteractionState,7 getSegmentSurfaceProps,8 scopeSegmentInteraction,9 type SegmentInteraction,10} from "@/lib/segment-interaction";11import {12 buildPageRuns,13 normalizePageCount,14 segmentDisplayLabel,15} from "@/lib/segments";16import { cn } from "@/lib/utils";1718import type { DocumentSegment } from "./segmented-document-model";1920/** One lane of the ribbon: segments positioned by their page ranges. */21export interface RibbonRow {22 id: string;23 label?: string;24 segments: DocumentSegment[];25}2627export interface PageRibbonProps {28 rows: RibbonRow[];29 pageCount: number;30 /** "vertical" — pages run top→bottom (split sidebar). "horizontal" — left→right (partition waterfall). */31 orientation?: "vertical" | "horizontal";32 /** 1-based current page; drawn as a cursor line + caret across the rows. */33 currentPage?: number | null;34 /** 0..1 fine-grained scroll cursor (horizontal only); overrides the page line. */35 scrollProgress?: number | null;36 /** Shared preview state. */37 interaction?: SegmentInteraction;38 /** Click a segment → jump the document to its first page. */39 onSelectPage?: (page: number) => void;40 /** Fired when a segment surface is clicked. */41 onSelect?: (segment: DocumentSegment) => void;42 showTicks?: boolean;43 /** Thickness of each row: column width (vertical) or row height (horizontal), px. */44 rowThickness?: number;45 className?: string;46}4748/**49 * A page-axis ribbon: every segment is drawn as a block spanning its pages.50 * One vertical row with tiled segments is the split sidebar; many horizontal51 * rows (consensus + votes) is the partition waterfall — same component, same52 * `Segment[]` model. Driven by shared interaction state so hovering a segment53 * here dims the others in the legend too.54 */55export function PageRibbon({56 rows,57 pageCount,58 orientation = "horizontal",59 currentPage,60 scrollProgress,61 interaction,62 onSelectPage,63 onSelect,64 showTicks = false,65 rowThickness,66 className,67}: PageRibbonProps) {68 const vertical = orientation === "vertical";69 const total = normalizePageCount(pageCount);70 const defaultThickness = vertical ? 44 : 10;71 const thickness =72 rowThickness != null && Number.isFinite(rowThickness) && rowThickness > 073 ? rowThickness74 : defaultThickness;75 const visibleSegments = React.useMemo(76 () =>77 rows.flatMap((row) =>78 row.segments.filter(79// … truncated
What it pulls in
Other registry items
Files it writes
More from retab-ui
All 130 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Alertalert | retab-ui | Components | Free | 1 dep | |
| Alert Dialogalert-dialog | retab-ui | Components | Free | 1 dep | |
| Aspect Ratioaspect-ratio | retab-ui | Components | Free | no deps | |
| Attachment Sidebarattachment-sidebar | retab-ui | Components | Free | 1 dep | |
| Autocompleteautocomplete | retab-ui | Components | Free | 2 deps | |
| Calendarcalendar | retab-ui | Components | Free | 2 deps | |
| Code Viewercode-viewer | retab-ui | Components | Free | 2 deps · 32 files | |
| Commandcommand | retab-ui | Components | Free | 2 deps |
