Consent

@sushindustries/ui

A non-modal consent bar with equal-weight answers. It renders the question and reports the click; the host owns the SDK, the storage and the law.

6 min read
View as MarkdownEdit on GitHub

Examples are the tab where the component is shown doing a job, not demonstrating a prop. The API tab already lists the props.

Viewport width
Phone22remthe floor, the narrowest this promises to work at
tanstacktanstack add https://adamjurek.com/r/tanstack/consent.jsonshadcnpnpm dlx shadcn@latest add https://adamjurek.com/r/shadcn/consent.json

Press Compare. The frames are real viewports, so a layout that breaks at 320 breaks here too rather than in somebody's hands.

In a page

import { useState } from "react";
import { Consent } from "@sushindustries/ui";
import { startAnalytics } from "./analytics";

export function RootLayout({ children }: { children: React.ReactNode }) {
	const [status, setStatus] = useState<"pending" | "granted" | "denied">(
		"pending",
	);

	return (
		<>
			{children}
			<Consent
				open={status === "pending"}
				onAccept={() => {
					setStatus("granted");
					startAnalytics();
				}}
				onDecline={() => setStatus("denied")}
			>
				I measure page views to see what is worth writing more of. Nothing
				personal, nothing sold.
			</Consent>
		</>
	);
}
tsx

What this example is not

Not a working consent system on its own. It has no storage, so a real startAnalytics call would still need to run this same check on every load - read the stored answer first, and only render ConsentConsentA non-modal consent bar with equal-weight answers. Vendor-agnostic: it renders the question and reports the click; the host owns the SDK and the answer.@sushindustries/ui · layout at all when none exists yet.