@authflowkit/ui
v0.2.3
Published
AuthFlow's styled auth components and the primitives they are built from
Maintainers
Readme
@authflowkit/ui
Ready-made sign-in, sign-up, email verification, password reset and two-factor
screens for Next.js apps using
@authflowkit/sdk. Dark and light themes
included, styled with plain CSS custom properties — no Tailwind, no config.
- Component reference: https://authflow.wewiselabs.com/docs/components
- Quickstart: https://authflow.wewiselabs.com/docs/quickstart
Install
npm install @authflowkit/sdk @authflowkit/uiNeeds React 18.2 or 19. Set up @authflowkit/sdk first — its README covers the
environment variables, the proxy route and the provider.
Use
Import the styles once, in your root layout:
import "@authflowkit/ui/styles.css";Every component must sit inside <AuthFlowProvider> from @authflowkit/sdk.
// app/sign-in/page.tsx
"use client";
import { SignIn } from "@authflowkit/ui";
export default function SignInPage() {
return <SignIn redirectTo="/dashboard" />;
}The pages you need
| Route | Component | Why |
| ---------- | ------------------- | ---------------------------------------------------------------------------------------------- |
| /sign-in | <SignIn /> | Email and password, plus the two-factor step when the user has it on. |
| /sign-up | <SignUp /> | Creates the account and asks the user to check their email. |
| /verify | <VerifyEmail /> | Fixed path — the verification email links here. Confirming the address signs the user in. |
| /reset | <ResetPassword /> | Fixed path — the reset email links here. With no token in the URL, it is the request form. |
<SignIn /> already links to /sign-up and /reset, and <SignUp /> and
<ResetPassword /> link back to /sign-in. If your routes differ, every link
and redirect is a prop.
Components
| Component | What it does |
| ------------------- | --------------------------------------------------------------------------------------- |
| <SignIn /> | Email and password sign-in, with the two-factor step in place. |
| <SignUp /> | Sign-up. Shows the same confirmation whether or not the address already has an account. |
| <VerifyEmail /> | Confirms the address from the emailed link, with a resend action for expired links. |
| <ResetPassword /> | Both halves of a password reset, on one route. |
| <UserButton /> | Who is signed in, and sign-out. Renders nothing when signed out. |
| <EnableTotp /> | Turn two-factor on or off: QR code, confirmation, and ten recovery codes shown once. |
| <TotpChallenge /> | The code step on its own, for a custom sign-in form. <SignIn /> renders it for you. |
Every prop, type, default and label key is in the component reference.
The primitives the screens are built from — Button, Input, Alert and
Card — are exported too.
Every password field has an eye button that shows what was typed, so people can
check it before submitting. On your own <Input type="password" />, change its
words with passwordToggleLabels={{ show: "…", hide: "…" }}. Recovery codes and
the two-factor key carry a copy icon that turns into a tick once copied.
Changing the text
Every piece of text is a labels prop with a default, so you can reword
anything without forking the component:
<SignIn labels={{ heading: "Welcome back", submit: "Log in" }} />Theming
Dark is the default. To let visitors switch, set the theme before the first paint and add a toggle:
// app/layout.tsx
import { AuthFlowProvider } from "@authflowkit/sdk";
import { ThemeProvider, ThemeScript } from "@authflowkit/ui";
import "@authflowkit/ui/styles.css";
export default function RootLayout({ children }) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<ThemeScript />
</head>
<body>
<ThemeProvider>
<AuthFlowProvider>{children}</AuthFlowProvider>
</ThemeProvider>
</body>
</html>
);
}Then put <ThemeToggle /> in your header, or build your own control with
useTheme().
- Don't set
data-themeon<html>yourself.<ThemeScript />owns it; a hard-coded value makes the page paint in one theme and then switch. suppressHydrationWarningis required, because the script changes that attribute before React loads.useTheme().themeisnulluntil the page mounts — the server cannot see the visitor's saved choice.
Pass defaultTheme="system" to both <ThemeScript /> and <ThemeProvider> to
follow the operating system until the visitor chooses.
Your brand colour
One variable. Set it in any stylesheet your app loads; the order doesn't matter:
:root {
--af-brand: #4f46e5; /* buttons, links, focus ring, glow */
--af-brand-ink: #ffffff; /* the text on a button in that colour */
}Every button, link, focus ring and glow takes your colour, in both themes. The hover and link shades are mixed from it: lighter on dark, darker on light.
--af-brand-ink defaults to near-black. Use white on a dark brand, and check
the pair reaches 4.5:1. The default theme is contrast-checked; your colour is
yours to check.
Overriding any other token
Every colour, radius and spacing value is a CSS custom property. Set the ones you want after importing the styles:
:root {
--af-radius: 4px;
}Fonts (optional)
The package ships no font files and makes no network request; the default stack
renders on its own. To use the intended typefaces, load them with next/font
and point them at the -loaded variables:
import { Space_Grotesk } from "next/font/google";
const ui = Space_Grotesk({
subsets: ["latin"],
variable: "--af-font-ui-loaded", // JetBrains_Mono -> --af-font-mono-loaded
});
// <html className={ui.variable}>License
MIT © Abeera Umair
