BigBlocks Docs

OAuthProviders

OAuth provider selection component for linking cloud backup storage

OAuthProviders

A component for displaying and managing OAuth provider connections for cloud backup storage. Supports multiple providers with official brand colors and flexible configuration.

OAuthProviders Demo

OAuth provider selection component for linking cloud backup storage with multiple providers.

Configuration

Linked Providers

google

Recent Events

No events yet...

Default Providers

Action: Link

Custom Providers

Action: Link

Note: Dropbox is disabled in this example

Different Actions

Sign In Context:
Action: Sign in with
Sign Up Context:
Action: Sign up with

Try:

  • Change action context to see different button labels
  • Click providers to link/unlink them
  • Try different sizes and disabled state
  • Notice linked providers show checkmarks
  • Watch events update in real-time

Installation

npx bigblocks add oauth-providers

Import

import { OAuthProviders } from 'bigblocks';

Props

PropTypeRequiredDefaultDescription
providersOAuthProvider[]NoDefault providersCustom provider configuration
action'signin' | 'signup' | 'link'No'link'Action context
callbackUrlstringNo-OAuth callback URL
linkedProvidersstring[]No[]Already linked provider IDs
onProviderClick(provider: string) => voidNo-Provider click handler
disabledbooleanNofalseDisable all providers
loadingbooleanNofalseLoading state
classNamestringNo-Additional CSS classes
size'1' | '2' | '3'No'2'Button size

Types

interface OAuthProvider {
  id: string;
  name: string;
  icon: React.ReactNode;
  enabled?: boolean;
}

Basic Usage

import { OAuthProviders } from 'bigblocks';

export default function BackupSettings() {
  const handleProviderClick = (provider: string) => {
    console.log('Selected provider:', provider);
    // Initiate OAuth flow
    window.location.href = `/api/auth/link?provider=${provider}`;
  };

  return (
    <OAuthProviders
      onProviderClick={handleProviderClick}
      linkedProviders={['google']}
    />
  );
}

Advanced Usage

With Custom Providers

import { OAuthProviders } from 'bigblocks';

const customProviders = [
  {
    id: 'google',
    name: 'Google',
    icon: <GoogleIcon />,
    enabled: true,
  },
  {
    id: 'github',
    name: 'GitHub',
    icon: <GitHubIcon />,
    enabled: true,
  },
  {
    id: 'microsoft',
    name: 'Microsoft',
    icon: <MicrosoftIcon />,
    enabled: false, // Disabled
  },
];

export default function CustomProviders() {
  return (
    <OAuthProviders
      providers={customProviders}
      onProviderClick={(provider) => {
        console.log('Clicked:', provider);
      }}
    />
  );
}

With Linked Status

import { OAuthProviders } from 'bigblocks';
import { useConnectedAccounts } from '@/hooks/useConnectedAccounts';

export default function LinkedProviders() {
  const { data: accounts } = useConnectedAccounts();
  const linkedProviders = accounts?.map(a => a.provider) || [];

  return (
    <OAuthProviders
      linkedProviders={linkedProviders}
      onProviderClick={(provider) => {
        if (linkedProviders.includes(provider)) {
          // Already linked - maybe unlink?
          console.log('Already linked:', provider);
        } else {
          // Link new provider
          window.location.href = `/api/auth/link?provider=${provider}`;
        }
      }}
    />
  );
}

Different Actions

import { OAuthProviders } from 'bigblocks';

export default function ActionExamples() {
  return (
    <div className="space-y-4">
      {/* Sign in with OAuth */}
      <OAuthProviders
        action="signin"
        onProviderClick={(provider) => {
          window.location.href = `/api/auth/signin?provider=${provider}`;
        }}
      />

      {/* Sign up with OAuth */}
      <OAuthProviders
        action="signup"
        onProviderClick={(provider) => {
          window.location.href = `/api/auth/signup?provider=${provider}`;
        }}
      />

      {/* Link for backup */}
      <OAuthProviders
        action="link"
        onProviderClick={(provider) => {
          window.location.href = `/api/auth/link?provider=${provider}`;
        }}
      />
    </div>
  );
}

With Loading State

import { OAuthProviders } from 'bigblocks';
import { useState } from 'react';

export default function LoadingExample() {
  const [isLoading, setIsLoading] = useState(false);

  const handleProviderClick = async (provider: string) => {
    setIsLoading(true);
    try {
      await linkProvider(provider);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <OAuthProviders
      onProviderClick={handleProviderClick}
      loading={isLoading}
      disabled={isLoading}
    />
  );
}

Custom Sizing

import { OAuthProviders } from 'bigblocks';

export default function SizingExample() {
  return (
    <div className="space-y-4">
      <OAuthProviders size="1" onProviderClick={console.log} />
      <OAuthProviders size="2" onProviderClick={console.log} />
      <OAuthProviders size="3" onProviderClick={console.log} />
    </div>
  );
}

Brand Colors

The component exports official brand colors for OAuth providers:

import { OAUTH_BRAND_COLORS } from 'bigblocks';

// Access brand colors
const googleBlue = OAUTH_BRAND_COLORS.google.blue;    // #4285F4
const githubDark = OAUTH_BRAND_COLORS.github;         // #24292e
const twitterBlue = OAUTH_BRAND_COLORS.twitter;       // #1DA1F2
const handcashGreen = OAUTH_BRAND_COLORS.handcash;    // #38CB7C
const discordPurple = OAUTH_BRAND_COLORS.discord;     // #5865F2
const facebookBlue = OAUTH_BRAND_COLORS.facebook;     // #1877F2
const microsoftBlue = OAUTH_BRAND_COLORS.microsoft;   // #00BCF2

Common Patterns

In Settings Page

import { OAuthProviders } from 'bigblocks';

export function SecuritySettings() {
  const { data: user } = useAuth();
  const linkedProviders = user?.connectedAccounts || [];

  return (
    <div className="space-y-4">
      <div>
        <h3 className="text-lg font-semibold">Cloud Backup Providers</h3>
        <p className="text-sm text-gray-600">
          Link providers to backup your wallet
        </p>
      </div>
      
      <OAuthProviders
        linkedProviders={linkedProviders}
        onProviderClick={(provider) => {
          if (linkedProviders.includes(provider)) {
            if (confirm(`Unlink ${provider}?`)) {
              unlinkProvider(provider);
            }
          } else {
            linkProvider(provider);
          }
        }}
      />
      
      <div className="text-sm text-gray-500">
        {linkedProviders.length === 0 && (
          <p>No providers linked yet</p>
        )}
        {linkedProviders.length > 0 && (
          <p>Linked: {linkedProviders.join(', ')}</p>
        )}
      </div>
    </div>
  );
}

In Signup Flow

import { OAuthProviders } from 'bigblocks';

export function SignupStep() {
  const [step, setStep] = useState('create');

  return (
    <div>
      {step === 'create' && (
        <div>
          <h2>Create Your Account</h2>
          <CreateIdentityForm onComplete={() => setStep('backup')} />
        </div>
      )}
      
      {step === 'backup' && (
        <div>
          <h2>Backup Your Wallet</h2>
          <p>Link a cloud provider for automatic backups</p>
          
          <OAuthProviders
            action="link"
            onProviderClick={(provider) => {
              // Store provider choice
              sessionStorage.setItem('backupProvider', provider);
              // Redirect to OAuth
              window.location.href = `/api/auth/link?provider=${provider}`;
            }}
          />
          
          <button onClick={() => setStep('complete')}>
            Skip for now
          </button>
        </div>
      )}
    </div>
  );
}

With Custom Styling

import { OAuthProviders } from 'bigblocks';

export function StyledProviders() {
  return (
    <div className="bg-gray-50 p-6 rounded-lg">
      <OAuthProviders
        className="gap-4"
        onProviderClick={(provider) => {
          console.log('Selected:', provider);
        }}
      />
    </div>
  );
}

Provider Setup

Each provider requires OAuth app configuration:

Google

  1. Visit Google Cloud Console
  2. Create OAuth 2.0 credentials
  3. Add redirect URI: https://yourdomain.com/api/auth/callback/google
  4. Enable Google Drive API for backup storage

GitHub

  1. Visit GitHub Developer Settings
  2. Create OAuth App
  3. Add redirect URI: https://yourdomain.com/api/auth/callback/github
  4. Request gist scope for backup storage

Twitter

  1. Visit Twitter Developer Portal
  2. Create OAuth 2.0 app
  3. Add redirect URI: https://yourdomain.com/api/auth/callback/twitter

HandCash

  1. Visit HandCash Developer Portal
  2. Create app
  3. Add redirect URI: https://yourdomain.com/api/auth/callback/handcash

Styling

The component uses Radix Themes buttons and can be customized:

/* Custom provider button styles */
.oauth-providers {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}

.oauth-provider-button {
  min-width: 120px;
}

.oauth-provider-button[data-linked="true"] {
  opacity: 0.7;
  position: relative;
}

.oauth-provider-button[data-linked="true"]::after {
  content: "✓";
  position: absolute;
  top: 0;
  right: 0;
  background: green;
  color: white;
  border-radius: 50%;
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
}

Best Practices

  1. Clear Action Context: Use appropriate action prop for context
  2. Loading States: Show loading feedback during OAuth flows
  3. Error Handling: Handle OAuth failures gracefully
  4. Security: Always validate OAuth responses server-side
  5. Accessibility: Ensure keyboard navigation works

Troubleshooting

Providers Not Showing

  • Check that providers array is properly configured
  • Ensure enabled is true for each provider
  • Verify component is wrapped in theme provider

Click Handler Not Working

  • Ensure onProviderClick is properly defined
  • Check for event propagation issues
  • Verify buttons aren't disabled

OAuth Flow Issues

  • Verify redirect URIs match exactly
  • Check OAuth app permissions/scopes
  • Ensure callback handlers are implemented

API Reference

Default Providers

The component includes these providers by default:

  • Google (id: 'google')
  • GitHub (id: 'github')
  • Twitter (id: 'twitter')
  • HandCash (id: 'handcash')

Each can be customized or filtered using the providers prop.

Notes for Improvement

Enhanced Implementation: The actual component is more sophisticated than the prompt suggested:

  • Supports custom provider configurations
  • Includes brand color constants
  • Has size variants for different contexts
  • More flexible action contexts (signin/signup/link)
  • Better TypeScript support with proper interfaces