Pre-built UI components for escrow management interfaces. All components can be installed via CLI and are fully customizable.
All components are installed using the npx trustless-work add command:
npx trustless-work add <component-path>List escrows created by a specific signer.
Installation:
# Table view
npx trustless-work add escrows/escrows-by-signer/table
# Cards view
npx trustless-work add escrows/escrows-by-signer/cardsUsage:
import { EscrowsBySignerCards } from "@/components/tw-blocks/escrows/escrows-by-signer/cards/EscrowsCards";
// or
import { EscrowsBySignerTable } from "@/components/tw-blocks/escrows/escrows-by-signer/table/EscrowsTable";
function MyPage() {
return (
<div>
<EscrowsBySignerCards />
{/* or */}
<EscrowsBySignerTable />
</div>
);
}List escrows filtered by user role (serviceProvider, approver, etc.).
Installation:
# Table view
npx trustless-work add escrows/escrows-by-role/table
# Cards view
npx trustless-work add escrows/escrows-by-role/cardsUsage:
import { EscrowsByRoleCards } from "@/components/tw-blocks/escrows/escrows-by-role/cards/EscrowsCards";
// or
import { EscrowsByRoleTable } from "@/components/tw-blocks/escrows/escrows-by-role/table/EscrowsTable";
function MyPage() {
return (
<div>
<EscrowsByRoleCards />
{/* or */}
<EscrowsByRoleTable />
</div>
);
}Installation:
# Form component
npx trustless-work add escrows/single-release/initialize-escrow/form
# Dialog component
npx trustless-work add escrows/single-release/initialize-escrow/dialogUsage:
import { InitializeEscrowForm } from "@/components/tw-blocks/escrows/single-release/initialize-escrow/form/InitializeEscrow";
// or
import { InitializeEscrowDialog } from "@/components/tw-blocks/escrows/single-release/initialize-escrow/dialog/InitializeEscrow";
function MyPage() {
return (
<div>
<InitializeEscrowForm />
{/* or */}
<InitializeEscrowDialog />
</div>
);
}Installation:
# Form component
npx trustless-work add escrows/multi-release/initialize-escrow/form
# Dialog component
npx trustless-work add escrows/multi-release/initialize-escrow/dialogUsage:
import { InitializeEscrowForm } from "@/components/tw-blocks/escrows/multi-release/initialize-escrow/form/InitializeEscrow";
// or
import { InitializeEscrowDialog } from "@/components/tw-blocks/escrows/multi-release/initialize-escrow/dialog/InitializeEscrow";
function MyPage() {
return (
<div>
<InitializeEscrowForm />
{/* or */}
<InitializeEscrowDialog />
</div>
);
}Works with both single-release and multi-release escrows.
Installation:
# Form component
npx trustless-work add escrows/single-multi-release/fund-escrow/form
# Button component
npx trustless-work add escrows/single-multi-release/fund-escrow/button
# Dialog component
npx trustless-work add escrows/single-multi-release/fund-escrow/dialogUsage:
import { FundEscrowForm } from "@/components/tw-blocks/escrows/single-multi-release/fund-escrow/form/FundEscrow";
import { FundEscrowButton } from "@/components/tw-blocks/escrows/single-multi-release/fund-escrow/button/FundEscrow";
import { FundEscrowDialog } from "@/components/tw-blocks/escrows/single-multi-release/fund-escrow/dialog/FundEscrow";
function MyPage() {
return (
<div>
<FundEscrowForm />
{/* or */}
<FundEscrowButton />
{/* or */}
<FundEscrowDialog />
</div>
);
}Works with both single-release and multi-release escrows.
Installation:
# Form component
npx trustless-work add escrows/single-multi-release/approve-milestone/form
# Button component
npx trustless-work add escrows/single-multi-release/approve-milestone/button
# Dialog component
npx trustless-work add escrows/single-multi-release/approve-milestone/dialogUsage:
import { ApproveMilestoneForm } from "@/components/tw-blocks/escrows/single-multi-release/approve-milestone/form/ApproveMilestone";
import { ApproveMilestoneButton } from "@/components/tw-blocks/escrows/single-multi-release/approve-milestone/button/ApproveMilestone";
import { ApproveMilestoneDialog } from "@/components/tw-blocks/escrows/single-multi-release/approve-milestone/dialog/ApproveMilestone";
function MyPage() {
return (
<div>
<ApproveMilestoneForm />
{/* or */}
<ApproveMilestoneButton />
{/* or */}
<ApproveMilestoneDialog />
</div>
);
}Works with both single-release and multi-release escrows.
Installation:
# Form component
npx trustless-work add escrows/single-multi-release/change-milestone-status/form
# Button component
npx trustless-work add escrows/single-multi-release/change-milestone-status/button
# Dialog component
npx trustless-work add escrows/single-multi-release/change-milestone-status/dialogUsage:
import { ChangeMilestoneStatusForm } from "@/components/tw-blocks/escrows/single-multi-release/change-milestone-status/form/ChangeMilestoneStatus";
import { ChangeMilestoneStatusButton } from "@/components/tw-blocks/escrows/single-multi-release/change-milestone-status/button/ChangeMilestoneStatus";
import { ChangeMilestoneStatusDialog } from "@/components/tw-blocks/escrows/single-multi-release/change-milestone-status/dialog/ChangeMilestoneStatus";
function MyPage() {
return (
<div>
<ChangeMilestoneStatusForm />
{/* or */}
<ChangeMilestoneStatusButton />
{/* or */}
<ChangeMilestoneStatusDialog />
</div>
);
}Installation:
npx trustless-work add escrows/single-release/release-escrow/buttonUsage:
import { ReleaseEscrowButton } from "@/components/tw-blocks/escrows/single-release/release-escrow/button/ReleaseEscrow";
function MyPage() {
return (
<div>
<ReleaseEscrowButton />
</div>
);
}Installation:
npx trustless-work add escrows/multi-release/release-milestone/buttonUsage:
import { ReleaseMilestoneButton } from "@/components/tw-blocks/escrows/multi-release/release-milestone/button/ReleaseMilestone";
function MyPage() {
return (
<div>
<ReleaseMilestoneButton />
</div>
);
}Installation:
npx trustless-work add escrows/single-release/dispute-escrow/buttonUsage:
import { DisputeEscrowButton } from "@/components/tw-blocks/escrows/single-release/dispute-escrow/button/DisputeEscrow";
function MyPage() {
return (
<div>
<DisputeEscrowButton />
</div>
);
}Installation:
npx trustless-work add escrows/multi-release/dispute-milestone/buttonUsage:
import { DisputeMilestoneButton } from "@/components/tw-blocks/escrows/multi-release/dispute-milestone/button/DisputeMilestone";
function MyPage() {
return (
<div>
<DisputeMilestoneButton />
</div>
);
}Installation:
# Form component
npx trustless-work add escrows/single-release/resolve-dispute/form
# Button component
npx trustless-work add escrows/single-release/resolve-dispute/button
# Dialog component
npx trustless-work add escrows/single-release/resolve-dispute/dialogUsage:
import { ResolveDisputeForm } from "@/components/tw-blocks/escrows/single-release/resolve-dispute/form/ResolveDispute";
import { ResolveDisputeButton } from "@/components/tw-blocks/escrows/single-release/resolve-dispute/button/ResolveDispute";
import { ResolveDisputeDialog } from "@/components/tw-blocks/escrows/single-release/resolve-dispute/dialog/ResolveDispute";
function MyPage() {
return (
<div>
<ResolveDisputeForm />
{/* or */}
<ResolveDisputeButton />
{/* or */}
<ResolveDisputeDialog />
</div>
);
}Installation:
# Form component
npx trustless-work add escrows/multi-release/resolve-dispute/form
# Button component
npx trustless-work add escrows/multi-release/resolve-dispute/button
# Dialog component
npx trustless-work add escrows/multi-release/resolve-dispute/dialogUsage:
import { ResolveDisputeForm } from "@/components/tw-blocks/escrows/multi-release/resolve-dispute/form/ResolveDispute";
import { ResolveDisputeButton } from "@/components/tw-blocks/escrows/multi-release/resolve-dispute/button/ResolveDispute";
import { ResolveDisputeDialog } from "@/components/tw-blocks/escrows/multi-release/resolve-dispute/dialog/ResolveDispute";
function MyPage() {
return (
<div>
<ResolveDisputeForm />
{/* or */}
<ResolveDisputeButton />
{/* or */}
<ResolveDisputeDialog />
</div>
);
}Installation:
# Form component
npx trustless-work add escrows/single-release/update-escrow/form
# Dialog component
npx trustless-work add escrows/single-release/update-escrow/dialogUsage:
import { UpdateEscrowForm } from "@/components/tw-blocks/escrows/single-release/update-escrow/form/UpdateEscrow";
// or
import { UpdateEscrowDialog } from "@/components/tw-blocks/escrows/single-release/update-escrow/dialog/UpdateEscrow";
function MyPage() {
return (
<div>
<UpdateEscrowForm />
{/* or */}
<UpdateEscrowDialog />
</div>
);
}Installation:
# Form component
npx trustless-work add escrows/multi-release/update-escrow/form
# Dialog component
npx trustless-work add escrows/multi-release/update-escrow/dialogUsage:
import { UpdateEscrowForm } from "@/components/tw-blocks/escrows/multi-release/update-escrow/form/UpdateEscrow";
// or
import { UpdateEscrowDialog } from "@/components/tw-blocks/escrows/multi-release/update-escrow/dialog/UpdateEscrow";
function MyPage() {
return (
<div>
<UpdateEscrowForm />
{/* or */}
<UpdateEscrowDialog />
</div>
);
}Multi Release Only
Installation:
# Form component
npx trustless-work add escrows/multi-release/withdraw-remaining-funds/form
# Button component
npx trustless-work add escrows/multi-release/withdraw-remaining-funds/button
# Dialog component
npx trustless-work add escrows/multi-release/withdraw-remaining-funds/dialogUsage:
import { WithdrawRemainingFundsForm } from "@/components/tw-blocks/escrows/multi-release/withdraw-remaining-funds/form/WithdrawRemainingFunds";
import { WithdrawRemainingFundsButton } from "@/components/tw-blocks/escrows/multi-release/withdraw-remaining-funds/button/WithdrawRemainingFunds";
import { WithdrawRemainingFundsDialog } from "@/components/tw-blocks/escrows/multi-release/withdraw-remaining-funds/dialog/WithdrawRemainingFunds";
function MyPage() {
return (
<div>
<WithdrawRemainingFundsForm />
{/* or */}
<WithdrawRemainingFundsButton />
{/* or */}
<WithdrawRemainingFundsDialog />
</div>
);
}Form components provide full form UI with inputs, validation, and submission handling.
Examples:
InitializeEscrowFormFundEscrowFormApproveMilestoneFormChangeMilestoneStatusFormResolveDisputeFormUpdateEscrowFormWithdrawRemainingFundsForm
Button components trigger actions with a single click. Usually used inline in lists or detail views.
Examples:
FundEscrowButtonApproveMilestoneButtonChangeMilestoneStatusButtonReleaseEscrowButtonReleaseMilestoneButtonDisputeEscrowButtonDisputeMilestoneButtonResolveDisputeButtonWithdrawRemainingFundsButton
Dialog components provide modal interfaces for actions. Usually triggered by buttons or other UI elements.
Examples:
InitializeEscrowDialogFundEscrowDialogApproveMilestoneDialogChangeMilestoneStatusDialogResolveDisputeDialogUpdateEscrowDialogWithdrawRemainingFundsDialog
Card-based UI for displaying escrow lists in a grid layout.
Examples:
EscrowsBySignerCardsEscrowsByRoleCards
Table-based UI for displaying escrow lists in a tabular format.
Examples:
EscrowsBySignerTableEscrowsByRoleTable
Here's how to use multiple components together in an escrow details view:
// escrows/escrows-by-role/details/Actions.tsx
import { UpdateEscrowDialog } from "../../single-release/update-escrow/dialog/UpdateEscrow";
/* import { UpdateEscrowDialog as UpdateEscrowDialogMultiRelease } from "../../multi-release/update-escrow/dialog/UpdateEscrow"; */
import { FundEscrowDialog } from "../../single-multi-release/fund-escrow/dialog/FundEscrow";
import { DisputeEscrowButton } from "../../single-release/dispute-escrow/button/DisputeEscrow";
import { ResolveDisputeDialog } from "../../single-release/resolve-dispute/dialog/ResolveDispute";
import { ReleaseEscrowButton } from "../../single-release/release-escrow/button/ReleaseEscrow";
import { useEscrowContext } from "@trustless-work/blocks";
export function EscrowActions() {
const { selectedEscrow } = useEscrowContext();
// Conditional rendering based on escrow flags and user roles
const shouldShowEditButton = /* your logic */;
const shouldShowDisputeButton = /* your logic */;
const shouldShowResolveButton = /* your logic */;
const shouldShowReleaseFundsButton = /* your logic */;
const hasConditionalButtons = shouldShowEditButton || shouldShowDisputeButton ||
shouldShowResolveButton || shouldShowReleaseFundsButton;
return (
<div className="flex items-start justify-start flex-col gap-2 w-full">
{hasConditionalButtons && (
<div className="flex flex-col gap-2 w-full">
{/* Render based on escrow type */}
{selectedEscrow?.type === 'single-release' && shouldShowEditButton && (
<UpdateEscrowDialog />
)}
{selectedEscrow?.type === 'multi-release' && shouldShowEditButton && (
<UpdateEscrowDialogMultiRelease />
)}
{/* Single-release only */}
{shouldShowDisputeButton && <DisputeEscrowButton />}
{shouldShowResolveButton && <ResolveDisputeDialog />}
{shouldShowReleaseFundsButton && <ReleaseEscrowButton />}
</div>
)}
{/* Works with both types */}
<FundEscrowDialog />
</div>
);
}Components should be conditionally rendered based on:
- Escrow type:
single-releasevsmulti-release - Escrow flags:
approved,dispute,released,resolved - User roles:
payer,serviceProvider,approver,disputeResolver - Milestone state: Completed, approved, disputed, etc.
Example:
// Check escrow type
if (selectedEscrow?.type === 'single-release') {
// Render single-release components
} else if (selectedEscrow?.type === 'multi-release') {
// Render multi-release components
}
// Check flags
if (selectedEscrow?.flags?.dispute && !selectedEscrow?.flags?.resolved) {
// Show resolve dispute dialog
}
// Check user role
if (userRole === 'approver' && allMilestonesApproved) {
// Show release button
}# Install all escrow blocks
npx trustless-work add escrows
# Install all single-release blocks
npx trustless-work add escrows/single-release
# Install all multi-release blocks
npx trustless-work add escrows/multi-release
# Install all shared blocks (single-multi-release)
npx trustless-work add escrows/single-multi-release# Specific component
npx trustless-work add escrows/single-release/initialize-escrow/dialog
# Multiple components
npx trustless-work add escrows/escrows-by-role/cards
npx trustless-work add escrows/single-release/release-escrow/buttonAll components are fully customizable. After installation:
- Edit generated files - Modify components in
components/tw-blocks/ - Update styles - Change Tailwind classes to match your design system
- Adjust logic - Modify component logic for your use case
- Add features - Extend components with additional functionality
Use the CLI to discover all available components:
npx trustless-work listThis prints all available folder paths for installation.
When building an escrow management interface, consider:
- Listings: Escrows by signer or role (cards/table)
- Initialize: Create new escrows (form/dialog)
- Fund: Deposit funds (form/button/dialog)
- Update: Modify escrow properties (form/dialog)
- Change Status: Update milestone status (form/button/dialog)
- Approve: Approve milestones (form/button/dialog)
- Release: Release funds (button)
- Dispute: Start disputes (button)
- Resolve: Resolve disputes (form/button/dialog)
- Withdraw: Withdraw remaining funds - multi-release only (form/button/dialog)
- Blocks Playground - See all components live
- GitHub Repository
- NPM Package