Integration Patterns
Common patterns for composing the library's building blocks into full application pages.
Pattern 1 — Standard list page
Combine PageListView, DataViewContainer, usePagination, and useSyncedSearchParams:
import { PageListView, DataViewContainer, GenericSearch } from "@xocialive/ui-components";
import { usePagination, useSyncedSearchParams } from "@xocialive/ui-components/hooks";
function UsersPage() {
const [params, setParams] = useSyncedSearchParams({
search: { type: "string", default: "" },
page: { type: "number", default: 1 },
});
const pagination = usePagination({ initialPage: params.page });
const { data, isLoading } = useQuery({
queryKey: ["users", params.search, pagination.page, pagination.pageSize],
queryFn: () => api.getUsers({ ...params, ...pagination.params }),
});
return (
<PageListView title="Users" actions={<Button onClick={openCreate}>Add user</Button>} isLoading={isLoading}>
<GenericSearch value={params.search} onChange={(s) => setParams((p) => ({ ...p, search: s, page: 1 }))} />
<DataViewContainer
data={data?.items ?? []}
columns={userColumns}
total={data?.total ?? 0}
pagination={pagination.params}
onPaginationChange={pagination.setParams}
renderCard={(user) => <UserCard user={user} />}
isLoading={isLoading}
/>
</PageListView>
);
}
Pattern 2 — Standard create/edit page
Combine PageItemView, GenericFrom, FormHeader, and useToast:
import { PageItemView, GenericFrom, FormHeader } from "@xocialive/ui-components";
import { useToast } from "@xocialive/ui-components/hooks";
function EditUserPage() {
const toast = useToast();
const navigate = useNavigate();
const handleSubmit = async (values: UserFormValues) => {
try {
await api.updateUser(id, values);
toast.success("User updated");
navigate("/users");
} catch (err) {
toast.error(apiErrorHandler(err));
}
};
return (
<PageItemView title="Edit User" onBack={() => navigate("/users")}>
<GenericFrom fields={userFields} validationSchema={userSchema} initialValues={user} onSubmit={handleSubmit} />
</PageItemView>
);
}
Pattern 3 — Modal with confirmation
Combine ModalWrapper, ConfirmationModal, and useDisclosure:
import { ModalWrapper, ConfirmationModal } from "@xocialive/ui-components";
import { useDisclosure, useToast } from "@xocialive/ui-components/hooks";
function UserRow({ user }: { user: User }) {
const editModal = useDisclosure();
const deleteModal = useDisclosure();
const toast = useToast();
const handleDelete = async () => {
await api.deleteUser(user.id);
toast.success("User deleted");
deleteModal.onClose();
};
return (
<>
<IconButton onClick={editModal.onOpen}>
<EditIcon />
</IconButton>
<IconButton onClick={deleteModal.onOpen}>
<DeleteIcon />
</IconButton>
<ModalWrapper open={editModal.open} onClose={editModal.onClose} title="Edit user">
<UserEditForm user={user} onSuccess={editModal.onClose} />
</ModalWrapper>
<ConfirmationModal
open={deleteModal.open}
onClose={deleteModal.onClose}
onConfirm={handleDelete}
title={`Delete ${user.name}?`}
message="This cannot be undone."
confirmLabel="Delete"
confirmColor="error"
/>
</>
);
}
Pattern 4 — Detail view page
Use PageItemView + GenericViewSection for read-only entity detail pages:
import { PageItemView, GenericViewSection, Section } from "@xocialive/ui-components";
function UserDetailPage({ user }: { user: User }) {
return (
<PageItemView title={user.name} onBack={() => navigate("/users")}>
<Section title="Personal Information">
<GenericViewSection
fields={[
{ label: "Full Name", value: user.name },
{ label: "Email", value: user.email },
{ label: "Role", value: <GenericEnumChip value={user.role} colorMap={ROLE_COLORS} /> },
{ label: "Status", value: <StatusToggle checked={user.isActive} onConfirm={toggleStatus} /> },
]}
/>
</Section>
</PageItemView>
);
}
Pattern 5 — Error handling
Use ErrorBoundary + DataContainer for layered error handling:
<ErrorBoundary onError={(err) => logError(err)}>
<DataContainer status={query.status} isEmpty={data.length === 0} onRetry={query.refetch}>
<DataGrid data={data} />
</DataContainer>
</ErrorBoundary>
ErrorBoundarycatches React render errors in the subtree.DataContainerhandles async state (loading, empty, error from the query).