Payment Required Lockout

Payment Required
402

The card said no, so the door closed.

Your last renewal did not go through, so the workspace is read only until a payment lands. Everything inside is untouched and waiting.

Unpaid invoice

Plan
Team, annual
Amount due
$588.00
Attempted
21 Jul 2026
Card
Visa ending 4417

What stays safe meanwhile

  • Every project, file and comment stays exactly as it is
  • Your team keeps read access while the balance is open
  • Nothing is deleted for ninety days after a failed renewal
About this block

Payment Required LockoutPRO

Billing lockout page: an accent card chip and headline with an update-payment seal button on the left, an unpaid invoice table and a square-bullet list of what stays untouched on the right.

Error26: Payment Required Lockout

The screen a workspace shows after a failed renewal: an accent card chip and headline with an update-payment button on the left, the unpaid invoice as a table and a square-bullet list of what stays untouched on the right.

Upgrade to Pro

Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.

Upgrade Now

Installation

Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.

Radix flavor

bash
npx shadcn add "https://ui.beste.co/r/error26?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://ui.beste.co/r-base/error26?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/error26.tsx, plus the two design-system primitives it renders through: badge6 for the square eyebrow and button1 for the seal call to action.

Quick start

The installed file exports error26Demo alongside the block: the exact props behind the preview above. Spread it to get a working lockout page in one line.

tsx
import { Error26, error26Demo } from "@/components/beste/block/error26";

export default function Billing() {
  return <Error26 {...error26Demo} />;
}

Then fill the invoice rows from your billing provider. Amounts are plain strings, so currency formatting stays yours:

tsx
import { Error26 } from "@/components/beste/block/error26";

export default function Billing({ invoice }: { invoice: { total: string; card: string } }) {
  return (
    <Error26
      label="Payment Required"
      code="402"
      heading="The card said no, <strong>so the door closed</strong>."
      description="Your last renewal did not go through, so the workspace is read only."
      labels={{ invoiceTitle: "Unpaid invoice", keptTitle: "What stays safe meanwhile" }}
      invoice={[
        { title: "Amount due", value: invoice.total },
        { title: "Card", value: invoice.card },
      ]}
      kept={["Every project, file and comment stays exactly as it is"]}
      button={{ label: "Update payment", href: "/billing" }}
      link={{ label: "Write to billing", href: "mailto:[email protected]" }}
    />
  );
}

Props

PropTypeDefaultDescription
labelstring–Eyebrow text rendered through the square-marker badge
codestring–Status code shown after the eyebrow divider
headingstring–Headline HTML, rendered as an h1; <strong> marks the accent clause
descriptionstring–Explanatory paragraph under the headline
labelsError26Labels{}Captions above the invoice table and the reassurance list
invoiceInvoiceRow[][]Rows of the unpaid invoice
keptstring[][]Square-bullet list of what is preserved during the lockout
buttonActionLink–Seal call to action under the description
linkActionLink–Text link beside the call to action
classNamestring–Extra classes for the outer <section>
ts
type Error26Labels = {
  invoiceTitle?: string;
  keptTitle?: string;
};

type InvoiceRow = {
  title: string;
  value: string;
};

type ActionLink = {
  label: string;
  href: string;
};

Behavior notes

  • The invoice is a dl with dt/dd pairs separated by divide-y, so the label and value relationship survives for screen readers instead of reading as two loose columns.
  • Rows wrap rather than truncate: a long plan name drops to its own line at narrow widths instead of colliding with the amount.
  • The invoice table and the reassurance list are independent. Either can be omitted and the right column collapses to whichever one is passed.
  • The layout is a single column until the lg breakpoint, where the message and the billing panel split into two columns.
  • Everything is static markup with no client state, so the page renders on the server and works with JavaScript disabled.

More Error blocks

View all Error
PRO

error16

403 Access Request

PRO

error27

Session Expired Sign In

PRO

error28

Region Unavailable Notice

Get Pro access