@bettercone/ui
Components

Utility Components

Helper components for conditional rendering and redirects

Utility Components

8 utility components for auth state management and conditional rendering.

Components

SignedIn

Render children only when user is signed in.

import { SignedIn } from '@bettercone/ui';

<SignedIn authClient={authClient}>
  <DashboardContent />
</SignedIn>

SignedOut

Render children only when user is signed out.

import { SignedOut } from '@bettercone/ui';

<SignedOut authClient={authClient}>
  <SignInPrompt />
</SignedOut>

AuthLoading

Show loading state while auth is initializing.

import { AuthLoading } from '@bettercone/ui';

<AuthLoading authClient={authClient}>
  <Spinner />
</AuthLoading>

RedirectToSignIn

Automatically redirect to sign-in page if not authenticated.

import { RedirectToSignIn } from '@bettercone/ui';

<RedirectToSignIn authClient={authClient} />

RedirectToSignUp

Automatically redirect to sign-up page.

import { RedirectToSignUp } from '@bettercone/ui';

<RedirectToSignUp authClient={authClient} />

PasswordInput

Password input with show/hide toggle.

import { PasswordInput } from '@bettercone/ui';

<PasswordInput 
  value={password}
  onChange={(e) => setPassword(e.target.value)}
/>

FormError

Display form error messages.

import { FormError } from '@bettercone/ui';

<FormError error="Invalid email or password" />

Provider Icons

OAuth provider icons (Google, GitHub, etc.).

import { GoogleIcon, GitHubIcon, DiscordIcon } from '@bettercone/ui';

<GoogleIcon className="w-5 h-5" />

Quick Start

Protected Page

import { SignedIn, RedirectToSignIn } from '@bettercone/ui';
import { authClient } from '@/lib/auth-client';

export default function DashboardPage() {
  return (
    <>
      <SignedIn authClient={authClient}>
        <Dashboard />
      </SignedIn>
      
      <RedirectToSignIn authClient={authClient} />
    </>
  );
}

Conditional UI

import { SignedIn, SignedOut } from '@bettercone/ui';

export default function Header() {
  return (
    <header>
      <Logo />
      
      <SignedIn authClient={authClient}>
        <UserButton authClient={authClient} />
      </SignedIn>
      
      <SignedOut authClient={authClient}>
        <Link href="/sign-in">Sign In</Link>
      </SignedOut>
    </header>
  );
}

Loading State

import { AuthLoading, SignedIn } from '@bettercone/ui';

export default function App() {
  return (
    <AuthLoading authClient={authClient}>
      <div className="flex items-center justify-center min-h-screen">
        <Spinner />
      </div>
    </AuthLoading>
    
    <SignedIn authClient={authClient}>
      <App />
    </SignedIn>
  );
}

Props Reference

SignedIn / SignedOut / AuthLoading

PropTypeDescription
authClientAnyAuthClientBetter Auth client (required)
childrenReactNodeContent to render

RedirectToSignIn / RedirectToSignUp

PropTypeDescription
authClientAnyAuthClientBetter Auth client (required)
redirectUrlstringURL to redirect to after auth

PasswordInput

PropTypeDescription
valuestringInput value
onChange(e) => voidChange handler
...propsInputPropsStandard input props

Common Patterns

Protected Route Pattern

// app/dashboard/page.tsx
import { SignedIn, RedirectToSignIn } from '@bettercone/ui';

export default function ProtectedPage() {
  return (
    <>
      <SignedIn authClient={authClient}>
        <ProtectedContent />
      </SignedIn>
      <RedirectToSignIn authClient={authClient} />
    </>
  );
}

Marketing Site Header

<header>
  <Logo />
  <nav>
    <Link href="/features">Features</Link>
    <Link href="/pricing">Pricing</Link>
  </nav>
  
  <div className="flex items-center gap-2">
    <SignedOut authClient={authClient}>
      <Button variant="ghost" asChild>
        <Link href="/sign-in">Sign In</Link>
      </Button>
      <Button asChild>
        <Link href="/sign-up">Get Started</Link>
      </Button>
    </SignedOut>
    
    <SignedIn authClient={authClient}>
      <Button asChild>
        <Link href="/dashboard">Dashboard</Link>
      </Button>
      <UserButton authClient={authClient} />
    </SignedIn>
  </div>
</header>