Why Use It
- Mirrors Tailwind's
rounded-*naming so the API feels native. - Keeps Tailwind and CSS radius semantics, so the resolved radius token stays the same physical size across normal element sizes.
- Supports arbitrary values like
roundbit-[18px]and step controls likeroundbit-step-4. - Lets you stay on normal HTML and CSS for direct clipping, then switch to
RoundbitFrameplusroundbit-border-*when borders or shadows must follow the stepped silhouette.
Installation
Install the registry item, then use the utility classes for direct clip mode or the frame primitive plus roundbit-border-* for layered effects.
$ bunx --bun shadcn@latest add https://sabraman.ru/r/roundbit.jsonQuick Start
For clip-only use cases, initialize the runtime on the nearest client subtree instead of mutating the whole document, then add roundbit-* classes the same way you would add rounded-*.
"use client";
import * as React from "react";
import { initRoundbit } from "@/lib/roundbit";
export function RoundbitQuickStartExample() {
const scopeRef = React.useRef<HTMLDivElement | null>(null);
React.useLayoutEffect(() => {
if (!scopeRef.current) {
return;
}
return initRoundbit(scopeRef.current).disconnect;
}, []);
return (
<div ref={scopeRef}>
<button
className="roundbit-xl border border-zinc-900/15 bg-zinc-100 px-5 py-4 text-zinc-950"
type="button"
>
roundbit-xl
</button>
</div>
);
}Playground
Use the live controls to see how the same radius behaves when you change the corner pattern, step grid, surface size, and frame mode.
Live Playground
Tune the same roundbit system in real time.
Switch between direct clip mode and the frame primitive, then change the radius source, corner pattern, step grid, and box size. The snippet below updates to the exact public API you should copy.
Mode
Radius
Corner pattern
Step grid
Surface size
Utility
roundbit-xl
Radius source
token: xl
Size
320 x 176
roundbit-xl
320 x 176
The selected radius stays the same physical size while the box grows or shrinks. Changing the width and height only lengthens the straight segments, except for the normal small-box clamp you already get from CSS border-radius behavior.
"use client";
import { useEffect, useRef } from "react";
import { initRoundbit } from "@/lib/roundbit";
export function RoundbitExample() {
const scopeRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
if (!scopeRef.current) {
return;
}
return initRoundbit(scopeRef.current).disconnect;
}, []);
return (
<div ref={scopeRef}>
<div
className="roundbit-xl border border-zinc-900/15 bg-zinc-100 p-5 text-zinc-950"
style={{ width: 320, height: 176 }}
>
<p className="font-mono text-[13px] text-zinc-950">roundbit-xl</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
Previewing all corners with the xl radius token.
</p>
</div>
</div>
);
}Examples
Direct Radius Examples
roundbit-xl
Uniform corners with the default step grid.
roundbit-xl
Uniform corners with the default step grid.
export function RoundbitXlExample() {
return (
<div className="roundbit-xl w-[320px] border border-zinc-900/15 bg-zinc-100 px-5 py-4 text-zinc-950">
<p className="font-mono text-[13px] text-zinc-950">roundbit-xl</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
Uniform corners with the default step grid.
</p>
</div>
);
}roundbit-[18px]
An arbitrary radius without changing the step system.
roundbit-[18px]
An arbitrary radius without changing the step system.
export function Roundbit18pxExample() {
return (
<div className="roundbit-[18px] w-[320px] border border-zinc-900/15 bg-zinc-100 px-5 py-4 text-zinc-950">
<p className="font-mono text-[13px] text-zinc-950">roundbit-[18px]</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
An arbitrary radius without changing the step system.
</p>
</div>
);
}roundbit-xl roundbit-step-1
A tighter stair pattern with the same radius token.
roundbit-xl roundbit-step-1
A tighter stair pattern with the same radius token.
export function RoundbitXlStep1Example() {
return (
<div className="roundbit-xl roundbit-step-1 w-[320px] border border-zinc-900/15 bg-zinc-100 px-5 py-4 text-zinc-950">
<p className="font-mono text-[13px] text-zinc-950">
roundbit-xl roundbit-step-1
</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
A tighter stair pattern with the same radius token.
</p>
</div>
);
}roundbit-xl roundbit-step-4
A chunkier stair pattern with the same radius token.
roundbit-xl roundbit-step-4
A chunkier stair pattern with the same radius token.
export function RoundbitXlStep4Example() {
return (
<div className="roundbit-xl roundbit-step-4 w-[320px] border border-zinc-900/15 bg-zinc-100 px-5 py-4 text-zinc-950">
<p className="font-mono text-[13px] text-zinc-950">
roundbit-xl roundbit-step-4
</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
A chunkier stair pattern with the same radius token.
</p>
</div>
);
}Direct Edge Examples
roundbit-t-xl
Only the top edge uses stepped corners.
roundbit-t-xl
Only the top edge uses stepped corners.
export function RoundbitTXlExample() {
return (
<div className="roundbit-t-xl w-[320px] border border-zinc-900/15 bg-zinc-100 px-5 py-4 text-zinc-950">
<p className="font-mono text-[13px] text-zinc-950">roundbit-t-xl</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
Only the top edge uses stepped corners.
</p>
</div>
);
}roundbit-r-xl
Only the right edge uses stepped corners.
roundbit-r-xl
Only the right edge uses stepped corners.
export function RoundbitRXlExample() {
return (
<div className="roundbit-r-xl w-[320px] border border-zinc-900/15 bg-zinc-100 px-5 py-4 text-zinc-950">
<p className="font-mono text-[13px] text-zinc-950">roundbit-r-xl</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
Only the right edge uses stepped corners.
</p>
</div>
);
}roundbit-b-xl
Only the bottom edge uses stepped corners.
roundbit-b-xl
Only the bottom edge uses stepped corners.
export function RoundbitBXlExample() {
return (
<div className="roundbit-b-xl w-[320px] border border-zinc-900/15 bg-zinc-100 px-5 py-4 text-zinc-950">
<p className="font-mono text-[13px] text-zinc-950">roundbit-b-xl</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
Only the bottom edge uses stepped corners.
</p>
</div>
);
}roundbit-l-xl
Only the left edge uses stepped corners.
roundbit-l-xl
Only the left edge uses stepped corners.
export function RoundbitLXlExample() {
return (
<div className="roundbit-l-xl w-[320px] border border-zinc-900/15 bg-zinc-100 px-5 py-4 text-zinc-950">
<p className="font-mono text-[13px] text-zinc-950">roundbit-l-xl</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
Only the left edge uses stepped corners.
</p>
</div>
);
}Direct Corner Examples
roundbit-tl-xl
Only the top-left corner uses the stepped radius.
roundbit-tl-xl
Only the top-left corner uses the stepped radius.
export function RoundbitTlXlExample() {
return (
<div className="roundbit-tl-xl w-[320px] border border-zinc-900/15 bg-zinc-100 px-5 py-4 text-zinc-950">
<p className="font-mono text-[13px] text-zinc-950">roundbit-tl-xl</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
Only the top-left corner uses the stepped radius.
</p>
</div>
);
}roundbit-tr-xl
Only the top-right corner uses the stepped radius.
roundbit-tr-xl
Only the top-right corner uses the stepped radius.
export function RoundbitTrXlExample() {
return (
<div className="roundbit-tr-xl w-[320px] border border-zinc-900/15 bg-zinc-100 px-5 py-4 text-zinc-950">
<p className="font-mono text-[13px] text-zinc-950">roundbit-tr-xl</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
Only the top-right corner uses the stepped radius.
</p>
</div>
);
}roundbit-br-xl
Only the bottom-right corner uses the stepped radius.
roundbit-br-xl
Only the bottom-right corner uses the stepped radius.
export function RoundbitBrXlExample() {
return (
<div className="roundbit-br-xl w-[320px] border border-zinc-900/15 bg-zinc-100 px-5 py-4 text-zinc-950">
<p className="font-mono text-[13px] text-zinc-950">roundbit-br-xl</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
Only the bottom-right corner uses the stepped radius.
</p>
</div>
);
}roundbit-bl-xl
Only the bottom-left corner uses the stepped radius.
roundbit-bl-xl
Only the bottom-left corner uses the stepped radius.
export function RoundbitBlXlExample() {
return (
<div className="roundbit-bl-xl w-[320px] border border-zinc-900/15 bg-zinc-100 px-5 py-4 text-zinc-950">
<p className="font-mono text-[13px] text-zinc-950">roundbit-bl-xl</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
Only the bottom-left corner uses the stepped radius.
</p>
</div>
);
}Frame Examples
RoundbitFrame + roundbit-xl
Uniform frame corners with one stable border, outline, and shadow setup.
RoundbitFrame + roundbit-xl
Uniform frame corners with one stable frame stroke and shadow setup.
import { RoundbitFrame } from "@/components/roundbit";
export function RoundbitFrameXlExample() {
return (
<RoundbitFrame
className="roundbit-xl roundbit-border-2 roundbit-border-solid roundbit-border-sky-500/85 w-[360px] shadow-[0_10px_0_rgba(36,56,102,0.26)]"
contentClassName="bg-[linear-gradient(180deg,#fbfdff_0%,#eff4ff_100%)] px-6 py-5 text-zinc-950"
>
<p className="font-mono text-[13px] text-zinc-950">
RoundbitFrame + roundbit-xl
</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
Uniform frame corners with one stable frame stroke and shadow setup.
</p>
</RoundbitFrame>
);
}RoundbitFrame + roundbit-tl-xl
A frame example with only the top-left corner stepped.
RoundbitFrame + roundbit-tl-xl
A frame example with only the top-left corner stepped.
import { RoundbitFrame } from "@/components/roundbit";
export function RoundbitFrameTlXlExample() {
return (
<RoundbitFrame
className="roundbit-tl-xl roundbit-border-2 roundbit-border-solid roundbit-border-sky-500/85 w-[360px] shadow-[0_10px_0_rgba(36,56,102,0.26)]"
contentClassName="bg-[linear-gradient(180deg,#fbfdff_0%,#eff4ff_100%)] px-6 py-5 text-zinc-950"
>
<p className="font-mono text-[13px] text-zinc-950">
RoundbitFrame + roundbit-tl-xl
</p>
<p className="mt-2 text-[13px] text-zinc-600 leading-relaxed">
A frame example with only the top-left corner stepped.
</p>
</RoundbitFrame>
);
}RoundbitFrame + roundbit-xl roundbit-step-4
A replaced-element wrapper using one outer radius pattern and a chunkier step grid.
import { RoundbitFrame } from "@/components/roundbit";
const IMAGE_SRC =
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 720 450'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0%25' stop-color='%23f8e7b1'/%3E%3Cstop offset='38%25' stop-color='%23f7b7a1'/%3E%3Cstop offset='74%25' stop-color='%238db6ff'/%3E%3Cstop offset='100%25' stop-color='%23191f35'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='720' height='450' fill='url(%23g)'/%3E%3Ccircle cx='176' cy='120' r='80' fill='%23ffffff' fill-opacity='.18'/%3E%3Cpath d='M0 348C92 302 178 270 266 270C396 270 450 362 560 362C620 362 668 344 720 308V450H0Z' fill='%230a1022' fill-opacity='.34'/%3E%3C/svg%3E";
export function RoundbitFrameXlStep4ImageExample() {
return (
<RoundbitFrame
className="roundbit-xl roundbit-step-4 roundbit-border-4 roundbit-border-solid roundbit-border-sky-500/90 w-[360px] shadow-[0_12px_0_rgba(36,56,102,0.3)]"
contentClassName="overflow-hidden bg-zinc-100"
>
{/* biome-ignore lint/performance/noImgElement: copy-paste example for a replaced element */}
<img
alt="Gradient placeholder"
className="block h-auto w-full"
height={450}
src={IMAGE_SRC}
width={720}
/>
</RoundbitFrame>
);
}API Reference
RoundbitFrameProps gives you a wrapper with an inner roundbit-content surface, while buildRoundbitPaths and initRoundbit cover the utility-only runtime path.
Also inherits: React.HTMLAttributes<HTMLDivElement>
| Prop | Type | Required |
|---|---|---|
contentClassName | string | No |
contentProps | React.HTMLAttributes<HTMLDivElement> | No |
| Prop | Type | Required |
|---|---|---|
corners | RoundbitCornerValues | Yes |
height | number | Yes |
inset | number | No |
step | number | No |
width | number | Yes |
Notes
roundbit-*is inspired by pixel-corner generators, but it follows Tailwind and CSS radius semantics instead of trying to reproduce generator output exactly.- Direct mode reads the resolved native
border-radiusback from CSS, so arbitrary values,%, andfullbehave like theirrounded-*counterparts. roundbit-step-2is the default grid.roundbit-step-1androundbit-step-4are style variants, not different radius systems.- Direct mode is
roundbit-*. Framed mode isRoundbitFrameplusroundbit-border-*. - Frame mode examples are shown one radius pattern at a time so every snippet stays copy-paste ready.
roundbit-border-*is the preferred frame API. Nativeborder-*still works onRoundbitFrameas a compatibility fallback.- Frame mode is the safe path for solid borders, uniform dashed/dotted/double borders, zero-offset solid outlines, and spread-free shadows.
- Mixed-side non-solid frame borders fall back to solid rendering instead of trying to fake a broken dashed or double shape.