Geo-restriction page: an accent globe chip and headline, the detected region in a bordered strip, a two-column ruled list of markets with their rollout status, and a notify-me seal button.
A geo-restriction page that answers the obvious question: an accent globe chip and headline, the detected region in a bordered strip, and a two-column ruled list of every market with its rollout status.
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.
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
npx shadcn add "https://ui.beste.co/r/error28?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/error28?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/error28.tsx, plus the two design-system primitives it renders through: badge6 for the square eyebrow and button1 for the seal call to action.
The installed file exports error28Demo alongside the block: the exact props behind the preview above. Spread it to get a working restriction page in one line.
import { Error28, error28Demo } from "@/components/beste/block/error28";
export default function Unavailable() {
return <Error28 {...error28Demo} />;
}Then pass the visitor's region from your edge middleware and your own market list:
import { Error28 } from "@/components/beste/block/error28";
export default function Unavailable({ country }: { country: string }) {
return (
<Error28
label="Unavailable Here"
code="451"
heading="This one cannot travel <strong>to your part of the map</strong>."
description="Licensing keeps this catalogue inside a handful of markets."
labels={{ detectedTitle: "We think you are in", regionsTitle: "Where it is live" }}
detectedRegion={country}
regions={[
{ title: "United Kingdom", status: "Live" },
{ title: "Germany", status: "Live" },
{ title: "Canada", status: "Next quarter" },
]}
button={{ label: "Tell me when it lands", href: "/notify" }}
link={{ label: "Read the licensing note", href: "/legal/licensing" }}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
label | string | – | Eyebrow text rendered through the square-marker badge |
code | string | – | Status code shown after the eyebrow divider |
heading | string | – | Headline HTML, rendered as an h1; <strong> marks the accent clause |
description | string | – | Explanatory paragraph under the headline |
labels | Error28Labels | {} | Captions for the detected-region strip and the market list |
detectedRegion | string | – | Where the visitor appears to be |
regions | RegionItem[] | [] | Markets and their rollout status |
button | ActionLink | – | Seal call to action at the bottom |
link | ActionLink | – | Text link beside the call to action |
className | string | – | Extra classes for the outer <section> |
type Error28Labels = {
detectedTitle?: string;
regionsTitle?: string;
};
type RegionItem = {
title: string;
status: string;
};
type ActionLink = {
label: string;
href: string;
};sm breakpoint up, with each row carrying its own bottom rule so the columns read as two continuous lists rather than a table.status is free text, not an enum, so "Live", "In licensing" and "Next quarter" all sit in the same column without any status styling to maintain.detectedRegion is set; its caption is a separate prop, so the value can appear alone.detectedRegion from your own edge middleware or geo header.heading is injected with dangerouslySetInnerHTML and accepts inline HTML; <strong> takes the accent colour. Keep the value under your own control, never user input.error7
Compact bordered 404 card with a circular icon, status label, heading, one-line explanation, and stacked full-width buttons. Sized for app shells and modals as well as full pages.
error26
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.
error17
Planned downtime page with a square eyebrow and status code, a bold accent headline, three bordered cells for the maintenance window, a working notify-me email form with a success state, and a live progress link.
error15
Server error page with a square eyebrow and status code over a hairline rule, a bold accent headline, a bordered incident table of reference, timestamp and service rows, and a retry seal button beside a status page link.
error16
Permission-denied page for team apps: an accent lock chip and bold headline on the left, the signed-in account card with an account switch link and a square-bullet list of access requirements on the right.
error14
Editorial 404 with a square eyebrow and status code over a hairline rule, an oversized accent-highlighted headline, and a ruled index of the sections visitors reach for next.