zudo-text

検索したい単語を入力

いつでも検索バーを開ける

@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 (onReorder fires once per valid, changed drop with the new order permutation). Extra props: canReorderNote, reorderResetKey, arrangeMode, onInsertNote, pendingPlacements, unnumberedIds. useDraftBarReorder (in draft-bar-reorder.tsx) owns the tab gesture and renders the insertion sequence

  • NoteNumberSlot — 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+1 prediction is made; a 4+ digit number grows by whole digits and is never ellipsized. NOTE_NUMBER_SLOT_CLS serves 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-bg token (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 dialogs

  • ConfirmDialog — 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. danger renders the confirm button in the danger variant. Promoted from the assets-filer's private FolderConfirmDialog; 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-sections and 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 timeout

useDebouncedQuery

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 640 for the mobile breakpoint

  • highlightMatches — splits a string into segments marking fuzzy-match positions (used in search result highlights)

  • DRAFT_DRAG_MIME — retained export; DraftBar tabs no longer use native HTML5 drag, so nothing drops with this MIME type any more

  • getIsDraftDragging — returns true while a ghost reorder gesture is active (an alias of isGhostReorderActive)

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, a resetKey change, 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+Arrow steps the focused item one place.

  • Touch: tabs have no touch drag (the browser pans); Pile handles use touch-action: none and 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/tokens.css and provide spacing, font sizes, and color aliases that map to the --theme-* CSS variables from @takazudo/color-themes.

Dependencies

  • @takazudo/shortcut-engine — used by ChordIndicator

  • @takazudo/backend-bridge — used by SpotlightPicker for the file search bridge

  • diff — used by DiffViewerDialog / DiffViewerPane

  • @tanstack/react-virtual — used by useWindowedList and CalendarView

  • lucide-react — used by IconPicker / PickableIcon

  • @takazudo/color-themes — used by HslPicker (hexToHsl/hslToHex/contrastTextColor)

  • @takazudo/date-utils — used by CalendarView / useVirtualizedWeeks (toIsoDate, isToday)

  • Peer dependencies: react >= 19, react-dom >= 19