@takazudo/ui-components
Shared React UI component library used across the zudotext app. Includes buttons, layout primitives, navigation components, dialogs, toast notifications, icons, and utility hooks. Its component examples are in the zudo-sg styleguide.
Main Exports
import {
// Components
Button,
IconButton,
EmptyState,
SidebarEmpty,
SidebarItem,
SidebarSearch,
Toast,
ToastDismissButton,
ErrorToast,
FileChangeToast,
UndoDeleteToast,
FontPicker,
DraftBar,
MergeToolbar,
DiffViewerDialog,
DiffViewerPane,
PanelDivider,
PageLayout,
ChordIndicator,
FileTree,
TabBar,
SectionTabs,
ShortcutCaptureInput,
Spinner,
ConfirmDialog,
ModalFrame,
MobileFullscreenDialog,
Tooltip,
SpotlightPicker,
BottomSheet,
DropdownListbox,
InlineEditField,
TimeSettingsPopover,
IconPicker,
PickableIcon,
CalendarView,
ItemDetailDialog,
ToolbarKebabMenu,
HslPicker,
NativeColorInput,
// Icons
ChevronLeftIcon,
ChevronRightIcon,
CheckIcon,
ChevronDownIcon,
ArrowsPointingOutIcon,
ArrowsPointingInIcon,
PlusIcon,
SearchIcon,
SlidersIcon,
InboxReturnIcon,
XMarkIcon,
FolderIcon,
SwapIcon,
LayoutLRIcon,
LayoutTBIcon,
TerminalLeftIcon,
TerminalRightIcon,
TerminalTopIcon,
TerminalBottomIcon,
ImageIcon,
TrashIcon,
SweepIcon,
PinIcon,
StarIcon,
StarOutlineIcon,
SparklesIcon,
CalendarIcon,
ListBulletIcon,
SplitHorizontalIcon,
SplitVerticalIcon,
PileViewIcon,
GridViewIcon,
ListDetailViewIcon,
TableViewIcon,
LinkIcon,
LinkOffIcon,
QuickActionsIcon,
DocumentIcon,
MindMapIcon,
ResetIcon,
HelpIcon,
GhostIcon,
PaperclipIcon,
ArchivesIcon,
InboxIcon,
SettingsIcon,
BellIcon,
PencilIcon,
AppPlusIcon,
LaunchAppIcon,
// Direction icons
SplitFrameRightIcon,
SplitFrameLeftIcon,
SplitFrameTopIcon,
SplitFrameBottomIcon,
FocusFrameRightIcon,
FocusFrameLeftIcon,
FocusFrameTopIcon,
FocusFrameBottomIcon,
CommandMenuIcon,
// Hooks
useTimedFeedback,
useDebouncedQuery,
useIsMobileViewport,
useKeyboardInset,
useWindowedList,
// Utilities
paneFloatBtnCls,
panelBorderCls,
MOBILE_BREAKPOINT_TOKEN,
MOBILE_BREAKPOINT_PX,
highlightMatches,
DRAFT_DRAG_MIME,
getIsDraftDragging,
} from "@takazudo/ui-components";
import type {
FileTreeEntry,
LayoutDirection,
TabBarProps,
TabBarTab,
SectionTabsProps,
SectionTabsTab,
SpinnerProps,
ModalFrameProps,
MobileFullscreenDialogProps,
TooltipProps,
SpotlightPickerProps,
SpotlightPickerMode,
ShortcutCaptureInputProps,
DropdownListboxProps,
DropdownListboxItem,
InlineEditFieldProps,
DiffViewerPaneProps,
CalendarViewProps,
ItemDetailDialogProps,
} from "@takazudo/ui-components";Key Components
Layout
PageLayout — main app layout container
PanelDivider — resizable split panel divider supporting horizontal/vertical directions
DraftBar — draft number selector with scrollable navigation, new-draft button, and pointer-driven ghost reorder (
onReorderfires once per valid, changed drop with the new order permutation). Extra props:canReorderNote,reorderResetKey,arrangeMode,onInsertNote,pendingPlacements,unnumberedIds.useDraftBarReorder(indraft-bar-reorder.tsx) owns the tab gesture and renders the insertion sequenceNoteNumberSlot — the one box a Note Tray number occupies, also holding the centered status glyph while a number is pending. Bounded geometry policy: the slot is as wide as a hidden "000" in its own font (tabular digits, semibold), so every 1–3 digit number shares one footprint and 9→10 / 99→100 move nothing; no
max+1prediction is made; a 4+ digit number grows by whole digits and is never ellipsized.NOTE_NUMBER_SLOT_CLSserves surfaces that cannot use the component
Navigation
SidebarItem — clickable sidebar list item
SidebarSearch — search input for sidebar filtering
SidebarEmpty — empty state for sidebar with message
FileTree — hierarchical file browser tree
TabBar — tab strip for switching between named panels
SectionTabs — tab strip variant used inside settings/dialog sections
Actions
Button — standard button component
IconButton — icon-only button
FontPicker — font family selector with monospace detection
ShortcutCaptureInput — keyboard shortcut capture input (records key combos)
DropdownListbox — accessible dropdown select component
InlineEditField — inline text edit (click to activate, Enter/Escape to commit/cancel)
Dialogs & Overlays
ModalFrame — base modal container (backdrop + centered card). The backdrop uses the
--overlay-bgtoken (bg-[var(--overlay-bg)]), the canonical modal scrim color.MobileFullscreenDialog — full-bleed dialog for viewports ≤
MOBILE_BREAKPOINT_PX(640 px); use for all settings-like dialogsConfirmDialog — the app's shared "are you sure?" modal (#6570). Cancel takes initial focus, Escape cancels on a capturing listener so a provider's own Escape handler underneath never sees it, the background is made inert while it is open, and the header carries the close (X) that also means Cancel.
dangerrenders the confirm button in the danger variant. Promoted from the assets-filer's privateFolderConfirmDialog; use it instead of hand-rolling a confirmation, so emptying a frame, deleting a folder and every other destructive prompt read and behave the same way.Tooltip — hover tooltip with configurable placement
SpotlightPicker — macOS Spotlight-style file/directory search modal (macOS-only; falls back to native OS dialog on other platforms)
BottomSheet — mobile slide-up bottom sheet
ItemDetailDialog — detail view dialog for kanban/todo items
TimeSettingsPopover — popover for configuring notification/recurrence settings
CalendarView — virtualized calendar view (week rows)
ToolbarKebabMenu — overflow/kebab menu for toolbars (mobile)
IconPicker / PickableIcon — icon selector and pickable icon tile from the Lucide icon set
HslPicker — canonical HSL color picker popover (body-portaled, viewport-flip positioning, gradient sliders, hex input, native-picker fallback via
NativeColorInput). Moved here from@takazudo/settings-sectionsand unified with the former kanban-board copy (#3303).usePopoverClose/getFixedPopoverStyle(outside-click / Escape / scroll dismiss + viewport-aware fixed positioning) are exported alongside it for other popover-style consumers.
Feedback
Toast / ToastDismissButton — toast notification system
ErrorToast — error-specific toast
FileChangeToast — file change notification toast
UndoDeleteToast — toast with undo action for delete operations (auto-expires after configurable duration)
Spinner — loading spinner
ChordIndicator — displays pending keyboard chord state (integrates with
@takazudo/shortcut-engine)
Diff & Merge
MergeToolbar — toolbar for merge conflict resolution (accept theirs/ours, show diff)
DiffViewerDialog — side-by-side diff viewer dialog
DiffViewerPane — embeddable diff viewer pane (without dialog chrome)
State
EmptyState — placeholder for empty content areas
Icons
55+ SVG icon components following a consistent API. From icons.ts (~46 icons):
ChevronLeftIcon, ChevronRightIcon, CheckIcon, ChevronDownIcon, ArrowsPointingOutIcon, ArrowsPointingInIcon, PlusIcon, SearchIcon, SlidersIcon, InboxReturnIcon, XMarkIcon, FolderIcon, SwapIcon, LayoutLRIcon, LayoutTBIcon, TerminalLeftIcon, TerminalRightIcon, TerminalTopIcon, TerminalBottomIcon, ImageIcon, TrashIcon, SweepIcon, PinIcon, StarIcon, StarOutlineIcon, SparklesIcon, CalendarIcon, ListBulletIcon, SplitHorizontalIcon, SplitVerticalIcon, PileViewIcon, GridViewIcon, ListDetailViewIcon, TableViewIcon, LinkIcon, LinkOffIcon, QuickActionsIcon, DocumentIcon, MindMapIcon, ResetIcon, HelpIcon, GhostIcon, PaperclipIcon, ArchivesIcon, InboxIcon, SettingsIcon, BellIcon, PencilIcon, AppPlusIcon, LaunchAppIcon
From direction-icons.ts (9 direction/command icons):
SplitFrameRightIcon, SplitFrameLeftIcon, SplitFrameTopIcon, SplitFrameBottomIcon, FocusFrameRightIcon, FocusFrameLeftIcon, FocusFrameTopIcon, FocusFrameBottomIcon, CommandMenuIcon
Hooks
useTimedFeedback
A hook for showing temporary feedback (e.g., "Copied!" after a copy action).
const { active, trigger } = useTimedFeedback();
// trigger() sets active to true, then false after a timeoutuseDebouncedQuery
Debounces a search query string to avoid triggering on every keystroke.
const debouncedQuery = useDebouncedQuery(query, 300);useIsMobileViewport
Returns true when the viewport width is ≤ MOBILE_BREAKPOINT_PX (640 px). Use in dialogs to switch between mobile and desktop layouts.
const isMobile = useIsMobileViewport();useKeyboardInset
Returns the current virtual keyboard inset height (pixels) — used on iOS to shift content above the on-screen keyboard.
useWindowedList
Windowed list hook backed by @tanstack/react-virtual — renders only the visible slice of a large list for performance.
Utilities
paneFloatBtnCls — CSS class string for floating pane buttons
panelBorderCls — CSS class string for panel borders
MOBILE_BREAKPOINT_TOKEN — Tailwind CSS class token string for the 640 px breakpoint
MOBILE_BREAKPOINT_PX — numeric constant
640for the mobile breakpointhighlightMatches — splits a string into segments marking fuzzy-match positions (used in search result highlights)
DRAFT_DRAG_MIME — retained export;
DraftBartabs no longer use native HTML5 drag, so nothing drops with this MIME type any moregetIsDraftDragging — returns
truewhile a ghost reorder gesture is active (an alias ofisGhostReorderActive)
Ghost reorder
useGhostReorder, isGhostReorderActive, GhostReorderLift and GhostReorderAnnouncer are the shared gesture for Note Tray tabs and Pile cards (use-ghost-reorder.ts, ghost-reorder-model.ts, ghost-reorder-lift.tsx). The hook owns gesture state only; the host owns persistence and receives exactly one onCommit (GhostReorderCommit: order, sourceId, beforeId, via) per valid, changed pointer drop or keyboard step.
A 4 px threshold lifts the source. Hit testing is by axis (
ReorderAxis) against peer midpoints captured at gesture start, and the surface autoscrolls near its own edge.The destination is a ghost: a dotted inset outline over a hatched accent tint (CSS in
tokens.css, via::after; a double Highlight outline under forced colors). The lift chip is portaled.Escape (captured, stops propagation),
pointercancel, an outside or no-op drop, a membership change, aresetKeychange, disabling and unmount all cancel with no write. A click after a drag is suppressed, focus returns to the same UUID, and a polite live region announces the result.Alt+Arrowsteps the focused item one place.Touch: tabs have no touch drag (the browser pans); Pile handles use
touch-action: noneand mobile Pile drag is disabled.
ContextMenu wrapLabels
ContextMenu truncates long row labels by default. wrapLabels (a prop that flows through the menu chain, MenuChainContext) wraps them instead and caps the menu at min(360px × scale, 100vw − 2 × spacing-lg). The Note Tray utility menus enable it.
Styling
The package uses Tailwind CSS 4 with custom design tokens:
// Import the Tailwind CSS entry point
import "@takazudo/ui-components/tailwind.css";Custom tokens are defined in src/ and provide spacing, font sizes, and color aliases that map to the --theme-* CSS variables from @takazudo/color-themes.
Dependencies
@takazudo/shortcut-engine— used byChordIndicator@takazudo/backend-bridge— used bySpotlightPickerfor the file search bridgediff— used byDiffViewerDialog/DiffViewerPane@tanstack/react-virtual— used byuseWindowedListandCalendarViewlucide-react— used byIconPicker/PickableIcon@takazudo/color-themes— used byHslPicker(hexToHsl/hslToHex/contrastTextColor)@takazudo/date-utils— used byCalendarView/useVirtualizedWeeks(toIsoDate,isToday)Peer dependencies:
react >= 19,react-dom >= 19