SeamRule · SeamText · Caret · RegFrame
The signature primitive. Name two hues once and every rule, clipped headline and tick draws from them — canvas effects included.
Install
$ npx shadcn@latest add wisp.pouriah.com/r/seam.jsonCSSno JS
Two tokens meet, and the seam talks
--wisp → --lantern
"use client";
import * as React from "react";
import { cx, useTokenColorExpr } from "@pouriahlabs/wisp-ui";
/**
* Seam — the signature primitive.
*
* Name two hues once and every gradient rule, clipped headline and tick on the
* page draws from them, canvas effects included. It is the cheapest component
* here and the one that makes a page look designed rather than assembled,
* because it forces the accent to be a *relationship* between two tokens
* instead of a single colour dropped in wherever emphasis is needed.
*/
interface SeamTokens {
fromToken?: string;
toToken?: string;
}
function seamVars(fromExpr: string, toExpr: string, angle: string): React.CSSProperties {
return {
"--wisp-seam-from": fromExpr,
"--wisp-seam-to": toExpr,
"--wisp-seam-angle": angle,
} as React.CSSProperties;
}
/** A rule that runs from one token to the other. Give it a width or height. */
export function SeamRule({
fromToken = "--wisp",
toToken = "--lantern",
orientation = "vertical",
className,
style,
...props
}: SeamTokens &
React.HTMLAttributes<HTMLDivElement> & { orientation?: "vertical" | "horizontal" }) {
const from = useTokenColorExpr(fromToken);
const to = useTokenColorExpr(toToken);
return (
<div
aria-hidden
className={cx("wisp-seam-rule", className)}
style={{
...seamVars(from, to, orientation === "vertical" ? "to bottom" : "to right"),
...style,
}}
{...props}
/>
);
}
/**
* The same gradient, clipped to text. Use it on a clause, not a whole
* paragraph — clipped text loses contrast against most grounds, so it belongs
* where emphasis is the job and legibility is already carried by size.
*/
export function SeamText({
fromToken = "--wisp",
toToken = "--lantern",
angle = "92deg",
as: Tag = "span",
className,
style,
children,
...props
}: SeamTokens & React.HTMLAttributes<HTMLElement> & { angle?: string; as?: React.ElementType }) {
const from = useTokenColorExpr(fromToken);
const to = useTokenColorExpr(toToken);
return (
<Tag
className={cx("wisp-seam-text", className)}
style={{ ...seamVars(from, to, angle), ...style }}
{...props}
>
{children}
</Tag>
);
}
/**
* A blinking terminal caret. Takes `currentColor`, so it inherits whatever it
* sits inside.
*/
export function Caret({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) {
return <span aria-hidden className={cx("wisp-caret", className)} {...props} />;
}
/** L-shaped corner ticks, like a viewport crop on an engineering drawing. */
export function RegFrame({
token,
tick = 10,
className,
style,
children,
...props
}: React.HTMLAttributes<HTMLDivElement> & { token?: string; tick?: number }) {
// Called unconditionally (Rules of Hooks); its result is only applied when a
// token is named, so the ticks otherwise inherit `currentColor` as before.
const inkExpr = useTokenColorExpr(token ?? "--wisp");
return (
<div
className={cx("wisp-reg relative", className)}
style={
{
"--wisp-tick": `${tick}px`,
...(token ? { "--wisp-tick-ink": inkExpr } : null),
...style,
} as React.CSSProperties
}
{...props}
>
{children}
</div>
);
}
Certified against the contract
- ✓Reduced motion paints one composed still frame — never a blank box
- ✓Pauses off-screen and in hidden tabs
- ✓Re-reads design tokens when the theme changes
- ✓SSR-safe: no hydration mismatch, no layout shift
- ✓Decorative layers are aria-hidden and pointer-events-none
- ✓Device pixel ratio clamped
- ✓Zero runtime dependencies beyond React