React components reference
Complete reference for all 85+ components, 12+ hooks, and utility functions exported by @cloudillo/react.
Layout Components
Container
Centered max-width container for page content.
import { Container } from '@cloudillo/react'
<Container>
<h1>Page Content</h1>
</Container>HBox, VBox, Group
Flexbox layout primitives.
import { HBox, VBox, Group } from '@cloudillo/react'
// Horizontal layout
<HBox gap="md">
<Button>Left</Button>
<Button>Right</Button>
</HBox>
// Vertical layout
<VBox gap="sm">
<Input label="Name" />
<Input label="Email" />
</VBox>
// Grouped items with spacing
<Group>
<Tag>React</Tag>
<Tag>TypeScript</Tag>
</Group>Props (shared):
gap?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'- Spacing between childrenalign?: 'start' | 'center' | 'end' | 'stretch'- Alignmentjustify?: 'start' | 'center' | 'end' | 'between' | 'around'- Justification
Panel
Bordered container with optional header.
import { Panel } from '@cloudillo/react'
<Panel title="Settings">
<p>Panel content here</p>
</Panel>Card
Elevated card container.
import { Card } from '@cloudillo/react'
<Card>
<h3>Card Title</h3>
<p>Card content</p>
</Card>Fcd (Filter-Content-Details)
Three-column responsive layout pattern for list views.
import { Fcd, FcdContainer, FcdFilter, FcdContent, FcdDetails } from '@cloudillo/react'
<FcdContainer>
<FcdFilter>
<FilterBar />
</FcdFilter>
<FcdContent>
<ItemList />
</FcdContent>
<FcdDetails>
<ItemDetails />
</FcdDetails>
</FcdContainer>Navigation Components
Sidebar
Collapsible sidebar with mobile support.
import {
useSidebar,
Sidebar,
SidebarContent,
SidebarHeader,
SidebarFooter,
SidebarNav,
SidebarSection,
SidebarToggle,
SidebarBackdrop,
SidebarResizeHandle
} from '@cloudillo/react'
function Layout() {
const sidebar = useSidebar({ defaultOpen: true })
return (
<div>
<SidebarBackdrop {...sidebar} />
<Sidebar {...sidebar}>
<SidebarHeader>
<Logo />
</SidebarHeader>
<SidebarContent>
<SidebarNav>
<SidebarSection title="Main">
<NavItem to="/home">Home</NavItem>
<NavItem to="/files">Files</NavItem>
</SidebarSection>
</SidebarNav>
</SidebarContent>
<SidebarFooter>
<ProfileCard />
</SidebarFooter>
<SidebarResizeHandle />
</Sidebar>
<SidebarToggle {...sidebar} />
</div>
)
}useSidebar options:
interface UseSidebarOptions {
defaultOpen?: boolean
defaultWidth?: number
minWidth?: number
maxWidth?: number
breakpoint?: number // Mobile breakpoint
}Additional components:
SidebarBackdrop- Mobile overlay backdrop that closes sidebar when tappedSidebarResizeHandle- Draggable handle for resizing sidebar widthSidebarContext/useSidebarContext- Context provider and hook for nested components
Nav, NavGroup, NavItem, NavLink
Navigation menu components.
import { Nav, NavGroup, NavItem, NavLink } from '@cloudillo/react'
<Nav>
<NavGroup title="Main">
<NavItem icon={<HomeIcon />}>
<NavLink to="/home">Home</NavLink>
</NavItem>
<NavItem icon={<FilesIcon />}>
<NavLink to="/files">Files</NavLink>
</NavItem>
</NavGroup>
</Nav>Tabs, Tab
Tabbed interface.
import { Tabs, Tab } from '@cloudillo/react'
<Tabs defaultValue="tab1">
<Tab value="tab1" label="General">
<GeneralSettings />
</Tab>
<Tab value="tab2" label="Advanced">
<AdvancedSettings />
</Tab>
</Tabs>Context: TabsContext is available for building custom tab implementations.
Form Components
Input
Text input with label and validation.
import { Input } from '@cloudillo/react'
<Input
label="Email"
type="email"
placeholder="you@example.com"
error="Invalid email address"
/>Props:
label?: string- Input labelerror?: string- Error messagehint?: string- Helper textsize?: 'sm' | 'md' | 'lg'- Input size- All standard
<input>props
TextArea
Multi-line text input.
import { TextArea } from '@cloudillo/react'
<TextArea
label="Description"
rows={4}
placeholder="Enter description..."
/>Select
Custom dropdown select.
import { Select } from '@cloudillo/react'
<Select
label="Country"
options={[
{ value: 'us', label: 'United States' },
{ value: 'uk', label: 'United Kingdom' },
{ value: 'de', label: 'Germany' }
]}
onChange={(value) => console.log(value)}
/>NativeSelect
Native browser select element.
import { NativeSelect } from '@cloudillo/react'
<NativeSelect label="Priority">
<option value="low">Low</option>
<option value="medium">Medium</option>
<option value="high">High</option>
</NativeSelect>NumberInput
Numeric input with increment/decrement buttons.
import { NumberInput } from '@cloudillo/react'
<NumberInput
label="Quantity"
min={0}
max={100}
step={1}
value={5}
onChange={(value) => console.log(value)}
/>ColorInput
Color picker input.
import { ColorInput } from '@cloudillo/react'
<ColorInput
label="Theme Color"
value="#3b82f6"
onChange={(color) => console.log(color)}
/>Toggle
On/off toggle switch.
import { Toggle } from '@cloudillo/react'
<Toggle
label="Enable notifications"
checked={enabled}
onChange={setEnabled}
/>Fieldset
Group related form fields.
import { Fieldset } from '@cloudillo/react'
<Fieldset legend="Contact Information">
<Input label="Phone" />
<Input label="Address" />
</Fieldset>InputGroup
Group input with addons (prefix/suffix).
import { InputGroup } from '@cloudillo/react'
<InputGroup>
<InputGroup.Addon>https://</InputGroup.Addon>
<Input placeholder="example.com" />
</InputGroup>TagInput
Multi-value tag input with autocomplete.
import { TagInput } from '@cloudillo/react'
<TagInput
label="Tags"
value={['react', 'typescript']}
onChange={setTags}
suggestions={['react', 'vue', 'angular', 'typescript']}
placeholder="Add tags..."
/>InlineEditForm
Inline editable text field.
import { InlineEditForm } from '@cloudillo/react'
<InlineEditForm
value={title}
onSave={(newValue) => updateTitle(newValue)}
placeholder="Click to edit..."
/>Button Components
Button
Primary button component.
import { Button } from '@cloudillo/react'
<Button variant="primary" onClick={handleClick}>
Save Changes
</Button>
<Button variant="secondary" size="sm">
Cancel
</Button>
<Button variant="danger" loading>
Deleting...
</Button>Props:
variant?: 'primary' | 'secondary' | 'danger' | 'ghost'size?: 'xs' | 'sm' | 'md' | 'lg'loading?: boolean- Shows spinnerdisabled?: booleanicon?: ReactNode- Left iconiconRight?: ReactNode- Right icon
LinkButton
Button styled as a link.
import { LinkButton } from '@cloudillo/react'
<LinkButton to="/settings">Go to Settings</LinkButton>Dialog & Overlay Components
Dialog
Modal dialog with backdrop.
import { Dialog, useDialog } from '@cloudillo/react'
function MyComponent() {
const dialog = useDialog()
return (
<>
<Button onClick={dialog.open}>Open Dialog</Button>
<Dialog {...dialog} title="Confirm Action">
<p>Are you sure you want to proceed?</p>
<HBox gap="sm">
<Button variant="secondary" onClick={dialog.close}>Cancel</Button>
<Button variant="primary" onClick={handleConfirm}>Confirm</Button>
</HBox>
</Dialog>
</>
)
}useDialog returns:
interface UseDialogReturn {
isOpen: boolean
open: () => void
close: () => void
toggle: () => void
}DialogContainer
Wrapper component for rendering dialogs at the root level.
import { DialogContainer } from '@cloudillo/react'
function App() {
return (
<>
<MainContent />
<DialogContainer />
</>
)
}Modal
Low-level modal wrapper.
import { Modal } from '@cloudillo/react'
<Modal isOpen={isOpen} onClose={handleClose}>
<div className="modal-content">
Custom modal content
</div>
</Modal>BottomSheet
Mobile-friendly bottom sheet.
import { BottomSheet } from '@cloudillo/react'
<BottomSheet
isOpen={isOpen}
onClose={handleClose}
snapPoints={['50%', '90%']}
>
<div>Sheet content</div>
</BottomSheet>Dropdown
Dropdown menu container.
import { Dropdown } from '@cloudillo/react'
<Dropdown
trigger={<Button>Options</Button>}
align="end"
>
<MenuItem onClick={handleEdit}>Edit</MenuItem>
<MenuItem onClick={handleDelete}>Delete</MenuItem>
</Dropdown>Popper
Floating positioned element (tooltips, popovers).
import { Popper } from '@cloudillo/react'
<Popper
trigger={<Button>Hover me</Button>}
placement="top"
>
<div>Tooltip content</div>
</Popper>QRCodeDialog
Dialog showing a QR code.
import { QRCodeDialog } from '@cloudillo/react'
<QRCodeDialog
isOpen={isOpen}
onClose={handleClose}
value="https://cloudillo.net/share/abc123"
title="Share Link"
/>Menu Components
Menu, MenuItem, MenuDivider, MenuHeader
Context menu and dropdown menu items.
import { Menu, MenuItem, MenuDivider, MenuHeader } from '@cloudillo/react'
<Menu>
<MenuHeader>Actions</MenuHeader>
<MenuItem icon={<EditIcon />} onClick={handleEdit}>
Edit
</MenuItem>
<MenuItem icon={<CopyIcon />} onClick={handleCopy}>
Copy
</MenuItem>
<MenuDivider />
<MenuItem icon={<TrashIcon />} variant="danger" onClick={handleDelete}>
Delete
</MenuItem>
</Menu>ActionSheet
Mobile action sheet (bottom menu).
import { ActionSheet, ActionSheetItem, ActionSheetDivider } from '@cloudillo/react'
<ActionSheet isOpen={isOpen} onClose={handleClose}>
<ActionSheetItem onClick={handleShare}>Share</ActionSheetItem>
<ActionSheetItem onClick={handleCopy}>Copy Link</ActionSheetItem>
<ActionSheetDivider />
<ActionSheetItem variant="danger" onClick={handleDelete}>
Delete
</ActionSheetItem>
</ActionSheet>Feedback Components
Toast
Toast notification system.
import { useToast, ToastContainer } from '@cloudillo/react'
// In your app root
function App() {
return (
<>
<ToastContainer />
<MainContent />
</>
)
}
// In any component
function MyComponent() {
const toast = useToast()
const handleSave = async () => {
try {
await saveData()
toast.success('Saved successfully!')
} catch (err) {
toast.error('Failed to save')
}
}
return <Button onClick={handleSave}>Save</Button>
}useToast methods:
toast.success(message, options?)- Success toasttoast.error(message, options?)- Error toasttoast.warning(message, options?)- Warning toasttoast.info(message, options?)- Info toasttoast.custom(content, options?)- Custom toast
Toast sub-components:
For building custom toast layouts:
import {
Toast,
ToastIcon,
ToastContent,
ToastTitle,
ToastMessage,
ToastActions,
ToastClose,
ToastProgress
} from '@cloudillo/react'
// Custom toast layout
<Toast variant="success">
<ToastIcon />
<ToastContent>
<ToastTitle>Success!</ToastTitle>
<ToastMessage>Your changes have been saved.</ToastMessage>
</ToastContent>
<ToastActions>
<Button size="sm">Undo</Button>
</ToastActions>
<ToastClose />
<ToastProgress />
</Toast>Context: ToastContext and useToastContext are available for building custom toast providers.
LoadingSpinner
Spinning loader indicator.
import { LoadingSpinner } from '@cloudillo/react'
<LoadingSpinner size="md" />
{isLoading && <LoadingSpinner />}Skeleton, SkeletonText, SkeletonCard, SkeletonList
Loading skeleton placeholders.
import { Skeleton, SkeletonText, SkeletonCard, SkeletonList } from '@cloudillo/react'
// Basic skeleton
<Skeleton width={200} height={20} />
// Text skeleton
<SkeletonText lines={3} />
// Card skeleton
<SkeletonCard />
// List skeleton
<SkeletonList count={5} />Progress
Progress bar.
import { Progress } from '@cloudillo/react'
<Progress value={75} max={100} />
<Progress value={uploadProgress} showLabel />EmptyState
Empty state placeholder.
import { EmptyState } from '@cloudillo/react'
<EmptyState
icon={<FilesIcon />}
title="No files yet"
description="Upload your first file to get started"
action={<Button>Upload File</Button>}
/>Profile Components
Avatar, AvatarStatus, AvatarBadge, AvatarGroup
User avatar components.
import { Avatar, AvatarStatus, AvatarBadge, AvatarGroup } from '@cloudillo/react'
// Basic avatar
<Avatar src={profilePic} name="Alice" size="md" />
// With status indicator
<Avatar src={profilePic}>
<AvatarStatus status="online" />
</Avatar>
// With badge
<Avatar src={profilePic}>
<AvatarBadge>3</AvatarBadge>
</Avatar>
// Group of avatars
<AvatarGroup max={3}>
<Avatar src={user1.pic} name={user1.name} />
<Avatar src={user2.pic} name={user2.name} />
<Avatar src={user3.pic} name={user3.name} />
<Avatar src={user4.pic} name={user4.name} />
</AvatarGroup>ProfilePicture, UnknownProfilePicture
Cloudillo profile picture components.
import { ProfilePicture, UnknownProfilePicture } from '@cloudillo/react'
<ProfilePicture idTag="alice.cloudillo.net" size="lg" />
<UnknownProfilePicture size="md" />IdentityTag
Display identity tag with icon.
import { IdentityTag } from '@cloudillo/react'
<IdentityTag idTag="alice.cloudillo.net" />ProfileCard
Profile card with picture, name, and actions.
import { ProfileCard } from '@cloudillo/react'
<ProfileCard
profile={profile}
onConnect={handleConnect}
onFollow={handleFollow}
/>ProfileAudienceCard
Profile card optimized for audience selection.
import { ProfileAudienceCard } from '@cloudillo/react'
<ProfileAudienceCard
profile={profile}
selected={isSelected}
onSelect={handleSelect}
/>EditProfileList
Editable list of profiles (for managing connections, etc.).
import { EditProfileList } from '@cloudillo/react'
<EditProfileList
profiles={connections}
onRemove={handleRemove}
emptyMessage="No connections yet"
/>Data Display Components
TreeView, TreeItem
Hierarchical tree view.
import { TreeView, TreeItem } from '@cloudillo/react'
<TreeView>
<TreeItem label="Documents" icon={<FolderIcon />}>
<TreeItem label="Report.pdf" icon={<FileIcon />} />
<TreeItem label="Notes.txt" icon={<FileIcon />} />
</TreeItem>
<TreeItem label="Images" icon={<FolderIcon />}>
<TreeItem label="Photo.jpg" icon={<ImageIcon />} />
</TreeItem>
</TreeView>Accordion, AccordionItem
Collapsible accordion sections.
import { Accordion, AccordionItem } from '@cloudillo/react'
<Accordion>
<AccordionItem title="General Settings">
<GeneralSettings />
</AccordionItem>
<AccordionItem title="Advanced Settings">
<AdvancedSettings />
</AccordionItem>
</Accordion>PropertyPanel, PropertySection, PropertyField
Property inspector panel (like IDE properties).
import { PropertyPanel, PropertySection, PropertyField } from '@cloudillo/react'
<PropertyPanel>
<PropertySection title="Appearance">
<PropertyField label="Width">
<NumberInput value={width} onChange={setWidth} />
</PropertyField>
<PropertyField label="Color">
<ColorInput value={color} onChange={setColor} />
</PropertyField>
</PropertySection>
</PropertyPanel>TimeFormat
Formatted time display (relative or absolute).
import { TimeFormat } from '@cloudillo/react'
<TimeFormat value={createdAt} />
// Renders: "2 hours ago" or "Jan 15, 2025"
Badge
Status badge.
import { Badge } from '@cloudillo/react'
<Badge variant="success">Active</Badge>
<Badge variant="warning">Pending</Badge>
<Badge variant="danger">Error</Badge>Tag, TagList
Tags and tag lists.
import { Tag, TagList } from '@cloudillo/react'
<Tag>React</Tag>
<TagList
tags={['react', 'typescript', 'cloudillo']}
onRemove={handleRemoveTag}
/>Filter & Toolbar Components
FilterBar
Filter bar with search and filters.
import {
FilterBar,
FilterBarSearch,
FilterBarItem,
FilterBarSection,
FilterBarDivider
} from '@cloudillo/react'
<FilterBar>
<FilterBarSearch
value={search}
onChange={setSearch}
placeholder="Search files..."
/>
<FilterBarDivider />
<FilterBarSection>
<FilterBarItem
label="Type"
value={typeFilter}
onChange={setTypeFilter}
options={typeOptions}
/>
<FilterBarItem
label="Date"
value={dateFilter}
onChange={setDateFilter}
options={dateOptions}
/>
</FilterBarSection>
</FilterBar>Alternative export: FilterBarComponent is also exported for cases where you need to avoid naming conflicts.
Toolbar
Action toolbar.
import { Toolbar, ToolbarGroup, ToolbarDivider, ToolbarSpacer } from '@cloudillo/react'
<Toolbar>
<ToolbarGroup>
<Button icon={<BoldIcon />} />
<Button icon={<ItalicIcon />} />
<Button icon={<UnderlineIcon />} />
</ToolbarGroup>
<ToolbarDivider />
<ToolbarGroup>
<Button icon={<AlignLeftIcon />} />
<Button icon={<AlignCenterIcon />} />
</ToolbarGroup>
<ToolbarSpacer />
<Button>Save</Button>
</Toolbar>Infinite Scroll Components
LoadMoreTrigger
Intersection observer trigger for infinite scroll.
import { LoadMoreTrigger } from '@cloudillo/react'
import { useInfiniteScroll } from '@cloudillo/react'
function FileList() {
const { items, isLoading, sentinelRef } = useInfiniteScroll({
fetchPage: async (cursor, limit) => {
const result = await api.files.list({ cursor, limit })
return {
items: result.data,
nextCursor: result.cursorPagination?.nextCursor ?? null,
hasMore: result.cursorPagination?.hasMore ?? false
}
}
})
return (
<div>
{items.map(file => <FileCard key={file.fileId} file={file} />)}
<LoadMoreTrigger ref={sentinelRef} isLoading={isLoading} />
</div>
)
}Utility Components
FormattedText
Render formatted text with markdown support.
import { FormattedText } from '@cloudillo/react'
<FormattedText content="**Bold** and *italic* text" />FontPicker
Font selection component. Works with the @cloudillo/fonts library for font metadata and pairing suggestions.
import { FontPicker } from '@cloudillo/react'
import { getSuggestedBodyFonts } from '@cloudillo/fonts'
<FontPicker
value={fontFamily}
onChange={setFontFamily}
/>
// Use with font pairings
const suggestedBodies = getSuggestedBodyFonts(headingFont)See @cloudillo/fonts for available fonts and pairing APIs.
Utility Hooks
useMergedRefs
Combine multiple refs into one.
import { useMergedRefs } from '@cloudillo/react'
function MyComponent({ forwardedRef }) {
const localRef = useRef()
const mergedRef = useMergedRefs(localRef, forwardedRef)
return <div ref={mergedRef} />
}useBodyScrollLock
Lock body scroll (for modals).
import { useBodyScrollLock } from '@cloudillo/react'
function Modal({ isOpen }) {
useBodyScrollLock(isOpen)
return isOpen ? <div className="modal">...</div> : null
}useEscapeKey
Handle Escape key press.
import { useEscapeKey } from '@cloudillo/react'
function Modal({ onClose }) {
useEscapeKey(onClose)
return <div className="modal">...</div>
}useOutsideClick
Detect clicks outside an element.
import { useOutsideClick } from '@cloudillo/react'
function Dropdown({ onClose }) {
const ref = useRef()
useOutsideClick(ref, onClose)
return <div ref={ref} className="dropdown">...</div>
}useMediaQuery
Responsive media query hook.
import { useMediaQuery } from '@cloudillo/react'
function MyComponent() {
const isMobile = useMediaQuery('(max-width: 768px)')
return isMobile ? <MobileView /> : <DesktopView />
}useIsMobile
Shorthand for mobile detection.
import { useIsMobile } from '@cloudillo/react'
function MyComponent() {
const isMobile = useIsMobile()
return isMobile ? <MobileNav /> : <DesktopNav />
}usePrefersReducedMotion
Accessibility: detect reduced motion preference.
import { usePrefersReducedMotion } from '@cloudillo/react'
function AnimatedComponent() {
const prefersReducedMotion = usePrefersReducedMotion()
return (
<div className={prefersReducedMotion ? 'no-animation' : 'animated'}>
...
</div>
)
}See Also
- @cloudillo/react - Main React library docs
- @cloudillo/core - Core SDK
- Patterns - Common usage patterns