@molecule/app-oauth-buttons-react
v1.0.3
Published
Config-driven OAuth provider button row composing @molecule/app-oauth-logos-react with layout variants (horizontal / vertical / grid) and brand-themed inline colors
Maintainers
Readme
@molecule/app-oauth-buttons-react
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Config-driven <OAuthButtons providers={[...]} /> row.
Lifts the bespoke OAuthButtons.tsx re-implemented by every flagship
Login / Signup page today into a single composable component, building
on @molecule/app-oauth-logos-react for the canonical brand marks.
providersaccepts the canonicalOAuthProviderId[]fromuseOAuth(config).providers(or any other source) — apps no longer need to map provider strings into bespoke button arrays.onSelect(provider)initiates the OAuth flow. Host apps typically passredirectfromuseOAuth(config)orsignInWithProviderfrom their auth bond.layouttoggles'horizontal' | 'vertical' | 'grid'— the grid variant auto-paginates into a 2-column layout above 4 providers.brandButtonsopt-in paints each button with its provider's exact brand-spec background (#ffffor Google,#24292ffor GitHub, etc.) via inlinestyle— those are provider-mandated color tokens ClassMap intentionally does not encode. It is independent oficonMode(logo color). Layout, padding, radius, and chrome all come from the wired ClassMap (cm.oauthButtonGroup,cm.oauthButton,cm.oauthButtonIcon).<OAuthDivider>is the composable "or continue with" rule — the config-driven<OAuthButtons>in@molecule/app-auth-ui-reactcomposes it above this row.
Companion locale bond:
@molecule/app-locales-oauth-buttons (79 languages).
Quick Start
import { OAuthButtons } from '@molecule/app-oauth-buttons-react'
import { useOAuth } from '@molecule/app-react'
import { oauthConfig } from '../config'
function LoginPage() {
const { providers, redirect } = useOAuth(oauthConfig)
return <OAuthButtons providers={providers} onSelect={redirect} layout="grid" showLabels />
}Type
feature
Installation
npm install @molecule/app-oauth-buttons-react @molecule/app-oauth-logos-react @molecule/app-react @molecule/app-ui react
npm install -D @types/reactAPI
Interfaces
BrandStyle
Inline-style payload for a single brand button.
interface BrandStyle {
/** Background color (CSS color token). */
background: string
/** Foreground / label color (CSS color token). */
color: string
/** Optional 1px border color when `background` is white/very light. */
borderColor?: string
}OAuthButtonsProps
Props accepted by <OAuthButtons />.
interface OAuthButtonsProps {
/**
* Ordered list of provider ids to render.
*
* Typically the `string[]` from `useOAuth(config).providers`. Known
* canonical ids (e.g. `'google'`, `'github'` — see `OAuthProviderId`)
* get their brand logo + localized label; unknown ids fall through to
* a synthesized label and a ClassMap-neutral button, so any string is
* safe to pass.
*/
providers: string[]
/**
* Optional click handler. Called with the provider id when the user
* activates a button.
*
* If omitted, buttons render as plain `<button type="button">` with no
* default behavior — host apps wire the handler (typically calling
* `redirect(provider)` from `useOAuth(...)` or an auth bond's inline
* `signInWithProvider(provider)`).
*
* May be sync or async. A fire-and-navigate `redirect` returns `void`;
* an inline flow (popup / PKCE / an auth bond that settles the session
* in place) returns a `Promise` that resolves when the handshake
* completes — in that case `onSuccess(provider)` fires on resolve.
*/
onSelect?: (provider: string) => void | Promise<unknown>
/**
* Called with the provider id when the OAuth handshake completes
* successfully — but ONLY when `onSelect` returns a `Promise` that
* resolves (an inline / popup / PKCE flow, e.g. an auth bond's
* `signInWithProvider` that settles the session in place). The
* component awaits that promise and invokes `onSuccess` on resolve.
*
* A full-page `redirect(provider)` onSelect returns `void` and
* navigates away, so there is nothing to await and `onSuccess` does
* NOT fire — that flow's completion is observed on the callback page by
* `useOAuth(config).onSuccess` instead. A rejected handshake also does
* not fire it.
*/
onSuccess?: (provider: string) => void
/**
* Layout variant. Defaults to `'horizontal'` (flex-wrap row).
*
* - `'horizontal'`: row that wraps when crowded.
* - `'vertical'`: stacked column (one button per line).
* - `'grid'`: 2-column grid (recommended for >4 providers).
*/
layout?: OAuthButtonsLayout
/** Icon size in pixels. Defaults to 30. */
iconSize?: number
/** Logo color mode — `'brand'` (default, official multi-color) or `'mono'`. */
iconMode?: 'brand' | 'mono'
/**
* When true, paint each button with its provider's brand-spec
* background/foreground colors (Google white, GitHub `#24292f`, etc.)
* via inline `style`. Defaults to `false` — buttons stay
* ClassMap-neutral so the row is visually uniform.
*
* Independent of `iconMode`: `iconMode` controls the *logo's* color
* rendering, `brandButtons` controls the *button surface*.
*/
brandButtons?: boolean
/**
* When true, render the localized provider label text next to the
* logo (e.g. `"Continue with GitHub"`). Defaults to `false` (icon-only
* pixel-identical row across providers).
*/
showLabels?: boolean
/** Extra class composed onto the button-group element. */
className?: string
}OAuthDividerProps
Props accepted by <OAuthDivider /> — the "or continue with" rule
rendered above an OAuth button row.
interface OAuthDividerProps {
/**
* i18n key for the divider label. Defaults to `'oauth.orContinueWith'`.
*/
labelKey?: string
/**
* Fallback divider text if the i18n key is missing. Defaults to
* `'or continue with'`.
*/
labelDefault?: string
/** Extra class composed onto the divider wrapper. */
className?: string
}Types
OAuthButtonsLayout
Layout variants for the OAuth button row.
type OAuthButtonsLayout = 'horizontal' | 'vertical' | 'grid'OAuthProviderId
Canonical list of supported providers.
type OAuthProviderId =
| 'github'
| 'gitlab'
| 'google'
| 'twitter'
| 'x'
| 'apple'
| 'facebook'
| 'microsoft'
| 'linkedin'
| 'discord'Functions
dedupeProviders(providers)
De-duplicates a provider list while preserving the caller's order.
Mirrors how host apps typically pass providers derived from
useOAuth(config).providers plus per-page overrides — duplicates can
sneak in via merge-and-pass patterns.
function dedupeProviders(providers: readonly T[]): T[]providers— Raw list (may contain duplicates).
Returns: Ordered list with duplicates removed.
getBrandStyle(provider)
Returns the inline style payload for a given provider id.
Unknown providers receive an empty object so the wired ClassMap's
default surface color governs — matching the icon-only fallback
behavior of <OAuthProviderLogo fallback={...} />.
function getBrandStyle(provider: string): CSSPropertiesprovider— Canonical provider id (e.g.'google').
Returns: Inline-style object for the button element.
getButtonLayoutStyle(layout)
Returns the inline-style overlay for an individual button in a given
layout. In 'vertical' mode each button stretches to fill the column.
function getButtonLayoutStyle(layout: OAuthButtonsLayout): CSSPropertieslayout— Selected layout variant.
Returns: Inline-style object to spread onto the button element.
getLayoutStyle(layout, providerCount)
Returns the inline-style overlay applied on top of cm.oauthButtonGroup
for a given layout variant.
function getLayoutStyle(layout: OAuthButtonsLayout, providerCount: number): CSSPropertieslayout— Selected layout variant.providerCount— Number of buttons rendered (drives grid columns).
Returns: Inline-style object to spread onto the wrapper element.
getProviderLabel(provider)
Returns the i18n entry (key + English default) for a given provider id.
Falls back to a synthesized entry for unknown ids so unrecognized providers still render with a sensible English label rather than a raw key string.
function getProviderLabel(provider: string): { key: string; default: string }provider— Canonical provider id (e.g.'google').
Returns: Translation key + English default for the provider.
OAuthButtons(props)
Renders one styled button per OAuth provider.
Composes the canonical brand logos from
@molecule/app-oauth-logos-react and pulls layout / chrome from
the wired ClassMap (cm.oauthButtonGroup, cm.oauthButton,
cm.oauthButtonIcon). When brandButtons is set, each button also
gets its provider's exact brand-spec background via inline style
(ClassMap intentionally does not encode provider brand colors).
This is the lower-level primitive — host apps that have an
oauthConfig object typically use the config-driven
<OAuthButtons> from @molecule/app-auth-ui-react, which composes
this row plus <OAuthDivider>.
function OAuthButtons({
providers,
onSelect,
onSuccess,
layout = 'horizontal',
iconSize = 30,
iconMode = 'brand',
brandButtons = false,
showLabels = false,
className,
}: OAuthButtonsProps): JSX.Element | nullprops— SeeOAuthButtonsProps.
OAuthDivider(props)
Renders a horizontal rule with centered label text — the "or continue with" divider shown between a login/signup form and the OAuth button row.
Split out as its own sub-component so the config-driven
<OAuthButtons> in @molecule/app-auth-ui-react can compose it
above <OAuthButtons> (the row) without re-implementing the markup.
function OAuthDivider({
labelKey = 'oauth.orContinueWith',
labelDefault = 'or continue with',
className,
}?: OAuthDividerProps): JSX.Elementprops— SeeOAuthDividerProps.
Constants
BRAND_STYLES
Brand-spec colors for each supported OAuth provider.
Sourced from each provider's official developer brand guidelines.
When a host app wants to override these (dark-mode tweaks, brand
exceptions), pass iconMode="mono" and let the wired ClassMap
paint everything via cm.oauthButton.
const BRAND_STYLES: Readonly<Record<OAuthProviderId, BrandStyle>>PROVIDER_LABELS
Canonical i18n key + English default for each supported provider.
Used by <OAuthButtons /> to render the localized provider name
(e.g. "Continue with {{provider}}"). The key matches the
companion locale bond @molecule/app-locales-oauth-buttons.
const PROVIDER_LABELS: Readonly<Record<OAuthProviderId, { key: string; default: string }>>Injection Notes
Requirements
Peer dependencies:
@molecule/app-oauth-logos-react^1.0.1@molecule/app-react^1.0.1@molecule/app-ui^1.0.1react^18.0.0 || ^19.0.0
Runtime Dependencies
@molecule/app-oauth-logos-react@molecule/app-react@molecule/app-uireact
Rendering-only: this package draws the buttons; the OAuth handshake
itself — authorize redirect, and the callback/code-to-session
exchange on return — belongs to useOAuth(config) (which needs the
@molecule/app-react Auth provider context) or your auth bond's
signInWithProvider. onSuccess(provider) fires only for an inline
onSelect that returns a Promise resolving on handshake completion
(popup / PKCE); a full-page redirect onSelect returns void, so
onSuccess does not fire and completion is observed by
useOAuth(config).onSuccess on the callback page instead. Requires a
wired ClassMap bond and a React I18nProvider ancestor —
getClassMap() and useTranslation() both throw before wiring.
Translations
Translation strings are provided by @molecule/app-locales-oauth-buttons.
